Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion src/uu/ls/src/dired.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@
/// Overall, the module ensures each entry in the DIRED output has the correct
/// byte position, considering additional lines or padding affecting positions.
///
use crate::display::LocaleQuoting;
use crate::{Config, LsError};
use std::fmt;
use std::io::{BufWriter, Stdout, Write};
use uucore::error::UResult;
use uucore::quoting_style::{Quotes, QuotingStyle};

#[derive(Debug, Clone, PartialEq)]
pub struct BytePosition {
Expand Down Expand Up @@ -126,12 +128,42 @@ pub fn print_dired_output(
writeln!(
out,
"//DIRED-OPTIONS// --quoting-style={}",
config.quoting_style
dired_quoting_style_name(config)
)
.map_err(LsError::WriteError)?;
Ok(())
}

/// The canonical `--quoting-style` name for the `//DIRED-OPTIONS//` trailer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nobody will read such a long comment :) could you please make it one or two lines?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nobody but yesagent

/// `QuotingStyle`'s `Display` impl collapses distinct style names together and adds suffixes GNU's trailer never uses, so this maps the config directly instead.
fn dired_quoting_style_name(config: &Config) -> &'static str {
match config.locale_quoting {
Some(LocaleQuoting::Single) => return "locale",
Some(LocaleQuoting::Double) => return "clocale",
None => {}
}
match config.quoting_style {
QuotingStyle::Literal { .. } => "literal",
QuotingStyle::C {
quotes: Quotes::None,
} => "escape",
// `Quotes::Single` is never produced by ls's own option parsing
// (only reachable through `locale_quoting`, handled above), but
// `c` is the closest canonical name if that ever changes.
QuotingStyle::C { .. } => "c",
QuotingStyle::Shell {
escape,
always_quote,
..
} => match (escape, always_quote) {
(false, false) => "shell",
(false, true) => "shell-always",
(true, false) => "shell-escape",
(true, true) => "shell-escape-always",
},
}
}

/// Helper function to print positions with a given prefix.
fn print_positions(
out: &mut BufWriter<Stdout>,
Expand Down
36 changes: 36 additions & 0 deletions tests/by-util/test_ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5644,6 +5644,42 @@ fn test_ls_dired_implies_long() {
.stdout_contains("//DIRED-OPTIONS// --quoting-style");
}

// Regression test for issue #14775.
#[test]
fn test_ls_dired_quoting_style_name() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("dir");

for style in [
"literal",
"shell",
"shell-always",
"shell-escape",
"shell-escape-always",
"c",
"escape",
"locale",
"clocale",
] {
scene
.ucmd()
.env("LC_ALL", "C")
.args(&["-l", "--dired", &format!("--quoting-style={style}"), "dir"])
.succeeds()
.stdout_contains(format!("//DIRED-OPTIONS// --quoting-style={style}"));
}

for (opt, style) in [("-N", "literal"), ("-Q", "c"), ("-b", "escape")] {
scene
.ucmd()
.env("LC_ALL", "C")
.args(&["-l", "--dired", opt, "dir"])
.succeeds()
.stdout_contains(format!("//DIRED-OPTIONS// --quoting-style={style}"));
}
}

#[test]
fn test_ls_dired_hyperlink() {
// we will have link but not the DIRED output
Expand Down
Loading