mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 13:37:48 +00:00
Merge pull request #2099 from tertsdiepraam/ls/cross_platform_colors
ls: cross-platform colors
This commit is contained in:
commit
46b95fb8bd
4 changed files with 124 additions and 208 deletions
44
Cargo.lock
generated
44
Cargo.lock
generated
|
@ -28,6 +28,15 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.4.12"
|
||||
|
@ -127,9 +136,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.2.3"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0"
|
||||
checksum = "cc38c385bfd7e444464011bb24820f40dd1c76bcdfa1b78611cb7c2e5cafab75"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
|
@ -169,7 +178,7 @@ version = "2.33.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"ansi_term 0.11.0",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
|
@ -452,9 +461,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
|
||||
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
|
@ -580,7 +589,7 @@ checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
|
|||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall 0.2.5",
|
||||
"redox_syscall 0.2.6",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
|
@ -783,6 +792,15 @@ dependencies = [
|
|||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lscolors"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d24b894c45c9da468621cdd615a5a79ee5e5523dd4f75c76ebc03d458940c16e"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "match_cfg"
|
||||
version = "0.1.0"
|
||||
|
@ -1176,9 +1194,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||
checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
@ -1189,7 +1207,7 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f"
|
||||
dependencies = [
|
||||
"redox_syscall 0.2.5",
|
||||
"redox_syscall 0.2.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1394,9 +1412,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.69"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
|
||||
checksum = "b9505f307c872bab8eb46f77ae357c8eba1fdacead58ee5a850116b1d7f82883"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.9",
|
||||
|
@ -1454,7 +1472,7 @@ checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"numtoa",
|
||||
"redox_syscall 0.2.5",
|
||||
"redox_syscall 0.2.6",
|
||||
"redox_termios",
|
||||
]
|
||||
|
||||
|
@ -1990,11 +2008,11 @@ dependencies = [
|
|||
"clap",
|
||||
"globset",
|
||||
"lazy_static",
|
||||
"lscolors",
|
||||
"number_prefix",
|
||||
"term_grid",
|
||||
"termsize",
|
||||
"time",
|
||||
"unicode-width",
|
||||
"uucore",
|
||||
"uucore_procs",
|
||||
]
|
||||
|
|
|
@ -16,18 +16,18 @@ path = "src/ls.rs"
|
|||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
lazy_static = "1.0.1"
|
||||
number_prefix = "0.4"
|
||||
term_grid = "0.1.5"
|
||||
termsize = "0.1.6"
|
||||
time = "0.1.40"
|
||||
unicode-width = "0.1.5"
|
||||
globset = "0.4.6"
|
||||
lscolors = { version="0.7.1", features=["ansi_term"] }
|
||||
uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["entries", "fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
atty = "0.2"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
atty = "0.2"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[[bin]]
|
||||
name = "ls"
|
||||
|
|
|
@ -7,27 +7,25 @@
|
|||
|
||||
// spell-checker:ignore (ToDO) cpio svgz webm somegroup nlink rmvb xspf
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
#[cfg(unix)]
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
mod quoting_style;
|
||||
mod version_cmp;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use globset::{self, Glob, GlobSet, GlobSetBuilder};
|
||||
use lscolors::LsColors;
|
||||
use number_prefix::NumberPrefix;
|
||||
use quoting_style::{escape_name, QuotingStyle};
|
||||
#[cfg(unix)]
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::fs::{DirEntry, FileType, Metadata};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
use std::fs::{self, DirEntry, FileType, Metadata};
|
||||
#[cfg(any(unix, target_os = "redox"))]
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::os::unix::fs::{FileTypeExt, MetadataExt};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::fs::MetadataExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -39,9 +37,7 @@ use std::{cmp::Reverse, process::exit};
|
|||
use term_grid::{Cell, Direction, Filling, Grid, GridOptions};
|
||||
use time::{strftime, Timespec};
|
||||
#[cfg(unix)]
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
#[cfg(unix)]
|
||||
use uucore::libc::{mode_t, S_ISGID, S_ISUID, S_ISVTX, S_IWOTH, S_IXGRP, S_IXOTH, S_IXUSR};
|
||||
use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR};
|
||||
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
static ABOUT: &str = "
|
||||
|
@ -54,30 +50,6 @@ fn get_usage() -> String {
|
|||
format!("{0} [OPTION]... [FILE]...", executable!())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
static DEFAULT_COLORS: &str = "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:";
|
||||
|
||||
#[cfg(unix)]
|
||||
lazy_static! {
|
||||
static ref LS_COLORS: String =
|
||||
std::env::var("LS_COLORS").unwrap_or_else(|_| DEFAULT_COLORS.to_string());
|
||||
static ref COLOR_MAP: HashMap<&'static str, &'static str> = {
|
||||
let codes = LS_COLORS.split(':');
|
||||
let mut map = HashMap::new();
|
||||
for c in codes {
|
||||
let p: Vec<_> = c.splitn(2, '=').collect();
|
||||
if p.len() == 2 {
|
||||
map.insert(p[0], p[1]);
|
||||
}
|
||||
}
|
||||
map
|
||||
};
|
||||
static ref RESET_CODE: &'static str = COLOR_MAP.get("rs").unwrap_or(&"0");
|
||||
static ref LEFT_CODE: &'static str = COLOR_MAP.get("lc").unwrap_or(&"\x1b[");
|
||||
static ref RIGHT_CODE: &'static str = COLOR_MAP.get("rc").unwrap_or(&"m");
|
||||
static ref END_CODE: &'static str = COLOR_MAP.get("ec").unwrap_or(&"");
|
||||
}
|
||||
|
||||
pub mod options {
|
||||
pub mod format {
|
||||
pub static ONELINE: &str = "1";
|
||||
|
@ -212,8 +184,7 @@ struct Config {
|
|||
time: Time,
|
||||
#[cfg(unix)]
|
||||
inode: bool,
|
||||
#[cfg(unix)]
|
||||
color: bool,
|
||||
color: Option<LsColors>,
|
||||
long: LongFormat,
|
||||
width: Option<u16>,
|
||||
quoting_style: QuotingStyle,
|
||||
|
@ -337,8 +308,7 @@ impl Config {
|
|||
Time::Modification
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
let color = match options.value_of(options::COLOR) {
|
||||
let needs_color = match options.value_of(options::COLOR) {
|
||||
None => options.is_present(options::COLOR),
|
||||
Some(val) => match val {
|
||||
"" | "always" | "yes" | "force" => true,
|
||||
|
@ -347,6 +317,12 @@ impl Config {
|
|||
},
|
||||
};
|
||||
|
||||
let color = if needs_color {
|
||||
Some(LsColors::from_env().unwrap_or_default())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let size_format = if options.is_present(options::size::HUMAN_READABLE) {
|
||||
SizeFormat::Binary
|
||||
} else if options.is_present(options::size::SI) {
|
||||
|
@ -520,7 +496,6 @@ impl Config {
|
|||
size_format,
|
||||
directory: options.is_present(options::DIRECTORY),
|
||||
time,
|
||||
#[cfg(unix)]
|
||||
color,
|
||||
#[cfg(unix)]
|
||||
inode: options.is_present(options::INODE),
|
||||
|
@ -1536,140 +1511,63 @@ fn get_file_name(name: &Path, strip: Option<&Path>) -> String {
|
|||
name.to_string_lossy().into_owned()
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn display_file_name(
|
||||
path: &Path,
|
||||
strip: Option<&Path>,
|
||||
metadata: &Metadata,
|
||||
config: &Config,
|
||||
) -> Cell {
|
||||
let mut name = escape_name(get_file_name(path, strip), &config.quoting_style);
|
||||
let file_type = metadata.file_type();
|
||||
|
||||
match config.indicator_style {
|
||||
IndicatorStyle::Classify | IndicatorStyle::FileType => {
|
||||
if file_type.is_dir() {
|
||||
name.push('/');
|
||||
}
|
||||
if file_type.is_symlink() {
|
||||
name.push('@');
|
||||
}
|
||||
}
|
||||
IndicatorStyle::Slash => {
|
||||
if file_type.is_dir() {
|
||||
name.push('/');
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
if config.format == Format::Long && metadata.file_type().is_symlink() {
|
||||
if let Ok(target) = path.read_link() {
|
||||
// We don't bother updating width here because it's not used for long listings
|
||||
let target_name = target.to_string_lossy().to_string();
|
||||
name.push_str(" -> ");
|
||||
name.push_str(&target_name);
|
||||
}
|
||||
}
|
||||
|
||||
name.into()
|
||||
#[cfg(unix)]
|
||||
fn file_is_executable(md: &Metadata) -> bool {
|
||||
// Mode always returns u32, but the flags might not be, based on the platform
|
||||
// e.g. linux has u32, mac has u16.
|
||||
// S_IXUSR -> user has execute permission
|
||||
// S_IXGRP -> group has execute persmission
|
||||
// S_IXOTH -> other users have execute permission
|
||||
md.mode() & ((S_IXUSR | S_IXGRP | S_IXOTH) as u32) != 0
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn color_name(name: String, typ: &str) -> String {
|
||||
let mut typ = typ;
|
||||
if !COLOR_MAP.contains_key(typ) {
|
||||
if typ == "or" {
|
||||
typ = "ln";
|
||||
} else if typ == "mi" {
|
||||
typ = "fi";
|
||||
}
|
||||
};
|
||||
if let Some(code) = COLOR_MAP.get(typ) {
|
||||
format!(
|
||||
"{}{}{}{}{}{}{}{}",
|
||||
*LEFT_CODE, code, *RIGHT_CODE, name, *END_CODE, *LEFT_CODE, *RESET_CODE, *RIGHT_CODE,
|
||||
)
|
||||
#[allow(clippy::clippy::collapsible_else_if)]
|
||||
fn classify_file(md: &Metadata) -> Option<char> {
|
||||
let file_type = md.file_type();
|
||||
|
||||
if file_type.is_dir() {
|
||||
Some('/')
|
||||
} else if file_type.is_symlink() {
|
||||
Some('@')
|
||||
} else {
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
macro_rules! has {
|
||||
($mode:expr, $perm:expr) => {
|
||||
$mode & ($perm as mode_t) != 0
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn display_file_name(
|
||||
path: &Path,
|
||||
strip: Option<&Path>,
|
||||
metadata: &Metadata,
|
||||
config: &Config,
|
||||
) -> Cell {
|
||||
let mut name = escape_name(get_file_name(path, strip), &config.quoting_style);
|
||||
if config.format != Format::Long && config.inode {
|
||||
name = get_inode(metadata) + " " + &name;
|
||||
}
|
||||
let mut width = UnicodeWidthStr::width(&*name);
|
||||
|
||||
let ext;
|
||||
if config.color || config.indicator_style != IndicatorStyle::None {
|
||||
let file_type = metadata.file_type();
|
||||
|
||||
let (code, sym) = if file_type.is_dir() {
|
||||
("di", Some('/'))
|
||||
} else if file_type.is_symlink() {
|
||||
if path.exists() {
|
||||
("ln", Some('@'))
|
||||
} else {
|
||||
("or", Some('@'))
|
||||
}
|
||||
} else if file_type.is_socket() {
|
||||
("so", Some('='))
|
||||
} else if file_type.is_fifo() {
|
||||
("pi", Some('|'))
|
||||
} else if file_type.is_block_device() {
|
||||
("bd", None)
|
||||
} else if file_type.is_char_device() {
|
||||
("cd", None)
|
||||
} else if file_type.is_file() {
|
||||
let mode = metadata.mode() as mode_t;
|
||||
let sym = if has!(mode, S_IXUSR | S_IXGRP | S_IXOTH) {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
if file_type.is_socket() {
|
||||
Some('=')
|
||||
} else if file_type.is_fifo() {
|
||||
Some('|')
|
||||
} else if file_type.is_file() && file_is_executable(&md) {
|
||||
Some('*')
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if has!(mode, S_ISUID) {
|
||||
("su", sym)
|
||||
} else if has!(mode, S_ISGID) {
|
||||
("sg", sym)
|
||||
} else if has!(mode, S_ISVTX) && has!(mode, S_IWOTH) {
|
||||
("tw", sym)
|
||||
} else if has!(mode, S_ISVTX) {
|
||||
("st", sym)
|
||||
} else if has!(mode, S_IWOTH) {
|
||||
("ow", sym)
|
||||
} else if has!(mode, S_IXUSR | S_IXGRP | S_IXOTH) {
|
||||
("ex", sym)
|
||||
} else if metadata.nlink() > 1 {
|
||||
("mh", sym)
|
||||
} else if let Some(e) = path.extension() {
|
||||
ext = format!("*.{}", e.to_string_lossy());
|
||||
(ext.as_str(), None)
|
||||
} else {
|
||||
("fi", None)
|
||||
}
|
||||
} else {
|
||||
("", None)
|
||||
};
|
||||
|
||||
if config.color {
|
||||
name = color_name(name, code);
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn display_file_name(
|
||||
path: &Path,
|
||||
strip: Option<&Path>,
|
||||
metadata: &Metadata,
|
||||
config: &Config,
|
||||
) -> Cell {
|
||||
let mut name = escape_name(get_file_name(path, strip), &config.quoting_style);
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
if config.format != Format::Long && config.inode {
|
||||
name = get_inode(metadata) + " " + &name;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ls_colors) = &config.color {
|
||||
name = color_name(&ls_colors, path, name, metadata);
|
||||
}
|
||||
|
||||
if config.indicator_style != IndicatorStyle::None {
|
||||
let sym = classify_file(metadata);
|
||||
|
||||
let char_opt = match config.indicator_style {
|
||||
IndicatorStyle::Classify => sym,
|
||||
|
@ -1692,23 +1590,24 @@ fn display_file_name(
|
|||
|
||||
if let Some(c) = char_opt {
|
||||
name.push(c);
|
||||
width += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if config.format == Format::Long && metadata.file_type().is_symlink() {
|
||||
if let Ok(target) = path.read_link() {
|
||||
// We don't bother updating width here because it's not used for long listings
|
||||
let code = if target.exists() { "fi" } else { "mi" };
|
||||
let target_name = color_name(target.to_string_lossy().to_string(), code);
|
||||
// We don't bother updating width here because it's not used for long
|
||||
name.push_str(" -> ");
|
||||
name.push_str(&target_name);
|
||||
name.push_str(&target.to_string_lossy());
|
||||
}
|
||||
}
|
||||
|
||||
Cell {
|
||||
contents: name,
|
||||
width,
|
||||
name.into()
|
||||
}
|
||||
|
||||
fn color_name(ls_colors: &LsColors, path: &Path, name: String, md: &Metadata) -> String {
|
||||
match ls_colors.style_for_path_with_metadata(path, Some(&md)) {
|
||||
Some(style) => style.to_ansi_term_style().paint(name).to_string(),
|
||||
None => name,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -629,20 +629,27 @@ fn test_ls_recursive() {
|
|||
result.stdout_contains(&"a\\b:\nb");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn test_ls_ls_color() {
|
||||
fn test_ls_color() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.mkdir("a");
|
||||
at.mkdir("a/nested_dir");
|
||||
let nested_dir = Path::new("a")
|
||||
.join("nested_dir")
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
at.mkdir(&nested_dir);
|
||||
at.mkdir("z");
|
||||
at.touch(&at.plus_as_string("a/nested_file"));
|
||||
let nested_file = Path::new("a")
|
||||
.join("nested_file")
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
at.touch(&nested_file);
|
||||
at.touch("test-color");
|
||||
|
||||
let a_with_colors = "\x1b[01;34ma\x1b[0m";
|
||||
let z_with_colors = "\x1b[01;34mz\x1b[0m";
|
||||
let nested_dir_with_colors = "\x1b[01;34mnested_dir\x1b[0m";
|
||||
let a_with_colors = "\x1b[1;34ma\x1b[0m";
|
||||
let z_with_colors = "\x1b[1;34mz\x1b[0m";
|
||||
let nested_dir_with_colors = "\x1b[1;34mnested_dir\x1b[0m";
|
||||
|
||||
// Color is disabled by default
|
||||
let result = scene.ucmd().succeeds();
|
||||
|
@ -678,14 +685,6 @@ fn test_ls_ls_color() {
|
|||
.succeeds()
|
||||
.stdout_contains(nested_dir_with_colors);
|
||||
|
||||
// Color has no effect
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--color=always")
|
||||
.arg("a/nested_file")
|
||||
.succeeds()
|
||||
.stdout_contains("a/nested_file\n");
|
||||
|
||||
// No output
|
||||
scene
|
||||
.ucmd()
|
||||
|
@ -825,7 +824,7 @@ fn test_ls_indicator_style() {
|
|||
let options = vec!["classify", "file-type", "slash"];
|
||||
for opt in options {
|
||||
// Verify that classify and file-type both contain indicators for symlinks.
|
||||
let result = scene
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(format!("--indicator-style={}", opt))
|
||||
.succeeds()
|
||||
|
@ -835,7 +834,7 @@ fn test_ls_indicator_style() {
|
|||
// Same test as above, but with the alternate flags.
|
||||
let options = vec!["--classify", "--file-type", "-p"];
|
||||
for opt in options {
|
||||
let result = scene
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(format!("{}", opt))
|
||||
.succeeds()
|
||||
|
@ -846,7 +845,7 @@ fn test_ls_indicator_style() {
|
|||
let options = vec!["classify", "file-type"];
|
||||
for opt in options {
|
||||
// Verify that classify and file-type both contain indicators for symlinks.
|
||||
let result = scene
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(format!("--indicator-style={}", opt))
|
||||
.succeeds()
|
||||
|
@ -970,7 +969,7 @@ fn test_ls_hidden_windows() {
|
|||
|
||||
let result = scene.ucmd().succeeds();
|
||||
assert!(!result.stdout_str().contains(file));
|
||||
let result = scene.ucmd().arg("-a").succeeds().stdout_contains(file);
|
||||
scene.ucmd().arg("-a").succeeds().stdout_contains(file);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue