Skip to content
Open
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
4 changes: 1 addition & 3 deletions src/uu/env/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ use std::env;
#[cfg(unix)]
use std::ffi::CString;
use std::ffi::{OsStr, OsString};
#[cfg(not(unix))]
use std::io;
use std::io::Write as _;
use std::io::stderr;
Expand Down Expand Up @@ -825,8 +824,7 @@ impl EnvAppData {

apply_change_directory(&opts)?;
if opts.program.is_empty() {
// no program provided, so just dump all env vars to stdout
print_all_env_vars(opts.line_ending)?;
print_all_env_vars(io::stdout(), opts.line_ending)?;
} else {
return self.run_program(&opts, self.do_debug_printing);
}
Expand Down
1 change: 0 additions & 1 deletion src/uu/ls/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ ls-help-long-format-no-group = Long format without group information.
Identical to --format=long with --no-group.
ls-help-long-no-owner = Long format without owner information.
ls-help-long-numeric-uid-gid = -l with numeric UIDs and GIDs.
ls-help-set-quoting-style = Set quoting style.
ls-help-literal-quoting-style = Use literal quoting style. Equivalent to `--quoting-style=literal`
ls-help-escape-quoting-style = Use escape quoting style. Equivalent to `--quoting-style=escape`
ls-help-c-quoting-style = Use C quoting style. Equivalent to `--quoting-style=c`
Expand Down
1 change: 0 additions & 1 deletion src/uu/ls/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ ls-help-long-format-no-group = Format long sans informations de groupe.
Identique à --format=long avec --no-group.
ls-help-long-no-owner = Format long sans informations de propriétaire.
ls-help-long-numeric-uid-gid = -l avec des UID et GID numériques.
ls-help-set-quoting-style = Définir le style de citation.
ls-help-literal-quoting-style = Utiliser le style de citation littéral. Équivalent à `--quoting-style=literal`
ls-help-escape-quoting-style = Utiliser le style de citation d'échappement. Équivalent à `--quoting-style=escape`
ls-help-c-quoting-style = Utiliser le style de citation C. Équivalent à `--quoting-style=c`
Expand Down
4 changes: 3 additions & 1 deletion src/uu/ls/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ use crate::{
};

pub mod options {
use uucore::quoting_style;

pub mod format {
pub static ONE_LINE: &str = "1";
pub static LONG: &str = "long";
Expand Down Expand Up @@ -97,7 +99,7 @@ pub mod options {
}

pub static HELP: &str = "help";
pub static QUOTING_STYLE: &str = "quoting-style";
pub use quoting_style::parser::QUOTING_STYLE;
pub static HIDE_CONTROL_CHARS: &str = "hide-control-chars";
pub static SHOW_CONTROL_CHARS: &str = "show-control-chars";
pub static WIDTH: &str = "width";
Expand Down
29 changes: 7 additions & 22 deletions src/uu/ls/src/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use uucore::{
fsext::metadata_get_time,
os_str_as_bytes_lossy,
parser::shortcut_value_parser::ShortcutValueParser,
show, translate,
quoting_style, show, translate,
version_cmp::version_cmp,
};

Expand Down Expand Up @@ -297,27 +297,12 @@ pub fn uu_app() -> Command {
)
// Quoting style
.arg(
Arg::new(QUOTING_STYLE)
.long(QUOTING_STYLE)
.help(translate!("ls-help-set-quoting-style"))
.value_parser(ShortcutValueParser::new([
PossibleValue::new("literal"),
PossibleValue::new("locale"),
PossibleValue::new("shell"),
PossibleValue::new("shell-escape"),
PossibleValue::new("shell-always"),
PossibleValue::new("shell-escape-always"),
PossibleValue::new("clocale"),
PossibleValue::new("c"),
PossibleValue::new("c-maybe"),
PossibleValue::new("escape"),
]))
.overrides_with_all([
QUOTING_STYLE,
options::quoting::LITERAL,
options::quoting::ESCAPE,
options::quoting::C,
]),
quoting_style::parser::clap_quoting_argument().overrides_with_all([
QUOTING_STYLE,
options::quoting::LITERAL,
options::quoting::ESCAPE,
options::quoting::C,
]),
)
.arg(
Arg::new(options::quoting::LITERAL)
Expand Down
2 changes: 1 addition & 1 deletion src/uu/printenv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ doctest = false
[dependencies]
clap = { workspace = true }
fluent = { workspace = true }
uucore = { workspace = true }
uucore = { workspace = true, features = ["quoting-style", "parser"] }

[lints]
workspace = true
Expand Down
1 change: 1 addition & 0 deletions src/uu/printenv/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ printenv-about = Display the values of the specified environment VARIABLE(s), or
printenv-usage = printenv [OPTION]... [VARIABLE]...
printenv-help-null = end each output line with 0 byte rather than newline
printenv-help-quoting-style = set quoting style

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.

could you please list the accepted values in the help, like ls does?

1 change: 1 addition & 0 deletions src/uu/printenv/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ printenv-about = Afficher les valeurs des VARIABLE(s) d'environnement spécifié
printenv-usage = printenv [OPTION]... [VARIABLE]...
printenv-help-null = terminer chaque ligne de sortie avec un octet 0 plutôt qu'un saut de ligne
printenv-help-quoting-style = indiquer le style d'encapsulation à utiliser
39 changes: 35 additions & 4 deletions src/uu/printenv/src/printenv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
// file that was distributed with this source code.

use std::env;
use std::io::Write;
use std::io::{IsTerminal, Write};

use clap::{Arg, ArgAction, Command};

use uucore::display::{OsWrite, print_all_env_vars};
use uucore::display::{OsWrite, print_all_env_vars, print_all_env_vars_quoted};
use uucore::error::UResult;
use uucore::i18n::get_ctype_encoding;
use uucore::line_ending::LineEnding;
use uucore::quoting_style::{
QuotingStyle, escape_name, parser as qs_parser, quoting_style_from_env,
};
use uucore::{format_usage, translate};

static OPT_NULL: &str = "null";

static ARG_VARIABLES: &str = "variables";

#[uucore::main(no_signals)]
Expand All @@ -26,14 +29,34 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();

let maybe_quoting_style = matches
.get_one::<String>(qs_parser::QUOTING_STYLE)
.and_then(QuotingStyle::parse)

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.

an invalid --quoting-style=foo is silently ignored here, could we reject it with a value_parser like ls does?
please add a test for it too

.or_else(|| {
std::io::stdout()
.is_terminal() // quoting style from env var is only used in TTY

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.

why only on a tty? stat and ls use QUOTING_STYLE whatever stdout is

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Only following GNU behavior here

.then(quoting_style_from_env)
.flatten()
});

let separator = LineEnding::from_zero_flag(matches.get_flag(OPT_NULL));

if variables.is_empty() {
print_all_env_vars(separator)?;
if let Some(quoting_style) = maybe_quoting_style {
print_all_env_vars_quoted(
std::io::stdout(),
separator,
quoting_style,
get_ctype_encoding(),
)?;
} else {
print_all_env_vars(std::io::stdout(), separator)?;
}
return Ok(());
}

let mut error_found = false;
let ctype = get_ctype_encoding();
for env_var in variables {
// we silently ignore a=b as variable but we trigger an error
if env_var.contains('=') {
Expand All @@ -42,6 +65,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}
if let Some(var) = env::var_os(env_var) {
let mut stdout = std::io::stdout().lock();

let var = if let Some(qs) = maybe_quoting_style {
escape_name(&var, qs, ctype)
} else {
var
};

stdout.write_all_os(&var)?;
write!(stdout, "{separator}")?;
} else {
Expand All @@ -66,6 +96,7 @@ pub fn uu_app() -> Command {
.help(translate!("printenv-help-null"))
.action(ArgAction::SetTrue),
)
.arg(qs_parser::clap_quoting_argument())
.arg(
Arg::new(ARG_VARIABLES)
.action(ArgAction::Append)
Expand Down
2 changes: 2 additions & 0 deletions src/uucore/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ common-help-suggestion = For more information, try '--help'.
help-flag-help = Print help information
help-flag-version = Print version information
help-set-quoting-style = Set quoting style
# Common error contexts
error-io = I/O error
error-permission-denied = Permission denied
Expand Down
2 changes: 2 additions & 0 deletions src/uucore/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ common-help-suggestion = Pour plus d'informations, essayez '--help'.
help-flag-help = Afficher les informations d'aide
help-flag-version = Afficher les informations de version
ls-help-set-quoting-style = Définir le style de citation.
# Contextes d'erreur communs
error-io = Erreur E/S
error-permission-denied = Permission refusée
Expand Down
33 changes: 31 additions & 2 deletions src/uucore/src/lib/features/quoting_style/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ impl QuotingStyle {
///
/// Used for e.g., the `QUOTING_STYLE` environment variable and the
/// `--quoting-style` option of `ls`.
pub fn parse(s: &str) -> Option<Self> {
Some(match s {
pub fn parse(s: impl AsRef<str>) -> Option<Self> {
Some(match s.as_ref() {
"literal" => Self::LITERAL,
"shell" => Self::SHELL,
"shell-always" => Self::SHELL_ALWAYS,
Expand Down Expand Up @@ -381,6 +381,35 @@ pub fn locale_aware_escape_dir_name(name: &OsStr, style: QuotingStyle) -> OsStri
escape_dir_name(name, style, i18n::get_ctype_encoding())
}

#[cfg(any(feature = "parser", feature = "parser-num"))]
pub mod parser {
use clap::Arg;
use clap::builder::PossibleValue;

use crate::parser::shortcut_value_parser::ShortcutValueParser;
use crate::translate;

pub const QUOTING_STYLE: &str = "quoting-style";

pub fn clap_quoting_argument() -> Arg {
Arg::new(QUOTING_STYLE)
.long(QUOTING_STYLE)
.help(translate!("help-set-quoting-style"))
.value_parser(ShortcutValueParser::new([
PossibleValue::new("literal"),
PossibleValue::new("locale"),
PossibleValue::new("shell"),
PossibleValue::new("shell-escape"),
PossibleValue::new("shell-always"),
PossibleValue::new("shell-escape-always"),
PossibleValue::new("clocale"),
PossibleValue::new("c"),
PossibleValue::new("c-maybe"),
PossibleValue::new("escape"),
]))
}
}

#[cfg(test)]
mod tests {
use crate::i18n::UEncoding;
Expand Down
36 changes: 30 additions & 6 deletions src/uucore/src/lib/mods/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ use std::{env, fmt};
// These used to be defined here, but they live in their own crate now.
pub use os_display::{Quotable, Quoted};

#[cfg(feature = "quoting-style")]
use crate::{
i18n::UEncoding,
quoting_style::{QuotingStyle, escape_name},
};

/// Print a path (or `OsStr`-like object) directly to stdout, with a trailing newline,
/// without losing any information if its encoding is invalid.
///
Expand Down Expand Up @@ -119,13 +125,31 @@ impl OsWrite for Box<dyn OsWrite> {
///
/// This function handles non-UTF-8 environment variable names and values correctly by using
/// raw bytes on Unix systems.
pub fn print_all_env_vars<T: fmt::Display>(line_ending: T) -> io::Result<()> {
let mut stdout = io::stdout().lock();
pub fn print_all_env_vars<W: OsWrite, T: fmt::Display>(mut w: W, line_ending: T) -> io::Result<()> {
for (name, value) in env::vars_os() {
stdout.write_all_os(&name)?;
stdout.write_all(b"=")?;
stdout.write_all_os(&value)?;
write!(stdout, "{line_ending}")?;
w.write_all_os(&name)?;
w.write_all(b"=")?;

w.write_all_os(&value)?;
write!(w, "{line_ending}")?;
}
Ok(())
}

/// Equivalent to [`print_all_env_vars`] that quotes
#[cfg(feature = "quoting-style")]
pub fn print_all_env_vars_quoted<W: OsWrite, T: fmt::Display>(
mut w: W,
line_ending: T,

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.

why gate the whole function behind quoting-style? only the escaping needs it

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

As mentioned above, created a specific print_all_env_vars_quoted

quoting_style: QuotingStyle,
encoding: UEncoding,
) -> io::Result<()> {
for (name, value) in env::vars_os() {
w.write_all_os(&escape_name(&name, quoting_style, encoding))?;
w.write_all(b"=")?;

w.write_all_os(&escape_name(&value, quoting_style, encoding))?;
write!(w, "{line_ending}")?;
}
Ok(())
}
Loading