From 08b6368551bbbc46218ab6d7efea9e79511d9294 Mon Sep 17 00:00:00 2001 From: ariasuni Date: Wed, 7 Jul 2021 00:31:25 +0200 Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20show=20icons=20when=20piped=20(?= =?UTF-8?q?also=20add=20--icons=3D{always,auto,never})?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/options/file_name.rs | 46 +++++++++++++++++++++++++++------------- src/options/flags.rs | 4 +++- src/options/view.rs | 2 +- src/output/file_name.rs | 30 ++++++++++++++++++-------- 4 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/options/file_name.rs b/src/options/file_name.rs index 2c1db1a6..72f85091 100644 --- a/src/options/file_name.rs +++ b/src/options/file_name.rs @@ -2,15 +2,15 @@ use crate::options::{flags, OptionsError, NumberSource}; use crate::options::parser::MatchedFlags; use crate::options::vars::{self, Vars}; -use crate::output::file_name::{Options, Classify, ShowIcons}; +use crate::output::file_name::{Options, Classify, UseIcons}; impl Options { - pub fn deduce(matches: &MatchedFlags<'_>, vars: &V) -> Result { + pub fn deduce(matches: &MatchedFlags<'_>, vars: &V, is_a_tty: bool) -> Result { let classify = Classify::deduce(matches)?; - let show_icons = ShowIcons::deduce(matches, vars)?; + let show_icons = UseIcons::deduce(matches, vars)?; - Ok(Self { classify, show_icons }) + Ok(Self { classify, show_icons, is_a_tty }) } } @@ -23,24 +23,40 @@ impl Classify { } } -impl ShowIcons { +impl UseIcons { pub fn deduce(matches: &MatchedFlags<'_>, vars: &V) -> Result { - if matches.has(&flags::NO_ICONS)? || !matches.has(&flags::ICONS)? { - Ok(Self::Off) + enum AlwaysOrAuto { Always, Automatic } + + let mode_opt = matches.get(&flags::ICONS)?; + if matches.has(&flags::NO_ICONS)? || (!matches.has(&flags::ICONS)? && mode_opt.is_none()) { + return Ok(Self::Never); } - else if let Some(columns) = vars.get(vars::EXA_ICON_SPACING).and_then(|s| s.into_string().ok()) { + + let mode = match mode_opt { + Some(word) => match word.to_str() { + Some("always") => AlwaysOrAuto::Always, + Some("auto") | Some("automatic") => AlwaysOrAuto::Automatic, + Some("never") => return Ok(Self::Never), + _ => return Err(OptionsError::BadArgument(&flags::COLOR, word.into())) + } + None => AlwaysOrAuto::Automatic, + }; + + let width = if let Some(columns) = vars.get(vars::EXA_ICON_SPACING).and_then(|s| s.into_string().ok()) { match columns.parse() { - Ok(width) => { - Ok(Self::On(width)) - } + Ok(width) => width, Err(e) => { let source = NumberSource::Env(vars::EXA_ICON_SPACING); - Err(OptionsError::FailedParse(columns, source, e)) + return Err(OptionsError::FailedParse(columns, source, e)); } } - } - else { - Ok(Self::On(1)) + } else { + 1 + }; + + match mode { + AlwaysOrAuto::Always => Ok(Self::Always(width)), + AlwaysOrAuto::Automatic => Ok(Self::Automatic(width)), } } } diff --git a/src/options/flags.rs b/src/options/flags.rs index 1761d66a..c9816ea5 100644 --- a/src/options/flags.rs +++ b/src/options/flags.rs @@ -41,7 +41,9 @@ pub static BYTES: Arg = Arg { short: Some(b'B'), long: "bytes", takes_ pub static GROUP: Arg = Arg { short: Some(b'g'), long: "group", takes_value: TakesValue::Forbidden }; pub static NUMERIC: Arg = Arg { short: Some(b'n'), long: "numeric", takes_value: TakesValue::Forbidden }; pub static HEADER: Arg = Arg { short: Some(b'h'), long: "header", takes_value: TakesValue::Forbidden }; -pub static ICONS: Arg = Arg { short: None, long: "icons", takes_value: TakesValue::Forbidden }; +// pub static ICONS: Arg = Arg { short: None, long: "icons", takes_value: TakesValue::Forbidden }; +pub static ICONS: Arg = Arg { short: None, long: "icons", takes_value: TakesValue::Optional(Some(ICONS_MODE)) }; +const ICONS_MODE: &[&str] = &["always", "auto", "never"]; pub static INODE: Arg = Arg { short: Some(b'i'), long: "inode", takes_value: TakesValue::Forbidden }; pub static LINKS: Arg = Arg { short: Some(b'H'), long: "links", takes_value: TakesValue::Forbidden }; pub static MODIFIED: Arg = Arg { short: Some(b'm'), long: "modified", takes_value: TakesValue::Forbidden }; diff --git a/src/options/view.rs b/src/options/view.rs index 41816fb1..8153d81e 100644 --- a/src/options/view.rs +++ b/src/options/view.rs @@ -12,7 +12,7 @@ impl View { pub fn deduce(matches: &MatchedFlags<'_>, vars: &V) -> Result { let mode = Mode::deduce(matches, vars)?; let width = TerminalWidth::deduce(vars)?; - let file_style = FileStyle::deduce(matches, vars)?; + let file_style = FileStyle::deduce(matches, vars, width.actual_terminal_width().is_some())?; Ok(Self { mode, width, file_style }) } } diff --git a/src/output/file_name.rs b/src/output/file_name.rs index b6a38c0e..dbf6ad6f 100644 --- a/src/output/file_name.rs +++ b/src/output/file_name.rs @@ -18,7 +18,10 @@ pub struct Options { pub classify: Classify, /// Whether to prepend icon characters before file names. - pub show_icons: ShowIcons, + pub show_icons: UseIcons, + + /// Whether we are in a console or redirecting the output + pub is_a_tty: bool, } impl Options { @@ -74,14 +77,16 @@ impl Default for Classify { /// Whether and how to show icons. #[derive(PartialEq, Debug, Copy, Clone)] -pub enum ShowIcons { +pub enum UseIcons { + /// Display icons next to file names, with the given number of spaces between + /// the icon and the file name, even when output isn’t going to a terminal. + Always(u32), - /// Don’t show icons at all. - Off, + /// Same as Always, but only when output is going to a terminal, not otherwise. + Automatic(u32), - /// Show icons next to file names, with the given number of spaces between - /// the icon and the file name. - On(u32), + /// Never display them, even when output is going to a terminal. + Never, } @@ -125,7 +130,13 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> { pub fn paint(&self) -> TextCellContents { let mut bits = Vec::new(); - if let ShowIcons::On(spaces_count) = self.options.show_icons { + let spaces_count_opt = match self.options.show_icons { + UseIcons::Always(spaces_count) => Some(spaces_count), + UseIcons::Automatic(spaces_count) if self.options.is_a_tty => Some(spaces_count), + _ => None, + }; + + if let Some(spaces_count) = spaces_count_opt { let style = iconify_style(self.style()); let file_icon = icon_for_file(self.file).to_string(); @@ -170,7 +181,8 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> { if ! target.name.is_empty() { let target_options = Options { classify: Classify::JustFilenames, - show_icons: ShowIcons::Off, + show_icons: UseIcons::Never, + is_a_tty: self.options.is_a_tty, }; let target_name = FileName {