Kaynağa Gözat

Code changes in preparation for recursion

Ben S 11 yıl önce
ebeveyn
işleme
6d4b30d531
6 değiştirilmiş dosya ile 60 ekleme ve 32 silme
  1. 12 12
      Cargo.lock
  2. 1 1
      Cargo.toml
  3. 1 0
      README.md
  4. 1 1
      src/file.rs
  5. 18 5
      src/main.rs
  6. 27 13
      src/options.rs

+ 12 - 12
Cargo.lock

@@ -2,17 +2,17 @@
 name = "exa"
 version = "0.1.0"
 dependencies = [
- "ansi_term 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "getopts 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ansi_term 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "natord 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "number_prefix 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "users 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "natord 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "number_prefix 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "users 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "ansi_term"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "regex 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -26,7 +26,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "getopts"
-version = "0.1.4"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -55,7 +55,7 @@ name = "libressl-pnacl-sys"
 version = "2.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "pnacl-build-helper 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnacl-build-helper 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -83,12 +83,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "natord"
-version = "1.0.6"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "number_prefix"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -107,7 +107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "pnacl-build-helper"
-version = "1.3.1"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -139,6 +139,6 @@ dependencies = [
 
 [[package]]
 name = "users"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 

+ 1 - 1
Cargo.toml

@@ -8,7 +8,7 @@ name = "exa"
 
 [dependencies]
 ansi_term = "0.4.2"
-getopts = "0.1.4"
+getopts = "0.2.0"
 natord = "1.0.6"
 number_prefix = "0.2.1"
 users = "0.2.1"

+ 1 - 0
README.md

@@ -21,6 +21,7 @@ exa is a replacement for `ls` written in Rust.
 - **-i**, **--inode**: show inode number column
 - **-l**, **--long**: display extended details and attributes
 - **-r**, **--reverse**: reverse sort order
+- **-R**, **--recurse**: recurse into subdirectories
 - **-s**, **--sort=(field)**: field to sort by
 - **-S**, **--blocks**: show number of file system blocks
 - **-x**, **--across**: sort multi-column view entries across

+ 1 - 1
src/file.rs

@@ -45,7 +45,7 @@ impl<'a> File<'a> {
 
     /// Create a new File object from the given Stat result, and other data.
     pub fn with_stat(stat: io::FileStat, path: &Path, parent: Option<&'a Dir>) -> File<'a> {
-        let v = path.filename().unwrap();  // fails if / or . or ..
+        let v = path.filename().unwrap_or_else(|| panic!("Failed to get filename for {:?}", path));  // fails if / or . or ..
         let filename = String::from_utf8_lossy(v);
 
         File {

+ 18 - 5
src/main.rs

@@ -1,6 +1,8 @@
 #![feature(collections, core, io, libc, os, path, std_misc)]
 
 extern crate ansi_term;
+extern crate getopts;
+extern crate natord;
 extern crate number_prefix;
 extern crate users;
 
@@ -12,7 +14,7 @@ use std::os::{args, set_exit_status};
 
 use dir::Dir;
 use file::File;
-use options::Options;
+use options::{Options, DirAction};
 
 pub mod column;
 pub mod dir;
@@ -30,15 +32,26 @@ fn exa(options: &Options) {
     // more than one of them.
     let mut count = 0;
 
+    let mut stack = options.path_strs.clone();
+
     // Separate the user-supplied paths into directories and files.
     // Files are shown first, and then each directory is expanded
     // and listed second.
-    for file in options.path_strings() {
-        let path = Path::new(file);
+    loop {
+        let file = match stack.pop() {
+            None => break,
+            Some(f) => f,
+        };
+
+        let path = Path::new(file.clone());
         match fs::stat(&path) {
             Ok(stat) => {
-                if !options.list_dirs && stat.kind == FileType::Directory {
-                    dirs.push(file.clone());
+                if stat.kind == FileType::Directory {
+                    match options.dir_action {
+                        DirAction::AsFile  => files.push(File::with_stat(stat, &path, None)),
+                        DirAction::List    => dirs.push(file.clone()),
+                        DirAction::Recurse => { /* todo */ },
+                    }
                 }
                 else {
                     // May as well reuse the stat result from earlier

+ 27 - 13
src/options.rs

@@ -1,6 +1,3 @@
-extern crate getopts;
-extern crate natord;
-
 use dir::Dir;
 use file::File;
 use column::{Column, SizeFormat};
@@ -13,14 +10,17 @@ use std::cmp::Ordering;
 use std::fmt;
 use std::slice::Iter;
 
+use getopts;
+use natord;
+
 use self::Misfire::*;
 
 /// The *Options* struct represents a parsed version of the user's
 /// command-line options.
 #[derive(PartialEq, Debug)]
 pub struct Options {
-    pub list_dirs: bool,
-    path_strs: Vec<String>,
+    pub dir_action: DirAction,
+    pub path_strs: Vec<String>,
     reverse: bool,
     show_invisibles: bool,
     sort_field: SortField,
@@ -43,6 +43,7 @@ impl Options {
             getopts::optflag("l", "long",      "display extended details and attributes"),
             getopts::optflag("i", "inode",     "show each file's inode number"),
             getopts::optflag("r", "reverse",   "reverse order of files"),
+            getopts::optflag("R", "recurse",   "recurse into directories"),
             getopts::optopt ("s", "sort",      "field to sort by", "WORD"),
             getopts::optflag("S", "blocks",    "show number of file system blocks"),
             getopts::optflag("x", "across",    "sort multi-column view entries across"),
@@ -64,7 +65,7 @@ impl Options {
         };
 
         Ok(Options {
-            list_dirs:       matches.opt_present("list-dirs"),
+            dir_action:      try!(dir_action(&matches)),
             path_strs:       if matches.free.is_empty() { vec![ ".".to_string() ] } else { matches.free.clone() },
             reverse:         matches.opt_present("reverse"),
             show_invisibles: matches.opt_present("all"),
@@ -73,11 +74,6 @@ impl Options {
         })
     }
 
-    /// Iterate over the non-option arguments left oven from getopts.
-    pub fn path_strings(&self) -> Iter<String> {
-        self.path_strs.iter()
-    }
-
     /// Display the files using this Option's View.
     pub fn view(&self, dir: Option<&Dir>, files: Vec<File>) {
         self.view.view(dir, files)
@@ -113,7 +109,13 @@ impl Options {
     }
 }
 
-/// User-supplied field to sort by
+/// What to do when encountering a directory?
+#[derive(PartialEq, Debug, Copy)]
+pub enum DirAction {
+    AsFile, List, Recurse
+}
+
+/// User-supplied field to sort by.
 #[derive(PartialEq, Debug, Copy)]
 pub enum SortField {
     Unsorted, Name, Extension, Size, FileInode
@@ -228,7 +230,7 @@ fn view(matches: &getopts::Matches) -> Result<View, Misfire> {
 /// Finds out which file size the user has asked for.
 fn file_size(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
     let binary = matches.opt_present("binary");
-    let bytes = matches.opt_present("bytes");
+    let bytes  = matches.opt_present("bytes");
 
     match (binary, bytes) {
         (true,  true ) => Err(Misfire::Conflict("binary", "bytes")),
@@ -238,6 +240,18 @@ fn file_size(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
     }
 }
 
+fn dir_action(matches: &getopts::Matches) -> Result<DirAction, Misfire> {
+    let recurse = matches.opt_present("recurse");
+    let list    = matches.opt_present("list-dirs");
+
+    match (recurse, list) {
+        (true,  true ) => Err(Misfire::Conflict("recurse", "list-dirs")),
+        (true,  false) => Ok(DirAction::Recurse),
+        (false, true ) => Ok(DirAction::AsFile),
+        (false, false) => Ok(DirAction::List),
+    }
+}
+
 #[derive(PartialEq, Copy, Debug)]
 pub struct Columns {
     size_format: SizeFormat,