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(fs)!: add --only-link option and changed --only-file and --only-d… #518

Closed
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: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ gen_test_dir:

nix build -L ./#trydump

find result/dump -type f \( -name "*.stdout" -o -name "*.stderr" \) -exec sh -c 'base=$(basename {}); if [ -e "tests/gen/${base%.*}.toml" ]; then cp {} tests/gen/; elif [ -e "tests/cmd/${base%.*}.toml" ]; then cp {} tests/cmd/; elif [ -e "tests/ptests/${base%.*}.toml" ]; then cp {} tests/ptests/; fi' \;
find result/dump -type f \( -name "*.stdout" -o -name "*.stderr" \) -exec sh -c 'base=$(basename {}); if [ -e "tests/gen/${base%.*}.toml" ]; then cp {} tests/gen/; elif [ -e "tests/ptests/${base%.*}.toml" ]; then cp {} tests/ptests/; fi' \;


@itest-gen:
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,10 @@ eza’s options are almost, but not quite, entirely unlike `ls`’s. Quick overv
- **-r**, **--reverse**: reverse the sort order
- **-s**, **--sort=(field)**: which field to sort by
- **--group-directories-first**: list directories before other files
- **-D**, **--only-dirs**: list only directories
- **-f**, **--only-files**: list only files
- **-D**, **--only-dirs**: list only directories and links to directories
- **-f**, **--only-files**: list only files and links to files
- **--only-links**: list only symbolic links
MartinFillon marked this conversation as resolved.
Show resolved Hide resolved
- **--no-links**: don't list symbolic links in **--only-files** or **--only-dirs** cases
- **--git-ignore**: ignore files mentioned in `.gitignore`
- **-I**, **--ignore-glob=(globs)**: glob patterns (pipe-separated) of files to ignore

Expand Down
6 changes: 4 additions & 2 deletions completions/fish/eza.fish
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ 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 -s D -l only-dirs -d "List only directories and links to directories"
complete -c eza -s f -l only-files -d "List only files and links to files"
complete -c eza -l only-links -d "List only links"
complete -c eza -l no-links -d "Doesn't list links in --only-files or --only-dirs context"

# Long view options
complete -c eza -s b -l binary -d "List file sizes with binary prefixes"
Expand Down
6 changes: 4 additions & 2 deletions completions/nush/eza.nu
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ export extern "eza" [
--width(-w) # Limits column output of grid, 0 implies auto-width
--reverse(-r) # Reverse the sort order
--sort(-s) # Which field to sort by
--only-dirs(-D) # List only directories
--only-files(-f) # List only files
--only-dirs(-D) # List only directories and links to dirs
--only-files(-f) # List only files and links to files
--only-links # List only links
--no-links # Don't list links in --only-links and --only-files context
--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
6 changes: 4 additions & 2 deletions completions/zsh/_eza
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ __eza() {
{-a,--all}"[Show hidden and 'dot' files. Use this twice to also show the '.' and '..' directories]" \
{-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]" \
{-f,--only-files}"[List only files]" \
{-D,--only-dirs}"[List only directories and links to directories]" \
{-f,--only-files}"[List only files and links to files]" \
--only-links"[List only links]" \
--no-links"[Doesn't list links in --only-files or --only-dirs context]" \
{-L,--level}"+[Limit the depth of recursion]" \
{-w,--width}"+[Limits column output of grid, 0 implies auto-width]" \
{-r,--reverse}"[Reverse the sort order]" \
Expand Down
9 changes: 7 additions & 2 deletions man/eza.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,16 @@ Sort fields starting with a capital letter will sort uppercase before lowercase:
: List directories before other files.

`-D`, `--only-dirs`
: List only directories, not files.
: List only directories and links pointing to directories, not files.

`-f`, `--only-files`
: List only files, not directories.
: List only files and links pointing to files, not directories.

`--only-links`
: List only links

`--only-links`
: Don't show links in `--only-files` or `--only-dirs` cases

LONG VIEW OPTIONS
=================
Expand Down
4 changes: 4 additions & 0 deletions powertest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ commands:
- --only-files
? - -f
- --only-files
? - null
- --only-links
? - null
- --no-links
? # TODO: add more globs
- -I
- --ignore-glob
Expand Down
33 changes: 33 additions & 0 deletions src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,28 @@ impl<'dir> File<'dir> {
false
}

pub fn symlink_target_is_directory(&self) -> bool {
if self.is_link() {
let target = self.link_target();
if let FileTarget::Ok(target) = target {
return target.is_directory();
}
}

false
}

pub fn symlink_target_is_file(&self) -> bool {
if self.is_link() {
let target = self.link_target();
if let FileTarget::Ok(target) = target {
return target.is_file();
}
}

false
}

/// If this file is a directory on the filesystem, then clone its
/// `PathBuf` for use in one of our own `Dir` values, and read a list of
/// its contents.
Expand All @@ -304,6 +326,17 @@ impl<'dir> File<'dir> {
self.metadata.is_file()
}

pub fn points_to_file(&self) -> bool {
if self.is_link() {
let target = self.link_target();
if let FileTarget::Ok(target) = target {
return target.points_to_file();
}
}

false
}

/// Whether this file is both a regular file *and* executable for the
/// current user. An executable file has a different purpose from an
/// executable directory, so they should be highlighted differently.
Expand Down
53 changes: 48 additions & 5 deletions src/fs/filter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Filtering and sorting the list of files before displaying them.

use log::debug;
use std::cmp::Ordering;
use std::iter::FromIterator;
#[cfg(unix)]
Expand All @@ -21,6 +22,12 @@ pub enum FileFilterFlags {

/// Whether to only show files.
OnlyFiles,

/// Whether to only show links.
OnlyLinks,

/// Whether to ignore links.
NoLinks,
}

/// The **file filter** processes a list of files before displaying them to
Expand Down Expand Up @@ -74,21 +81,57 @@ 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::{NoLinks, OnlyDirs, OnlyFiles, OnlyLinks};

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

debug!("Filtering files: {:?}", self.flags);

match (
self.flags.contains(&OnlyDirs),
self.flags.contains(&OnlyFiles),
self.flags.contains(&OnlyLinks),
) {
(true, false) => {
(true, false, false) => {
// On pass -'-only-dirs' flag only
files.retain(File::is_directory);
if self.flags.contains(&NoLinks) {
files.retain(File::is_directory);
} else {
files.retain(File::points_to_directory);
}
}
(true, false, true) => {
// On pass -'-only-dirs' and '-only-links' flags
if !self.flags.contains(&NoLinks) {
files.retain(File::symlink_target_is_directory);
}
}
(false, true) => {
(false, true, false) => {
// On pass -'-only-files' flag only
files.retain(File::is_file);
if self.flags.contains(&NoLinks) {
files.retain(File::is_file);
} else {
files.retain(File::points_to_file);
}
}
(false, true, true) => {
debug!("Filtering files: links and files");
// On pass -'-only-files' and '-only-links' flags
if !self.flags.contains(&NoLinks) {
files.retain(File::symlink_target_is_file);
}
}
(false, false, true) => {
// On pass -'-only-links' flag only
if !self.flags.contains(&NoLinks) {
files.retain(File::is_link);
}
}
(false, false, false) => {
// On pass no flags
if self.flags.contains(&NoLinks) {
files.retain(|f| f.is_file() || f.is_directory());
}
}
_ => {}
}
Expand Down
2 changes: 2 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::ONLY_LINKS)?, FFF::OnlyLinks),
(matches.has(&flags::NO_LINKS)?, FFF::NoLinks),
] {
if *has {
filter_flags.push(flag.clone());
Expand Down
5 changes: 4 additions & 1 deletion src/options/flags.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![cfg_attr(rustfmt, rustfmt_skip)]
use crate::options::parser::{Arg, Args, TakesValue, Values};

// exa options
Expand Down Expand Up @@ -41,6 +42,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 ONLY_LINKS: Arg = Arg { short: None, long: "only-links", takes_value: TakesValue::Forbidden };
pub static NO_LINKS: Arg = Arg { short: None, long: "no-links", takes_value: TakesValue::Forbidden };
const SORTS: Values = &[ "name", "Name", "size", "extension",
"Extension", "modified", "changed", "accessed",
"created", "inode", "type", "none" ];
Expand Down Expand Up @@ -93,7 +96,7 @@ pub static ALL_ARGS: Args = Args(&[
&WIDTH, &NO_QUOTES, &ABSOLUTE,

&ALL, &ALMOST_ALL, &LIST_DIRS, &LEVEL, &REVERSE, &SORT, &DIRS_FIRST,
&IGNORE_GLOB, &GIT_IGNORE, &ONLY_DIRS, &ONLY_FILES,
&IGNORE_GLOB, &GIT_IGNORE, &ONLY_DIRS, &ONLY_FILES, &ONLY_LINKS, &NO_LINKS,

&BINARY, &BYTES, &GROUP, &NUMERIC, &HEADER, &ICONS, &INODE, &LINKS, &MODIFIED, &CHANGED,
&BLOCKSIZE, &TOTAL_SIZE, &TIME, &ACCESSED, &CREATED, &TIME_STYLE, &HYPERLINK, &MOUNTS,
Expand Down
6 changes: 4 additions & 2 deletions src/options/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ FILTERING AND SORTING OPTIONS
-r, --reverse reverse the sort order
-s, --sort SORT_FIELD which field to sort by
--group-directories-first list directories before other files
-D, --only-dirs list only directories
-f, --only-files list only files
-D, --only-dirs list only directories and links to directories
-f, --only-files list only files and links to files
--only-links list only symbolic links
--no-links don't list symbolic links in --only-files or --only-dirs cases
-I, --ignore-glob GLOBS glob patterns (pipe-separated) of files to ignore";

static GIT_FILTER_HELP: &str = " \
Expand Down
2 changes: 2 additions & 0 deletions tests/cmd/only-dirs_no_links_unix.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
exa
vagrant
2 changes: 2 additions & 0 deletions tests/cmd/only-dirs_no_links_unix.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin.name = "eza"
args = "tests/itest --only-dirs --no-links"
File renamed without changes.
3 changes: 3 additions & 0 deletions tests/cmd/only-dirs_unix.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dir-symlink -> vagrant/debug
exa
vagrant
2 changes: 2 additions & 0 deletions tests/cmd/only-dirs_unix.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin.name = "eza"
args = "tests/itest --only-dirs"
Empty file.
1 change: 1 addition & 0 deletions tests/cmd/only-files_no_links_unix.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a
2 changes: 2 additions & 0 deletions tests/cmd/only-files_no_links_unix.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin.name = "eza"
args = "tests/itest/vagrant/debug --only-files --no-links"
Empty file.
Empty file.
2 changes: 2 additions & 0 deletions tests/cmd/only-files_unix.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin.name = "eza"
args = "tests/itest --only-files"
Empty file.
Empty file.
2 changes: 2 additions & 0 deletions tests/cmd/only-links_and_files_unix.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin.name = "eza"
args = "tests/itest/vagrant/debug --only-files"
Empty file.
2 changes: 2 additions & 0 deletions tests/cmd/only-links_unix.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
symlink -> a
symlink-broken -> ./b
2 changes: 2 additions & 0 deletions tests/cmd/only-links_unix.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin.name = "eza"
args = "tests/itest/vagrant/debug --only-links"
50 changes: 0 additions & 50 deletions tests/gen/absolute_recurse_unix.stdout

This file was deleted.

22 changes: 0 additions & 22 deletions tests/gen/absolute_unix.stdout

This file was deleted.

1 change: 1 addition & 0 deletions tests/gen/only_dir_recursive_long_unix.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -3054,6 +3054,7 @@ tests/test_dir/specials:

tests/test_dir/symlinks:
dir
symlink3 -> dir

tests/test_dir/symlinks/dir:

Expand Down
1 change: 1 addition & 0 deletions tests/gen/only_dir_recursive_unix.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -3054,6 +3054,7 @@ tests/test_dir/specials:

tests/test_dir/symlinks:
dir
symlink3 -> dir

tests/test_dir/symlinks/dir:

Expand Down
6 changes: 4 additions & 2 deletions tests/ptests/ptest_2439b7d68089135b.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ FILTERING AND SORTING OPTIONS
-r, --reverse reverse the sort order
-s, --sort SORT_FIELD which field to sort by
--group-directories-first list directories before other files
-D, --only-dirs list only directories
-f, --only-files list only files
-D, --only-dirs list only directories and links to directories
-f, --only-files list only files and links to files
--only-links list only symbolic links
--no-links don't list symbolic links in --only-files or --only-dirs cases
-I, --ignore-glob GLOBS glob patterns (pipe-separated) of files to ignore
--git-ignore ignore files mentioned in '.gitignore'
Valid sort fields: name, Name, extension, Extension, size, type,
Expand Down