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