mirror of
https://github.com/uutils/coreutils
synced 2024-12-14 15:22:38 +00:00
dircolors should use the datastructures when printing
This commit is contained in:
parent
0e8c171c80
commit
5d19f79cd0
2 changed files with 134 additions and 74 deletions
|
@ -12,7 +12,7 @@ use std::io::{BufRead, BufReader};
|
|||
use std::path::Path;
|
||||
|
||||
use clap::{crate_version, Arg, ArgAction, Command};
|
||||
use uucore::colors::FILE_ATTRIBUTE_CODES;
|
||||
use uucore::colors::{FILE_ATTRIBUTE_CODES, FILE_COLORS, FILE_TYPES};
|
||||
use uucore::display::Quotable;
|
||||
use uucore::error::{UResult, USimpleError, UUsageError};
|
||||
use uucore::{help_about, help_section, help_usage};
|
||||
|
@ -58,6 +58,89 @@ pub fn guess_syntax() -> OutputFmt {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_colors_format_strings(fmt: &OutputFmt) -> (String, String) {
|
||||
let prefix = match fmt {
|
||||
OutputFmt::Shell => "LS_COLORS='".to_string(),
|
||||
OutputFmt::CShell => "setenv LS_COLORS '".to_string(),
|
||||
OutputFmt::Display => String::new(),
|
||||
OutputFmt::Unknown => unreachable!(),
|
||||
};
|
||||
|
||||
let suffix = match fmt {
|
||||
OutputFmt::Shell => "';\nexport LS_COLORS".to_string(),
|
||||
OutputFmt::CShell => "'".to_string(),
|
||||
OutputFmt::Display => String::new(),
|
||||
OutputFmt::Unknown => unreachable!(),
|
||||
};
|
||||
|
||||
(prefix, suffix)
|
||||
}
|
||||
|
||||
pub fn generate_type_output(fmt: &OutputFmt) -> String {
|
||||
match fmt {
|
||||
OutputFmt::Display => FILE_TYPES
|
||||
.iter()
|
||||
.map(|&(_, key, val)| format!("\x1b[{}m{}\t{}\x1b[0m", val, key, val))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n"),
|
||||
_ => {
|
||||
// Existing logic for other formats
|
||||
FILE_TYPES
|
||||
.iter()
|
||||
.map(|&(_, v1, v2)| format!("{}={}", v1, v2))
|
||||
.collect::<Vec<String>>()
|
||||
.join(":")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ExtensionFormat {
|
||||
StarDot, // Format as ".*ext"
|
||||
Dot, // Format as ".ext"
|
||||
NoDot, // Format as "ext"
|
||||
}
|
||||
|
||||
fn generate_ls_colors(fmt: &OutputFmt, format: ExtensionFormat, sep: &str) -> String {
|
||||
match fmt {
|
||||
OutputFmt::Display => {
|
||||
let mut display_parts = vec![];
|
||||
let type_output = generate_type_output(fmt);
|
||||
display_parts.push(type_output);
|
||||
for &(extension, code) in FILE_COLORS.iter() {
|
||||
display_parts.push(format!("\x1b[{}m*{}\t{}\x1b[0m", code, extension, code));
|
||||
}
|
||||
display_parts.join("\n")
|
||||
}
|
||||
_ => {
|
||||
// existing logic for other formats
|
||||
let mut parts = vec![];
|
||||
for &(extension, code) in FILE_COLORS.iter() {
|
||||
let formatted_extension = match format {
|
||||
ExtensionFormat::StarDot => format!("*{}", extension),
|
||||
ExtensionFormat::Dot => extension.to_string(),
|
||||
ExtensionFormat::NoDot => {
|
||||
if extension.starts_with('.') {
|
||||
extension[1..].to_string()
|
||||
} else {
|
||||
extension.to_string()
|
||||
}
|
||||
}
|
||||
};
|
||||
parts.push(format!("{}={}", formatted_extension, code));
|
||||
}
|
||||
let (prefix, suffix) = get_colors_format_strings(&fmt);
|
||||
let ls_colors = parts.join(sep);
|
||||
format!(
|
||||
"{}{}:{}:{}",
|
||||
prefix,
|
||||
generate_type_output(&fmt),
|
||||
ls_colors,
|
||||
suffix
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args.collect_ignore();
|
||||
|
@ -126,7 +209,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
|
||||
let result;
|
||||
if files.is_empty() {
|
||||
result = parse(INTERNAL_DB.lines(), &out_format, "");
|
||||
println!(
|
||||
"{}",
|
||||
generate_ls_colors(&out_format, ExtensionFormat::StarDot, ":")
|
||||
);
|
||||
|
||||
return Ok(());
|
||||
} else if files.len() > 1 {
|
||||
return Err(UUsageError::new(
|
||||
1,
|
||||
|
@ -287,12 +375,9 @@ where
|
|||
{
|
||||
// 1790 > $(dircolors | wc -m)
|
||||
let mut result = String::with_capacity(1790);
|
||||
match fmt {
|
||||
OutputFmt::Shell => result.push_str("LS_COLORS='"),
|
||||
OutputFmt::CShell => result.push_str("setenv LS_COLORS '"),
|
||||
OutputFmt::Display => (),
|
||||
OutputFmt::Unknown => unreachable!(),
|
||||
}
|
||||
let (prefix, suffix) = get_colors_format_strings(&fmt);
|
||||
|
||||
result.push_str(&prefix);
|
||||
|
||||
let term = env::var("TERM").unwrap_or_else(|_| "none".to_owned());
|
||||
let term = term.as_str();
|
||||
|
@ -331,6 +416,7 @@ where
|
|||
state = ParseState::Continue;
|
||||
}
|
||||
if state != ParseState::Pass {
|
||||
let search_key = lower.as_str();
|
||||
if key.starts_with('.') {
|
||||
if *fmt == OutputFmt::Display {
|
||||
result.push_str(format!("\x1b[{val}m*{key}\t{val}\x1b[0m\n").as_str());
|
||||
|
@ -345,7 +431,10 @@ where
|
|||
}
|
||||
} else if lower == "options" || lower == "color" || lower == "eightbit" {
|
||||
// Slackware only. Ignore
|
||||
} else if let Some(s) = FILE_ATTRIBUTE_CODES.get(lower.as_str()) {
|
||||
} else if let Some((_, s)) = FILE_ATTRIBUTE_CODES
|
||||
.iter()
|
||||
.find(|&&(key, _)| key == search_key)
|
||||
{
|
||||
if *fmt == OutputFmt::Display {
|
||||
result.push_str(format!("\x1b[{val}m{s}\t{val}\x1b[0m\n").as_str());
|
||||
} else {
|
||||
|
@ -363,15 +452,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
match fmt {
|
||||
OutputFmt::Shell => result.push_str("';\nexport LS_COLORS"),
|
||||
OutputFmt::CShell => result.push('\''),
|
||||
OutputFmt::Display => {
|
||||
if fmt == &OutputFmt::Display {
|
||||
// remove latest "\n"
|
||||
result.pop();
|
||||
}
|
||||
OutputFmt::Unknown => unreachable!(),
|
||||
}
|
||||
result.push_str(&suffix);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
|
|
@ -4,19 +4,15 @@
|
|||
// file that was distributed with this source code.
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/* The keywords COLOR, OPTIONS, and EIGHTBIT (honored by the
|
||||
* slackware version of dircolors) are recognized but ignored.
|
||||
* Global config options can be specified before TERM or COLORTERM entries
|
||||
* below are TERM or COLORTERM entries, which can be glob patterns, which
|
||||
* restrict following config to systems with matching environment variables.
|
||||
* COLORTERM ?*
|
||||
*/
|
||||
|
||||
pub static TERMS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
||||
let mut m = HashMap::new();
|
||||
[
|
||||
pub static TERMS: Lazy<Vec<&str>> = Lazy::new(|| {
|
||||
vec![
|
||||
"Eterm",
|
||||
"ansi",
|
||||
"*color*",
|
||||
|
@ -43,11 +39,6 @@ pub static TERMS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
|||
"vt100",
|
||||
"xterm*",
|
||||
]
|
||||
.iter()
|
||||
.for_each(|&term| {
|
||||
m.insert(term, "");
|
||||
});
|
||||
m
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -64,34 +55,27 @@ pub static TERMS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
|||
#NORMAL 00 # no color code at all
|
||||
#FILE 00 # regular file: use no color at all
|
||||
*/
|
||||
// FILE_TYPES with Lazy initialization
|
||||
pub static FILE_TYPES: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
||||
let mut m = HashMap::new();
|
||||
[
|
||||
("RESET", "0"), // reset to "normal" color
|
||||
("DIR", "01;34"), // directory
|
||||
("LINK", "01;36"), // symbolic link
|
||||
("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", "00"), // 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"), // files with execute permission
|
||||
pub static FILE_TYPES: Lazy<Vec<(&'static str, &'static str, &'static str)>> = Lazy::new(|| {
|
||||
vec![
|
||||
("RESET", "rs", "0"), // reset to "normal" color
|
||||
("DIR", "di", "01;34"), // directory
|
||||
("LINK", "ln", "01;36"), // symbolic link
|
||||
("MULTIHARDLINK", "mh", "00"), // regular file with more than one link
|
||||
("FIFO", "pi", "40;33"), // pipe
|
||||
("SOCK", "so", "01;35"), // socket
|
||||
("DOOR", "do", "01;35"), // door
|
||||
("BLK", "bd", "40;33;01"), // block device driver
|
||||
("CHR", "cd", "40;33;01"), // character device driver
|
||||
("ORPHAN", "or", "40;31;01"), // symlink to nonexistent file, or non-stat'able file
|
||||
("MISSING", "mi", "00"), // ... and the files they point to
|
||||
("SETUID", "su", "37;41"), // file that is setuid (u+s)
|
||||
("SETGID", "sg", "30;43"), // file that is setgid (g+s)
|
||||
("CAPABILITY", "ca", "00"), // file with capability
|
||||
("STICKY_OTHER_WRITABLE", "tw", "30;42"), // dir that is sticky and other-writable (+t,o+w)
|
||||
("OTHER_WRITABLE", "ow", "34;42"), // dir that is other-writable (o+w) and not sticky
|
||||
("STICKY", "st", "37;44"), // dir with the sticky bit set (+t) and not other-writable
|
||||
("EXEC", "ex", "01;32"), // files with execute permission
|
||||
]
|
||||
.iter()
|
||||
.for_each(|&(k, v)| {
|
||||
m.insert(k, v);
|
||||
});
|
||||
m
|
||||
});
|
||||
|
||||
/*
|
||||
|
@ -99,9 +83,9 @@ pub static FILE_TYPES: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
|||
# to color below. Put the extension, a space, and the color init string.
|
||||
# (and any comments you want to add after a '#')
|
||||
*/
|
||||
pub static FILE_COLORS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
||||
let mut m = HashMap::new();
|
||||
[
|
||||
pub static FILE_COLORS: Lazy<Vec<(&str, &str)>> = Lazy::new(|| {
|
||||
vec![
|
||||
/*
|
||||
// Executables (Windows)
|
||||
(".cmd", "01;32"),
|
||||
(".exe", "01;32"),
|
||||
|
@ -109,7 +93,7 @@ pub static FILE_COLORS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
|||
(".btm", "01;32"),
|
||||
(".bat", "01;32"),
|
||||
(".sh", "01;32"),
|
||||
(".csh", "01;32"),
|
||||
(".csh", "01;32"),*/
|
||||
// Archives or compressed
|
||||
(".tar", "01;31"),
|
||||
(".tgz", "01;31"),
|
||||
|
@ -207,6 +191,7 @@ pub static FILE_COLORS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
|||
(".yuv", "01;35"),
|
||||
(".cgm", "01;35"),
|
||||
(".emf", "01;35"),
|
||||
// https://wiki.xiph.org/MIME_Types_and_File_Extensions
|
||||
(".ogv", "01;35"),
|
||||
(".ogx", "01;35"),
|
||||
// Audio formats
|
||||
|
@ -222,13 +207,14 @@ pub static FILE_COLORS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
|||
(".ogg", "00;36"),
|
||||
(".ra", "00;36"),
|
||||
(".wav", "00;36"),
|
||||
// https://wiki.xiph.org/MIME_Types_and_File_Extensions
|
||||
(".oga", "00;36"),
|
||||
(".opus", "00;36"),
|
||||
(".spx", "00;36"),
|
||||
(".xspf", "00;36"),
|
||||
// Backup files
|
||||
("*~", "00;90"),
|
||||
("*#", "00;90"),
|
||||
("~", "00;90"),
|
||||
("#", "00;90"),
|
||||
(".bak", "00;90"),
|
||||
(".old", "00;90"),
|
||||
(".orig", "00;90"),
|
||||
|
@ -245,16 +231,10 @@ pub static FILE_COLORS: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
|||
(".rpmorig", "00;90"),
|
||||
(".rpmsave", "00;90"),
|
||||
]
|
||||
.iter()
|
||||
.for_each(|&(k, v)| {
|
||||
m.insert(k, v);
|
||||
});
|
||||
m
|
||||
});
|
||||
|
||||
pub static FILE_ATTRIBUTE_CODES: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
||||
let mut m = HashMap::new();
|
||||
[
|
||||
pub static FILE_ATTRIBUTE_CODES: Lazy<Vec<(&str, &str)>> = Lazy::new(|| {
|
||||
vec![
|
||||
("normal", "no"),
|
||||
("norm", "no"),
|
||||
("file", "fi"),
|
||||
|
@ -293,9 +273,4 @@ pub static FILE_ATTRIBUTE_CODES: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
|||
("multihardlink", "mh"),
|
||||
("clrtoeol", "cl"),
|
||||
]
|
||||
.iter()
|
||||
.for_each(|&(k, v)| {
|
||||
m.insert(k, v);
|
||||
});
|
||||
m
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue