mirror of
https://github.com/Llewellynvdm/exa.git
synced 2024-11-25 13:27:33 +00:00
Move some stuff out to rust-ansi-term crate
This commit is contained in:
parent
eecfd88363
commit
d2647df0ca
@ -6,4 +6,8 @@ authors = [ "ogham@bsago.me" ]
|
|||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
||||||
name = "exa"
|
name = "exa"
|
||||||
|
|
||||||
|
[dependencies.ansi_term]
|
||||||
|
|
||||||
|
git = "https://github.com/ogham/rust-ansi-term.git"
|
252
src/colours.rs
252
src/colours.rs
@ -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<Colour>,
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
#![feature(phase)]
|
#![feature(phase)]
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
#[phase(plugin)] extern crate regex_macros;
|
#[phase(plugin)] extern crate regex_macros;
|
||||||
|
extern crate ansi_term;
|
||||||
|
|
||||||
use std::os;
|
use std::os;
|
||||||
|
|
||||||
@ -8,9 +9,9 @@ use file::File;
|
|||||||
use dir::Dir;
|
use dir::Dir;
|
||||||
use options::Options;
|
use options::Options;
|
||||||
use unix::Unix;
|
use unix::Unix;
|
||||||
use colours::Plain;
|
|
||||||
|
|
||||||
pub mod colours;
|
use ansi_term::{Plain, strip_formatting};
|
||||||
|
|
||||||
pub mod column;
|
pub mod column;
|
||||||
pub mod dir;
|
pub mod dir;
|
||||||
pub mod format;
|
pub mod format;
|
||||||
@ -88,7 +89,7 @@ fn exa(options: &Options, print_header: bool, string: String) {
|
|||||||
// results are cached.
|
// results are cached.
|
||||||
|
|
||||||
let lengths: Vec<Vec<uint>> = table.iter()
|
let lengths: Vec<Vec<uint>> = 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();
|
.collect();
|
||||||
|
|
||||||
let column_widths: Vec<uint> = range(0, options.columns.len())
|
let column_widths: Vec<uint> = range(0, options.columns.len())
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use colours::{Plain, Style, Red, Green, Yellow, Blue, Purple, Cyan, Grey};
|
|
||||||
use std::io::{fs, IoResult};
|
use std::io::{fs, IoResult};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::str::from_utf8_lossy;
|
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 column::{Column, Permissions, FileName, FileSize, User, Group, HardLinks, Inode, Blocks};
|
||||||
use format::{format_metric_bytes, format_IEC_bytes};
|
use format::{format_metric_bytes, format_IEC_bytes};
|
||||||
use unix::Unix;
|
use unix::Unix;
|
||||||
@ -10,6 +11,8 @@ use sort::SortPart;
|
|||||||
use dir::Dir;
|
use dir::Dir;
|
||||||
use filetype::HasType;
|
use filetype::HasType;
|
||||||
|
|
||||||
|
static Grey: Colour = Fixed(244);
|
||||||
|
|
||||||
// Instead of working with Rust's Paths, we have our own File object
|
// Instead of working with Rust's Paths, we have our own File object
|
||||||
// that holds the Path and various cached information. Each file is
|
// that holds the Path and various cached information. Each file is
|
||||||
// definitely going to have its filename used at least once, its stat
|
// definitely going to have its filename used at least once, its stat
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use colours::{Plain, Style, Red, Green, Yellow, Blue, Cyan, Grey, Fixed};
|
|
||||||
use file::File;
|
use file::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
|
use ansi_term::{Colour, Plain, Style, Red, Green, Yellow, Blue, Cyan, Fixed};
|
||||||
|
|
||||||
|
static Grey: Colour = Fixed(244);
|
||||||
|
|
||||||
pub enum FileType {
|
pub enum FileType {
|
||||||
Normal, Directory, Executable, Immediate, Compiled, Symlink, Special,
|
Normal, Directory, Executable, Immediate, Compiled, Symlink, Special,
|
||||||
Image, Video, Music, Lossless, Compressed, Document, Temp, Crypto,
|
Image, Video, Music, Lossless, Compressed, Document, Temp, Crypto,
|
||||||
@ -136,4 +139,3 @@ impl<'a> HasType for File<'a> {
|
|||||||
return Normal; // no filetype
|
return Normal; // no filetype
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user