浏览代码

Move File fields to their own module

Ben S 10 年之前
父节点
当前提交
085067d18e
共有 4 个文件被更改,包括 141 次插入136 次删除
  1. 3 4
      src/dir.rs
  2. 20 20
      src/feature/git.rs
  3. 92 87
      src/file.rs
  4. 26 25
      src/output/details.rs

+ 3 - 4
src/dir.rs

@@ -1,6 +1,5 @@
 use feature::Git;
-use file::File;
-use file;
+use file::{File, fields};
 
 use std::io;
 use std::fs;
@@ -65,11 +64,11 @@ impl Dir {
     }
 
     /// Get a string describing the Git status of the given file.
-    pub fn git_status(&self, path: &Path, prefix_lookup: bool) -> file::Git {
+    pub fn git_status(&self, path: &Path, prefix_lookup: bool) -> fields::Git {
         match (&self.git, prefix_lookup) {
             (&Some(ref git), false)  => git.status(path),
             (&Some(ref git), true)   => git.dir_status(path),
-            (&None, _)               => file::Git::empty()
+            (&None, _)               => fields::Git::empty()
         }
     }
 }

+ 20 - 20
src/feature/git.rs

@@ -2,7 +2,7 @@ use std::path::{Path, PathBuf};
 
 use git2;
 
-use file;
+use file::fields;
 
 /// Container of Git statuses for all the files in this folder's Git repository.
 pub struct Git {
@@ -28,48 +28,48 @@ impl Git {
     }
 
     /// Get the status for the file at the given path, if present.
-    pub fn status(&self, path: &Path) -> file::Git {
+    pub fn status(&self, path: &Path) -> fields::Git {
         let status = self.statuses.iter()
                                   .find(|p| p.0.as_path() == path);
         match status {
-            Some(&(_, s)) =>  file::Git { staged: index_status(s),        unstaged: working_tree_status(s) },
-            None          =>  file::Git { staged: file::GitStatus::NotModified, unstaged: file::GitStatus::NotModified }
+            Some(&(_, s)) =>  fields::Git { staged: index_status(s),        unstaged: working_tree_status(s) },
+            None          =>  fields::Git { staged: fields::GitStatus::NotModified, unstaged: fields::GitStatus::NotModified }
         }
     }
 
     /// Get the combined status for all the files whose paths begin with the
     /// path that gets passed in. This is used for getting the status of
     /// directories, which don't really have an 'official' status.
-    pub fn dir_status(&self, dir: &Path) -> file::Git {
+    pub fn dir_status(&self, dir: &Path) -> fields::Git {
         let s = self.statuses.iter()
                              .filter(|p| p.0.starts_with(dir))
                              .fold(git2::Status::empty(), |a, b| a | b.1);
 
-        file::Git { staged: index_status(s), unstaged: working_tree_status(s) }
+        fields::Git { staged: index_status(s), unstaged: working_tree_status(s) }
     }
 }
 
 /// The character to display if the file has been modified, but not staged.
-fn working_tree_status(status: git2::Status) -> file::GitStatus {
+fn working_tree_status(status: git2::Status) -> fields::GitStatus {
     match status {
-        s if s.contains(git2::STATUS_WT_NEW)         => file::GitStatus::New,
-        s if s.contains(git2::STATUS_WT_MODIFIED)    => file::GitStatus::Modified,
-        s if s.contains(git2::STATUS_WT_DELETED)     => file::GitStatus::Deleted,
-        s if s.contains(git2::STATUS_WT_RENAMED)     => file::GitStatus::Renamed,
-        s if s.contains(git2::STATUS_WT_TYPECHANGE)  => file::GitStatus::TypeChange,
-        _                                            => file::GitStatus::NotModified,
+        s if s.contains(git2::STATUS_WT_NEW)         => fields::GitStatus::New,
+        s if s.contains(git2::STATUS_WT_MODIFIED)    => fields::GitStatus::Modified,
+        s if s.contains(git2::STATUS_WT_DELETED)     => fields::GitStatus::Deleted,
+        s if s.contains(git2::STATUS_WT_RENAMED)     => fields::GitStatus::Renamed,
+        s if s.contains(git2::STATUS_WT_TYPECHANGE)  => fields::GitStatus::TypeChange,
+        _                                            => fields::GitStatus::NotModified,
     }
 }
 
 /// The character to display if the file has been modified, and the change
 /// has been staged.
-fn index_status(status: git2::Status) -> file::GitStatus {
+fn index_status(status: git2::Status) -> fields::GitStatus {
     match status {
-        s if s.contains(git2::STATUS_INDEX_NEW)         => file::GitStatus::New,
-        s if s.contains(git2::STATUS_INDEX_MODIFIED)    => file::GitStatus::Modified,
-        s if s.contains(git2::STATUS_INDEX_DELETED)     => file::GitStatus::Deleted,
-        s if s.contains(git2::STATUS_INDEX_RENAMED)     => file::GitStatus::Renamed,
-        s if s.contains(git2::STATUS_INDEX_TYPECHANGE)  => file::GitStatus::TypeChange,
-        _                                               => file::GitStatus::NotModified,
+        s if s.contains(git2::STATUS_INDEX_NEW)         => fields::GitStatus::New,
+        s if s.contains(git2::STATUS_INDEX_MODIFIED)    => fields::GitStatus::Modified,
+        s if s.contains(git2::STATUS_INDEX_DELETED)     => fields::GitStatus::Deleted,
+        s if s.contains(git2::STATUS_INDEX_RENAMED)     => fields::GitStatus::Renamed,
+        s if s.contains(git2::STATUS_INDEX_TYPECHANGE)  => fields::GitStatus::TypeChange,
+        _                                               => fields::GitStatus::NotModified,
     }
 }

+ 92 - 87
src/file.rs

@@ -3,7 +3,6 @@ use std::env::current_dir;
 use std::fs;
 use std::io;
 use std::os::unix;
-use std::os::unix::raw::{blkcnt_t, gid_t, ino_t, nlink_t, time_t, uid_t};
 use std::os::unix::fs::{MetadataExt, PermissionsExt};
 use std::path::{Component, Path, PathBuf};
 
@@ -13,66 +12,7 @@ use dir::Dir;
 use options::TimeType;
 use feature::Attribute;
 
-pub enum Type {
-    File, Directory, Pipe, Link, Special,
-}
-
-pub struct Permissions {
-    pub file_type:      Type,
-    pub user_read:      bool,
-    pub user_write:     bool,
-    pub user_execute:   bool,
-    pub group_read:     bool,
-    pub group_write:    bool,
-    pub group_execute:  bool,
-    pub other_read:     bool,
-    pub other_write:    bool,
-    pub other_execute:  bool,
-    pub attribute:      bool,
-}
-
-pub struct Links {
-    pub count: nlink_t,
-    pub multiple: bool,
-}
-
-pub struct Inode(pub ino_t);
-
-pub enum Blocks {
-    Some(blkcnt_t),
-    None,
-}
-
-pub struct User(pub uid_t);
-
-pub struct Group(pub gid_t);
-
-pub enum Size {
-    Some(u64),
-    None,
-}
-
-pub struct Time(pub time_t);
-
-pub enum GitStatus {
-    NotModified,
-    New,
-    Modified,
-    Deleted,
-    Renamed,
-    TypeChange,
-}
-
-pub struct Git {
-    pub staged:   GitStatus,
-    pub unstaged: GitStatus,
-}
-
-impl Git {
-    pub fn empty() -> Git {
-        Git { staged: GitStatus::NotModified, unstaged: GitStatus::NotModified }
-    }
-}
+use self::fields as f;
 
 /// A **File** is a wrapper around one of Rust's Path objects, along with
 /// associated data about the file.
@@ -222,34 +162,34 @@ impl<'a> File<'a> {
     /// This is important, because a file with multiple links is uncommon,
     /// while you can come across directories and other types with multiple
     /// links much more often.
-    pub fn links(&self) -> Links {
+    pub fn links(&self) -> f::Links {
         let count = self.stat.as_raw().nlink();
 
-        Links {
+        f::Links {
             count: count,
             multiple: self.is_file() && count > 1,
         }
     }
 
-    pub fn inode(&self) -> Inode {
-        Inode(self.stat.as_raw().ino())
+    pub fn inode(&self) -> f::Inode {
+        f::Inode(self.stat.as_raw().ino())
     }
 
-    pub fn blocks(&self) -> Blocks {
+    pub fn blocks(&self) -> f::Blocks {
         if self.is_file() || self.is_link() {
-            Blocks::Some(self.stat.as_raw().blocks())
+            f::Blocks::Some(self.stat.as_raw().blocks())
         }
         else {
-            Blocks::None
+            f::Blocks::None
         }
     }
 
-    pub fn user(&self) -> User {
-        User(self.stat.as_raw().uid())
+    pub fn user(&self) -> f::User {
+        f::User(self.stat.as_raw().uid())
     }
 
-    pub fn group(&self) -> Group {
-        Group(self.stat.as_raw().gid())
+    pub fn group(&self) -> f::Group {
+        f::Group(self.stat.as_raw().gid())
     }
 
     /// This file's size, formatted using the given way, as a coloured string.
@@ -258,52 +198,52 @@ impl<'a> File<'a> {
     /// some filesystems, I've never looked at one of those numbers and gained
     /// any information from it, so by emitting "-" instead, the table is less
     /// cluttered with numbers.
-    pub fn size(&self) -> Size {
+    pub fn size(&self) -> f::Size {
         if self.is_directory() {
-            Size::None
+            f::Size::None
         }
         else {
-            Size::Some(self.stat.len())
+            f::Size::Some(self.stat.len())
         }
     }
 
-    pub fn timestamp(&self, time_type: TimeType) -> Time {
+    pub fn timestamp(&self, time_type: TimeType) -> f::Time {
         let time_in_seconds = match time_type {
             TimeType::FileAccessed => self.stat.as_raw().atime(),
             TimeType::FileModified => self.stat.as_raw().mtime(),
             TimeType::FileCreated  => self.stat.as_raw().ctime(),
         };
 
-        Time(time_in_seconds)
+        f::Time(time_in_seconds)
     }
 
     /// This file's type, represented by a coloured character.
     ///
     /// Although the file type can usually be guessed from the colour of the
     /// file, `ls` puts this character there, so people will expect it.
-    fn type_char(&self) -> Type {
+    fn type_char(&self) -> f::Type {
         if self.is_file() {
-            Type::File
+            f::Type::File
         }
         else if self.is_directory() {
-            Type::Directory
+            f::Type::Directory
         }
         else if self.is_pipe() {
-            Type::Pipe
+            f::Type::Pipe
         }
         else if self.is_link() {
-            Type::Link
+            f::Type::Link
         }
         else {
-            Type::Special
+            f::Type::Special
         }
     }
 
-    pub fn permissions(&self) -> Permissions {
+    pub fn permissions(&self) -> f::Permissions {
         let bits = self.stat.permissions().mode();
         let has_bit = |bit| { bits & bit == bit };
 
-        Permissions {
+        f::Permissions {
             file_type:      self.type_char(),
             user_read:      has_bit(unix::fs::USER_READ),
             user_write:     has_bit(unix::fs::USER_WRITE),
@@ -364,9 +304,9 @@ impl<'a> File<'a> {
         choices.contains(&&self.name[..])
     }
 
-    pub fn git_status(&self) -> Git {
+    pub fn git_status(&self) -> f::Git {
         match self.dir {
-            None    => Git { staged: GitStatus::NotModified, unstaged: GitStatus::NotModified },
+            None    => f::Git { staged: f::GitStatus::NotModified, unstaged: f::GitStatus::NotModified },
             Some(d) => {
                 let cwd = match current_dir() {
                     Err(_)  => Path::new(".").join(&self.path),
@@ -404,6 +344,71 @@ fn ext<'a>(name: &'a str) -> Option<String> {
     name.rfind('.').map(|p| name[p+1..].to_ascii_lowercase())
 }
 
+pub mod fields {
+    use std::os::unix::raw::{blkcnt_t, gid_t, ino_t, nlink_t, time_t, uid_t};
+
+    pub enum Type {
+        File, Directory, Pipe, Link, Special,
+    }
+
+    pub struct Permissions {
+        pub file_type:      Type,
+        pub user_read:      bool,
+        pub user_write:     bool,
+        pub user_execute:   bool,
+        pub group_read:     bool,
+        pub group_write:    bool,
+        pub group_execute:  bool,
+        pub other_read:     bool,
+        pub other_write:    bool,
+        pub other_execute:  bool,
+        pub attribute:      bool,
+    }
+
+    pub struct Links {
+        pub count: nlink_t,
+        pub multiple: bool,
+    }
+
+    pub struct Inode(pub ino_t);
+
+    pub enum Blocks {
+        Some(blkcnt_t),
+        None,
+    }
+
+    pub struct User(pub uid_t);
+
+    pub struct Group(pub gid_t);
+
+    pub enum Size {
+        Some(u64),
+        None,
+    }
+
+    pub struct Time(pub time_t);
+
+    pub enum GitStatus {
+        NotModified,
+        New,
+        Modified,
+        Deleted,
+        Renamed,
+        TypeChange,
+    }
+
+    pub struct Git {
+        pub staged:   GitStatus,
+        pub unstaged: GitStatus,
+    }
+
+    impl Git {
+        pub fn empty() -> Git {
+            Git { staged: GitStatus::NotModified, unstaged: GitStatus::NotModified }
+        }
+    }
+}
+
 #[cfg(broken_test)]
 pub mod test {
     pub use super::*;

+ 26 - 25
src/output/details.rs

@@ -2,7 +2,8 @@ use colours::Colours;
 use column::{Alignment, Column, Cell};
 use feature::Attribute;
 use dir::Dir;
-use file::{Blocks, File, Git, GitStatus, Group, Inode, Links, Permissions, Size, Time, Type, User};
+use file::File;
+use file::fields as f;
 use options::{Columns, FileFilter, RecurseOptions, SizeFormat};
 use users::{OSUsers, Users};
 
@@ -197,21 +198,21 @@ impl Table {
         }
     }
 
-    fn render_permissions(&self, permissions: Permissions) -> Cell {
+    fn render_permissions(&self, permissions: f::Permissions) -> Cell {
         let c = self.colours.perms;
         let bit = |bit, chr: &'static str, style: Style| {
             if bit { style.paint(chr) } else { self.colours.punctuation.paint("-") }
         };
 
         let file_type = match permissions.file_type {
-            Type::File       => self.colours.filetypes.normal.paint("."),
-            Type::Directory  => self.colours.filetypes.directory.paint("d"),
-            Type::Pipe       => self.colours.filetypes.special.paint("|"),
-            Type::Link       => self.colours.filetypes.symlink.paint("l"),
-            Type::Special    => self.colours.filetypes.special.paint("?"),
+            f::Type::File       => self.colours.filetypes.normal.paint("."),
+            f::Type::Directory  => self.colours.filetypes.directory.paint("d"),
+            f::Type::Pipe       => self.colours.filetypes.special.paint("|"),
+            f::Type::Link       => self.colours.filetypes.symlink.paint("l"),
+            f::Type::Special    => self.colours.filetypes.special.paint("?"),
         };
 
-        let x_colour = if let Type::File = permissions.file_type { c.user_execute_file }
+        let x_colour = if let f::Type::File = permissions.file_type { c.user_execute_file }
                                                             else { c.user_execute_other };
 
         let string = ANSIStrings( &[
@@ -234,26 +235,26 @@ impl Table {
         }
     }
 
-    fn render_links(&self, links: Links) -> Cell {
+    fn render_links(&self, links: f::Links) -> Cell {
         let style = if links.multiple { self.colours.links.multi_link_file }
                                  else { self.colours.links.normal };
 
         Cell::paint(style, &self.numeric.format_int(links.count))
     }
 
-    fn render_blocks(&self, blocks: Blocks) -> Cell {
+    fn render_blocks(&self, blocks: f::Blocks) -> Cell {
         match blocks {
-            Blocks::Some(blocks)  => Cell::paint(self.colours.blocks, &blocks.to_string()),
-            Blocks::None          => Cell::paint(self.colours.punctuation, "-"),
+            f::Blocks::Some(blocks)  => Cell::paint(self.colours.blocks, &blocks.to_string()),
+            f::Blocks::None          => Cell::paint(self.colours.punctuation, "-"),
         }
     }
 
-    fn render_inode(&self, inode: Inode) -> Cell {
+    fn render_inode(&self, inode: f::Inode) -> Cell {
         Cell::paint(self.colours.inode, &inode.0.to_string())
     }
 
-    fn render_size(&self, size: Size, size_format: SizeFormat) -> Cell {
-        if let Size::Some(offset) = size {
+    fn render_size(&self, size: f::Size, size_format: SizeFormat) -> Cell {
+        if let f::Size::Some(offset) = size {
             let result = match size_format {
                 SizeFormat::DecimalBytes  => decimal_prefix(offset as f64),
                 SizeFormat::BinaryBytes   => binary_prefix(offset as f64),
@@ -278,7 +279,7 @@ impl Table {
         }
     }
 
-    fn render_time(&self, timestamp: Time) -> Cell {
+    fn render_time(&self, timestamp: f::Time) -> Cell {
         let date = LocalDateTime::at(timestamp.0);
 
         let format = if date.year() == self.current_year {
@@ -291,15 +292,15 @@ impl Table {
         Cell::paint(self.colours.date, &format.format(date, &self.time))
     }
 
-    fn render_git_status(&self, git: Git) -> Cell {
+    fn render_git_status(&self, git: f::Git) -> Cell {
         let render_char = |chr| {
             match chr {
-                GitStatus::NotModified  => self.colours.punctuation.paint("-"),
-                GitStatus::New          => self.colours.git.renamed.paint("N"),
-                GitStatus::Modified     => self.colours.git.renamed.paint("M"),
-                GitStatus::Deleted      => self.colours.git.renamed.paint("D"),
-                GitStatus::Renamed      => self.colours.git.renamed.paint("R"),
-                GitStatus::TypeChange   => self.colours.git.renamed.paint("T"),
+                f::GitStatus::NotModified  => self.colours.punctuation.paint("-"),
+                f::GitStatus::New          => self.colours.git.renamed.paint("N"),
+                f::GitStatus::Modified     => self.colours.git.renamed.paint("M"),
+                f::GitStatus::Deleted      => self.colours.git.renamed.paint("D"),
+                f::GitStatus::Renamed      => self.colours.git.renamed.paint("R"),
+                f::GitStatus::TypeChange   => self.colours.git.renamed.paint("T"),
             }
         };
 
@@ -309,7 +310,7 @@ impl Table {
         }
     }
 
-    fn render_user(&mut self, user: User) -> Cell {
+    fn render_user(&mut self, user: f::User) -> Cell {
         let user_name = match self.users.get_user_by_uid(user.0) {
             Some(user)  => user.name,
             None        => user.0.to_string(),
@@ -320,7 +321,7 @@ impl Table {
         Cell::paint(style, &*user_name)
     }
 
-    fn render_group(&mut self, group: Group) -> Cell {
+    fn render_group(&mut self, group: f::Group) -> Cell {
         let mut style = self.colours.users.group_not_yours;
 
         let group_name = match self.users.get_group_by_gid(group.0) {