Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add --no-|show-symlinks flags for filtering output #1028

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ eza’s options are almost, but not quite, entirely unlike `ls`’s. Quick overv
- **--group-directories-first**: list directories before other files
- **-D**, **--only-dirs**: list only directories
- **-f**, **--only-files**: list only files
- **--no-symlinks**: don't show symbolic links
- **--show-symlinks**: explicitly show links (with `--only-dirs`, `--only-files`, to show symlinks that match the filter)
- **--git-ignore**: ignore files mentioned in `.gitignore`
- **-I**, **--ignore-glob=(globs)**: glob patterns (pipe-separated) of files to ignore

Expand Down
2 changes: 2 additions & 0 deletions completions/fish/eza.fish
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ complete -c eza -s s -l sort -d "Which field to sort by" -x -a "
complete -c eza -s I -l ignore-glob -d "Ignore files that match these glob patterns" -r
complete -c eza -s D -l only-dirs -d "List only directories"
complete -c eza -s f -l only-files -d "List only files"
complete -c eza -l show-symlinks -d "Explicitly show symbolic links (For use with --only-dirs | --only-files)"
complete -c eza -l no-symlinks -d "Do not show symbolic links"

# Long view options
complete -c eza -s b -l binary -d "List file sizes with binary prefixes"
Expand Down
2 changes: 2 additions & 0 deletions completions/nush/eza.nu
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export extern "eza" [
--sort(-s) # Which field to sort by
--only-dirs(-D) # List only directories
--only-files(-f) # List only files
--show-symlinks # Explicitly show symbolic links (for use with --only-dirs | --only-files)
--no-symlinks # Do not show symbolic links
--binary(-b) # List file sizes with binary prefixes
--bytes(-B) # List file sizes in bytes, without any prefixes
--group(-g) # List each file's group
Expand Down
2 changes: 2 additions & 0 deletions completions/zsh/_eza
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ __eza() {
{-A,--almost-all}"[Equivalent to --all; included for compatibility with \'ls -A\']" \
{-d,--list-dirs}"[List directories like regular files]" \
{-D,--only-dirs}"[List only directories]" \
--no-symlinks"[Do not show symbolic links]"
--show-symlinks"[Explictly show symbolic links: for use with '--only-dirs'| '--only-files']"
{-f,--only-files}"[List only files]" \
{-L,--level}"+[Limit the depth of recursion]" \
{-w,--width}"+[Limits column output of grid, 0 implies auto-width]" \
Expand Down
5 changes: 5 additions & 0 deletions man/eza.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ Sort fields starting with a capital letter will sort uppercase before lowercase:
`-f`, `--only-files`
: List only files, not directories.

`--show-symlinks`
: Explicitly show symbolic links (when used with `--only-files` | `--only-dirs`)

`--no-symlinks`
: Do not show symbolic links

LONG VIEW OPTIONS
=================
Expand Down
38 changes: 31 additions & 7 deletions src/fs/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ pub enum FileFilterFlags {

/// Whether to only show files.
OnlyFiles,

/// Whether to ignore symlinks
NoSymlinks,

/// Whether to explicitly show symlinks
ShowSymlinks,
}

/// The **file filter** processes a list of files before displaying them to
Expand Down Expand Up @@ -68,28 +74,47 @@ pub struct FileFilter {

/// Whether to ignore Git-ignored patterns.
pub git_ignore: GitIgnore,

/// Whether to ignore symlinks
pub no_symlinks: bool,

/// Whether to explicitly show symlinks
pub show_symlinks: bool,
}

impl FileFilter {
/// Remove every file in the given vector that does *not* pass the
/// filter predicate for files found inside a directory.
pub fn filter_child_files(&self, files: &mut Vec<File<'_>>) {
use FileFilterFlags::{OnlyDirs, OnlyFiles};
use FileFilterFlags::{NoSymlinks, OnlyDirs, OnlyFiles, ShowSymlinks};

files.retain(|f| !self.ignore_patterns.is_ignored(&f.name));

match (
self.flags.contains(&OnlyDirs),
self.flags.contains(&OnlyFiles),
self.flags.contains(&NoSymlinks),
self.flags.contains(&ShowSymlinks),
) {
(true, false) => {
// On pass -'-only-dirs' flag only
(true, false, false, false) => {
// On pass '--only-dirs' flag only
files.retain(File::is_directory);
}
(true, false, true, false) => {
files.retain(File::is_directory);
}
(false, true) => {
// On pass -'-only-files' flag only
(true, false, false, true) => {
files.retain(|f| f.is_directory() || f.points_to_directory());
}
(false, true, false, false) => {
files.retain(File::is_file);
}
(false, true, false, true) => {
files.retain(|f| f.is_file() || f.is_link() && !f.points_to_directory());
}
(false, false, true, false) => {
files.retain(|f| !f.is_link());
}
_ => {}
}
}
Expand All @@ -99,7 +124,7 @@ impl FileFilter {
///
/// The rules are different for these types of files than the other
/// type because the ignore rules can be used with globbing. For
/// example, running `exa -I='*.tmp' .vimrc` shouldn’t filter out the
/// example, running `exa -I='*. tmp' .vimrc` shouldn’t filter out the
/// dotfile, because it’s been directly specified. But running
/// `exa -I='*.ogg' music/*` should filter out the ogg files obtained
/// from the glob, even though the globbing is done by the shell!
Expand Down Expand Up @@ -249,7 +274,6 @@ impl SortField {
Self::ChangedDate => a.changed_time().cmp(&b.changed_time()),
Self::CreatedDate => a.created_time().cmp(&b.created_time()),
Self::ModifiedAge => b.modified_time().cmp(&a.modified_time()), // flip b and a

Self::FileType => match a.type_char().cmp(&b.type_char()) { // todo: this recomputes
Ordering::Equal => natord::compare(&a.name, &b.name),
order => order,
Expand Down
4 changes: 4 additions & 0 deletions src/options/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ impl FileFilter {
(matches.has(&flags::REVERSE)?, FFF::Reverse),
(matches.has(&flags::ONLY_DIRS)?, FFF::OnlyDirs),
(matches.has(&flags::ONLY_FILES)?, FFF::OnlyFiles),
(matches.has(&flags::NO_SYMLINKS)?, FFF::NoSymlinks),
(matches.has(&flags::SHOW_SYMLINKS)?, FFF::ShowSymlinks),
] {
if *has {
filter_flags.push(flag.clone());
Expand All @@ -27,6 +29,8 @@ impl FileFilter {
#[rustfmt::skip]
return Ok(Self {
list_dirs_first: matches.has(&flags::DIRS_FIRST)?,
no_symlinks: filter_flags.contains(&FFF::NoSymlinks),
show_symlinks: filter_flags.contains(&FFF::ShowSymlinks),
flags: filter_flags,
sort_field: SortField::deduce(matches)?,
dot_filter: DotFilter::deduce(matches)?,
Expand Down
4 changes: 3 additions & 1 deletion src/options/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ pub static GIT_IGNORE: Arg = Arg { short: None, long: "git-ignore", t
pub static DIRS_FIRST: Arg = Arg { short: None, long: "group-directories-first", takes_value: TakesValue::Forbidden };
pub static ONLY_DIRS: Arg = Arg { short: Some(b'D'), long: "only-dirs", takes_value: TakesValue::Forbidden };
pub static ONLY_FILES: Arg = Arg { short: Some(b'f'), long: "only-files", takes_value: TakesValue::Forbidden };
pub static NO_SYMLINKS: Arg = Arg { short: None, long: "no-symlinks", takes_value: TakesValue::Forbidden };
pub static SHOW_SYMLINKS: Arg = Arg { short: None, long: "show-symlinks", takes_value: TakesValue::Forbidden };
const SORTS: Values = &[ "name", "Name", "size", "extension",
"Extension", "modified", "changed", "accessed",
"created", "inode", "type", "none" ];
Expand Down Expand Up @@ -97,7 +99,7 @@ pub static ALL_ARGS: Args = Args(&[

&BINARY, &BYTES, &GROUP, &NUMERIC, &HEADER, &ICONS, &INODE, &LINKS, &MODIFIED, &CHANGED,
&BLOCKSIZE, &TOTAL_SIZE, &TIME, &ACCESSED, &CREATED, &TIME_STYLE, &HYPERLINK, &MOUNTS,
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME, &SMART_GROUP,
&NO_PERMISSIONS, &NO_FILESIZE, &NO_USER, &NO_TIME, &SMART_GROUP, &NO_SYMLINKS, &SHOW_SYMLINKS,

&GIT, &NO_GIT, &GIT_REPOS, &GIT_REPOS_NO_STAT,
&EXTENDED, &OCTAL, &SECURITY_CONTEXT, &STDIN, &FILE_FLAGS
Expand Down