diff --git a/Cargo.toml b/Cargo.toml index 7f398ae68..19ec44f2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ generic = [ "comm", "cp", "cut", + "dircolors", "dirname", "echo", "env", @@ -102,6 +103,7 @@ cksum = { optional=true, path="src/cksum" } comm = { optional=true, path="src/comm" } cp = { optional=true, path="src/cp" } cut = { optional=true, path="src/cut" } +dircolors= { optional=true, path="src/dircolors" } dirname = { optional=true, path="src/dirname" } du = { optional=true, path="src/du" } echo = { optional=true, path="src/echo" } diff --git a/Makefile b/Makefile index b31261214..2af905cea 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,7 @@ PROGS := \ comm \ cp \ cut \ + dircolors \ dirname \ echo \ env \ @@ -136,6 +137,7 @@ TEST_PROGS := \ comm \ cp \ cut \ + dircolors \ dirname \ echo \ env \ diff --git a/README.md b/README.md index 91a68a0f0..e2dbea174 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,6 @@ To do - date - dd - df -- dircolors - expr (almost done, no regular expressions) - getlimits - install diff --git a/src/dircolors/Cargo.toml b/src/dircolors/Cargo.toml new file mode 100644 index 000000000..e5aff0373 --- /dev/null +++ b/src/dircolors/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "dircolors" +version = "0.0.1" +authors = [] + +[lib] +name = "uu_dircolors" +path = "dircolors.rs" + +[dependencies] +getopts = "*" +glob = "*" +libc = "*" +uucore = { path="../uucore" } + +[[bin]] +name = "dircolors" +path = "main.rs" diff --git a/src/dircolors/colors.rs b/src/dircolors/colors.rs new file mode 100644 index 000000000..8338dd6f3 --- /dev/null +++ b/src/dircolors/colors.rs @@ -0,0 +1,192 @@ +pub const INTERNAL_DB: &'static str = + r#"# Configuration file for dircolors, a utility to help you set the +# LS_COLORS environment variable used by GNU ls with the --color option. +# Copyright (C) 1996-2016 Free Software Foundation, Inc. +# Copying and distribution of this file, with or without modification, +# are permitted provided the copyright notice and this notice are preserved. +# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the +# slackware version of dircolors) are recognized but ignored. +# Below are TERM entries, which can be a glob patterns, to match +# against the TERM environment variable to determine if it is colorizable. +TERM Eterm +TERM ansi +TERM color-xterm +TERM con[0-9]*x[0-9]* +TERM cons25 +TERM console +TERM cygwin +TERM dtterm +TERM eterm-color +TERM gnome +TERM gnome-256color +TERM hurd +TERM jfbterm +TERM konsole +TERM kterm +TERM linux +TERM linux-c +TERM mach-color +TERM mach-gnu-color +TERM mlterm +TERM putty +TERM putty-256color +TERM rxvt* +TERM screen* +TERM st +TERM st-256color +TERM terminator +TERM tmux* +TERM vt100 +TERM xterm* +# Below are the color init strings for the basic file types. A color init +# string consists of one or more of the following numeric codes: +# Attribute codes: +# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed +# Text color codes: +# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white +# Background color codes: +# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white +#NORMAL 00 # no color code at all +#FILE 00 # regular file: use no color at all +RESET 0 # reset to "normal" color +DIR 01;34 # directory +LINK 01;36 # symbolic link. (If you set this to 'target' instead of a + # numerical value, the color is as for the file pointed to.) +MULTIHARDLINK 00 # regular file with more than one link +FIFO 40;33 # pipe +SOCK 01;35 # socket +DOOR 01;35 # door +BLK 40;33;01 # block device driver +CHR 40;33;01 # character device driver +ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... +MISSING 00 # ... and the files they point to +SETUID 37;41 # file that is setuid (u+s) +SETGID 30;43 # file that is setgid (g+s) +CAPABILITY 30;41 # file with capability +STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w) +OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky +STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable +# This is for files with execute permission: +EXEC 01;32 +# List any file extensions like '.gz' or '.tar' that you would like ls +# to colorize below. Put the extension, a space, and the color init string. +# (and any comments you want to add after a '#') +# If you use DOS-style suffixes, you may want to uncomment the following: +#.cmd 01;32 # executables (bright green) +#.exe 01;32 +#.com 01;32 +#.btm 01;32 +#.bat 01;32 +# Or if you want to colorize scripts even if they do not have the +# executable bit actually set. +#.sh 01;32 +#.csh 01;32 + # archives or compressed (bright red) +.tar 01;31 +.tgz 01;31 +.arc 01;31 +.arj 01;31 +.taz 01;31 +.lha 01;31 +.lz4 01;31 +.lzh 01;31 +.lzma 01;31 +.tlz 01;31 +.txz 01;31 +.tzo 01;31 +.t7z 01;31 +.zip 01;31 +.z 01;31 +.Z 01;31 +.dz 01;31 +.gz 01;31 +.lrz 01;31 +.lz 01;31 +.lzo 01;31 +.xz 01;31 +.bz2 01;31 +.bz 01;31 +.tbz 01;31 +.tbz2 01;31 +.tz 01;31 +.deb 01;31 +.rpm 01;31 +.jar 01;31 +.war 01;31 +.ear 01;31 +.sar 01;31 +.rar 01;31 +.alz 01;31 +.ace 01;31 +.zoo 01;31 +.cpio 01;31 +.7z 01;31 +.rz 01;31 +.cab 01;31 +# image formats +.jpg 01;35 +.jpeg 01;35 +.gif 01;35 +.bmp 01;35 +.pbm 01;35 +.pgm 01;35 +.ppm 01;35 +.tga 01;35 +.xbm 01;35 +.xpm 01;35 +.tif 01;35 +.tiff 01;35 +.png 01;35 +.svg 01;35 +.svgz 01;35 +.mng 01;35 +.pcx 01;35 +.mov 01;35 +.mpg 01;35 +.mpeg 01;35 +.m2v 01;35 +.mkv 01;35 +.webm 01;35 +.ogm 01;35 +.mp4 01;35 +.m4v 01;35 +.mp4v 01;35 +.vob 01;35 +.qt 01;35 +.nuv 01;35 +.wmv 01;35 +.asf 01;35 +.rm 01;35 +.rmvb 01;35 +.flc 01;35 +.avi 01;35 +.fli 01;35 +.flv 01;35 +.gl 01;35 +.dl 01;35 +.xcf 01;35 +.xwd 01;35 +.yuv 01;35 +.cgm 01;35 +.emf 01;35 +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.ogv 01;35 +.ogx 01;35 +# audio formats +.aac 00;36 +.au 00;36 +.flac 00;36 +.m4a 00;36 +.mid 00;36 +.midi 00;36 +.mka 00;36 +.mp3 00;36 +.mpc 00;36 +.ogg 00;36 +.ra 00;36 +.wav 00;36 +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.oga 00;36 +.opus 00;36 +.spx 00;36 +.xspf 00;36"#; diff --git a/src/dircolors/dircolors.rs b/src/dircolors/dircolors.rs new file mode 100644 index 000000000..f6224a36a --- /dev/null +++ b/src/dircolors/dircolors.rs @@ -0,0 +1,380 @@ +#![crate_name = "uu_dircolors"] + +// This file is part of the uutils coreutils package. +// +// (c) Jian Zeng +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. +// + +extern crate libc; +extern crate glob; +extern crate getopts; + +#[macro_use] +extern crate uucore; + +use getopts::Options; + +use std::fs::File; +use std::io::{BufRead, BufReader, Write}; +use std::borrow::Borrow; +use std::env; + +static NAME: &'static str = "dircolors"; +static VERSION: &'static str = env!("CARGO_PKG_VERSION"); + +mod colors; +use colors::INTERNAL_DB; + +#[derive(PartialEq, Debug)] +enum OutputFmt { + Shell, + CShell, + Unknown, +} + +macro_rules! disp_err { + ($($args:tt)+) => ({ + pipe_write!(&mut ::std::io::stderr(), "{}: ", NAME); + pipe_writeln!(&mut ::std::io::stderr(), $($args)+); + pipe_writeln!(&mut ::std::io::stderr(), "Try '{} --help' for more information.", NAME); + }) +} + +fn guess_syntax() -> OutputFmt { + match env::var("SHELL") { + Ok(s) => { + if s.is_empty() { + return OutputFmt::Unknown; + } + if let Some(last) = s.rsplit('/').next() { + if last == "csh" || last == "tcsh" { + OutputFmt::CShell + } else { + OutputFmt::Shell + } + } else { + OutputFmt::Shell + } + } + Err(_) => OutputFmt::Unknown, + } +} + +pub fn uumain(args: Vec) -> i32 { + let mut opts = Options::new(); + + opts.optflag("b", "sh", "output Bourne shell code to set LS_COLORS"); + opts.optflag("", + "bourne-shell", + "output Bourne shell code to set LS_COLORS"); + opts.optflag("c", "csh", "output C shell code to set LS_COLORS"); + opts.optflag("", "c-shell", "output C shell code to set LS_COLORS"); + opts.optflag("p", "print-database", "print the byte counts"); + + opts.optflag("h", "help", "display this help and exit"); + opts.optflag("", "version", "output version information and exit"); + + let matches = match opts.parse(&args[1..]) { + Ok(m) => m, + Err(f) => crash!(1, "Invalid options\n{}", f), + }; + + if matches.opt_present("help") { + println!("Usage: {} [OPTION]... [FILE] +Output commands to set the LS_COLORS environment variable. + +Determine format of output: + -b, --sh, --bourne-shell output Bourne shell code to set LS_COLORS + -c, --csh, --c-shell output C shell code to set LS_COLORS + -p, --print-database output defaults + --help display this help and exit + --version output version information and exit + +If FILE is specified, read it to determine which colors to use for which +file types and extensions. Otherwise, a precompiled database is used. +For details on the format of these files, run 'dircolors --print-database'.", + NAME); + return 0; + } + + if matches.opt_present("version") { + println!("{} {}", NAME, VERSION); + return 0; + } + + if (matches.opt_present("csh") || matches.opt_present("c-shell") || + matches.opt_present("sh") || matches.opt_present("bourne-shell")) && + matches.opt_present("print-database") { + disp_err!("the options to output dircolors' internal database and\nto select a shell \ + syntax are mutually exclusive"); + return 1; + } + + if matches.opt_present("print-database") { + if !matches.free.is_empty() { + disp_err!("extra operand ‘{}’\nfile operands cannot be combined with \ + --print-database (-p)", + matches.free[0]); + return 1; + } + println!("{}", INTERNAL_DB); + return 0; + } + + let mut out_format = OutputFmt::Unknown; + if matches.opt_present("csh") || matches.opt_present("c-shell") { + out_format = OutputFmt::CShell; + } else if matches.opt_present("sh") || matches.opt_present("bourne-shell") { + out_format = OutputFmt::Shell; + } + + if out_format == OutputFmt::Unknown { + match guess_syntax() { + OutputFmt::Unknown => { + show_info!("no SHELL environment variable, and no shell type option given"); + return 1; + } + fmt => out_format = fmt, + } + } + + let result; + if matches.free.is_empty() { + result = parse(INTERNAL_DB.lines(), out_format, "") + } else { + if matches.free.len() > 1 { + disp_err!("extra operand ‘{}’", matches.free[1]); + return 1; + } + match File::open(matches.free[0].as_str()) { + Ok(f) => { + let fin = BufReader::new(f); + result = parse(fin.lines().filter_map(|l| l.ok()), + out_format, + matches.free[0].as_str()) + } + Err(e) => { + show_info!("{}: {}", matches.free[0], e); + return 1; + } + } + } + match result { + Ok(s) => { + println!("{}", s); + 0 + } + Err(s) => { + show_info!("{}", s); + 1 + } + } +} + +trait StrUtils { + fn purify(&self) -> &Self; + fn split_two(&self) -> (&str, &str); + fn fnmatch(&self, pattern: &str) -> bool; +} + +impl StrUtils for str { + /// Remove comments and trim whitespaces + fn purify(&self) -> &Self { + let mut line = self; + for (n, c) in self.chars().enumerate() { + if c != '#' { + continue; + } + + // Ignore if '#' is at the beginning of line + if n == 0 { + line = &self[..0]; + break; + } + + // Ignore the content after '#' + // only if it is preceded by at least one whitespace + if self.chars().nth(n - 1).unwrap().is_whitespace() { + line = &self[..n]; + } + } + line.trim() + } + + /// Like split_whitespace() but only produce 2 components + fn split_two(&self) -> (&str, &str) { + if let Some(b) = self.find(char::is_whitespace) { + let key = &self[..b]; + if let Some(e) = self[b..].find(|c: char| !c.is_whitespace()) { + (key, &self[b + e..]) + } else { + (key, "") + } + } else { + ("", "") + } + } + + fn fnmatch(&self, pat: &str) -> bool { + pat.parse::().unwrap().matches(self) + } +} + +#[derive(PartialEq)] +enum ParseState { + Global, + Matched, + Continue, + Pass, +} +use std::collections::HashMap; +fn parse(lines: T, fmt: OutputFmt, fp: &str) -> Result + where T: IntoIterator, + T::Item: Borrow +{ + // 1440 > $(dircolors | wc -m) + let mut result = String::with_capacity(1440); + match fmt { + OutputFmt::Shell => result.push_str("LS_COLORS='"), + OutputFmt::CShell => result.push_str("setenv LS_COLORS '"), + _ => unreachable!(), + } + + let mut table: HashMap<&str, &str> = HashMap::with_capacity(48); + table.insert("normal", "no"); + table.insert("norm", "no"); + table.insert("file", "fi"); + table.insert("reset", "rs"); + table.insert("dir", "di"); + table.insert("lnk", "ln"); + table.insert("link", "ln"); + table.insert("symlink", "ln"); + table.insert("orphan", "or"); + table.insert("missing", "mi"); + table.insert("fifo", "pi"); + table.insert("pipe", "pi"); + table.insert("sock", "so"); + table.insert("blk", "bd"); + table.insert("block", "bd"); + table.insert("chr", "cd"); + table.insert("char", "cd"); + table.insert("door", "do"); + table.insert("exec", "ex"); + table.insert("left", "lc"); + table.insert("leftcode", "lc"); + table.insert("right", "rc"); + table.insert("rightcode", "rc"); + table.insert("end", "ec"); + table.insert("endcode", "ec"); + table.insert("suid", "su"); + table.insert("setuid", "su"); + table.insert("sgid", "sg"); + table.insert("setgid", "sg"); + table.insert("sticky", "st"); + table.insert("other_writable", "ow"); + table.insert("owr", "ow"); + table.insert("sticky_other_writable", "tw"); + table.insert("owt", "tw"); + table.insert("capability", "ca"); + table.insert("multihardlink", "mh"); + table.insert("clrtoeol", "cl"); + + let term = env::var("TERM").unwrap_or("none".to_owned()); + let term = term.as_str(); + + let mut state = ParseState::Global; + + for (num, line) in lines.into_iter().enumerate() { + let num = num + 1; + let line = line.borrow().purify(); + if line.is_empty() { + continue; + } + + let (key, val) = line.split_two(); + if val.is_empty() { + return Err(format!("{}:{}: invalid line; missing second token", fp, num)); + } + let lower = key.to_lowercase(); + + if lower == "term" { + if term.fnmatch(val) { + state = ParseState::Matched; + } else if state != ParseState::Matched { + state = ParseState::Pass; + } + } else { + if state == ParseState::Matched { + // prevent subsequent mismatched TERM from + // cancelling the input + state = ParseState::Continue; + } + if state != ParseState::Pass { + if key.starts_with(".") { + result.push_str(format!("*{}={}:", key, val).as_str()); + } else if key.starts_with("*") { + result.push_str(format!("{}={}:", key, val).as_str()); + } else if lower == "options" || lower == "color" || lower == "eightbit" { + // Slackware only. Ignore + } else { + if let Some(s) = table.get(lower.as_str()) { + result.push_str(format!("{}={}:", s, val).as_str()); + } else { + return Err(format!("{}:{}: unrecognized keyword {}", fp, num, key)); + } + } + } + } + } + + match fmt { + OutputFmt::Shell => result.push_str("';\nexport LS_COLORS"), + OutputFmt::CShell => result.push('\''), + _ => unreachable!(), + } + + Ok(result) +} + +#[test] +fn test_shell_syntax() { + use std::env; + let last = env!("SHELL"); + env::set_var("SHELL", "/path/csh"); + assert_eq!(OutputFmt::CShell, guess_syntax()); + env::set_var("SHELL", "csh"); + assert_eq!(OutputFmt::CShell, guess_syntax()); + env::set_var("SHELL", "/path/bash"); + assert_eq!(OutputFmt::Shell, guess_syntax()); + env::set_var("SHELL", "bash"); + assert_eq!(OutputFmt::Shell, guess_syntax()); + env::set_var("SHELL", "bash"); + assert_eq!(OutputFmt::Shell, guess_syntax()); + env::set_var("SHELL", "/asd/bar"); + assert_eq!(OutputFmt::Shell, guess_syntax()); + env::set_var("SHELL", "foo"); + assert_eq!(OutputFmt::Shell, guess_syntax()); + env::set_var("SHELL", ""); + assert_eq!(OutputFmt::Unknown, guess_syntax()); + env::remove_var("SHELL"); + assert_eq!(OutputFmt::Unknown, guess_syntax()); + + env::set_var("SHELL", last); +} + +#[test] +fn test_strutils() { + let s = " asd#zcv #hk\t\n "; + assert_eq!("asd#zcv", s.purify()); + + let s = "con256asd"; + assert!(s.fnmatch("*[2][3-6][5-9]?sd")); + + let s = "zxc \t\nqwe jlk hjl"; + let (k, v) = s.split_two(); + assert_eq!("zxc", k); + assert_eq!("qwe jlk hjl", v); +} diff --git a/src/dircolors/main.rs b/src/dircolors/main.rs new file mode 100644 index 000000000..ff64af3c5 --- /dev/null +++ b/src/dircolors/main.rs @@ -0,0 +1,5 @@ +extern crate uu_dircolors; + +fn main() { + std::process::exit(uu_dircolors::uumain(std::env::args().collect())); +} diff --git a/tests/dircolors.rs b/tests/dircolors.rs new file mode 100644 index 000000000..7a33ab95e --- /dev/null +++ b/tests/dircolors.rs @@ -0,0 +1,71 @@ +#[macro_use] +mod common; + +use common::util::*; + +static UTIL_NAME: &'static str = "dircolors"; + +#[test] +fn test1() { + test_helper("test1", "gnome"); +} + +#[test] +fn test_keywords() { + test_helper("keywords", ""); +} + +#[test] +fn test_internal_db() { + let (at, mut ucmd) = testing(UTIL_NAME); + ucmd.arg("-p"); + let out = ucmd.run().stdout; + let filename = "internal.expected"; + assert_eq!(out, at.read(filename)); +} + +#[test] +fn test_bash_default() { + let (at, mut ucmd) = testing(UTIL_NAME); + ucmd.arg("-b"); + let out = ucmd.env("TERM", "screen").run().stdout; + let filename = "bash_def.expected"; + assert_eq!(out, at.read(filename)); +} + +#[test] +fn test_csh_default() { + let (at, mut ucmd) = testing(UTIL_NAME); + ucmd.arg("-c"); + let out = ucmd.env("TERM", "screen").run().stdout; + let filename = "csh_def.expected"; + assert_eq!(out, at.read(filename)); +} + +#[test] +fn test_no_env() { + // no SHELL and TERM + let (_, mut ucmd) = testing(UTIL_NAME); + ucmd.fails(); +} + +#[test] +fn test_exclusive_option() { + let (_, mut ucmd) = testing(UTIL_NAME); + ucmd.arg("-cp"); + ucmd.fails(); +} + +fn test_helper(file_name: &str, term: &str) { + let (at, mut ucmd) = testing(UTIL_NAME); + ucmd.arg("-c").env("TERM", term); + let out = ucmd.arg(format!("{}.txt", file_name)).run().stdout; + let filename = format!("{}.csh.expected", file_name); + assert_eq!(out, at.read(&filename)); + + let (at, mut ucmd) = testing(UTIL_NAME); + ucmd.arg("-b").env("TERM", term); + let out = ucmd.arg(format!("{}.txt", file_name)).run().stdout; + let filename = format!("{}.sh.expected", file_name); + assert_eq!(out, at.read(&filename)); +} diff --git a/tests/fixtures/dircolors/bash_def.expected b/tests/fixtures/dircolors/bash_def.expected new file mode 100644 index 000000000..d0bd0d33b --- /dev/null +++ b/tests/fixtures/dircolors/bash_def.expected @@ -0,0 +1,2 @@ +LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'; +export LS_COLORS diff --git a/tests/fixtures/dircolors/csh_def.expected b/tests/fixtures/dircolors/csh_def.expected new file mode 100644 index 000000000..2d1e1d374 --- /dev/null +++ b/tests/fixtures/dircolors/csh_def.expected @@ -0,0 +1 @@ +setenv LS_COLORS 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:' diff --git a/tests/fixtures/dircolors/internal.expected b/tests/fixtures/dircolors/internal.expected new file mode 100644 index 000000000..8566587f4 --- /dev/null +++ b/tests/fixtures/dircolors/internal.expected @@ -0,0 +1,191 @@ +# Configuration file for dircolors, a utility to help you set the +# LS_COLORS environment variable used by GNU ls with the --color option. +# Copyright (C) 1996-2016 Free Software Foundation, Inc. +# Copying and distribution of this file, with or without modification, +# are permitted provided the copyright notice and this notice are preserved. +# The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the +# slackware version of dircolors) are recognized but ignored. +# Below are TERM entries, which can be a glob patterns, to match +# against the TERM environment variable to determine if it is colorizable. +TERM Eterm +TERM ansi +TERM color-xterm +TERM con[0-9]*x[0-9]* +TERM cons25 +TERM console +TERM cygwin +TERM dtterm +TERM eterm-color +TERM gnome +TERM gnome-256color +TERM hurd +TERM jfbterm +TERM konsole +TERM kterm +TERM linux +TERM linux-c +TERM mach-color +TERM mach-gnu-color +TERM mlterm +TERM putty +TERM putty-256color +TERM rxvt* +TERM screen* +TERM st +TERM st-256color +TERM terminator +TERM tmux* +TERM vt100 +TERM xterm* +# Below are the color init strings for the basic file types. A color init +# string consists of one or more of the following numeric codes: +# Attribute codes: +# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed +# Text color codes: +# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white +# Background color codes: +# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white +#NORMAL 00 # no color code at all +#FILE 00 # regular file: use no color at all +RESET 0 # reset to "normal" color +DIR 01;34 # directory +LINK 01;36 # symbolic link. (If you set this to 'target' instead of a + # numerical value, the color is as for the file pointed to.) +MULTIHARDLINK 00 # regular file with more than one link +FIFO 40;33 # pipe +SOCK 01;35 # socket +DOOR 01;35 # door +BLK 40;33;01 # block device driver +CHR 40;33;01 # character device driver +ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... +MISSING 00 # ... and the files they point to +SETUID 37;41 # file that is setuid (u+s) +SETGID 30;43 # file that is setgid (g+s) +CAPABILITY 30;41 # file with capability +STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w) +OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky +STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable +# This is for files with execute permission: +EXEC 01;32 +# List any file extensions like '.gz' or '.tar' that you would like ls +# to colorize below. Put the extension, a space, and the color init string. +# (and any comments you want to add after a '#') +# If you use DOS-style suffixes, you may want to uncomment the following: +#.cmd 01;32 # executables (bright green) +#.exe 01;32 +#.com 01;32 +#.btm 01;32 +#.bat 01;32 +# Or if you want to colorize scripts even if they do not have the +# executable bit actually set. +#.sh 01;32 +#.csh 01;32 + # archives or compressed (bright red) +.tar 01;31 +.tgz 01;31 +.arc 01;31 +.arj 01;31 +.taz 01;31 +.lha 01;31 +.lz4 01;31 +.lzh 01;31 +.lzma 01;31 +.tlz 01;31 +.txz 01;31 +.tzo 01;31 +.t7z 01;31 +.zip 01;31 +.z 01;31 +.Z 01;31 +.dz 01;31 +.gz 01;31 +.lrz 01;31 +.lz 01;31 +.lzo 01;31 +.xz 01;31 +.bz2 01;31 +.bz 01;31 +.tbz 01;31 +.tbz2 01;31 +.tz 01;31 +.deb 01;31 +.rpm 01;31 +.jar 01;31 +.war 01;31 +.ear 01;31 +.sar 01;31 +.rar 01;31 +.alz 01;31 +.ace 01;31 +.zoo 01;31 +.cpio 01;31 +.7z 01;31 +.rz 01;31 +.cab 01;31 +# image formats +.jpg 01;35 +.jpeg 01;35 +.gif 01;35 +.bmp 01;35 +.pbm 01;35 +.pgm 01;35 +.ppm 01;35 +.tga 01;35 +.xbm 01;35 +.xpm 01;35 +.tif 01;35 +.tiff 01;35 +.png 01;35 +.svg 01;35 +.svgz 01;35 +.mng 01;35 +.pcx 01;35 +.mov 01;35 +.mpg 01;35 +.mpeg 01;35 +.m2v 01;35 +.mkv 01;35 +.webm 01;35 +.ogm 01;35 +.mp4 01;35 +.m4v 01;35 +.mp4v 01;35 +.vob 01;35 +.qt 01;35 +.nuv 01;35 +.wmv 01;35 +.asf 01;35 +.rm 01;35 +.rmvb 01;35 +.flc 01;35 +.avi 01;35 +.fli 01;35 +.flv 01;35 +.gl 01;35 +.dl 01;35 +.xcf 01;35 +.xwd 01;35 +.yuv 01;35 +.cgm 01;35 +.emf 01;35 +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.ogv 01;35 +.ogx 01;35 +# audio formats +.aac 00;36 +.au 00;36 +.flac 00;36 +.m4a 00;36 +.mid 00;36 +.midi 00;36 +.mka 00;36 +.mp3 00;36 +.mpc 00;36 +.ogg 00;36 +.ra 00;36 +.wav 00;36 +# http://wiki.xiph.org/index.php/MIME_Types_and_File_Extensions +.oga 00;36 +.opus 00;36 +.spx 00;36 +.xspf 00;36 diff --git a/tests/fixtures/dircolors/keywords.csh.expected b/tests/fixtures/dircolors/keywords.csh.expected new file mode 100644 index 000000000..f7f1f4ead --- /dev/null +++ b/tests/fixtures/dircolors/keywords.csh.expected @@ -0,0 +1 @@ +setenv LS_COLORS 'no=00:fi=00:rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:lc=\e[:rc=m:ec=\xff:' diff --git a/tests/fixtures/dircolors/keywords.sh.expected b/tests/fixtures/dircolors/keywords.sh.expected new file mode 100644 index 000000000..fdbf6871e --- /dev/null +++ b/tests/fixtures/dircolors/keywords.sh.expected @@ -0,0 +1,2 @@ +LS_COLORS='no=00:fi=00:rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:lc=\e[:rc=m:ec=\xff:'; +export LS_COLORS diff --git a/tests/fixtures/dircolors/keywords.txt b/tests/fixtures/dircolors/keywords.txt new file mode 100644 index 000000000..ac131d7ba --- /dev/null +++ b/tests/fixtures/dircolors/keywords.txt @@ -0,0 +1,23 @@ +NORMAL 00 # no color code at all +FILE 00 # regular file: use no color at all +RESET 0 # reset to "normal" color +Dir 01;34 # directory +LINK 01;36 # symbolic link. (If you set this to 'target' instead of a +multihardlink 00 # regular file with more than one link +fifo 40;33 # pipe +SOCK 01;35 # socket +DOOR 01;35 # door +BLK 40;33;01 # block device driver +CHR 40;33;01 # character device driver +orphan 40;31;01 # symlink to nonexistent file, or non-stat'able file ... +MISSING 00 # ... and the files they point to +setuid 37;41 # file that is setuid (u+s) +SETGID 30;43 # file that is setgid (g+s) +CAPABILITY 30;41 # file with capability +STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w) +Other_writable 34;42 # dir that is other-writable (o+w) and not sticky +STICKY 37;44 # dir with the sticky bit set (+t) and not other-writable +EXEC 01;32 +LEFTCODE \e[ +RIGHTCODE m +ENDCODE \xff diff --git a/tests/fixtures/dircolors/test1.csh.expected b/tests/fixtures/dircolors/test1.csh.expected new file mode 100644 index 000000000..5d7186935 --- /dev/null +++ b/tests/fixtures/dircolors/test1.csh.expected @@ -0,0 +1 @@ +setenv LS_COLORS '*.xspf=00;36:no=00:fi=00:su=37;41:sg=30;43:ca=30;41:' diff --git a/tests/fixtures/dircolors/test1.sh.expected b/tests/fixtures/dircolors/test1.sh.expected new file mode 100644 index 000000000..c34901ea4 --- /dev/null +++ b/tests/fixtures/dircolors/test1.sh.expected @@ -0,0 +1,2 @@ +LS_COLORS='*.xspf=00;36:no=00:fi=00:su=37;41:sg=30;43:ca=30;41:'; +export LS_COLORS diff --git a/tests/fixtures/dircolors/test1.txt b/tests/fixtures/dircolors/test1.txt new file mode 100644 index 000000000..855a642ba --- /dev/null +++ b/tests/fixtures/dircolors/test1.txt @@ -0,0 +1,24 @@ +.xspf 00;36 +NORMAL 00 # no color code at all +FILE 00 # regular file: use no color at all +# Below are the color init strings for the basic file types. A color init +# string consists of one or more of the following numeric codes: +# Attribute codes: +# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed +# Text color codes: +# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white +# Background color codes: +# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white +TERM screen* +.rar 12;34 +.tar 01;31 +.tgz 01;31 +.arc 01;31 +ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file ... +MISSING 00 # ... and the files they point to +.arj 01;31 +.taz 01;31 +TERM gnome +SETUID 37;41 # file that is setuid (u+s) +SETGID 30;43 # file that is setgid (g+s) +CAPABILITY 30;41 # file with capability