From d2647df0ca5a41b2d87c5062c51167b3408d5e88 Mon Sep 17 00:00:00 2001 From: Ben S Date: Tue, 1 Jul 2014 19:00:36 +0100 Subject: [PATCH] Move some stuff out to rust-ansi-term crate --- Cargo.toml | 6 +- src/colours.rs | 252 ------------------------------------------------ src/exa.rs | 7 +- src/file.rs | 5 +- src/filetype.rs | 6 +- 5 files changed, 17 insertions(+), 259 deletions(-) delete mode 100644 src/colours.rs diff --git a/Cargo.toml b/Cargo.toml index b1a6463..6d7268a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,8 @@ authors = [ "ogham@bsago.me" ] [[bin]] -name = "exa" \ No newline at end of file +name = "exa" + +[dependencies.ansi_term] + +git = "https://github.com/ogham/rust-ansi-term.git" \ No newline at end of file diff --git a/src/colours.rs b/src/colours.rs deleted file mode 100644 index d78b188..0000000 --- a/src/colours.rs +++ /dev/null @@ -1,252 +0,0 @@ -// Provide standard values for the eight standard colours and custom -// values for up to 256. There are terminals that can do the full RGB -// spectrum, but for something as simple as discerning file types this -// doesn't really seem worth it. - -// Bear in mind that the first eight (and their bold variants) are -// user-definable and can look different on different terminals, but -// the other 256 have their values fixed. - -pub enum Colour { - Black, Red, Green, Yellow, Blue, Purple, Cyan, White, Fixed(u8), -} - -// These are the standard numeric sequences. -// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html - -impl Colour { - fn foreground_code(&self) -> String { - match *self { - Black => "30".to_string(), - Red => "31".to_string(), - Green => "32".to_string(), - Yellow => "33".to_string(), - Blue => "34".to_string(), - Purple => "35".to_string(), - Cyan => "36".to_string(), - White => "37".to_string(), - Fixed(num) => format!("38;5;{}", num), - } - } - - fn background_code(&self) -> String { - match *self { - Black => "40".to_string(), - Red => "41".to_string(), - Green => "42".to_string(), - Yellow => "43".to_string(), - Blue => "44".to_string(), - Purple => "45".to_string(), - Cyan => "46".to_string(), - White => "47".to_string(), - Fixed(num) => format!("48;5;{}", num), - } - } -} - -// Prefer using a fixed grey, such as Fixed(244), to bold black, as -// bold black looks really weird on some terminals. - -pub static Grey: Colour = Fixed(244); - -// There are only three different styles: plain (no formatting), only -// a foreground colour, and a catch-all for anything more complicated -// than that. It's technically possible to write other cases such as -// "bold foreground", but probably isn't worth writing all the code. - -pub enum Style { - Plain, - Foreground(Colour), - Style(StyleStruct), -} - -// Having a struct inside an enum is currently unfinished in Rust, but -// should be put in there when that feature is complete. - -pub struct StyleStruct { - foreground: Colour, - background: Option, - bold: bool, - underline: bool, -} - -impl Style { - pub fn paint(&self, input: &str) -> String { - match *self { - Plain => input.to_string(), - Foreground(c) => c.paint(input), - Style(s) => match s { - StyleStruct { foreground, background, bold, underline } => { - let bg = match background { - Some(c) => format!("{};", c.background_code()), - None => "".to_string() - }; - let bo = if bold { "1;" } else { "" }; - let un = if underline { "4;" } else { "" }; - let painted = format!("\x1B[{}{}{}{}m{}\x1B[0m", bo, un, bg, foreground.foreground_code(), input.to_string()); - return painted.to_string(); - } - } - } - } -} - -impl Style { - pub fn bold(&self) -> Style { - match *self { - Plain => Style(StyleStruct { foreground: White, background: None, bold: true, underline: false }), - Foreground(c) => Style(StyleStruct { foreground: c, background: None, bold: true, underline: false }), - Style(st) => Style(StyleStruct { foreground: st.foreground, background: st.background, bold: true, underline: st.underline }), - } - } - - pub fn underline(&self) -> Style { - match *self { - Plain => Style(StyleStruct { foreground: White, background: None, bold: false, underline: true }), - Foreground(c) => Style(StyleStruct { foreground: c, background: None, bold: false, underline: true }), - Style(st) => Style(StyleStruct { foreground: st.foreground, background: st.background, bold: st.bold, underline: true }), - } - } - - pub fn on(&self, background: Colour) -> Style { - match *self { - Plain => Style(StyleStruct { foreground: White, background: Some(background), bold: false, underline: false }), - Foreground(c) => Style(StyleStruct { foreground: c, background: Some(background), bold: false, underline: false }), - Style(st) => Style(StyleStruct { foreground: st.foreground, background: Some(background), bold: st.bold, underline: st.underline }), - } - } -} - -impl Colour { - // This is a short-cut so you don't have to use Blue.normal() just - // to turn Blue into a Style. Annoyingly, this means that Blue and - // Blue.normal() aren't of the same type, but this hasn't been an - // issue so far. - - pub fn paint(&self, input: &str) -> String { - let re = format!("\x1B[{}m{}\x1B[0m", self.foreground_code(), input); - return re.to_string(); - } - - pub fn underline(&self) -> Style { - Style(StyleStruct { foreground: *self, background: None, bold: false, underline: true }) - } - - pub fn bold(&self) -> Style { - Style(StyleStruct { foreground: *self, background: None, bold: true, underline: false }) - } - - pub fn normal(&self) -> Style { - Style(StyleStruct { foreground: *self, background: None, bold: false, underline: false }) - } - - pub fn on(&self, background: Colour) -> Style { - Style(StyleStruct { foreground: *self, background: Some(background), bold: false, underline: false }) - } -} - -pub fn strip_formatting(input: &String) -> String { - let re = regex!("\x1B\\[.+?m"); - re.replace_all(input.as_slice(), "").to_string() -} - -#[test] -fn test_red() { - let hi = Red.paint("hi"); - assert!(hi == "\x1B[31mhi\x1B[0m".to_string()); -} - -#[test] -fn test_black() { - let hi = Black.normal().paint("hi"); - assert!(hi == "\x1B[30mhi\x1B[0m".to_string()); -} - -#[test] -fn test_yellow_bold() { - let hi = Yellow.bold().paint("hi"); - assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string()); -} - -#[test] -fn test_yellow_bold_2() { - let hi = Yellow.normal().bold().paint("hi"); - assert!(hi == "\x1B[1;33mhi\x1B[0m".to_string()); -} - -#[test] -fn test_blue_underline() { - let hi = Blue.underline().paint("hi"); - assert!(hi == "\x1B[4;34mhi\x1B[0m".to_string()); -} - -#[test] -fn test_green_bold_underline() { - let hi = Green.bold().underline().paint("hi"); - assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string()); -} - -#[test] -fn test_green_bold_underline_2() { - let hi = Green.underline().bold().paint("hi"); - assert!(hi == "\x1B[1;4;32mhi\x1B[0m".to_string()); -} - -#[test] -fn test_purple_on_white() { - let hi = Purple.on(White).paint("hi"); - assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string()); -} - -#[test] -fn test_purple_on_white_2() { - let hi = Purple.normal().on(White).paint("hi"); - assert!(hi == "\x1B[47;35mhi\x1B[0m".to_string()); -} - -#[test] -fn test_cyan_bold_on_white() { - let hi = Cyan.bold().on(White).paint("hi"); - assert!(hi == "\x1B[1;47;36mhi\x1B[0m".to_string()); -} - -#[test] -fn test_cyan_underline_on_white() { - let hi = Cyan.underline().on(White).paint("hi"); - assert!(hi == "\x1B[4;47;36mhi\x1B[0m".to_string()); -} - -#[test] -fn test_cyan_bold_underline_on_white() { - let hi = Cyan.bold().underline().on(White).paint("hi"); - assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string()); -} - -#[test] -fn test_cyan_underline_bold_on_white() { - let hi = Cyan.underline().bold().on(White).paint("hi"); - assert!(hi == "\x1B[1;4;47;36mhi\x1B[0m".to_string()); -} - -#[test] -fn test_fixed() { - let hi = Fixed(100).paint("hi"); - assert!(hi == "\x1B[38;5;100mhi\x1B[0m".to_string()); -} - -#[test] -fn test_fixed_on_purple() { - let hi = Fixed(100).on(Purple).paint("hi"); - assert!(hi == "\x1B[45;38;5;100mhi\x1B[0m".to_string()); -} - -#[test] -fn test_fixed_on_fixed() { - let hi = Fixed(100).on(Fixed(200)).paint("hi"); - assert!(hi == "\x1B[48;5;200;38;5;100mhi\x1B[0m".to_string()); -} - - - - - diff --git a/src/exa.rs b/src/exa.rs index cdf1562..10103fb 100644 --- a/src/exa.rs +++ b/src/exa.rs @@ -1,6 +1,7 @@ #![feature(phase)] extern crate regex; #[phase(plugin)] extern crate regex_macros; +extern crate ansi_term; use std::os; @@ -8,9 +9,9 @@ use file::File; use dir::Dir; use options::Options; use unix::Unix; -use colours::Plain; -pub mod colours; +use ansi_term::{Plain, strip_formatting}; + pub mod column; pub mod dir; pub mod format; @@ -88,7 +89,7 @@ fn exa(options: &Options, print_header: bool, string: String) { // results are cached. let lengths: Vec> = table.iter() - .map(|row| row.iter().map(|col| colours::strip_formatting(col).len()).collect()) + .map(|row| row.iter().map(|col| strip_formatting(col).len()).collect()) .collect(); let column_widths: Vec = range(0, options.columns.len()) diff --git a/src/file.rs b/src/file.rs index ebfbe31..d21b930 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,8 +1,9 @@ -use colours::{Plain, Style, Red, Green, Yellow, Blue, Purple, Cyan, Grey}; use std::io::{fs, IoResult}; use std::io; use std::str::from_utf8_lossy; +use ansi_term::{Colour, Plain, Style, Red, Green, Yellow, Blue, Purple, Cyan, Fixed}; + use column::{Column, Permissions, FileName, FileSize, User, Group, HardLinks, Inode, Blocks}; use format::{format_metric_bytes, format_IEC_bytes}; use unix::Unix; @@ -10,6 +11,8 @@ use sort::SortPart; use dir::Dir; use filetype::HasType; +static Grey: Colour = Fixed(244); + // Instead of working with Rust's Paths, we have our own File object // that holds the Path and various cached information. Each file is // definitely going to have its filename used at least once, its stat diff --git a/src/filetype.rs b/src/filetype.rs index d6e2ef0..2db1466 100644 --- a/src/filetype.rs +++ b/src/filetype.rs @@ -1,7 +1,10 @@ -use colours::{Plain, Style, Red, Green, Yellow, Blue, Cyan, Grey, Fixed}; use file::File; use std::io; +use ansi_term::{Colour, Plain, Style, Red, Green, Yellow, Blue, Cyan, Fixed}; + +static Grey: Colour = Fixed(244); + pub enum FileType { Normal, Directory, Executable, Immediate, Compiled, Symlink, Special, Image, Video, Music, Lossless, Compressed, Document, Temp, Crypto, @@ -136,4 +139,3 @@ impl<'a> HasType for File<'a> { return Normal; // no filetype } } -