瀏覽代碼

Add exa_colors to make exa themable

This adds support for the EXA_COLORS environment variable, and defines a bunch of exa-specific two-letter codes that I pretty much made up arbitrarily that control parts of the interface.

Fixes #160, which I didn’t expect to actually fix this release cycle, but it unexpectedly became easy to do!
Benjamin Sago 8 年之前
父節點
當前提交
f6b7b7f298
共有 4 個文件被更改,包括 98 次插入17 次删除
  1. 10 17
      src/options/colours.rs
  2. 5 0
      src/options/vars.rs
  3. 79 0
      src/style/colours.rs
  4. 4 0
      xtests/run.sh

+ 10 - 17
src/options/colours.rs

@@ -76,21 +76,12 @@ impl Colours {
 
         if let Some(lsc) = vars.get(vars::LS_COLORS) {
             let lsc = lsc.to_string_lossy();
-            LSColors(lsc.as_ref()).each_pair(|pair| {
-                match pair.key {
-                    "di" => colours.filekinds.directory    = pair.to_style(),
-                    "ex" => colours.filekinds.executable   = pair.to_style(),
-                    "fi" => colours.filekinds.normal       = pair.to_style(),
-                    "pi" => colours.filekinds.pipe         = pair.to_style(),
-                    "so" => colours.filekinds.socket       = pair.to_style(),
-                    "bd" => colours.filekinds.block_device = pair.to_style(),
-                    "cd" => colours.filekinds.char_device  = pair.to_style(),
-                    "ln" => colours.filekinds.symlink      = pair.to_style(),
-                    "or" => colours.broken_arrow           = pair.to_style(),
-                    "mi" => colours.broken_filename        = pair.to_style(),
-                     _   => {/* don’t change anything */},
-                }
-            })
+            LSColors(lsc.as_ref()).each_pair(|pair| colours.set_ls(&pair));
+        }
+
+        if let Some(exa) = vars.get(vars::EXA_COLORS) {
+            let exa = exa.to_string_lossy();
+            LSColors(exa.as_ref()).each_pair(|pair| colours.set_exa(&pair));
         }
 
         Ok(colours)
@@ -269,10 +260,12 @@ mod customs_test {
     // Test impl that just returns the value it has.
     impl Vars for MockVars {
         fn get(&self, name: &'static str) -> Option<OsString> {
-            if name == "LS_COLORS" && !self.ls.is_empty() {
+            use options::vars;
+
+            if name == vars::LS_COLORS && !self.ls.is_empty() {
                 OsString::from(self.ls.clone()).into()
             }
-            else if name == "EXA_COLORS" && !self.exa.is_empty() {
+            else if name == vars::EXA_COLORS && !self.exa.is_empty() {
                 OsString::from(self.exa.clone()).into()
             }
             else {

+ 5 - 0
src/options/vars.rs

@@ -15,6 +15,11 @@ pub static COLUMNS: &str = "COLUMNS";
 
 // exa-specific variables
 
+/// Environment variable used to colour exa’s interface when colours are
+/// enabled. This includes all the colours that LS_COLORS would recognise,
+/// overriding them if necessary. It can also contain exa-specific codes.
+pub static EXA_COLORS: &str = "EXA_COLORS";
+
 /// Environment variable used to switch on strict argument checking, such as
 /// complaining if an argument was specified twice, or if two conflict.
 /// This is meant to be so you don’t accidentally introduce the wrong

+ 79 - 0
src/style/colours.rs

@@ -4,6 +4,8 @@ use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Purple, Fixed};
 use output::render;
 use output::file_name::Colours as FileNameColours;
 
+use style::lsc::Pair;
+
 
 #[derive(Debug, Default, PartialEq)]
 pub struct Colours {
@@ -192,6 +194,83 @@ impl Colours {
 }
 
 
+impl Colours {
+    pub fn set_ls(&mut self, pair: &Pair) {
+        match pair.key {
+            "di" => self.filekinds.directory    = pair.to_style(),
+            "ex" => self.filekinds.executable   = pair.to_style(),
+            "fi" => self.filekinds.normal       = pair.to_style(),
+            "pi" => self.filekinds.pipe         = pair.to_style(),
+            "so" => self.filekinds.socket       = pair.to_style(),
+            "bd" => self.filekinds.block_device = pair.to_style(),
+            "cd" => self.filekinds.char_device  = pair.to_style(),
+            "ln" => self.filekinds.symlink      = pair.to_style(),
+            "or" => self.broken_arrow           = pair.to_style(),
+            "mi" => self.broken_filename        = pair.to_style(),
+             _   => {/* don’t change anything */},
+        }
+    }
+
+    pub fn set_exa(&mut self, pair: &Pair) {
+        match pair.key {
+            "di" => self.filekinds.directory      = pair.to_style(),
+            "ex" => self.filekinds.executable     = pair.to_style(),
+            "fi" => self.filekinds.normal         = pair.to_style(),
+            "pi" => self.filekinds.pipe           = pair.to_style(),
+            "so" => self.filekinds.socket         = pair.to_style(),
+            "bd" => self.filekinds.block_device   = pair.to_style(),
+            "cd" => self.filekinds.char_device    = pair.to_style(),
+            "ln" => self.filekinds.symlink        = pair.to_style(),
+            "or" => self.broken_arrow             = pair.to_style(),
+            "mi" => self.broken_filename          = pair.to_style(),
+
+            "ur" => self.perms.user_read          = pair.to_style(),
+            "uw" => self.perms.user_write         = pair.to_style(),
+            "ux" => self.perms.user_execute_file  = pair.to_style(),
+            "ue" => self.perms.user_execute_other = pair.to_style(),
+            "gr" => self.perms.group_read         = pair.to_style(),
+            "gw" => self.perms.group_write        = pair.to_style(),
+            "gx" => self.perms.group_execute      = pair.to_style(),
+            "tr" => self.perms.other_read         = pair.to_style(),
+            "tw" => self.perms.other_write        = pair.to_style(),
+            "tx" => self.perms.other_execute      = pair.to_style(),
+            "su" => self.perms.special_user_file  = pair.to_style(),
+            "sf" => self.perms.special_other      = pair.to_style(),
+            "xa" => self.perms.attribute          = pair.to_style(),
+
+            "sn" => self.size.numbers             = pair.to_style(),
+            "sb" => self.size.unit                = pair.to_style(),
+            "df" => self.size.major               = pair.to_style(),
+            "ds" => self.size.minor               = pair.to_style(),
+
+            "uu" => self.users.user_you           = pair.to_style(),
+            "un" => self.users.user_someone_else  = pair.to_style(),
+            "gu" => self.users.group_yours        = pair.to_style(),
+            "gn" => self.users.group_not_yours    = pair.to_style(),
+
+            "lc" => self.links.normal             = pair.to_style(),
+            "lm" => self.links.multi_link_file    = pair.to_style(),
+
+            "ga" => self.git.new                  = pair.to_style(),
+            "gm" => self.git.modified             = pair.to_style(),
+            "gd" => self.git.deleted              = pair.to_style(),
+            "gv" => self.git.renamed              = pair.to_style(),
+            "gt" => self.git.typechange           = pair.to_style(),
+
+            "xx" => self.punctuation              = pair.to_style(),
+            "da" => self.date                     = pair.to_style(),
+            "in" => self.inode                    = pair.to_style(),
+            "bl" => self.blocks                   = pair.to_style(),
+            "hd" => self.header                   = pair.to_style(),
+            "lp" => self.symlink_path             = pair.to_style(),
+            "cc" => self.control_char             = pair.to_style(),
+
+             _   => {/* still don’t change anything */},
+        }
+    }
+}
+
+
 impl render::BlocksColours for Colours {
     fn block_count(&self)  -> Style { self.blocks }
     fn no_blocks(&self)    -> Style { self.punctuation }

+ 4 - 0
xtests/run.sh

@@ -32,6 +32,10 @@ export EXA_STRICT="1"
 # We also don’t want to see reams and reams of debug output.
 export EXA_DEBUG=""
 
+# And default colours by default
+export LS_COLORS=""
+export EXA_COLORS=""
+
 
 # Check that no files were created more than a year ago.
 # Files not from the current year use a different date format, meaning