From e1fee4be7dc45cbf0e548b9cfb9e09cdd155936a Mon Sep 17 00:00:00 2001 From: Alex-1611 Date: Sun, 10 Nov 2024 17:28:14 +0200 Subject: [PATCH] implemented -p flag --- src/app.rs | 4 ++ src/config_file.rs | 8 ++++ src/display.rs | 1 + src/flags.rs | 4 ++ src/flags/slash_indicator.rs | 78 ++++++++++++++++++++++++++++++++++++ src/meta/mod.rs | 4 ++ src/meta/slash_indicator.rs | 68 +++++++++++++++++++++++++++++++ 7 files changed, 167 insertions(+) create mode 100644 src/flags/slash_indicator.rs create mode 100644 src/meta/slash_indicator.rs diff --git a/src/app.rs b/src/app.rs index fa329592e..0c9c1b0fb 100644 --- a/src/app.rs +++ b/src/app.rs @@ -32,6 +32,10 @@ pub struct Cli { #[arg(short = 'F', long = "classify")] pub indicators: bool, + /// Append "/" at the end of the directories names + #[arg(short = 'p', long = "slash-indicator")] + pub slash_indicator: bool, + /// Display extended file metadata as a table #[arg(short, long)] pub long: bool, diff --git a/src/config_file.rs b/src/config_file.rs index e91b5884c..49e94fbcd 100644 --- a/src/config_file.rs +++ b/src/config_file.rs @@ -32,6 +32,7 @@ pub struct Config { pub icons: Option, pub ignore_globs: Option>, pub indicators: Option, + pub slash_indicator: Option, pub layout: Option, pub recursion: Option, pub size: Option, @@ -117,6 +118,7 @@ impl Config { icons: None, ignore_globs: None, indicators: None, + slash_indicator: None, layout: None, recursion: None, size: None, @@ -288,6 +290,11 @@ icons: # Possible values: false, true indicators: false +# == Slash Indicator == +# Whether to add indicator "/" to directories. +# Possible values: false, true +slash_indicator: false + # == Layout == # Which layout to use. "oneline" might be a bit confusing here and should be # called "one-per-line". It might be changed in the future. @@ -406,6 +413,7 @@ mod tests { }), ignore_globs: None, indicators: Some(false), + slash_indicator: Some(false), layout: Some(Layout::Grid), recursion: Some(config_file::Recursion { enabled: Some(false), diff --git a/src/display.rs b/src/display.rs index ca037f0b7..48d34bac3 100644 --- a/src/display.rs +++ b/src/display.rs @@ -408,6 +408,7 @@ fn get_output( flags.literal.0, ), meta.indicator.render(flags), + meta.slash_indicator.render(flags), ]); if !(flags.no_symlink.0 || flags.dereference.0 || flags.layout == Layout::Grid) { block_vec.push(meta.symlink.render(colors, flags)) diff --git a/src/flags.rs b/src/flags.rs index 52e7a49a0..e2f1fea6d 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -8,6 +8,7 @@ pub mod hyperlink; pub mod icons; pub mod ignore_globs; pub mod indicators; +pub mod slash_indicator; pub mod layout; pub mod literal; pub mod permission; @@ -32,6 +33,7 @@ pub use icons::IconTheme; pub use icons::Icons; pub use ignore_globs::IgnoreGlobs; pub use indicators::Indicators; +pub use slash_indicator::SlashIndicator; pub use layout::Layout; pub use literal::Literal; pub use permission::PermissionFlag; @@ -63,6 +65,7 @@ pub struct Flags { pub dereference: Dereference, pub display: Display, pub display_indicators: Indicators, + pub slash_indicator: SlashIndicator, pub icons: Icons, pub ignore_globs: IgnoreGlobs, pub layout: Layout, @@ -97,6 +100,7 @@ impl Flags { size: SizeFlag::configure_from(cli, config), permission: PermissionFlag::configure_from(cli, config), display_indicators: Indicators::configure_from(cli, config), + slash_indicator: SlashIndicator::configure_from(cli, config), icons: Icons::configure_from(cli, config), ignore_globs: IgnoreGlobs::configure_from(cli, config)?, no_symlink: NoSymlink::configure_from(cli, config), diff --git a/src/flags/slash_indicator.rs b/src/flags/slash_indicator.rs new file mode 100644 index 000000000..c41cc171c --- /dev/null +++ b/src/flags/slash_indicator.rs @@ -0,0 +1,78 @@ +//! This module defines the [SlashIndicator] flag. To set it up from [Cli], a [Config] and its +//! [Default] value, use the [configure_from](Configurable::configure_from) method. + +use super::Configurable; + +use crate::app::Cli; +use crate::config_file::Config; + +/// The flag showing whether to print slash indicator for directories. +#[derive(Clone, Debug, Copy, PartialEq, Eq, Default)] +pub struct SlashIndicator(pub bool); + +impl Configurable for SlashIndicator { + /// Get a potential `SlashIndicator` value from [Cli]. + /// + /// If the "SlashIndicator" argument is passed, this returns an `SlashIndicator` with value `true` in a + /// [Some]. Otherwise this returns [None]. + fn from_cli(cli: &Cli) -> Option { + if cli.slash_indicator { + Some(Self(true)) + } else { + None + } + } + + /// Get a potential `SlashIndicator` value from a [Config]. + /// + /// If the `Config::slash_indicator` has value, + /// this returns its value as the value of the `SlashIndicator`, in a [Some]. + /// Otherwise this returns [None]. + fn from_config(config: &Config) -> Option { + config.slash_indicator.as_ref().map(|ind| Self(*ind)) + } +} + +#[cfg(test)] +mod test { + use clap::Parser; + + use super::SlashIndicator; + + use crate::app::Cli; + use crate::config_file::Config; + use crate::flags::Configurable; + + #[test] + fn test_from_cli_none() { + let argv = ["lsd"]; + let cli = Cli::try_parse_from(argv).unwrap(); + assert_eq!(None, SlashIndicator::from_cli(&cli)); + } + + #[test] + fn test_from_cli_true() { + let argv = ["lsd", "--slash-indicator"]; + let cli = Cli::try_parse_from(argv).unwrap(); + assert_eq!(Some(SlashIndicator(true)), SlashIndicator::from_cli(&cli)); + } + + #[test] + fn test_from_config_none() { + assert_eq!(None, SlashIndicator::from_config(&Config::with_none())); + } + + #[test] + fn test_from_config_true() { + let mut c = Config::with_none(); + c.slash_indicator = Some(true); + assert_eq!(Some(SlashIndicator(true)), SlashIndicator::from_config(&c)); + } + + #[test] + fn test_from_config_false() { + let mut c = Config::with_none(); + c.slash_indicator = Some(false); + assert_eq!(Some(SlashIndicator(false)), SlashIndicator::from_config(&c)); + } +} diff --git a/src/meta/mod.rs b/src/meta/mod.rs index e8384fd19..8aaa6a9e4 100644 --- a/src/meta/mod.rs +++ b/src/meta/mod.rs @@ -3,6 +3,7 @@ mod date; mod filetype; pub mod git_file_status; mod indicator; +mod slash_indicator; mod inode; mod links; mod locale; @@ -23,6 +24,7 @@ pub use self::date::Date; pub use self::filetype::FileType; pub use self::git_file_status::GitFileStatus; pub use self::indicator::Indicator; +pub use self::slash_indicator::SlashIndicator; pub use self::inode::INode; pub use self::links::Links; pub use self::name::Name; @@ -52,6 +54,7 @@ pub struct Meta { pub size: Option, pub symlink: SymLink, pub indicator: Indicator, + pub slash_indicator: SlashIndicator, pub inode: Option, pub links: Option, pub content: Option>, @@ -356,6 +359,7 @@ impl Meta { size, date, indicator: Indicator::from(file_type), + slash_indicator: SlashIndicator::from(file_type), owner: owner.unwrap_or_default(), permissions_or_attributes: permissions_or_attributes.unwrap_or_default(), name, diff --git a/src/meta/slash_indicator.rs b/src/meta/slash_indicator.rs new file mode 100644 index 000000000..e72e0b89d --- /dev/null +++ b/src/meta/slash_indicator.rs @@ -0,0 +1,68 @@ +use crate::color::{ColoredString, Colors}; +use crate::flags::Flags; +use crate::meta::FileType; + +#[derive(Clone, Debug)] +pub struct SlashIndicator(&'static str); + +impl From for SlashIndicator { + fn from(file_type: FileType) -> Self { + let res = match file_type { + FileType::Directory { .. } => "/", + _ => "", + }; + + SlashIndicator(res) + } +} + +impl SlashIndicator { + pub fn render(&self, flags: &Flags) -> ColoredString { + if flags.slash_indicator.0 && !flags.display_indicators.0{ + ColoredString::new(Colors::default_style(), self.0.to_string()) + } else { + ColoredString::new(Colors::default_style(), "".into()) + } + } +} + +#[cfg(test)] +mod test { + use super::SlashIndicator; + use crate::flags::{Flags, SlashIndicator as SlashIndicatorFlag}; + use crate::meta::FileType; + + #[test] + fn test_directory_slash_indicator() { + let flags = Flags { + slash_indicator: SlashIndicatorFlag(true), + ..Default::default() + }; + + let file_type = SlashIndicator::from(FileType::Directory { uid: false }); + + assert_eq!("/", file_type.render(&flags).to_string()); + } + + #[test] + fn test_not_represented_indicators() { + let flags = Flags { + slash_indicator: SlashIndicatorFlag(true), + ..Default::default() + }; + + // Test multiple non-directory file types + let file_types = vec![ + FileType::File { exec: false, uid: false }, + FileType::Pipe, + FileType::Socket, + FileType::SymLink { is_dir: false }, + ]; + + for file_type in file_types { + let indicator = SlashIndicator::from(file_type); + assert_eq!("", indicator.render(&flags).to_string()); + } + } + +}