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

This commit is contained in:
PThorpe92 2024-06-17 19:47:57 -04:00 committed by Christina Rust
parent 7e21ed993c
commit 99b2fc214e
8 changed files with 51 additions and 8 deletions

View File

@ -110,6 +110,8 @@ ezas 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

View File

@ -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"

View File

@ -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

View File

@ -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]" \

View File

@ -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
=================

View File

@ -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
@ -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);
}
(false, true) => {
// On pass -'-only-files' flag only
(true, false, true, false) => {
files.retain(File::is_directory);
}
(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());
}
_ => {}
}
}
@ -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` shouldnt filter out the
/// example, running `exa -I='*. tmp' .vimrc` shouldnt filter out the
/// dotfile, because its 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!
@ -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,

View File

@ -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());
@ -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)?,

View File

@ -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" ];
@ -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