diff --git a/README.md b/README.md index e288822a3..012bfe047 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ eza’s options are almost, but not quite, entirely unlike `ls`’s. Quick overv - **--colo[u]r-scale=(field)**: highlight levels of `field` distinctly(all, age, size) - **--color-scale-mode=(mode)**: use gradient or fixed colors in --color-scale. valid options are `fixed` or `gradient` - **--icons=(when)**: when to display icons (always, auto, never) -- **--hyperlink**: display entries as hyperlinks +- **--hyperlink=(when)**: display entries as hyperlinks (always, auto, never) - **--absolute=(mode)**: display entries with their absolute path (on, follow, off) - **-w**, **--width=(columns)**: set screen width in columns diff --git a/completions/bash/eza b/completions/bash/eza index dbecd8a91..f1033d10e 100644 --- a/completions/bash/eza +++ b/completions/bash/eza @@ -18,6 +18,11 @@ _eza() { return ;; + --hyperlink) + mapfile -t COMPREPLY < <(compgen -W 'always automatic auto never' -- "$cur") + return + ;; + -L|--level) mapfile -t COMPREPLY < <(compgen -W '{0..9}' -- "$cur") return diff --git a/completions/fish/eza.fish b/completions/fish/eza.fish index 91334b583..dc8ed4cd8 100644 --- a/completions/fish/eza.fish +++ b/completions/fish/eza.fish @@ -37,7 +37,12 @@ complete -c eza -l icons -d "When to display icons" -x -a " never\t'Never display icons' " complete -c eza -l no-quotes -d "Don't quote file names with spaces" -complete -c eza -l hyperlink -d "Display entries as hyperlinks" +complete -c eza -l hyperlink -d "Display entries as hyperlinks" -x -a " + always\t'Always display hyperlinks' + auto\t'Display hyperlinks if standard output is a terminal' + automatic\t'Display hyperlinks if standard output is a terminal' + never\t'Never display hyperlinks' +" complete -c eza -l absolute -d "Display entries with their absolute path" -x -a " on\t'Show absolute path for listed entries' follow\t'Show absolute path with followed symlinks' diff --git a/completions/zsh/_eza b/completions/zsh/_eza index 67cf0284d..dbf46f551 100644 --- a/completions/zsh/_eza +++ b/completions/zsh/_eza @@ -25,7 +25,7 @@ __eza() { --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]" \ - --hyperlink"[Display entries as hyperlinks]" \ + --hyperlink="[Display entries as hyperlinks]:(when):(always auto automatic never)" \ --absolute"[Display entries with their absolute path]:(mode):(on follow off)" \ --group-directories-first"[Sort directories before other files]" \ --git-ignore"[Ignore files mentioned in '.gitignore']" \ diff --git a/man/eza.1.md b/man/eza.1.md index 1917ab23f..c0965bfd4 100644 --- a/man/eza.1.md +++ b/man/eza.1.md @@ -110,9 +110,14 @@ The default value is ‘`automatic`’. `--no-quotes` : Don't quote file names with spaces. -`--hyperlink` +`--hyperlink=WHEN` : Display entries as hyperlinks +Valid settings are ‘`always`’, ‘`automatic`’ (or ‘`auto`’ for short), and ‘`never`’. +The default value is ‘`automatic`’. + +The default behavior (‘`automatic`’ or ‘`auto`’) is to add hyperlink control chars to the output only when the standard output is connected to a real terminal. If the output of `eza` is redirected to a file or piped into another program, hyperlink will not be used. Setting this option to ‘`always`’ causes `eza` to always output hyperlinks, while ‘`never`’ disables the use of hyperlinks. + `-w`, `--width=COLS` : Set screen width in columns. diff --git a/powertest.yaml b/powertest.yaml index 8889db07d..4fc6e7d03 100644 --- a/powertest.yaml +++ b/powertest.yaml @@ -67,6 +67,10 @@ commands: - --no-quotes ? - null - --hyperlink + : values: + - auto + - always + - never ? - null - --absolute : values: diff --git a/src/options/file_name.rs b/src/options/file_name.rs index e3cdd69e8..80e557d11 100644 --- a/src/options/file_name.rs +++ b/src/options/file_name.rs @@ -108,13 +108,19 @@ impl QuoteStyle { } impl EmbedHyperlinks { - fn deduce(matches: &MatchedFlags<'_>) -> Result { - let flagged = matches.has(&flags::HYPERLINK)?; + pub fn deduce(matches: &MatchedFlags<'_>) -> Result { + let Some(word) = matches.get(&flags::HYPERLINK)? else { + return Ok(Self::Automatic); + }; - if flagged { - Ok(Self::On) + if word == "always" { + Ok(Self::Always) + } else if word == "auto" || word == "automatic" { + Ok(Self::Automatic) + } else if word == "never" { + Ok(Self::Never) } else { - Ok(Self::Off) + Err(OptionsError::BadArgument(&flags::HYPERLINK, word.into())) } } } diff --git a/src/options/flags.rs b/src/options/flags.rs index a707157f0..88a3c20fa 100644 --- a/src/options/flags.rs +++ b/src/options/flags.rs @@ -65,7 +65,7 @@ pub static TIME: Arg = Arg { short: Some(b't'), long: "time", take pub static ACCESSED: Arg = Arg { short: Some(b'u'), long: "accessed", takes_value: TakesValue::Forbidden }; pub static CREATED: Arg = Arg { short: Some(b'U'), long: "created", takes_value: TakesValue::Forbidden }; pub static TIME_STYLE: Arg = Arg { short: None, long: "time-style", takes_value: TakesValue::Necessary(Some(TIME_STYLES)) }; -pub static HYPERLINK: Arg = Arg { short: None, long: "hyperlink", takes_value: TakesValue::Forbidden }; +pub static HYPERLINK: Arg = Arg { short: None, long: "hyperlink", takes_value: TakesValue::Optional(Some(WHEN), "auto") }; 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"]; diff --git a/src/options/help.rs b/src/options/help.rs index 0e456d070..60a7e29b4 100644 --- a/src/options/help.rs +++ b/src/options/help.rs @@ -21,11 +21,11 @@ DISPLAY OPTIONS -X, --dereference dereference symbolic links when displaying information -F, --classify=WHEN display type indicator by file names (always, auto, never) --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 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 - --hyperlink display entries as hyperlinks + --hyperlink=WHEN display entries as hyperlinks (always, auto, never) --absolute display entries with their absolute path (on, follow, off) -w, --width COLS set screen width in columns diff --git a/src/output/file_name.rs b/src/output/file_name.rs index ba8947bc0..c4b276609 100644 --- a/src/output/file_name.rs +++ b/src/output/file_name.rs @@ -55,6 +55,14 @@ impl Options { mount_style: MountStyle::JustDirectoryNames, } } + + pub fn do_embed_hyperlinks(&self) -> bool { + match self.embed_hyperlinks { + EmbedHyperlinks::Always => true, + EmbedHyperlinks::Never => false, + EmbedHyperlinks::Automatic => self.is_a_tty, + } + } } /// When displaying a file name, there needs to be some way to handle broken @@ -115,8 +123,14 @@ pub enum ShowIcons { /// Whether to embed hyperlinks. #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum EmbedHyperlinks { - Off, - On, + /// Embed links even when output isn’t going to a terminal. + Always, + + /// Embed links when output is going to a terminal, but not otherwise. + Automatic, + + /// Never embed links, even when output is going to a terminal. + Never, } /// Whether to show absolute paths @@ -265,7 +279,7 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> { classify: Classify::JustFilenames, quote_style: QuoteStyle::QuoteSpaces, show_icons: ShowIcons::Never, - embed_hyperlinks: EmbedHyperlinks::Off, + embed_hyperlinks: EmbedHyperlinks::Never, is_a_tty: self.options.is_a_tty, absolute: Absolute::Off, }; @@ -411,7 +425,7 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> { let mut bits = Vec::new(); let mut display_hyperlink = false; - if self.options.embed_hyperlinks == EmbedHyperlinks::On { + if self.options.do_embed_hyperlinks() { if let Some(abs_path) = self .file .absolute_path()