diff --git a/Cargo.lock b/Cargo.lock index 41683d0..31db78f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,14 +2,14 @@ name = "exa" version = "0.2.0" dependencies = [ - "ansi_term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "datetime 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.2.9 (git+https://github.com/alexcrichton/git2-rs.git)", "locale 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "natord 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "pad 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -18,7 +18,7 @@ dependencies = [ [[package]] name = "ansi_term" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -57,14 +57,14 @@ version = "0.2.9" source = "git+https://github.com/alexcrichton/git2-rs.git#3a5f0b5698c5203fa48e33094158990a2c53c979" dependencies = [ "bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.2.12 (git+https://github.com/alexcrichton/git2-rs.git)", "url 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libc" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -72,7 +72,7 @@ name = "libgit2-sys" version = "0.2.12" source = "git+https://github.com/alexcrichton/git2-rs.git#3a5f0b5698c5203fa48e33094158990a2c53c979" dependencies = [ - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -92,7 +92,7 @@ name = "libssh2-sys" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -103,7 +103,7 @@ name = "libz-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -112,7 +112,7 @@ name = "locale" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -121,7 +121,7 @@ name = "log" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -145,10 +145,10 @@ dependencies = [ [[package]] name = "num_cpus" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -165,7 +165,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libressl-pnacl-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -196,7 +196,7 @@ name = "rand" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -244,6 +244,6 @@ name = "users" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/colours.rs b/src/colours.rs new file mode 100644 index 0000000..46397a0 --- /dev/null +++ b/src/colours.rs @@ -0,0 +1,52 @@ +use ansi_term::Style; +use ansi_term::Style::Plain; +use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Fixed}; + +use file::GREY; + +use std::default::Default; + +#[derive(Clone, Copy, Debug, Default, PartialEq)] +pub struct Colours { + pub normal: Style, + pub directory: Style, + pub symlink: Style, + pub special: Style, + pub executable: Style, + pub image: Style, + pub video: Style, + pub music: Style, + pub lossless: Style, + pub crypto: Style, + pub document: Style, + pub compressed: Style, + pub temp: Style, + pub immediate: Style, + pub compiled: Style, +} + +impl Colours { + pub fn plain() -> Colours { + Colours::default() + } + + pub fn colourful() -> Colours { + Colours { + normal: Plain, + directory: Blue.bold(), + symlink: Cyan.normal(), + special: Yellow.normal(), + executable: Green.bold(), + image: Fixed(133).normal(), + video: Fixed(135).normal(), + music: Fixed(92).normal(), + lossless: Fixed(93).normal(), + crypto: Fixed(109).normal(), + document: Fixed(105).normal(), + compressed: Red.normal(), + temp: GREY.normal(), + immediate: Yellow.bold().underline(), + compiled: Fixed(137).normal(), + } + } +} diff --git a/src/file.rs b/src/file.rs index bae78f6..8daffa3 100644 --- a/src/file.rs +++ b/src/file.rs @@ -22,10 +22,11 @@ use number_prefix::{binary_prefix, decimal_prefix, Prefixed, Standalone, PrefixN use datetime::local::{LocalDateTime, DatePiece}; use datetime::format::{DateFormat}; +use colours::Colours; use column::{Column, Cell}; use column::Column::*; use dir::Dir; -use filetype::file_type; +use filetype::file_colour; use options::{SizeFormat, TimeType}; use output::details::UserLocale; use feature::Attribute; @@ -132,12 +133,12 @@ impl<'a> File<'a> { /// /// It consists of the file name coloured in the appropriate style, /// with special formatting for a symlink. - pub fn file_name_view(&self) -> String { + pub fn file_name_view(&self, colours: &Colours) -> String { if self.is_link() { - self.symlink_file_name_view() + self.symlink_file_name_view(colours) } else { - self.file_colour().paint(&*self.name).to_string() + file_colour(colours, self).paint(&*self.name).to_string() } } @@ -149,9 +150,9 @@ impl<'a> File<'a> { /// an error, highlight the target and arrow in red. The error would /// be shown out of context, and it's almost always because the /// target doesn't exist. - fn symlink_file_name_view(&self) -> String { + fn symlink_file_name_view(&self, colours: &Colours) -> String { let name = &*self.name; - let style = self.file_colour(); + let style = file_colour(colours, self); if let Ok(path) = fs::read_link(&self.path) { let target_path = match self.dir { @@ -186,7 +187,7 @@ impl<'a> File<'a> { style.paint(name), GREY.paint("=>"), ANSIStrings(&[ Cyan.paint(&path_prefix), - file.file_colour().paint(&file.name) ])) + file_colour(colours, &file).paint(&file.name) ])) }, Err(filename) => format!("{} {} {}", style.paint(name), @@ -199,11 +200,6 @@ impl<'a> File<'a> { } } - /// The `ansi_term::Style` that this file's name should be painted. - pub fn file_colour(&self) -> Style { - file_type(&self).style() - } - /// The Unicode 'display width' of the filename. /// /// This is related to the number of graphemes in the string: most diff --git a/src/filetype.rs b/src/filetype.rs index a1b39c3..dadc415 100644 --- a/src/filetype.rs +++ b/src/filetype.rs @@ -1,55 +1,25 @@ -use file::{File, GREY}; -use self::FileType::*; - use ansi_term::Style; -use ansi_term::Style::Plain; -use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Fixed}; -#[derive(Debug)] -pub enum FileType { - Normal, Directory, Executable, Immediate, Compiled, Symlink, Special, - Image, Video, Music, Lossless, Compressed, Document, Temp, Crypto, -} +use file::File; +use colours::Colours; -impl FileType { - pub fn style(&self) -> Style { - match *self { - Normal => Plain, - Directory => Blue.bold(), - Symlink => Cyan.normal(), - Special => Yellow.normal(), - Executable => Green.bold(), - Image => Fixed(133).normal(), - Video => Fixed(135).normal(), - Music => Fixed(92).normal(), - Lossless => Fixed(93).normal(), - Crypto => Fixed(109).normal(), - Document => Fixed(105).normal(), - Compressed => Red.normal(), - Temp => GREY.normal(), - Immediate => Yellow.bold().underline(), - Compiled => Fixed(137).normal(), - } - } -} - -pub fn file_type(file: &File) -> FileType { +pub fn file_colour(colours: &Colours, file: &File) -> Style { match file { - f if f.is_directory() => Directory, - f if f.is_executable_file() => Executable, - f if f.is_link() => Symlink, - f if !f.is_file() => Special, - f if f.is_immediate() => Immediate, - f if f.is_image() => Image, - f if f.is_video() => Video, - f if f.is_music() => Music, - f if f.is_lossless() => Lossless, - f if f.is_crypto() => Crypto, - f if f.is_document() => Document, - f if f.is_compressed() => Compressed, - f if f.is_temp() => Temp, - f if f.is_compiled() => Compiled, - _ => Normal, + f if f.is_directory() => colours.directory, + f if f.is_executable_file() => colours.executable, + f if f.is_link() => colours.symlink, + f if !f.is_file() => colours.special, + f if f.is_immediate() => colours.immediate, + f if f.is_image() => colours.image, + f if f.is_video() => colours.video, + f if f.is_music() => colours.music, + f if f.is_lossless() => colours.lossless, + f if f.is_crypto() => colours.crypto, + f if f.is_document() => colours.document, + f if f.is_compressed() => colours.compressed, + f if f.is_temp() => colours.temp, + f if f.is_compiled() => colours.compiled, + _ => colours.normal, } } diff --git a/src/main.rs b/src/main.rs index e8ee7e3..7865457 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,8 +25,8 @@ use std::thread; use dir::Dir; use file::File; use options::{Options, View}; -use output::lines_view; +mod colours; mod column; mod dir; mod feature; @@ -189,7 +189,7 @@ impl<'a> Exa<'a> { match self.options.view { View::Grid(g) => g.view(files), View::Details(d) => d.view(dir, files), - View::Lines => lines_view(files), + View::Lines(l) => l.view(files), } } } diff --git a/src/options.rs b/src/options.rs index 8143e71..bff0d12 100644 --- a/src/options.rs +++ b/src/options.rs @@ -1,9 +1,10 @@ +use colours::Colours; use dir::Dir; use file::File; use column::Column; use column::Column::*; use feature::Attribute; -use output::{Grid, Details}; +use output::{Grid, Details, Lines}; use term::dimensions; use std::cmp::Ordering; @@ -38,7 +39,7 @@ pub struct FileFilter { #[derive(PartialEq, Debug, Copy, Clone)] pub enum View { Details(Details), - Lines, + Lines(Lines), Grid(Grid), } @@ -257,6 +258,7 @@ impl View { header: matches.opt_present("header"), recurse: dir_action.recurse_options().map(|o| (o, filter)), xattr: Attribute::feature_implemented() && matches.opt_present("extended"), + colours: if dimensions().is_some() { Colours::colourful() } else { Colours::plain() }, }; Ok(View::Details(details)) @@ -298,33 +300,44 @@ impl View { else if Attribute::feature_implemented() && matches.opt_present("extended") { Err(Misfire::Useless("extended", false, "long")) } - else if matches.opt_present("oneline") { - if matches.opt_present("across") { - Err(Misfire::Useless("across", true, "oneline")) + else if let Some((width, _)) = dimensions() { + if matches.opt_present("oneline") { + if matches.opt_present("across") { + Err(Misfire::Useless("across", true, "oneline")) + } + else { + let lines = Lines { + colours: Colours::colourful(), + }; + + Ok(View::Lines(lines)) + } } else { - Ok(View::Lines) - } - } - else { - if let Some((width, _)) = dimensions() { let grid = Grid { across: matches.opt_present("across"), - console_width: width + console_width: width, + colours: Colours::colourful(), }; Ok(View::Grid(grid)) } - else { - // If the terminal width couldn't be matched for some reason, such - // as the program's stdout being connected to a file, then - // fallback to the lines view. - Ok(View::Lines) - } + } + else { + // If the terminal width couldn't be matched for some reason, such + // as the program's stdout being connected to a file, then + // fallback to the lines view. + let lines = Lines { + colours: Colours::plain(), + }; + + Ok(View::Lines(lines)) } } } + + #[derive(PartialEq, Debug, Copy, Clone)] pub enum SizeFormat { DecimalBytes, diff --git a/src/output/details.rs b/src/output/details.rs index 5e69081..3870ace 100644 --- a/src/output/details.rs +++ b/src/output/details.rs @@ -1,3 +1,4 @@ +use colours::Colours; use column::{Alignment, Column, Cell}; use feature::Attribute; use dir::Dir; @@ -37,6 +38,8 @@ pub struct Details { /// Whether to show each file's extended attributes. pub xattr: bool, + + pub colours: Colours, } impl Details { @@ -55,7 +58,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); + table.add_file(file, depth, index == src.len() - 1, &self.colours); // There are two types of recursion that exa supports: a tree // view, which is dealt with here, and multiple listings, which is @@ -150,11 +153,11 @@ impl Table { } /// 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) { + fn add_file(&mut self, file: &File, depth: usize, last: bool, colours: &Colours) { let row = Row { depth: depth, cells: self.cells_for_file(file), - name: file.file_name_view(), + name: file.file_name_view(colours), last: last, attrs: file.xattrs.clone(), children: file.this.is_some(), diff --git a/src/output/grid.rs b/src/output/grid.rs index f87e916..0c2e950 100644 --- a/src/output/grid.rs +++ b/src/output/grid.rs @@ -1,6 +1,8 @@ +use colours::Colours; use column::Alignment::Left; use file::File; -use super::lines::lines_view; +use filetype::file_colour; +use super::lines::Lines; use std::cmp::max; use std::iter::repeat; @@ -9,6 +11,7 @@ use std::iter::repeat; pub struct Grid { pub across: bool, pub console_width: usize, + pub colours: Colours, } impl Grid { @@ -81,7 +84,7 @@ impl Grid { } let ref file = files[num]; - let styled_name = file.file_colour().paint(&file.name).to_string(); + let styled_name = file_colour(&self.colours, file).paint(&file.name).to_string(); if x == widths.len() - 1 { // The final column doesn't need to have trailing spaces print!("{}", styled_name); @@ -96,7 +99,7 @@ impl Grid { } else { // Drop down to lines view if the file names are too big for a grid - lines_view(files); + Lines { colours: self.colours }.view(files); } } } diff --git a/src/output/lines.rs b/src/output/lines.rs index 6649c29..b61494f 100644 --- a/src/output/lines.rs +++ b/src/output/lines.rs @@ -1,8 +1,16 @@ +use colours::Colours; use file::File; +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Lines { + pub colours: Colours, +} + /// The lines view literally just displays each file, line-by-line. -pub fn lines_view(files: &[File]) { - for file in files { - println!("{}", file.file_name_view()); +impl Lines { + pub fn view(&self, files: &[File]) { + for file in files { + println!("{}", file.file_name_view(&self.colours)); + } } } diff --git a/src/output/mod.rs b/src/output/mod.rs index 22b8726..8606d23 100644 --- a/src/output/mod.rs +++ b/src/output/mod.rs @@ -4,4 +4,4 @@ mod lines; pub use self::grid::Grid; pub use self::details::Details; -pub use self::lines::lines_view; +pub use self::lines::Lines;