Sfoglia il codice sorgente

Update most of the other columns to use colours

Ben S 10 anni fa
parent
commit
5a37d1b6b1
3 ha cambiato i file con 161 aggiunte e 65 eliminazioni
  1. 96 3
      src/colours.rs
  2. 55 53
      src/file.rs
  3. 10 9
      src/output/details.rs

+ 96 - 3
src/colours.rs

@@ -1,6 +1,6 @@
 use ansi_term::Style;
 use ansi_term::Style::Plain;
-use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Fixed};
+use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Purple, Fixed};
 
 use file::GREY;
 
@@ -8,7 +8,21 @@ use std::default::Default;
 
 #[derive(Clone, Copy, Debug, Default, PartialEq)]
 pub struct Colours {
-    pub filetypes: FileTypes,
+    pub filetypes:  FileTypes,
+    pub perms:      Permissions,
+    pub size:       Size,
+    pub users:      Users,
+    pub links:      Links,
+
+    pub punctuation:  Style,
+    pub date:         Style,
+    pub inode:        Style,
+    pub blocks:       Style,
+    pub header:       Style,
+
+    pub symlink_path:     Style,
+    pub broken_arrow:     Style,
+    pub broken_filename:  Style,
 }
 
 #[derive(Clone, Copy, Debug, Default, PartialEq)]
@@ -30,6 +44,44 @@ pub struct FileTypes {
 	pub compiled: Style,
 }
 
+#[derive(Clone, Copy, Debug, Default, PartialEq)]
+pub struct Permissions {
+    pub user_read:          Style,
+    pub user_write:         Style,
+    pub user_execute_file:  Style,
+    pub user_execute_other: Style,
+
+    pub group_read:    Style,
+    pub group_write:   Style,
+    pub group_execute: Style,
+
+    pub other_read:    Style,
+    pub other_write:   Style,
+    pub other_execute: Style,
+
+    pub attribute:  Style,
+}
+
+#[derive(Clone, Copy, Debug, Default, PartialEq)]
+pub struct Size {
+    pub numbers: Style,
+    pub unit: Style,
+}
+
+#[derive(Clone, Copy, Debug, Default, PartialEq)]
+pub struct Users {
+    pub user_you: Style,
+    pub user_someone_else: Style,
+    pub group_yours: Style,
+    pub group_not_yours: Style,
+}
+
+#[derive(Clone, Copy, Debug, Default, PartialEq)]
+pub struct Links {
+    pub normal: Style,
+    pub multi_link_file: Style,
+}
+
 impl Colours {
     pub fn plain() -> Colours {
         Colours::default()
@@ -53,7 +105,48 @@ impl Colours {
                 temp:        GREY.normal(),
                 immediate:   Yellow.bold().underline(),
                 compiled:    Fixed(137).normal(),
-            }
+            },
+
+            perms: Permissions {
+                user_read:           Yellow.bold(),
+                user_write:          Red.bold(),
+                user_execute_file:   Green.bold().underline(),
+                user_execute_other:  Green.bold(),
+                group_read:          Yellow.normal(),
+                group_write:         Red.normal(),
+                group_execute:       Green.normal(),
+                other_read:          Yellow.normal(),
+                other_write:         Red.normal(),
+                other_execute:       Green.normal(),
+                attribute:           Plain,
+            },
+
+            size: Size {
+                numbers:  Green.bold(),
+                unit:     Green.normal(),
+            },
+
+            users: Users {
+                user_you:           Yellow.bold(),
+                user_someone_else:  Plain,
+                group_yours:        Yellow.bold(),
+                group_not_yours:    Plain,
+            },
+
+            links: Links {
+                normal:          Red.bold(),
+                multi_link_file: Red.on(Yellow),
+            },
+
+            punctuation:  Fixed(244).normal(),
+            date:         Blue.normal(),
+            inode:        Purple.normal(),
+            blocks:       Cyan.normal(),
+            header:       Plain.underline(),
+
+            symlink_path:     Cyan.normal(),
+            broken_arrow:     Red.normal(),
+            broken_filename:  Red.underline()
         }
     }
 }

+ 55 - 53
src/file.rs

@@ -9,7 +9,7 @@ use std::path::{Component, Path, PathBuf};
 
 use ansi_term::{ANSIString, ANSIStrings, Colour, Style};
 use ansi_term::Style::Plain;
-use ansi_term::Colour::{Red, Green, Yellow, Blue, Purple, Cyan, Fixed};
+use ansi_term::Colour::Fixed;
 
 use users::Users;
 
@@ -114,16 +114,16 @@ impl<'a> File<'a> {
     }
 
     /// Get the data for a column, formatted as a coloured string.
-    pub fn display<U: Users>(&self, column: &Column, users_cache: &mut U, locale: &UserLocale) -> Cell {
+    pub fn display<U: Users>(&self, column: &Column, colours: &Colours, users_cache: &mut U, locale: &UserLocale) -> Cell {
         match *column {
-            Permissions     => self.permissions_string(),
-            FileSize(f)     => self.file_size(f, &locale.numeric),
-            Timestamp(t, y) => self.timestamp(t, y, &locale.time),
-            HardLinks       => self.hard_links(&locale.numeric),
-            Inode           => self.inode(),
-            Blocks          => self.blocks(&locale.numeric),
-            User            => self.user(users_cache),
-            Group           => self.group(users_cache),
+            Permissions     => self.permissions_string(colours),
+            FileSize(f)     => self.file_size(colours, f, &locale.numeric),
+            Timestamp(t, y) => self.timestamp(colours, t, y, &locale.time),
+            HardLinks       => self.hard_links(colours, &locale.numeric),
+            Inode           => self.inode(colours),
+            Blocks          => self.blocks(colours, &locale.numeric),
+            User            => self.user(colours, users_cache),
+            Group           => self.group(colours, users_cache),
             GitStatus       => self.git_status(),
         }
     }
@@ -185,14 +185,14 @@ impl<'a> File<'a> {
 
                     format!("{} {} {}",
                             style.paint(name),
-                            GREY.paint("=>"),
-                            ANSIStrings(&[ Cyan.paint(&path_prefix),
+                            colours.punctuation.paint("=>"),
+                            ANSIStrings(&[ colours.symlink_path.paint(&path_prefix),
                                            file_colour(colours, &file).paint(&file.name) ]))
                 },
                 Err(filename) => format!("{} {} {}",
                                          style.paint(name),
-                                         Red.paint("=>"),
-                                         Red.underline().paint(&filename)),
+                                         colours.broken_arrow.paint("=>"),
+                                         colours.broken_filename.paint(&filename)),
             }
         }
         else {
@@ -236,8 +236,10 @@ impl<'a> File<'a> {
     }
 
     /// This file's number of hard links as a coloured string.
-    fn hard_links(&self, locale: &locale::Numeric) -> Cell {
-        let style = if self.has_multiple_links() { Red.on(Yellow) } else { Red.normal() };
+    fn hard_links(&self, colours: &Colours, locale: &locale::Numeric) -> Cell {
+        let style = if self.has_multiple_links() { colours.links.multi_link_file }
+                                            else { colours.links.normal };
+
         Cell::paint(style, &locale.format_int(self.stat.as_raw().nlink())[..])
     }
 
@@ -251,18 +253,18 @@ impl<'a> File<'a> {
     }
 
     /// This file's inode as a coloured string.
-    fn inode(&self) -> Cell {
+    fn inode(&self, colours: &Colours) -> Cell {
         let inode = self.stat.as_raw().ino();
-        Cell::paint(Purple.normal(), &inode.to_string()[..])
+        Cell::paint(colours.inode, &inode.to_string()[..])
     }
 
     /// This file's number of filesystem blocks (if available) as a coloured string.
-    fn blocks(&self, locale: &locale::Numeric) -> Cell {
+    fn blocks(&self, colours: &Colours, locale: &locale::Numeric) -> Cell {
         if self.is_file() || self.is_link() {
-            Cell::paint(Cyan.normal(), &locale.format_int(self.stat.as_raw().blocks())[..])
+            Cell::paint(colours.blocks, &locale.format_int(self.stat.as_raw().blocks())[..])
         }
         else {
-            Cell { text: GREY.paint("-").to_string(), length: 1 }
+            Cell { text: colours.punctuation.paint("-").to_string(), length: 1 }
         }
     }
 
@@ -271,7 +273,7 @@ impl<'a> File<'a> {
     /// If the user is not present, then it formats the uid as a number
     /// instead. This usually happens when a user is deleted, but still owns
     /// files.
-    fn user<U: Users>(&self, users_cache: &mut U) -> Cell {
+    fn user<U: Users>(&self, colours: &Colours, users_cache: &mut U) -> Cell {
         let uid = self.stat.as_raw().uid();
 
         let user_name = match users_cache.get_user_by_uid(uid) {
@@ -279,23 +281,23 @@ impl<'a> File<'a> {
             None => uid.to_string(),
         };
 
-        let style = if users_cache.get_current_uid() == uid { Yellow.bold() } else { Plain };
+        let style = if users_cache.get_current_uid() == uid { colours.users.user_you } else { colours.users.user_someone_else };
         Cell::paint(style, &*user_name)
     }
 
     /// This file's group name as a coloured string.
     ///
     /// As above, if not present, it formats the gid as a number instead.
-    fn group<U: Users>(&self, users_cache: &mut U) -> Cell {
+    fn group<U: Users>(&self, colours: &Colours, users_cache: &mut U) -> Cell {
         let gid = self.stat.as_raw().gid();
-        let mut style = Plain;
+        let mut style = colours.users.group_not_yours;
 
         let group_name = match users_cache.get_group_by_gid(gid as u32) {
             Some(group) => {
                 let current_uid = users_cache.get_current_uid();
                 if let Some(current_user) = users_cache.get_user_by_uid(current_uid) {
                     if current_user.primary_group == group.gid || group.members.contains(&current_user.name) {
-                        style = Yellow.bold();
+                        style = colours.users.group_yours;
                     }
                 }
                 group.name
@@ -312,7 +314,7 @@ 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.
-    fn file_size(&self, size_format: SizeFormat, locale: &locale::Numeric) -> Cell {
+    fn file_size(&self, colours: &Colours, size_format: SizeFormat, locale: &locale::Numeric) -> Cell {
         if self.is_directory() {
             Cell { text: GREY.paint("-").to_string(), length: 1 }
         }
@@ -320,17 +322,17 @@ impl<'a> File<'a> {
             let result = match size_format {
                 SizeFormat::DecimalBytes => decimal_prefix(self.stat.len() as f64),
                 SizeFormat::BinaryBytes  => binary_prefix(self.stat.len() as f64),
-                SizeFormat::JustBytes    => return Cell::paint(Green.bold(), &locale.format_int(self.stat.len())[..]),
+                SizeFormat::JustBytes    => return Cell::paint(colours.size.numbers, &locale.format_int(self.stat.len())[..]),
             };
 
             match result {
-                Standalone(bytes) => Cell::paint(Green.bold(), &*bytes.to_string()),
+                Standalone(bytes) => Cell::paint(colours.size.numbers, &*bytes.to_string()),
                 Prefixed(prefix, n) => {
                     let number = if n < 10f64 { locale.format_float(n, 1) } else { locale.format_int(n as isize) };
                     let symbol = prefix.symbol();
 
                     Cell {
-                        text: ANSIStrings( &[ Green.bold().paint(&number[..]), Green.paint(symbol) ]).to_string(),
+                        text: ANSIStrings( &[ colours.size.unit.paint(&number[..]), colours.size.unit.paint(symbol) ]).to_string(),
                         length: number.len() + symbol.len(),
                     }
                 }
@@ -338,7 +340,7 @@ impl<'a> File<'a> {
         }
     }
 
-    fn timestamp(&self, time_type: TimeType, current_year: i64, locale: &locale::Time) -> Cell {
+    fn timestamp(&self, colours: &Colours, time_type: TimeType, current_year: i64, locale: &locale::Time) -> Cell {
 
         let time_in_seconds = match time_type {
             TimeType::FileAccessed => self.stat.as_raw().atime(),
@@ -355,28 +357,28 @@ impl<'a> File<'a> {
                 DateFormat::parse("{2>:D} {:M} {5>:Y}").unwrap()
             };
 
-        Cell::paint(Blue.normal(), &format.format(date, locale))
+        Cell::paint(colours.date, &format.format(date, locale))
     }
 
     /// 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) -> ANSIString {
+    fn type_char(&self, colours: &Colours) -> ANSIString {
         if self.is_file() {
-            Plain.paint(".")
+            colours.filetypes.normal.paint(".")
         }
         else if self.is_directory() {
-            Blue.paint("d")
+            colours.filetypes.directory.paint("d")
         }
         else if self.is_pipe() {
-            Yellow.paint("|")
+            colours.filetypes.special.paint("|")
         }
         else if self.is_link() {
-            Cyan.paint("l")
+            colours.filetypes.symlink.paint("l")
         }
         else {
-            Purple.paint("?")
+            colours.filetypes.special.paint("?")
         }
     }
 
@@ -385,8 +387,8 @@ impl<'a> File<'a> {
     /// Returns "@" or  " " depending on wheter the file contains an extented
     /// attribute or not. Also returns " " in case the attributes cannot be read
     /// for some reason.
-    fn attribute_marker(&self) -> ANSIString {
-        if self.xattrs.len() > 0 { Plain.paint("@") } else { Plain.paint(" ") }
+    fn attribute_marker(&self, colours: &Colours) -> ANSIString {
+        if self.xattrs.len() > 0 { colours.perms.attribute.paint("@") } else { Plain.paint(" ") }
     }
 
     /// Generate the "rwxrwxrwx" permissions string, like how ls does it.
@@ -394,24 +396,24 @@ impl<'a> File<'a> {
     /// Each character is given its own colour. The first three permission
     /// bits are bold because they're the ones used most often, and executable
     /// files are underlined to make them stand out more.
-    fn permissions_string(&self) -> Cell {
+    fn permissions_string(&self, colours: &Colours) -> Cell {
 
         let bits = self.stat.permissions().mode();
-        let executable_colour = if self.is_file() { Green.bold().underline() }
-                                                         else { Green.bold() };
+        let executable_colour = if self.is_file() { colours.perms.user_execute_file }
+                                             else { colours.perms.user_execute_other };
 
         let string = ANSIStrings(&[
-            self.type_char(),
-            File::permission_bit(bits, unix::fs::USER_READ,     "r", Yellow.bold()),
-            File::permission_bit(bits, unix::fs::USER_WRITE,    "w", Red.bold()),
+            self.type_char(colours),
+            File::permission_bit(bits, unix::fs::USER_READ,     "r", colours.perms.user_read),
+            File::permission_bit(bits, unix::fs::USER_WRITE,    "w", colours.perms.user_write),
             File::permission_bit(bits, unix::fs::USER_EXECUTE,  "x", executable_colour),
-            File::permission_bit(bits, unix::fs::GROUP_READ,    "r", Yellow.normal()),
-            File::permission_bit(bits, unix::fs::GROUP_WRITE,   "w", Red.normal()),
-            File::permission_bit(bits, unix::fs::GROUP_EXECUTE, "x", Green.normal()),
-            File::permission_bit(bits, unix::fs::OTHER_READ,    "r", Yellow.normal()),
-            File::permission_bit(bits, unix::fs::OTHER_WRITE,   "w", Red.normal()),
-            File::permission_bit(bits, unix::fs::OTHER_EXECUTE, "x", Green.normal()),
-            self.attribute_marker()
+            File::permission_bit(bits, unix::fs::GROUP_READ,    "r", colours.perms.group_read),
+            File::permission_bit(bits, unix::fs::GROUP_WRITE,   "w", colours.perms.group_write),
+            File::permission_bit(bits, unix::fs::GROUP_EXECUTE, "x", colours.perms.group_execute),
+            File::permission_bit(bits, unix::fs::OTHER_READ,    "r", colours.perms.other_read),
+            File::permission_bit(bits, unix::fs::OTHER_WRITE,   "w", colours.perms.other_write),
+            File::permission_bit(bits, unix::fs::OTHER_EXECUTE, "x", colours.perms.other_execute),
+            self.attribute_marker(colours)
         ]).to_string();
 
         Cell { text: string, length: 11 }

+ 10 - 9
src/output/details.rs

@@ -7,7 +7,6 @@ use options::{Columns, FileFilter, RecurseOptions};
 use users::OSUsers;
 
 use locale;
-use ansi_term::Style::Plain;
 
 /// With the **Details** view, the output gets formatted into columns, with
 /// each `Column` object showing some piece of information about the file,
@@ -46,7 +45,7 @@ impl Details {
     pub fn view(&self, dir: Option<&Dir>, files: &[File]) {
         // First, transform the Columns object into a vector of columns for
         // the current directory.
-        let mut table = Table::with_columns(self.columns.for_dir(dir));
+        let mut table = Table::with_options(self.colours, self.columns.for_dir(dir));
         if self.header { table.add_header() }
 
         // Then add files to the table and print it out.
@@ -58,7 +57,7 @@ impl Details {
     /// is present.
     fn add_files_to_table(&self, table: &mut Table, src: &[File], depth: usize) {
         for (index, file) in src.iter().enumerate() {
-            table.add_file(file, depth, index == src.len() - 1, &self.colours);
+            table.add_file(file, depth, index == src.len() - 1);
 
             // There are two types of recursion that exa supports: a tree
             // view, which is dealt with here, and multiple listings, which is
@@ -114,17 +113,19 @@ struct Table {
     users:   OSUsers,
     locale:  UserLocale,
     rows:    Vec<Row>,
+    colours: Colours,
 }
 
 impl Table {
     /// Create a new, empty Table object, setting the caching fields to their
     /// empty states.
-    fn with_columns(columns: Vec<Column>) -> Table {
+    fn with_options(colours: Colours, columns: Vec<Column>) -> Table {
         Table {
             columns: columns,
             users: OSUsers::empty_cache(),
             locale: UserLocale::new(),
             rows: Vec::new(),
+            colours: colours,
         }
     }
 
@@ -134,8 +135,8 @@ impl Table {
     fn add_header(&mut self) {
         let row = Row {
             depth:    0,
-            cells:    self.columns.iter().map(|c| Cell::paint(Plain.underline(), c.header())).collect(),
-            name:     Plain.underline().paint("Name").to_string(),
+            cells:    self.columns.iter().map(|c| Cell::paint(self.colours.header, c.header())).collect(),
+            name:     self.colours.header.paint("Name").to_string(),
             last:     false,
             attrs:    Vec::new(),
             children: false,
@@ -148,16 +149,16 @@ impl Table {
     /// this file, per-column.
     fn cells_for_file(&mut self, file: &File) -> Vec<Cell> {
         self.columns.clone().iter()
-                    .map(|c| file.display(c, &mut self.users, &self.locale))
+                    .map(|c| file.display(c, &self.colours, &mut self.users, &self.locale))
                     .collect()
     }
 
     /// Get the cells for the given file, and add the result to the table.
-    fn add_file(&mut self, file: &File, depth: usize, last: bool, colours: &Colours) {
+    fn add_file(&mut self, file: &File, depth: usize, last: bool) {
         let row = Row {
             depth:    depth,
             cells:    self.cells_for_file(file),
-            name:     file.file_name_view(colours),
+            name:     file.file_name_view(&self.colours),
             last:     last,
             attrs:    file.xattrs.clone(),
             children: file.this.is_some(),