Skip to content

Commit

Permalink
feat: Support ln=target in LS_COLORS
Browse files Browse the repository at this point in the history
Setting "ln=target" highlights a link in the same color as the
referred file. Dangling/orphaned links are always colored using the
specified "or=" color.

(Credit to @LarsHaalck who wrote the original ogham/exa#960)
  • Loading branch information
jbrubake committed Jun 7, 2024
1 parent c4007bc commit 4f3c057
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 9 deletions.
13 changes: 12 additions & 1 deletion src/output/file_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,18 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
f if f.is_directory() => self.colours.directory(),
#[cfg(unix)]
f if f.is_executable_file() => self.colours.executable_file(),
f if f.is_link() => self.colours.symlink(),
f if f.is_link() => {
if let crate::theme::LinkStyle::AnsiStyle(x) = self.colours.symlink() { x } else {
if let FileTarget::Ok(file) = self.target.as_ref().unwrap() {
return FileName {
file,
target: None,
..*self
}.style()
}
return Style::default();
}
}
#[cfg(unix)]
f if f.is_pipe() => self.colours.pipe(),
#[cfg(unix)]
Expand Down
10 changes: 8 additions & 2 deletions src/output/render/filetype.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use nu_ansi_term::{AnsiString as ANSIString, Style};

use crate::fs::fields as f;
use crate::theme::LinkStyle;

impl f::Type {
pub fn render<C: Colours>(self, colours: &C) -> ANSIString<'static> {
Expand All @@ -9,7 +10,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"),
Expand All @@ -22,7 +28,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;
Expand Down
2 changes: 1 addition & 1 deletion src/theme/default_theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,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(),
Expand Down
8 changes: 5 additions & 3 deletions src/theme/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::output::file_name::Colours as FileNameColours;
use crate::output::render;

mod ui_styles;
pub use self::ui_styles::LinkStyle;
pub use self::ui_styles::UiStyles;

mod lsc;
Expand Down Expand Up @@ -253,7 +254,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 }
Expand Down Expand Up @@ -493,8 +494,9 @@ mod customs_test {
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_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; });

// EZA_COLORS can affect all those colours too:
test!(exa_di: ls "", exa "di=32" => colours c -> { c.filekinds.directory = Green.normal(); });
Expand All @@ -504,7 +506,7 @@ mod customs_test {
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_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(); });

// EZA_COLORS will even override options from LS_COLORS:
Expand Down
21 changes: 19 additions & 2 deletions src/theme/ui_styles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,24 @@ pub struct UiStyles {
pub broken_path_overlay: Style, // bO
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LinkStyle {
AnsiStyle(Style),
Target,
}

impl Default for LinkStyle {
fn default() -> Self {
LinkStyle::AnsiStyle(Style::default())
}
}

#[rustfmt::skip]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct FileKinds {
pub normal: Style, // fi
pub directory: Style, // di
pub symlink: Style, // ln
pub symlink: LinkStyle, // ln
pub pipe: Style, // pi
pub block_device: Style, // bd
pub char_device: Style, // cd
Expand Down Expand Up @@ -179,7 +191,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:
Expand Down

0 comments on commit 4f3c057

Please sign in to comment.