1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

ls: overrideable -n option (#1917)

This commit is contained in:
Terts Diepraam 2021-03-26 19:12:01 +01:00 committed by GitHub
parent 83f8140aaf
commit 955c547adf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 103 additions and 45 deletions

View file

@ -84,6 +84,7 @@ pub mod options {
pub static COMMAS: &str = "m"; pub static COMMAS: &str = "m";
pub static LONG_NO_OWNER: &str = "g"; pub static LONG_NO_OWNER: &str = "g";
pub static LONG_NO_GROUP: &str = "o"; pub static LONG_NO_GROUP: &str = "o";
pub static LONG_NUMERIC_UID_GID: &str = "numeric-uid-gid";
} }
pub mod files { pub mod files {
pub static ALL: &str = "all"; pub static ALL: &str = "all";
@ -114,7 +115,6 @@ pub mod options {
pub static CLASSIFY: &str = "classify"; pub static CLASSIFY: &str = "classify";
pub static INODE: &str = "inode"; pub static INODE: &str = "inode";
pub static DEREFERENCE: &str = "dereference"; pub static DEREFERENCE: &str = "dereference";
pub static NUMERIC_UID_GID: &str = "numeric-uid-gid";
pub static REVERSE: &str = "reverse"; pub static REVERSE: &str = "reverse";
pub static RECURSIVE: &str = "recursive"; pub static RECURSIVE: &str = "recursive";
pub static COLOR: &str = "color"; pub static COLOR: &str = "color";
@ -167,7 +167,6 @@ struct Config {
classify: bool, classify: bool,
ignore_backups: bool, ignore_backups: bool,
size_format: SizeFormat, size_format: SizeFormat,
numeric_uid_gid: bool,
directory: bool, directory: bool,
time: Time, time: Time,
#[cfg(unix)] #[cfg(unix)]
@ -183,6 +182,8 @@ struct LongFormat {
author: bool, author: bool,
group: bool, group: bool,
owner: bool, owner: bool,
#[cfg(unix)]
numeric_uid_gid: bool,
} }
impl Config { impl Config {
@ -210,7 +211,7 @@ impl Config {
(Format::Columns, options::format::COLUMNS) (Format::Columns, options::format::COLUMNS)
}; };
// The -o and -g options are tricky. They cannot override with each // The -o, -n and -g options are tricky. They cannot override with each
// other because it's possible to combine them. For example, the option // other because it's possible to combine them. For example, the option
// -og should hide both owner and group. Furthermore, they are not // -og should hide both owner and group. Furthermore, they are not
// reset if -l or --format=long is used. So these should just show the // reset if -l or --format=long is used. So these should just show the
@ -223,42 +224,26 @@ impl Config {
// which always applies. // which always applies.
// //
// The idea here is to not let these options override with the other // The idea here is to not let these options override with the other
// options, but manually check the last index they occur. If this index // options, but manually whether they have an index that's greater than
// is larger than the index for the other format options, we apply the // the other format options. If so, we set the appropriate format.
// long format. if format != Format::Long {
match options.indices_of(opt).map(|x| x.max().unwrap()) { let idx = options.indices_of(opt).map(|x| x.max().unwrap()).unwrap_or(0);
None => { if [options::format::LONG_NO_OWNER, options::format::LONG_NO_GROUP, options::format::LONG_NUMERIC_UID_GID]
if options.is_present(options::format::LONG_NO_GROUP) .iter()
|| options.is_present(options::format::LONG_NO_OWNER) .flat_map(|opt| options.indices_of(opt))
{ .flatten()
format = Format::Long; .any(|i| i >= idx)
} else if options.is_present(options::format::ONELINE) { {
format = Format::OneLine; format = Format::Long;
} } else {
} if let Some(mut indices) = options.indices_of(options::format::ONELINE) {
Some(mut idx) => { if indices.any(|i| i > idx) {
if let Some(indices) = options.indices_of(options::format::LONG_NO_OWNER) {
let i = indices.max().unwrap();
if i > idx {
format = Format::Long;
idx = i;
}
}
if let Some(indices) = options.indices_of(options::format::LONG_NO_GROUP) {
let i = indices.max().unwrap();
if i > idx {
format = Format::Long;
idx = i;
}
}
if let Some(indices) = options.indices_of(options::format::ONELINE) {
let i = indices.max().unwrap();
if i > idx && format != Format::Long {
format = Format::OneLine; format = Format::OneLine;
} }
} }
} }
} }
let files = if options.is_present(options::files::ALL) { let files = if options.is_present(options::files::ALL) {
Files::All Files::All
@ -328,10 +313,14 @@ impl Config {
let group = !options.is_present(options::NO_GROUP) let group = !options.is_present(options::NO_GROUP)
&& !options.is_present(options::format::LONG_NO_GROUP); && !options.is_present(options::format::LONG_NO_GROUP);
let owner = !options.is_present(options::format::LONG_NO_OWNER); let owner = !options.is_present(options::format::LONG_NO_OWNER);
#[cfg(unix)]
let numeric_uid_gid = options.is_present(options::format::LONG_NUMERIC_UID_GID);
LongFormat { LongFormat {
author, author,
group, group,
owner, owner,
#[cfg(unix)]
numeric_uid_gid,
} }
}; };
@ -355,7 +344,6 @@ impl Config {
classify: options.is_present(options::CLASSIFY), classify: options.is_present(options::CLASSIFY),
ignore_backups: options.is_present(options::IGNORE_BACKUPS), ignore_backups: options.is_present(options::IGNORE_BACKUPS),
size_format, size_format,
numeric_uid_gid: options.is_present(options::NUMERIC_UID_GID),
directory: options.is_present(options::DIRECTORY), directory: options.is_present(options::DIRECTORY),
time, time,
#[cfg(unix)] #[cfg(unix)]
@ -444,22 +432,36 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
options::format::COLUMNS, options::format::COLUMNS,
]), ]),
) )
// The next three arguments do not override with the other format // The next four arguments do not override with the other format
// options, see the comment in Config::from for the reason. // options, see the comment in Config::from for the reason.
// Ideally, they would use Arg::override_with, with their own name
// but that doesn't seem to work in all cases. Example:
// ls -1g1
// even though `ls -11` and `ls -1 -g -1` work.
.arg( .arg(
Arg::with_name(options::format::ONELINE) Arg::with_name(options::format::ONELINE)
.short(options::format::ONELINE) .short(options::format::ONELINE)
.help("List one file per line.") .help("List one file per line.")
.multiple(true)
) )
.arg( .arg(
Arg::with_name(options::format::LONG_NO_GROUP) Arg::with_name(options::format::LONG_NO_GROUP)
.short(options::format::LONG_NO_GROUP) .short(options::format::LONG_NO_GROUP)
.help("Long format without group information. Identical to --format=long with --no-group.") .help("Long format without group information. Identical to --format=long with --no-group.")
.multiple(true)
) )
.arg( .arg(
Arg::with_name(options::format::LONG_NO_OWNER) Arg::with_name(options::format::LONG_NO_OWNER)
.short(options::format::LONG_NO_OWNER) .short(options::format::LONG_NO_OWNER)
.help("Long format without owner information.") .help("Long format without owner information.")
.multiple(true)
)
.arg(
Arg::with_name(options::format::LONG_NUMERIC_UID_GID)
.short("n")
.long(options::format::LONG_NUMERIC_UID_GID)
.help("-l with numeric UIDs and GIDs.")
.multiple(true)
) )
// Time arguments // Time arguments
@ -657,12 +659,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
file the link references rather than the link itself.", file the link references rather than the link itself.",
), ),
) )
.arg(
Arg::with_name(options::NUMERIC_UID_GID)
.short("n")
.long(options::NUMERIC_UID_GID)
.help("-l with numeric UIDs and GIDs."),
)
.arg( .arg(
Arg::with_name(options::REVERSE) Arg::with_name(options::REVERSE)
.short("r") .short("r")
@ -852,7 +849,7 @@ fn pad_left(string: String, count: usize) -> String {
} }
fn display_items(items: &[PathBuf], strip: Option<&Path>, config: &Config) { fn display_items(items: &[PathBuf], strip: Option<&Path>, config: &Config) {
if config.format == Format::Long || config.numeric_uid_gid { if config.format == Format::Long {
let (mut max_links, mut max_size) = (1, 1); let (mut max_links, mut max_size) = (1, 1);
for item in items { for item in items {
let (links, size) = display_dir_entry_size(item, config); let (links, size) = display_dir_entry_size(item, config);
@ -994,7 +991,7 @@ use uucore::entries;
#[cfg(unix)] #[cfg(unix)]
fn display_uname(metadata: &Metadata, config: &Config) -> String { fn display_uname(metadata: &Metadata, config: &Config) -> String {
if config.numeric_uid_gid { if config.long.numeric_uid_gid {
metadata.uid().to_string() metadata.uid().to_string()
} else { } else {
entries::uid2usr(metadata.uid()).unwrap_or_else(|_| metadata.uid().to_string()) entries::uid2usr(metadata.uid()).unwrap_or_else(|_| metadata.uid().to_string())
@ -1003,7 +1000,7 @@ fn display_uname(metadata: &Metadata, config: &Config) -> String {
#[cfg(unix)] #[cfg(unix)]
fn display_group(metadata: &Metadata, config: &Config) -> String { fn display_group(metadata: &Metadata, config: &Config) -> String {
if config.numeric_uid_gid { if config.long.numeric_uid_gid {
metadata.gid().to_string() metadata.gid().to_string()
} else { } else {
entries::gid2grp(metadata.gid()).unwrap_or_else(|_| metadata.gid().to_string()) entries::gid2grp(metadata.gid()).unwrap_or_else(|_| metadata.gid().to_string())

View file

@ -297,15 +297,24 @@ fn test_ls_long_formats() {
// Regex for three names, so all of author, group and owner // Regex for three names, so all of author, group and owner
let re_three = Regex::new(r"[xrw-]{9} \d ([-0-9_a-z]+ ){3}0").unwrap(); let re_three = Regex::new(r"[xrw-]{9} \d ([-0-9_a-z]+ ){3}0").unwrap();
#[cfg(unix)]
let re_three_num = Regex::new(r"[xrw-]{9} \d (\d+ ){3}0").unwrap();
// Regex for two names, either: // Regex for two names, either:
// - group and owner // - group and owner
// - author and owner // - author and owner
// - author and group // - author and group
let re_two = Regex::new(r"[xrw-]{9} \d ([-0-9_a-z]+ ){2}0").unwrap(); let re_two = Regex::new(r"[xrw-]{9} \d ([-0-9_a-z]+ ){2}0").unwrap();
#[cfg(unix)]
let re_two_num = Regex::new(r"[xrw-]{9} \d (\d+ ){2}0").unwrap();
// Regex for one name: author, group or owner // Regex for one name: author, group or owner
let re_one = Regex::new(r"[xrw-]{9} \d [-0-9_a-z]+ 0").unwrap(); let re_one = Regex::new(r"[xrw-]{9} \d [-0-9_a-z]+ 0").unwrap();
#[cfg(unix)]
let re_one_num = Regex::new(r"[xrw-]{9} \d \d+ 0").unwrap();
// Regex for no names // Regex for no names
let re_zero = Regex::new(r"[xrw-]{9} \d 0").unwrap(); let re_zero = Regex::new(r"[xrw-]{9} \d 0").unwrap();
@ -329,6 +338,19 @@ fn test_ls_long_formats() {
println!("stdout = {:?}", result.stdout); println!("stdout = {:?}", result.stdout);
assert!(re_three.is_match(&result.stdout)); assert!(re_three.is_match(&result.stdout));
#[cfg(unix)]
{
let result = scene
.ucmd()
.arg("-n")
.arg("--author")
.arg("test-long-formats")
.succeeds();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
assert!(re_three_num.is_match(&result.stdout));
}
for arg in &[ for arg in &[
"-l", // only group and owner "-l", // only group and owner
"-g --author", // only author and group "-g --author", // only author and group
@ -344,6 +366,19 @@ fn test_ls_long_formats() {
println!("stderr = {:?}", result.stderr); println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout); println!("stdout = {:?}", result.stdout);
assert!(re_two.is_match(&result.stdout)); assert!(re_two.is_match(&result.stdout));
#[cfg(unix)]
{
let result = scene
.ucmd()
.arg("-n")
.args(&arg.split(" ").collect::<Vec<_>>())
.arg("test-long-formats")
.succeeds();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
assert!(re_two_num.is_match(&result.stdout));
}
} }
for arg in &[ for arg in &[
@ -364,6 +399,19 @@ fn test_ls_long_formats() {
println!("stderr = {:?}", result.stderr); println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout); println!("stdout = {:?}", result.stdout);
assert!(re_one.is_match(&result.stdout)); assert!(re_one.is_match(&result.stdout));
#[cfg(unix)]
{
let result = scene
.ucmd()
.arg("-n")
.args(&arg.split(" ").collect::<Vec<_>>())
.arg("test-long-formats")
.succeeds();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
assert!(re_one_num.is_match(&result.stdout));
}
} }
for arg in &[ for arg in &[
@ -387,6 +435,19 @@ fn test_ls_long_formats() {
println!("stderr = {:?}", result.stderr); println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout); println!("stdout = {:?}", result.stdout);
assert!(re_zero.is_match(&result.stdout)); assert!(re_zero.is_match(&result.stdout));
#[cfg(unix)]
{
let result = scene
.ucmd()
.arg("-n")
.args(&arg.split(" ").collect::<Vec<_>>())
.arg("test-long-formats")
.succeeds();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
assert!(re_zero.is_match(&result.stdout));
}
} }
} }