diff --git a/src/output/file_name.rs b/src/output/file_name.rs index b6a38c0e..c292ef28 100644 --- a/src/output/file_name.rs +++ b/src/output/file_name.rs @@ -302,7 +302,21 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> { match self.file { f if f.is_directory() => self.colours.directory(), f if f.is_executable_file() => self.colours.executable_file(), - f if f.is_link() => self.colours.symlink(), + f if f.is_link() => { + match self.colours.symlink() { + crate::theme::LinkStyle::AnsiStyle(x) => x, + _ => { + if let FileTarget::Ok(file) = self.target.as_ref().unwrap() { + return FileName { + file: &file, + target: None, + ..*self + }.style() + } + return Style::default(); + } + } + } f if f.is_pipe() => self.colours.pipe(), f if f.is_block_device() => self.colours.block_device(), f if f.is_char_device() => self.colours.char_device(), diff --git a/src/output/render/filetype.rs b/src/output/render/filetype.rs index c3bc1c81..5b6d1b97 100644 --- a/src/output/render/filetype.rs +++ b/src/output/render/filetype.rs @@ -1,7 +1,6 @@ use ansi_term::{ANSIString, Style}; -use crate::fs::fields as f; - +use crate::{fs::fields as f, theme::LinkStyle}; impl f::Type { pub fn render(self, colours: &C) -> ANSIString<'static> { @@ -9,7 +8,12 @@ impl f::Type { Self::File => colours.normal().paint("."), Self::Directory => colours.directory().paint("d"), Self::Pipe => colours.pipe().paint("|"), - Self::Link => colours.symlink().paint("l"), + Self::Link => { + match colours.symlink() { + LinkStyle::AnsiStyle(s) => s.paint("l"), + LinkStyle::Target => colours.normal().paint("l") + } + } Self::BlockDevice => colours.block_device().paint("b"), Self::CharDevice => colours.char_device().paint("c"), Self::Socket => colours.socket().paint("s"), @@ -23,7 +27,7 @@ pub trait Colours { fn normal(&self) -> Style; fn directory(&self) -> Style; fn pipe(&self) -> Style; - fn symlink(&self) -> Style; + fn symlink(&self) -> LinkStyle; fn block_device(&self) -> Style; fn char_device(&self) -> Style; fn socket(&self) -> Style; diff --git a/src/theme/default_theme.rs b/src/theme/default_theme.rs index b4269b73..46c5c5ee 100644 --- a/src/theme/default_theme.rs +++ b/src/theme/default_theme.rs @@ -13,7 +13,7 @@ impl UiStyles { filekinds: FileKinds { normal: Style::default(), directory: Blue.bold(), - symlink: Cyan.normal(), + symlink: LinkStyle::AnsiStyle(Cyan.normal()), pipe: Yellow.normal(), block_device: Yellow.bold(), char_device: Yellow.bold(), diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 255f054d..89080ef5 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -7,6 +7,7 @@ use crate::output::render; mod ui_styles; pub use self::ui_styles::UiStyles; pub use self::ui_styles::Size as SizeColours; +pub use self::ui_styles::LinkStyle as LinkStyle; mod lsc; pub use self::lsc::LSColors; @@ -210,7 +211,7 @@ impl render::FiletypeColours for Theme { fn normal(&self) -> Style { self.ui.filekinds.normal } fn directory(&self) -> Style { self.ui.filekinds.directory } fn pipe(&self) -> Style { self.ui.filekinds.pipe } - fn symlink(&self) -> Style { self.ui.filekinds.symlink } + fn symlink(&self) -> LinkStyle { self.ui.filekinds.symlink } fn block_device(&self) -> Style { self.ui.filekinds.block_device } fn char_device(&self) -> Style { self.ui.filekinds.char_device } fn socket(&self) -> Style { self.ui.filekinds.socket } @@ -403,26 +404,27 @@ mod customs_test { // LS_COLORS can affect all of these colours: - test!(ls_di: ls "di=31", exa "" => colours c -> { c.filekinds.directory = Red.normal(); }); - test!(ls_ex: ls "ex=32", exa "" => colours c -> { c.filekinds.executable = Green.normal(); }); - test!(ls_fi: ls "fi=33", exa "" => colours c -> { c.filekinds.normal = Yellow.normal(); }); - test!(ls_pi: ls "pi=34", exa "" => colours c -> { c.filekinds.pipe = Blue.normal(); }); - test!(ls_so: ls "so=35", exa "" => colours c -> { c.filekinds.socket = Purple.normal(); }); - test!(ls_bd: ls "bd=36", exa "" => colours c -> { c.filekinds.block_device = Cyan.normal(); }); - test!(ls_cd: ls "cd=35", exa "" => colours c -> { c.filekinds.char_device = Purple.normal(); }); - test!(ls_ln: ls "ln=34", exa "" => colours c -> { c.filekinds.symlink = Blue.normal(); }); - test!(ls_or: ls "or=33", exa "" => colours c -> { c.broken_symlink = Yellow.normal(); }); + test!(ls_di: ls "di=31", exa "" => colours c -> { c.filekinds.directory = Red.normal(); }); + test!(ls_ex: ls "ex=32", exa "" => colours c -> { c.filekinds.executable = Green.normal(); }); + test!(ls_fi: ls "fi=33", exa "" => colours c -> { c.filekinds.normal = Yellow.normal(); }); + test!(ls_pi: ls "pi=34", exa "" => colours c -> { c.filekinds.pipe = Blue.normal(); }); + test!(ls_so: ls "so=35", exa "" => colours c -> { c.filekinds.socket = Purple.normal(); }); + test!(ls_bd: ls "bd=36", exa "" => colours c -> { c.filekinds.block_device = Cyan.normal(); }); + test!(ls_cd: ls "cd=35", exa "" => colours c -> { c.filekinds.char_device = Purple.normal(); }); + test!(ls_ln: ls "ln=34", exa "" => colours c -> { c.filekinds.symlink = LinkStyle::AnsiStyle(Blue.normal()); }); + test!(ls_or: ls "or=33", exa "" => colours c -> { c.broken_symlink = Yellow.normal(); }); + test!(ls_ln_target: ls "ln=target", exa "" => colours c -> { c.filekinds.symlink = LinkStyle::Target; }); // EXA_COLORS can affect all those colours too: - test!(exa_di: ls "", exa "di=32" => colours c -> { c.filekinds.directory = Green.normal(); }); - test!(exa_ex: ls "", exa "ex=33" => colours c -> { c.filekinds.executable = Yellow.normal(); }); - test!(exa_fi: ls "", exa "fi=34" => colours c -> { c.filekinds.normal = Blue.normal(); }); - test!(exa_pi: ls "", exa "pi=35" => colours c -> { c.filekinds.pipe = Purple.normal(); }); - test!(exa_so: ls "", exa "so=36" => colours c -> { c.filekinds.socket = Cyan.normal(); }); - test!(exa_bd: ls "", exa "bd=35" => colours c -> { c.filekinds.block_device = Purple.normal(); }); - test!(exa_cd: ls "", exa "cd=34" => colours c -> { c.filekinds.char_device = Blue.normal(); }); - test!(exa_ln: ls "", exa "ln=33" => colours c -> { c.filekinds.symlink = Yellow.normal(); }); - test!(exa_or: ls "", exa "or=32" => colours c -> { c.broken_symlink = Green.normal(); }); + test!(exa_di: ls "", exa "di=32" => colours c -> { c.filekinds.directory = Green.normal(); }); + test!(exa_ex: ls "", exa "ex=33" => colours c -> { c.filekinds.executable = Yellow.normal(); }); + test!(exa_fi: ls "", exa "fi=34" => colours c -> { c.filekinds.normal = Blue.normal(); }); + test!(exa_pi: ls "", exa "pi=35" => colours c -> { c.filekinds.pipe = Purple.normal(); }); + test!(exa_so: ls "", exa "so=36" => colours c -> { c.filekinds.socket = Cyan.normal(); }); + test!(exa_bd: ls "", exa "bd=35" => colours c -> { c.filekinds.block_device = Purple.normal(); }); + test!(exa_cd: ls "", exa "cd=34" => colours c -> { c.filekinds.char_device = Blue.normal(); }); + test!(exa_ln: ls "", exa "ln=33" => colours c -> { c.filekinds.symlink = LinkStyle::AnsiStyle(Yellow.normal()); }); + test!(exa_or: ls "", exa "or=32" => colours c -> { c.broken_symlink = Green.normal(); }); // EXA_COLORS will even override options from LS_COLORS: test!(ls_exa_di: ls "di=31", exa "di=32" => colours c -> { c.filekinds.directory = Green.normal(); }); diff --git a/src/theme/ui_styles.rs b/src/theme/ui_styles.rs index f92c5442..bf60004c 100644 --- a/src/theme/ui_styles.rs +++ b/src/theme/ui_styles.rs @@ -27,11 +27,22 @@ pub struct UiStyles { pub broken_path_overlay: Style, } + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum LinkStyle { + AnsiStyle(Style), + Target +} + +impl Default for LinkStyle { + fn default() -> Self { LinkStyle::AnsiStyle(Style::default()) } +} + #[derive(Clone, Copy, Debug, Default, PartialEq)] pub struct FileKinds { pub normal: Style, pub directory: Style, - pub symlink: Style, + pub symlink: LinkStyle, pub pipe: Style, pub block_device: Style, pub char_device: Style, @@ -125,7 +136,12 @@ impl UiStyles { "so" => self.filekinds.socket = pair.to_style(), // SOCK "bd" => self.filekinds.block_device = pair.to_style(), // BLK "cd" => self.filekinds.char_device = pair.to_style(), // CHR - "ln" => self.filekinds.symlink = pair.to_style(), // LINK + "ln" => { + self.filekinds.symlink = match pair.value { + "target" => LinkStyle::Target, + _ => LinkStyle::AnsiStyle(pair.to_style()) + } + } "or" => self.broken_symlink = pair.to_style(), // ORPHAN _ => return false, // Codes we don’t do anything with: