diff --git a/completions/bash/eza b/completions/bash/eza index dbecd8a91..8b7fb0169 100644 --- a/completions/bash/eza +++ b/completions/bash/eza @@ -52,6 +52,10 @@ _eza() { mapfile -t COMPREPLY < <(compgen -W 'on follow off --' -- "$cur") return ;; + --quotes) + mapfile -t COMPREPLY < <(compgen -W 'always auto automatic never --' -- "$cur") + return + ;; esac case "$cur" in @@ -59,7 +63,7 @@ _eza() { --*) # colo[u]r isn’t parsed correctly so we filter these options out and add them by hand parse_help=$(eza --help | grep -oE ' (--[[:alnum:]@-]+)' | tr -d ' ' | grep -v '\--colo') - completions=$(echo '--color --colour --color-scale --colour-scale --color-scale-mode --colour-scale-mode' "$parse_help") + completions=$(echo '--color --colour --color-scale --colour-scale --color-scale-mode --colour-scale-mode --quotes' "$parse_help") mapfile -t COMPREPLY < <(compgen -W "$completions" -- "$cur") ;; diff --git a/completions/fish/eza.fish b/completions/fish/eza.fish index 7589c5d8e..415dd96c8 100644 --- a/completions/fish/eza.fish +++ b/completions/fish/eza.fish @@ -36,7 +36,12 @@ complete -c eza -l icons -d "When to display icons" -x -a " automatic\t'Display icons if standard output is a terminal' never\t'Never display icons' " -complete -c eza -l no-quotes -d "Don't quote file names with spaces" +complete -c eza -l quotes -d "When to quote filenames" -x -a " + always\t'Always quote filenames, even filenames with no spaces/special characters' + auto\t'Quote filenames if they contain spaces or special characters' + automatic\t'Quote filenames if they contain spaces or special characters' + never\t'Never quote filenames' +" complete -c eza -l hyperlink -d "Display entries as hyperlinks" complete -c eza -l follow-symlinks -d "Drill down into symbolic links that point to directories" complete -c eza -l absolute -d "Display entries with their absolute path" -x -a " diff --git a/completions/nush/eza.nu b/completions/nush/eza.nu index 4cc434355..b7d1a42d1 100644 --- a/completions/nush/eza.nu +++ b/completions/nush/eza.nu @@ -16,7 +16,7 @@ export extern "eza" [ --color-scale-mode # Use gradient or fixed colors in --color-scale --colour-scale-mode # Use gradient or fixed colors in --colour-scale --icons # When to display icons - --no-quotes # Don't quote file names with spaces + --quotes # When to quote filenames (always, auto, automatic, never) --hyperlink # Display entries as hyperlinks --absolute # Display entries with their absolute path --follow-symlinks # Drill down into symbolic links that point to directories diff --git a/completions/zsh/_eza b/completions/zsh/_eza index 6f6a4b817..d925ce60b 100644 --- a/completions/zsh/_eza +++ b/completions/zsh/_eza @@ -24,7 +24,7 @@ __eza() { --colo{,u}r-scale"[highlight levels of 'field' distinctly]:(fields):(all age size)" \ --colo{,u}r-scale-mode"[Use gradient or fixed colors in --color-scale]:(mode):(fixed gradient)" \ --icons="[When to display icons]:(when):(always auto automatic never)" \ - --no-quotes"[Don't quote filenames with spaces]" \ + --quotes="[When to quote filenames]: (when): (always auto automatic never) \ --hyperlink"[Display entries as hyperlinks]" \ --absolute"[Display entries with their absolute path]:(mode):(on follow off)" \ --follow-symlinks"[Drill down into symbolic links that point to directories]" \ diff --git a/man/eza.1.md b/man/eza.1.md index 71b3de20d..d45b84b5c 100644 --- a/man/eza.1.md +++ b/man/eza.1.md @@ -110,8 +110,11 @@ The default value is ‘`automatic`’. `automatic` or `auto` will display icons only when the standard output is connected to a real terminal. If `eza` is ran while in a `tty`, or the output of `eza` is either redirected to a file or piped into another program, icons will not be used. Setting this option to ‘`always`’ causes `eza` to always display icons, while ‘`never`’ disables the use of icons. -`--no-quotes` -: Don't quote file names with spaces. +`--quotes=WHEN` +: When to quote file names. Default is `auto` which is only when there are spaces in the name. + +Valid settings are `always`, `automatic` (or `auto` for short), or `never` +`always` will quote every file name, `never` will never quote any file name, and `automatic` will only quote file names when there are spaces in the name. `--hyperlink` : Display entries as hyperlinks @@ -350,6 +353,17 @@ Specifies the separator to use when file names are piped from stdin. Defaults to Specifies the directory where eza will look for its configuration and theme files. Defaults to `$XDG_CONFIG_HOME/eza` or `$HOME/.config/eza` if `XDG_CONFIG_HOME` is not set. +======= +## `EZA_QUOTING_STYLE` + +Options are 'never' | 'always' | 'auto' + +'never' is equivalent to the `ls`' `-N` option or `QUOTING_STYLE=literal` option, where file names are never quoted + +'auto' is the default, and equivalent to the `ls`' `-Q` option or `QUOTING_STYLE=shell-escape` option, where file names are quoted when they contain spaces. + +'always' is equivalent to the `ls` `QUOTING_STYLE=shell-escape-always` option, where all file names are quoted. + EXIT STATUSES ============= diff --git a/src/options/file_name.rs b/src/options/file_name.rs index b6c9b9ef1..cd208b6b2 100644 --- a/src/options/file_name.rs +++ b/src/options/file_name.rs @@ -105,10 +105,25 @@ impl ShowIcons { impl QuoteStyle { pub fn deduce(matches: &MatchedFlags<'_>) -> Result { - if matches.has(&flags::NO_QUOTES)? { - Ok(Self::NoQuotes) + let env = std::env::var("EZA_QUOTING_STYLE"); + let env = env.unwrap_or_else(|_| "auto".to_string()); + let env = match env.to_ascii_lowercase().as_str() { + "always" => Self::Always, + "never" => Self::Never, + _ => Self::Auto, + }; + if matches.get(&flags::QUOTES)?.is_none() { + Ok(env) + } else if let Some(word) = matches.get(&flags::QUOTES)? { + match word.to_str() { + Some("always") => Ok(Self::Always), + Some("never") => Ok(Self::Never), + Some("auto" | "automatic") => Ok(Self::Auto), + Some(arg) => Err(OptionsError::BadArgument(&flags::QUOTES, arg.into())), + _ => Err(OptionsError::BadArgument(&flags::QUOTES, "auto".into())), + } } else { - Ok(Self::QuoteSpaces) + Ok(env) } } } diff --git a/src/options/flags.rs b/src/options/flags.rs index 581fd7e65..52457d4f3 100644 --- a/src/options/flags.rs +++ b/src/options/flags.rs @@ -21,14 +21,13 @@ pub static TREE: Arg = Arg { short: Some(b'T'), long: "tree", pub static CLASSIFY: Arg = Arg { short: Some(b'F'), long: "classify", takes_value: TakesValue::Optional(Some(WHEN), "auto") }; pub static DEREF_LINKS: Arg = Arg { short: Some(b'X'), long: "dereference", takes_value: TakesValue::Forbidden }; pub static WIDTH: Arg = Arg { short: Some(b'w'), long: "width", takes_value: TakesValue::Necessary(None) }; -pub static NO_QUOTES: Arg = Arg { short: None, long: "no-quotes", takes_value: TakesValue::Forbidden }; pub static ABSOLUTE: Arg = Arg { short: None, long: "absolute", takes_value: TakesValue::Optional(Some(ABSOLUTE_MODES), "on") }; pub static FOLLOW_LINKS: Arg = Arg { short: None, long: "follow-symlinks", takes_value: TakesValue::Forbidden }; +pub static QUOTES: Arg = Arg { short: None, long: "quotes", takes_value: TakesValue::Necessary(Some(WHEN)) }; const ABSOLUTE_MODES: &[&str] = &["on", "follow", "off"]; pub static COLOR: Arg = Arg { short: None, long: "color", takes_value: TakesValue::Optional(Some(WHEN), "auto") }; pub static COLOUR: Arg = Arg { short: None, long: "colour", takes_value: TakesValue::Optional(Some(WHEN), "auto") }; -const WHEN: &[&str] = &["always", "auto", "never"]; pub static COLOR_SCALE: Arg = Arg { short: None, long: "color-scale", takes_value: TakesValue::Optional(Some(SCALES), "all") }; pub static COLOUR_SCALE: Arg = Arg { short: None, long: "colour-scale", takes_value: TakesValue::Optional(Some(SCALES), "all") }; @@ -52,9 +51,6 @@ pub static ONLY_DIRS: Arg = Arg { short: Some(b'D'), long: "only-dirs", takes_ pub static ONLY_FILES: Arg = Arg { short: Some(b'f'), long: "only-files", takes_value: TakesValue::Forbidden }; pub static NO_SYMLINKS: Arg = Arg { short: None, long: "no-symlinks", takes_value: TakesValue::Forbidden }; pub static SHOW_SYMLINKS: Arg = Arg { short: None, long: "show-symlinks", takes_value: TakesValue::Forbidden }; -const SORTS: Values = &[ "name", "Name", "size", "extension", - "Extension", "modified", "changed", "accessed", - "created", "inode", "type", "none" ]; // display options pub static BINARY: Arg = Arg { short: Some(b'b'), long: "binary", takes_value: TakesValue::Forbidden }; @@ -76,8 +72,6 @@ pub static TIME_STYLE: Arg = Arg { short: None, long: "time-style", take pub static HYPERLINK: Arg = Arg { short: None, long: "hyperlink", takes_value: TakesValue::Forbidden }; pub static MOUNTS: Arg = Arg { short: Some(b'M'), long: "mounts", takes_value: TakesValue::Forbidden }; pub static SMART_GROUP: Arg = Arg { short: None, long: "smart-group", takes_value: TakesValue::Forbidden }; -const TIMES: Values = &["modified", "changed", "accessed", "created"]; -const TIME_STYLES: Values = &["default", "long-iso", "full-iso", "iso", "relative"]; // suppressing columns pub static NO_PERMISSIONS: Arg = Arg { short: None, long: "no-permissions", takes_value: TakesValue::Forbidden }; @@ -96,12 +90,17 @@ pub static SECURITY_CONTEXT: Arg = Arg { short: Some(b'Z'), long: "context", pub static STDIN: Arg = Arg { short: None, long: "stdin", takes_value: TakesValue::Forbidden }; pub static FILE_FLAGS: Arg = Arg { short: Some(b'O'), long: "flags", takes_value: TakesValue::Forbidden }; +const TIMES: Values = &["modified", "changed", "accessed", "created"]; +const TIME_STYLES: Values = &["default", "long-iso", "full-iso", "iso", "relative"]; +const WHEN: Values = &["always", "auto", "automatic", "never"]; +const SORTS: Values = &[ "name", "Name", "size", "extension", "Extension", "modified", "changed", "accessed", "created", "inode", "type", "none" ]; + pub static ALL_ARGS: Args = Args(&[ &VERSION, &HELP, &ONE_LINE, &LONG, &GRID, &ACROSS, &RECURSE, &TREE, &CLASSIFY, &DEREF_LINKS, &FOLLOW_LINKS, &COLOR, &COLOUR, &COLOR_SCALE, &COLOUR_SCALE, &COLOR_SCALE_MODE, &COLOUR_SCALE_MODE, - &WIDTH, &NO_QUOTES, &ABSOLUTE, + &WIDTH, &ABSOLUTE, "ES, &ALL, &ALMOST_ALL, &LIST_DIRS, &LEVEL, &REVERSE, &SORT, &DIRS_FIRST, &DIRS_LAST, &IGNORE_GLOB, &GIT_IGNORE, &ONLY_DIRS, &ONLY_FILES, diff --git a/src/options/help.rs b/src/options/help.rs index f23a2dd45..393f66e3d 100644 --- a/src/options/help.rs +++ b/src/options/help.rs @@ -29,8 +29,8 @@ DISPLAY OPTIONS --colo[u]r=WHEN when to use terminal colours (always, auto, never) --colo[u]r-scale highlight levels of 'field' distinctly(all, age, size) --colo[u]r-scale-mode use gradient or fixed colors in --color-scale (fixed, gradient) - --icons=WHEN when to display icons (always, auto, never) - --no-quotes don't quote file names with spaces + --icons=WHEN when to display icons (always, auto(matic), never) + --quotes when to quote file names (always, auto(matic), never) --hyperlink display entries as hyperlinks --absolute display entries with their absolute path (on, follow, off) --follow-symlinks drill down into symbolic links that point to directories diff --git a/src/output/escape.rs b/src/output/escape.rs index 69f136c96..fb78c4eed 100644 --- a/src/output/escape.rs +++ b/src/output/escape.rs @@ -38,7 +38,7 @@ pub fn escape( } } - if quote_style != QuoteStyle::NoQuotes && needs_quotes { + if quote_style != QuoteStyle::Never && needs_quotes || quote_style == QuoteStyle::Always { bits.insert(bits_starting_length, quote_bit.clone()); bits.push(quote_bit); } diff --git a/src/output/file_name.rs b/src/output/file_name.rs index ae232a3d9..e7e7a6465 100644 --- a/src/output/file_name.rs +++ b/src/output/file_name.rs @@ -137,11 +137,11 @@ pub enum Absolute { #[derive(PartialEq, Debug, Copy, Clone)] pub enum QuoteStyle { /// Don't ever quote file names. - NoQuotes, - - /// Use single quotes for file names that contain spaces and no single quotes - /// Use double quotes for file names that contain single quotes. - QuoteSpaces, + Never, + /// Quote file names that contain spaces (default) + Auto, + /// Always quote file names. + Always, } /// A **file name** holds all the information necessary to display the name @@ -269,7 +269,7 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> { if !target.name.is_empty() { let target_options = Options { classify: Classify::JustFilenames, - quote_style: QuoteStyle::QuoteSpaces, + quote_style: QuoteStyle::Auto, show_icons: ShowIcons::Never, embed_hyperlinks: EmbedHyperlinks::Off, is_a_tty: self.options.is_a_tty,