mirror of
https://github.com/eza-community/eza
synced 2024-09-30 05:06:30 +00:00
Merge branch 'main' into cafk-powertest
This commit is contained in:
commit
df714e52c9
4
.github/workflows/flake.yml
vendored
4
.github/workflows/flake.yml
vendored
|
@ -13,5 +13,5 @@ jobs:
|
|||
uses: DeterminateSystems/flake-checker-action@v5 # This action
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@v4
|
||||
- name: Build default package
|
||||
run: nix build
|
||||
- name: Nix Flake Check
|
||||
run: nix flake check --all-systems
|
||||
|
|
8
.github/workflows/unit-tests.yml
vendored
8
.github/workflows/unit-tests.yml
vendored
|
@ -28,7 +28,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
rust: [1.65.0, stable, beta, nightly]
|
||||
rust: [1.70.0, stable, beta, nightly]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
|
@ -40,7 +40,11 @@ jobs:
|
|||
toolchain: ${{ matrix.rust }}
|
||||
|
||||
- name: Install cargo-hack
|
||||
run: cargo install cargo-hack@0.5.27
|
||||
uses: nick-fields/retry@v2
|
||||
with:
|
||||
timeout_minutes: 5
|
||||
max_attemps: 5
|
||||
command: cargo install cargo-hack
|
||||
|
||||
- name: Run unit tests
|
||||
run: cargo hack test
|
||||
|
|
15
.github/workflows/winget.yml
vendored
Normal file
15
.github/workflows/winget.yml
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
name: Publish to Winget
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: vedantmgoyal2009/winget-releaser@v2
|
||||
with:
|
||||
identifier: eza-community.eza
|
||||
installers-regex: '-pc-windows-gnu\.zip$'
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -28,3 +28,6 @@ stage
|
|||
# VHS testing stuff
|
||||
out.gif
|
||||
tests/tmp
|
||||
|
||||
## Dynamically generated
|
||||
tests/test_dir
|
||||
|
|
143
CHANGELOG.md
143
CHANGELOG.md
|
@ -2,6 +2,146 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.12.0] - 2023-09-14
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Expand `--all` help
|
||||
- RUSTSEC-2020-0071
|
||||
- Generalize gitignore to ignore all eza deb packages
|
||||
- Canonicalize errors when the destination of a symbolic link is bad
|
||||
- Handle other canonicalize errors in hyperlinks and git
|
||||
- Fix windows build when canonicalize returns an error
|
||||
- Change trycmd config to use test/itest folder for testing
|
||||
- Revert to old apt install command suggestion and add hint
|
||||
- Remove stray backslashes
|
||||
- Is_some_and is an unstable Rust feature until 1.70
|
||||
- Revert "Support for Windows Hidden Files"
|
||||
- Shellcheck warnings
|
||||
- Revert "Support for Windows Hidden Files"
|
||||
- Shellcheck warnings
|
||||
- Exit 13 on os error 13
|
||||
- Rewrite comment
|
||||
- Improve trace strings
|
||||
- Tracing typo
|
||||
|
||||
### Documentation
|
||||
|
||||
- Expand `--all` documentation
|
||||
- Add pthorpe92 gist
|
||||
- Remove xtests section from readme
|
||||
- Add deprecation warning to xtests/readme
|
||||
- Add deprecation warning to just xtest commands
|
||||
- Add deprecation warning to vagrantfile
|
||||
- Add MacPorts install info
|
||||
- Add gentoo
|
||||
- Fix gentoo install
|
||||
- Add docs for --git-repos & --git-repos-no-status
|
||||
- Fix gpg armor flag for deb release in readme
|
||||
- Add better explanation of git repos + no status
|
||||
- Add scoop install info
|
||||
- Remove color specifications. change unknown git repo status to `~`
|
||||
- Fix missing color specification from man page
|
||||
|
||||
### Features
|
||||
|
||||
- Add audit workflow
|
||||
- Add trycmd as dev-dependency
|
||||
- Add minimal trycmd binary
|
||||
- Add a few trycmd tests as example
|
||||
- Document and change output for --git-repos
|
||||
- Add apt installation workflow
|
||||
- Adds filtering on Windows hidden files
|
||||
- Adds filtering on Windows hidden files
|
||||
- Adds filtering on Windows hidden files
|
||||
- Added shellcheck to treefmt
|
||||
- Adds filtering on Windows hidden files
|
||||
- Add PERMISSION_DENIED exit code
|
||||
|
||||
### Miscellaneous Tasks
|
||||
|
||||
- Bump chrono from 0.4.27 to 0.4.30
|
||||
- Removal of xtests
|
||||
- Removal of vagrant
|
||||
- Remove deprecated devtools
|
||||
- Run spellcheck
|
||||
|
||||
### Refactor
|
||||
|
||||
- Over-engineer deb-package.sh
|
||||
- Hide xtests folder
|
||||
- Split trycmd into tests for all, unix and windows
|
||||
- Limit unit-tests run on workflow change to unit-tests itself
|
||||
- Moved generateTest.sh to devtools/
|
||||
- Renamed the file
|
||||
- Add tracing to various code parts
|
||||
- Make std::process::exit global
|
||||
|
||||
### Revert
|
||||
|
||||
- "Support for Windows Hidden Files"
|
||||
|
||||
### Styling
|
||||
|
||||
- Remove TODO message on the absolute_path property
|
||||
- Fix shellcheck issues in deb-package.sh
|
||||
- Fix shellcheck issues in deb-package.sh
|
||||
- Fix shellcheck issues in deb-package.sh
|
||||
|
||||
### Testing
|
||||
|
||||
- Remove vhs from flake
|
||||
- Remove vhs-runner files
|
||||
- Dump trycmd from nix sandbox
|
||||
- Fix name of trydump
|
||||
- Add trycmd
|
||||
- Add nix feature
|
||||
- Add example long tests for sandbox
|
||||
- Set itests files to unix epoch
|
||||
- Set itest files to unix epoch
|
||||
- Refactor setting unix epoch
|
||||
- Auto discard old definitions
|
||||
- Fix test reference
|
||||
- Add long_all_nix.toml
|
||||
- Add long_blocksize_nix.toml
|
||||
- Add long_extended_nix.toml
|
||||
- Add long_git_nix.toml
|
||||
- Add long_git_repos_nix.toml
|
||||
- Add long_git_repos_no_status_nix.toml
|
||||
- Add long_grid_nix.toml
|
||||
- Add long_header_nix.toml
|
||||
- Add long_icons_nix.toml
|
||||
- Add long_octal_nix.toml
|
||||
- Add long_time_style_relative_nix.toml
|
||||
- Freeze nix tests
|
||||
- Fix trydump when no files to delete
|
||||
- Adding more content to test
|
||||
- Modified unix and all tests
|
||||
- Regenerate nix tests
|
||||
- Convert windows tests with new itest dir
|
||||
- Fixed windows tests being wrong
|
||||
- Added a test generator
|
||||
- Add more unix_tests
|
||||
- Fixed unix tests to remove any distro specific
|
||||
- Removed git test breaking on nix
|
||||
|
||||
### Build
|
||||
|
||||
- Add compression, checksum gen for bin
|
||||
- Update flake.lock, cargo.lock
|
||||
- Add deny.toml
|
||||
- Remove org warnings
|
||||
- Remove itest
|
||||
- Update flake.lock
|
||||
- Add itest, idump
|
||||
- Make trycmd part of checks
|
||||
|
||||
### Ci
|
||||
|
||||
- Don't use nix feature on ci
|
||||
- Enforce conventional commits
|
||||
- Enforce conventional commits
|
||||
|
||||
## [0.11.1] - 2023-09-11
|
||||
|
||||
### Bug Fixes
|
||||
|
@ -37,6 +177,8 @@ All notable changes to this project will be documented in this file.
|
|||
### Miscellaneous Tasks
|
||||
|
||||
- Bump actions/checkout from 3 to 4
|
||||
- Bump uzers to v0.11.3
|
||||
- Release 0.11.1
|
||||
|
||||
### Testing
|
||||
|
||||
|
@ -174,6 +316,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Cafkafk -> eza-community
|
||||
- Add gpg public key for the deb repository
|
||||
- Add section about debian and ubuntu installation
|
||||
- Add guidelines for commit messages
|
||||
|
||||
### Features
|
||||
|
||||
|
|
244
Cargo.lock
generated
244
Cargo.lock
generated
|
@ -2,6 +2,15 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
|
@ -17,6 +26,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "ansiterm"
|
||||
version = "0.12.2"
|
||||
|
@ -104,6 +119,12 @@ version = "1.4.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
|
@ -131,6 +152,58 @@ dependencies = [
|
|||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"ciborium-ll",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-io"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-ll"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
|
@ -152,6 +225,42 @@ version = "0.8.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
|
||||
dependencies = [
|
||||
"anes",
|
||||
"cast",
|
||||
"ciborium",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"is-terminal",
|
||||
"itertools",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.8"
|
||||
|
@ -247,10 +356,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "eza"
|
||||
version = "0.11.1"
|
||||
version = "0.12.0"
|
||||
dependencies = [
|
||||
"ansiterm",
|
||||
"chrono",
|
||||
"criterion",
|
||||
"gethostname",
|
||||
"git2",
|
||||
"glob",
|
||||
|
@ -332,6 +442,12 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.0"
|
||||
|
@ -415,6 +531,32 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix 0.38.13",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.22"
|
||||
|
@ -561,6 +703,12 @@ version = "1.18.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-src"
|
||||
version = "111.26.0+1.1.1u"
|
||||
|
@ -657,6 +805,34 @@ version = "0.3.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.66"
|
||||
|
@ -736,6 +912,35 @@ dependencies = [
|
|||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.23"
|
||||
|
@ -763,6 +968,12 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
|
@ -804,6 +1015,17 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.3"
|
||||
|
@ -931,6 +1153,16 @@ version = "0.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5082dc942361cdfb74eab98bf995762d6015e5bb3a20bf7c5c71213778b4fcb4"
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.2.0"
|
||||
|
@ -1127,6 +1359,16 @@ version = "0.2.87"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
18
Cargo.toml
18
Cargo.toml
|
@ -4,13 +4,13 @@ description = "A modern replacement for ls"
|
|||
authors = ["Christina Sørensen <christina@cafkafk.com>"]
|
||||
categories = ["command-line-utilities"]
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
exclude = ["/devtools/*", "/Justfile", "/Vagrantfile", "/screenshots.png"]
|
||||
rust-version = "1.70.0"
|
||||
exclude = ["/devtools/*", "/Justfile", "/Vagrantfile", "/screenshots.png", "/tests"]
|
||||
readme = "README.md"
|
||||
homepage = "https://github.com/eza-community/eza"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/eza-community/eza"
|
||||
version = "0.11.1"
|
||||
version = "0.12.0"
|
||||
|
||||
|
||||
[package.metadata.deb]
|
||||
|
@ -25,6 +25,7 @@ assets = [
|
|||
[ "target/release/eza", "/usr/bin/eza", "0755" ],
|
||||
[ "target/release/../man/eza.1", "/usr/share/man/man1/eza.1", "0644" ],
|
||||
[ "target/release/../man/eza_colors.5", "/usr/share/man/man5/eza_colors.5", "0644" ],
|
||||
[ "target/release/../man/eza_colors-explanation.5", "/usr/share/man/man5/eza_colors-explanation.5", "0644" ],
|
||||
[ "completions/bash/eza", "/usr/share/bash-completion/completions/eza", "0644" ],
|
||||
[ "completions/zsh/_eza", "/usr/share/zsh/site-functions/_eza", "0644" ],
|
||||
[ "completions/fish/eza.fish", "/usr/share/fish/vendor_completions.d/eza.fish", "0644" ],
|
||||
|
@ -71,11 +72,12 @@ uzers = "0.11.3"
|
|||
chrono = { version = "0.4.30", default-features = false, features = ["clock"] }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.5.1", features = ["html_reports"] }
|
||||
trycmd = "0.14"
|
||||
|
||||
[features]
|
||||
default = [ "git" ]
|
||||
git = [ "git2" ]
|
||||
default = ["git"]
|
||||
git = ["git2"]
|
||||
vendored-openssl = ["git2/vendored-openssl"]
|
||||
vendored-libgit2 = ["git2/vendored-libgit2"]
|
||||
# Should only be used inside of flake.nix
|
||||
|
@ -93,4 +95,8 @@ debug = false
|
|||
[profile.release]
|
||||
lto = true
|
||||
strip = true
|
||||
opt-level = "s"
|
||||
opt-level = 3
|
||||
|
||||
[[bench]]
|
||||
name = "my_benchmark"
|
||||
harness = false
|
||||
|
|
135
Justfile
135
Justfile
|
@ -109,41 +109,134 @@ all-release: build-release test-release
|
|||
sleep 10
|
||||
gh pr create --draft --title "chore: release $(grep '^version' Cargo.toml | head -n 1 | grep -E '([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+)?' -o)" --body "This PR was auto-generated by our lovely just file" --reviewer cafkafk
|
||||
|
||||
# If you're not cafkafk and she isn't dead, you probably don't need to run
|
||||
# this!
|
||||
#----------------#
|
||||
# binaries #
|
||||
#----------------#
|
||||
|
||||
tar BINARY TARGET:
|
||||
tar czvf ./target/"bin-$(convco version)"/{{BINARY}}_{{TARGET}}.tar.gz -C ./target/{{TARGET}}/release/ ./{{BINARY}}
|
||||
|
||||
zip BINARY TARGET:
|
||||
zip -j ./target/"bin-$(convco version)"/{{BINARY}}_{{TARGET}}.zip ./target/{{TARGET}}/release/{{BINARY}}
|
||||
|
||||
binary BINARY TARGET:
|
||||
rustup target add {{TARGET}}
|
||||
cross build --release --target {{TARGET}}
|
||||
just tar {{BINARY}} {{TARGET}}
|
||||
just zip {{BINARY}} {{TARGET}}
|
||||
|
||||
checksum:
|
||||
echo "# Checksums"
|
||||
echo "## sha256sum"
|
||||
echo '```'
|
||||
sha256sum ./target/"bin-$(convco version)"/*
|
||||
echo '```'
|
||||
echo "## md5sum"
|
||||
echo '```'
|
||||
md5sum ./target/"bin-$(convco version)"/*
|
||||
echo '```'
|
||||
|
||||
alias c := cross
|
||||
|
||||
# Generate release binaries for EZA
|
||||
#
|
||||
# usage: cross
|
||||
@cross:
|
||||
rustup toolchain install stable
|
||||
# Setup Output Directory
|
||||
mkdir -p ./target/"bin-$(convco version)"
|
||||
|
||||
# Build
|
||||
# Install Toolchains/Targets
|
||||
rustup toolchain install stable
|
||||
|
||||
## Linux
|
||||
cross build --target x86_64-unknown-linux-gnu --release
|
||||
tar czvf ./target/"bin-$(convco version)"/eza_x86_64-unknown-linux-gnu.tar.gz -C ./target/x86_64-unknown-linux-gnu/release/ ./eza
|
||||
cross build --target aarch64-unknown-linux-gnu --release
|
||||
tar czvf ./target/"bin-$(convco version)"/eza_aarch64-unknown-linux-gnu.tar.gz -C ./target/aarch64-unknown-linux-gnu/release/ ./eza
|
||||
cross build --target arm-unknown-linux-gnueabihf --release
|
||||
tar czvf ./target/"bin-$(convco version)"/arm-unknown-linux-gnueabihf.tar.gz -C ./target/arm-unknown-linux-gnueabihf/release/ ./eza
|
||||
### x86
|
||||
just binary eza x86_64-unknown-linux-gnu
|
||||
just binary eza x86_64-unknown-linux-musl
|
||||
|
||||
### aarch
|
||||
just binary eza aarch64-unknown-linux-gnu
|
||||
|
||||
### arm
|
||||
just binary eza arm-unknown-linux-gnueabihf
|
||||
|
||||
## MacOS
|
||||
# TODO: just binary eza x86_64-apple-darwin
|
||||
|
||||
## Windows
|
||||
cross build --target x86_64-pc-windows-gnu --release
|
||||
zip -j ./target/"bin-$(convco version)"/x86_64-pc-windows-gnu.zip ./target/x86_64-pc-windows-gnu/release/eza.exe
|
||||
### x86
|
||||
just binary eza.exe x86_64-pc-windows-gnu
|
||||
# TODO: just binary eza.exe x86_64-pc-windows-gnullvm
|
||||
# TODO: just binary eza.exe x86_64-pc-windows-msvc
|
||||
|
||||
# Generate Checksums
|
||||
echo "# Checksums"
|
||||
echo "## sha256sum"
|
||||
echo "```"
|
||||
sha256sum ./target/"bin-$(convco version)"/*
|
||||
echo "```"
|
||||
echo "## md5sum"
|
||||
echo "```"
|
||||
md5sum ./target/"bin-$(convco version)"/*
|
||||
echo "```"
|
||||
just checksum
|
||||
|
||||
#---------------------#
|
||||
# Integration testing #
|
||||
#---------------------#
|
||||
|
||||
alias gen := gen_test_dir
|
||||
|
||||
test_dir := "tests/test_dir"
|
||||
|
||||
gen_test_dir:
|
||||
#!/usr/bin/env bash
|
||||
rm {{test_dir}} -r;
|
||||
mkdir -p {{test_dir}}
|
||||
cd {{test_dir}};
|
||||
|
||||
# BEGIN grid
|
||||
mkdir -p grid
|
||||
cd grid
|
||||
|
||||
mkdir $(seq -w 001 1000);
|
||||
seq 0001 1000 | split -l 1 -a 3 -d - file_
|
||||
|
||||
# Set time to unix epoch
|
||||
touch --date=@0 *;
|
||||
|
||||
cd ..
|
||||
|
||||
# END grid
|
||||
|
||||
# BEGIN git
|
||||
|
||||
mkdir -p git
|
||||
cd git
|
||||
|
||||
mkdir $(seq -w 001 10);
|
||||
for f in ./*
|
||||
do
|
||||
cd $f
|
||||
git init
|
||||
seq 01 10 | split -l 1 -a 3 -d - file_
|
||||
cd ..
|
||||
done
|
||||
|
||||
cd ..
|
||||
|
||||
# END git
|
||||
|
||||
# BEGIN test_root
|
||||
|
||||
sudo mkdir root
|
||||
sudo chmod 777 root
|
||||
sudo mkdir root/empty
|
||||
|
||||
# END test_root
|
||||
|
||||
# BEGIN mknod
|
||||
|
||||
mkdir -p specials
|
||||
|
||||
sudo mknod specials/block-device b 3 60
|
||||
sudo mknod specials/char-device c 14 40
|
||||
sudo mknod specials/named-pipe p
|
||||
|
||||
# END test_root
|
||||
|
||||
eza -l --grid;
|
||||
|
||||
# Runs integration tests in nix sandbox
|
||||
#
|
||||
# Required nix, likely won't work on windows.
|
||||
|
|
139
README.md
139
README.md
|
@ -8,7 +8,8 @@ eza is a modern, maintained replacement for ls, built on [exa](https://github.co
|
|||
|
||||
[![Built with Nix](https://img.shields.io/badge/Built_With-Nix-5277C3.svg?logo=nixos&labelColor=73C3D5)](https://nixos.org)
|
||||
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)
|
||||
<a href="https://matrix.to/#/#eza:gitter.im"><img alt="Gitter" src="https://img.shields.io/gitter/room/eza-community/eza?logo=element&link=https%3A%2F%2Fapp.gitter.im%2F%23%2Froom%2F%23eza%3Agitter.im&link=Gitter%20matrix%20room%20for%20Eza"></a>
|
||||
|
||||
<a href="https://matrix.to/#/#eza-community:gitter.im"><img alt="Gitter" src="https://img.shields.io/gitter/room/eza-community/eza?logo=element&link=https%3A%2F%2Fapp.gitter.im%2F%23%2Froom%2F%23eza%3Agitter.im&link=Gitter%20matrix%20room%20for%20Eza" width=200></a>
|
||||
|
||||
[![Unit tests](https://github.com/eza-community/eza/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/eza-community/eza/actions/workflows/unit-tests.yml)
|
||||
![Crates.io](https://img.shields.io/crates/v/eza?link=https%3A%2F%2Fcrates.io%2Fcrates%2Feza)
|
||||
|
@ -27,20 +28,20 @@ And it’s **small**, **fast**, and just **one single binary**.
|
|||
|
||||
By deliberately making some decisions differently, eza attempts to be a more featureful, more user-friendly version of `ls`.
|
||||
|
||||
|
||||
---
|
||||
|
||||
**eza** features not in exa (non-exhaustive):
|
||||
|
||||
- Fixes [“The Grid Bug”](https://github.com/eza-community/eza/issues/66#issuecomment-1656758327) introduced in exa 2021.
|
||||
- Hyperlink support.
|
||||
- Mount point details.
|
||||
- Selinux context output.
|
||||
- Git repo status output.
|
||||
- Human readable relative dates.
|
||||
- Several security fixes.
|
||||
- Many smaller bug fixes/changes!
|
||||
- Support for `bright` terminal colours.
|
||||
- Fixes [“The Grid Bug”](https://github.com/eza-community/eza/issues/66#issuecomment-1656758327) introduced in exa 2021.
|
||||
- Hyperlink support.
|
||||
- Mount point details.
|
||||
- Selinux context output.
|
||||
- Git repo status output.
|
||||
- Human readable relative dates.
|
||||
- Several security fixes.
|
||||
- Support for `bright` terminal colours.
|
||||
- Many smaller bug fixes/changes!
|
||||
|
||||
---
|
||||
|
||||
<a id="try-it">
|
||||
|
@ -53,7 +54,7 @@ If you already have Nix setup with flake support, you can try out eza with the `
|
|||
|
||||
nix run github:eza-community/eza
|
||||
|
||||
Nix will build eza and run it.
|
||||
Nix will build eza and run it.
|
||||
|
||||
If you want to pass arguments this way, use e.g. `nix run github:eza-community/eza -- -ol`.
|
||||
|
||||
|
@ -98,21 +99,24 @@ pacman -S eza
|
|||
Eza is available from [deb.gierens.de](http://deb.gierens.de). The GPG public
|
||||
key is in this repo under [deb.asc](/deb.asc).
|
||||
|
||||
To install eza from this repo use:
|
||||
First make sure you have the `gpg` command, and otherwise install it via:
|
||||
|
||||
```bash
|
||||
wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | sudo tee /etc/apt/trusted.gpg.d/gierens.asc
|
||||
echo "deb http://deb.gierens.de stable main" | sudo tee /etc/apt/sources.list.d/gierens.list
|
||||
sudo apt update
|
||||
sudo apt install -y gpg
|
||||
```
|
||||
|
||||
Then install eza via:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/apt/keyrings
|
||||
wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg
|
||||
echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://deb.gierens.de stable main" | sudo tee /etc/apt/sources.list.d/gierens.list
|
||||
sudo chmod 644 /etc/apt/keyrings/gierens.gpg /etc/apt/sources.list.d/gierens.list
|
||||
sudo apt update
|
||||
sudo apt install -y eza
|
||||
```
|
||||
|
||||
**Note:** on some systems like Docker containers apt might require the key
|
||||
to be in dearmored format, then use this command instead:
|
||||
```bash
|
||||
wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/gierens.asc
|
||||
```
|
||||
before proceeding with the others from above.
|
||||
|
||||
### Nix (Linux, MacOS)
|
||||
|
||||
[![nixpkgs unstable package](https://repology.org/badge/version-for-repo/nix_unstable/eza.svg)](https://repology.org/project/eza/versions)
|
||||
|
@ -154,28 +158,24 @@ The preceding repository also contains the Bash, Fish, and Zsh completions.
|
|||
|
||||
### Fedora
|
||||
|
||||
You can install Eza from [openSUSE:Factory/eza](https://build.opensuse.org/package/show/openSUSE:Factory/eza):
|
||||
Fedora support is in the works.
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=2238264
|
||||
|
||||
### Void Linux
|
||||
|
||||
[![Void Linux package](https://repology.org/badge/version-for-repo/void_x86_64/eza.svg)](https://repology.org/project/eza/versions)
|
||||
|
||||
Eza is available as the [eza](https://github.com/void-linux/void-packages/tree/master/srcpkgs/eza) package in the official Void Linux repository.
|
||||
|
||||
```bash
|
||||
tee /etc/yum.repos.d/opensuse-tumbleweed-oss.repo <<EOL
|
||||
[opensuse-tumbleweed-oss]
|
||||
name=OpenSUSE Tumbleweed OSS
|
||||
baseurl=https://download.opensuse.org/tumbleweed/repo/oss/
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
gpgkey=https://download.opensuse.org/tumbleweed/repo/oss/repodata/repomd.xml.key
|
||||
EOL
|
||||
|
||||
dnf install eza
|
||||
sudo xbps-install eza
|
||||
```
|
||||
|
||||
The preceding repository also contains the Bash, Fish, and Zsh completions.
|
||||
|
||||
### Brew (MacOS)
|
||||
|
||||
[![Homebrew package](https://repology.org/badge/version-for-repo/homebrew/eza.svg)](https://repology.org/project/eza/versions)
|
||||
|
||||
|
||||
Eza is available from [Homebrew](https://formulae.brew.sh/formula/eza#default).
|
||||
|
||||
To install eza, run:
|
||||
|
@ -196,11 +196,23 @@ To install eza, run:
|
|||
sudo port install eza
|
||||
```
|
||||
|
||||
### Winget (Windows)
|
||||
|
||||
[![Windows package](https://repology.org/badge/version-for-repo/winget/eza.svg)](https://repology.org/project/eza/versions)
|
||||
|
||||
|
||||
Eza is available on Winget.
|
||||
|
||||
To install eza, run:
|
||||
|
||||
```shell
|
||||
winget install eza-community.eza
|
||||
```
|
||||
|
||||
### Scoop (Windows)
|
||||
|
||||
[![Windows package](https://repology.org/badge/version-for-repo/scoop/eza.svg)](https://repology.org/project/eza/versions)
|
||||
|
||||
|
||||
Eza is available from [Scoop](https://scoop.sh/#/apps?q=eza&id=a52070d25f94bbcc884f80bef53eb47ed1268198).
|
||||
|
||||
To install eza, run:
|
||||
|
@ -209,7 +221,35 @@ To install eza, run:
|
|||
scoop install eza
|
||||
```
|
||||
|
||||
### Completions
|
||||
|
||||
#### For zsh:
|
||||
|
||||
> **Note**
|
||||
> Change `~/.zshrc` to your preferred zsh config file.
|
||||
|
||||
##### Clone the repository:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/eza-community/eza.git
|
||||
```
|
||||
|
||||
##### Add the completion path to your zsh configuration:
|
||||
|
||||
Replace `<path_to_eza>` with the actual path where you cloned the `eza` repository.
|
||||
|
||||
```sh
|
||||
echo 'export FPATH="<path_to_eza>/completions/zsh:$FPATH"' >> ~/.zshrc
|
||||
```
|
||||
|
||||
##### Reload your zsh configuration:
|
||||
|
||||
```sh
|
||||
source ~/.zshrc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Click sections to expand.
|
||||
|
||||
<a id="options">
|
||||
|
@ -294,13 +334,10 @@ Some of the options accept parameters:
|
|||
<summary> Development </summary>
|
||||
<h1>Development
|
||||
|
||||
<a href="https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html">
|
||||
<img src="https://img.shields.io/badge/rustc-1.63.0+-lightgray.svg" alt="Rust 1.63.0+" />
|
||||
<a href="https://blog.rust-lang.org/2023/06/01/Rust-1.70.0.html">
|
||||
<img src="https://img.shields.io/badge/rustc-1.70.0+-lightgray.svg" alt="Rust 1.70.0" />
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/eza-community/eza/blob/master/LICENCE">
|
||||
<img src="https://img.shields.io/badge/licence-MIT-green" alt="MIT Licence" />
|
||||
</a>
|
||||
</h1></a>
|
||||
|
||||
eza is written in [Rust](https://www.rust-lang.org/).
|
||||
|
@ -313,22 +350,22 @@ Once Rust is installed, you can compile eza with Cargo:
|
|||
cargo test
|
||||
|
||||
- The [just](https://github.com/casey/just) command runner can be used to run some helpful development commands, in a manner similar to `make`.
|
||||
Run `just --list` to get an overview of what’s available.
|
||||
Run `just --list` to get an overview of what’s available.
|
||||
|
||||
- If you are compiling a copy for yourself, be sure to run `cargo build --release` or `just build-release` to benefit from release-mode optimisations.
|
||||
Copy the resulting binary, which will be in the `target/release` directory, into a folder in your `$PATH`.
|
||||
`/usr/local/bin` is usually a good choice.
|
||||
Copy the resulting binary, which will be in the `target/release` directory, into a folder in your `$PATH`.
|
||||
`/usr/local/bin` is usually a good choice.
|
||||
|
||||
- To compile and install the manual pages, you will need [pandoc](https://pandoc.org/).
|
||||
The `just man` command will compile the Markdown into manual pages, which it will place in the `target/man` directory.
|
||||
To use them, copy them into a directory that `man` will read.
|
||||
`/usr/local/share/man` is usually a good choice.
|
||||
The `just man` command will compile the Markdown into manual pages, which it will place in the `target/man` directory.
|
||||
To use them, copy them into a directory that `man` will read.
|
||||
`/usr/local/share/man` is usually a good choice.
|
||||
|
||||
- eza depends on [libgit2](https://github.com/rust-lang/git2-rs) for certain features.
|
||||
If you’re unable to compile libgit2, you can opt out of Git support by running `cargo build --no-default-features`.
|
||||
If you’re unable to compile libgit2, you can opt out of Git support by running `cargo build --no-default-features`.
|
||||
|
||||
- If you intend to compile for musl, you will need to use the flag `vendored-openssl` if you want to get the Git feature working.
|
||||
The full command is `cargo build --release --target=x86_64-unknown-linux-musl --features vendored-openssl,git`.
|
||||
The full command is `cargo build --release --target=x86_64-unknown-linux-musl --features vendored-openssl,git`.
|
||||
|
||||
### Developing on Nix (experimental) ❄️
|
||||
|
||||
|
@ -337,12 +374,12 @@ If you have a working Nix installation with flake support, you can use nix to ma
|
|||
nix develop
|
||||
|
||||
The Nix Flake has a few features:
|
||||
|
||||
- Run `nix flake check` to run `treefmt` on the repo.
|
||||
- Run `nix build` and manually test `./results/bin/eza -- <arguments>` for easy debugging.
|
||||
- Run `nix build .#test` to run `cargo test` via the flake.
|
||||
- Run `nix build .#clippy` to lint with clippy (still work in progress).
|
||||
|
||||
|
||||
## Star History
|
||||
|
||||
[![Star History Chart](https://api.star-history.com/svg?repos=eza-community/eza&type=Date)](https://star-history.com/#eza-community/eza&Date)
|
||||
|
|
8
benches/my_benchmark.rs
Normal file
8
benches/my_benchmark.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
c.bench_function("logger", |b| b.iter(|| eza::logger::configure(black_box(std::env::var_os(eza::options::vars::EXA_DEBUG)))));
|
||||
}
|
||||
|
||||
criterion_group!(benches, criterion_benchmark);
|
||||
criterion_main!(benches);
|
|
@ -1,5 +1,5 @@
|
|||
_eza()
|
||||
{
|
||||
# shellcheck shell=bash
|
||||
_eza() {
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
|
@ -9,27 +9,27 @@ _eza()
|
|||
;;
|
||||
|
||||
--colour)
|
||||
COMPREPLY=( $( compgen -W 'always auto never' -- "$cur" ) )
|
||||
mapfile -t COMPREPLY < <(compgen -W 'always auto never' -- "$cur")
|
||||
return
|
||||
;;
|
||||
|
||||
-L|--level)
|
||||
COMPREPLY=( $( compgen -W '{0..9}' -- "$cur" ) )
|
||||
mapfile -t COMPREPLY < <(compgen -W '{0..9}' -- "$cur")
|
||||
return
|
||||
;;
|
||||
|
||||
-s|--sort)
|
||||
COMPREPLY=( $( compgen -W 'name filename Name Filename size filesize extension Extension date time modified changed accessed created type inode oldest newest age none --' -- "$cur" ) )
|
||||
mapfile -t COMPREPLY < <(compgen -W 'name filename Name Filename size filesize extension Extension date time modified changed accessed created type inode oldest newest age none --' -- "$cur")
|
||||
return
|
||||
;;
|
||||
|
||||
-t|--time)
|
||||
COMPREPLY=( $( compgen -W 'modified changed accessed created --' -- "$cur" ) )
|
||||
mapfile -t COMPREPLY < <(compgen -W 'modified changed accessed created --' -- "$cur")
|
||||
return
|
||||
;;
|
||||
|
||||
--time-style)
|
||||
COMPREPLY=( $( compgen -W 'default iso long-iso full-iso relative --' -- "$cur" ) )
|
||||
mapfile -t COMPREPLY < <(compgen -W 'default iso long-iso full-iso relative --' -- "$cur")
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
@ -38,14 +38,14 @@ _eza()
|
|||
# _parse_help doesn’t pick up short options when they are on the same line than long options
|
||||
--*)
|
||||
# colo[u]r isn’t parsed correctly so we filter these options out and add them by hand
|
||||
parse_help=$( eza --help | grep -oE ' (--[[:alnum:]@-]+)' | tr -d ' ' | grep -v '\--colo' )
|
||||
completions=$( echo '--color --colour --color-scale --colour-scale' $parse_help )
|
||||
COMPREPLY=( $( compgen -W "$completions" -- "$cur" ) )
|
||||
parse_help=$(eza --help | grep -oE ' (--[[:alnum:]@-]+)' | tr -d ' ' | grep -v '\--colo')
|
||||
completions=$(echo '--color --colour --color-scale --colour-scale' "$parse_help")
|
||||
mapfile -t COMPREPLY < <(compgen -W "$completions" -- "$cur")
|
||||
;;
|
||||
|
||||
-*)
|
||||
completions=$( eza --help | grep -oE ' (-[[:alnum:]@])' | tr -d ' ' )
|
||||
COMPREPLY=( $( compgen -W "$completions" -- "$cur" ) )
|
||||
completions=$(eza --help | grep -oE ' (-[[:alnum:]@])' | tr -d ' ')
|
||||
mapfile -t COMPREPLY < <(compgen -W "$completions" -- "$cur")
|
||||
;;
|
||||
|
||||
*)
|
||||
|
|
0
completions/fish/eza.fish
Executable file → Normal file
0
completions/fish/eza.fish
Executable file → Normal file
|
@ -47,6 +47,9 @@ for ARCH in "${!TARGETS[@]}"; do
|
|||
mkdir -p "${DEB_TMP_DIR}${DOCDIR}/man5"
|
||||
mkdir -p "${DEB_TMP_DIR}/DEBIAN"
|
||||
mkdir -p "${DEB_TMP_DIR}/usr/share/doc/${NAME}"
|
||||
mkdir -p "${DEB_TMP_DIR}/usr/share/bash-completion/completions/"
|
||||
mkdir -p "${DEB_TMP_DIR}/usr/share/fish/vendor_completions.d/"
|
||||
mkdir -p "${DEB_TMP_DIR}/usr/share/zsh/vendor-completions/"
|
||||
chmod 755 -R "${DEB_TMP_DIR}"
|
||||
|
||||
echo " -> extract executable"
|
||||
|
@ -60,6 +63,11 @@ for ARCH in "${!TARGETS[@]}"; do
|
|||
gzip -cn9 target/man/eza_colors-explanation.5 > "${DEB_TMP_DIR}${DOCDIR}man5/eza_colors-explanation.5.gz"
|
||||
chmod 644 "${DEB_TMP_DIR}${DOCDIR}"/**/*.gz
|
||||
|
||||
echo " -> copy completions"
|
||||
cp completions/bash/eza "${DEB_TMP_DIR}/usr/share/bash-completion/completions/"
|
||||
cp completions/fish/eza.fish "${DEB_TMP_DIR}/usr/share/fish/vendor_completions.d/"
|
||||
cp completions/zsh/_eza "${DEB_TMP_DIR}/usr/share/zsh/vendor-completions/"
|
||||
|
||||
echo " -> create control file"
|
||||
touch "${DEB_TMP_DIR}/DEBIAN/control"
|
||||
cat > "${DEB_TMP_DIR}/DEBIAN/control" <<EOM
|
||||
|
|
43
devtools/generate-trycmd-test.sh
Executable file
43
devtools/generate-trycmd-test.sh
Executable file
|
@ -0,0 +1,43 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Generate test data for the program
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "Usage: $0 <test name> <test argument>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up previous test data
|
||||
|
||||
if [ -f tests/cmd/"$1".toml ]; then
|
||||
rm tests/cmd/"$1".toml
|
||||
fi
|
||||
|
||||
if [ -f tests/cmd/"$1".stdout ]; then
|
||||
rm tests/cmd/"$1".stdout
|
||||
fi
|
||||
|
||||
if [ -f tests/cmd/"$1".stderr ]; then
|
||||
rm tests/cmd/"$1".stderr
|
||||
fi
|
||||
|
||||
# Generate test data
|
||||
|
||||
touch tests/cmd/"$1".toml
|
||||
|
||||
echo 'bin.name = "eza"' >> tests/cmd/"$1".toml
|
||||
echo 'args = "'"$2"'"' >> tests/cmd/"$1".toml
|
||||
|
||||
# Generate expected output
|
||||
|
||||
if [ -f target/debug/eza ]; then
|
||||
target/debug/eza "$2" > tests/cmd/"$1".stdout 2> tests/cmd/"$1".stderr
|
||||
returncode=$?
|
||||
if [ $returncode -ne 0 ]; then
|
||||
echo -e 'status.code = '$returncode'' >> tests/cmd/"$1".toml
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
echo "Please build the program first"
|
||||
exit 1
|
||||
fi
|
|
@ -160,6 +160,7 @@
|
|||
checks = {
|
||||
formatting = treefmtEval.config.build.check self;
|
||||
build = packages.check;
|
||||
default = packages.default;
|
||||
test = packages.test;
|
||||
lint = packages.clippy;
|
||||
trycmd = packages.trycmd;
|
||||
|
|
|
@ -150,7 +150,7 @@ These options are available when running with `--long` (`-l`):
|
|||
: Use the modified timestamp field.
|
||||
|
||||
`-M`, `--mounts`
|
||||
: Show mount details (Linux only)
|
||||
: Show mount details (Linux and Mac only)
|
||||
|
||||
`-n`, `--numeric`
|
||||
: List numeric user and group IDs.
|
||||
|
@ -197,16 +197,16 @@ These options are available when running with `--long` (`-l`):
|
|||
|
||||
`--git` [if eza was built with git support]
|
||||
: List each file’s Git status, if tracked.
|
||||
This adds a two-character column indicating the staged and unstaged statuses respectively. The status character can be ‘`-`’ for not modified, ‘`M`’ for a modified file, ‘`N`’ for a new file, ‘`D`’ for deleted, ‘`R`’ for renamed, ‘`T`’ for type-change, ‘`I`’ for ignored, and ‘`U`’ for conflicted. :Directories will be shown to have the status of their contents, which is how ‘deleted’ is possible if a directory contains a file that has a certain status, it will be shown to have that status.
|
||||
|
||||
`--git-repos` [if eza was built with git support]
|
||||
: List each directory’s Git status, if tracked.
|
||||
Symbols shown are `|`= clean, `+`= dirty, and `~`= for unknown.
|
||||
|
||||
`--git-repos-no-status` [if eza was built with git support]
|
||||
: List if a directory is a Git repository, but not its status.
|
||||
All Git repository directories will be shown as (themed) `-` without status indicated.
|
||||
|
||||
This adds a two-character column indicating the staged and unstaged statuses respectively. The status character can be ‘`-`’ for not modified, ‘`M`’ for a modified file, ‘`N`’ for a new file, ‘`D`’ for deleted, ‘`R`’ for renamed, ‘`T`’ for type-change, ‘`I`’ for ignored, and ‘`U`’ for conflicted.
|
||||
|
||||
Directories will be shown to have the status of their contents, which is how ‘deleted’ is possible: if a directory contains a file that has a certain status, it will be shown to have that status.
|
||||
|
||||
`--no-git`
|
||||
: Don't show Git status (always overrides `--git`, `--git-repos`, `--git-repos-no-status`)
|
||||
|
|
|
@ -25,9 +25,7 @@ files; setting `EXA_COLORS="reset"` will highlight nothing.
|
|||
|
||||
- eza now supports bright colours! As supported by most modern 256\-colour terminals, you can now choose from `bright` colour codes when selecting your custom colours in your `#EXA_COLORS` environment variable.
|
||||
|
||||
"Immediate" files are the files you should look at when downloading and building a project for the first time: READMEs, Makefiles, Cargo.toml, and others.
|
||||
They are highlighted in _yellow_ and _underlined_.
|
||||
|
||||
- Build (Makefile, Cargo.toml, package.json) are yellow and underlined.
|
||||
- Images (png, jpeg, gif) are purple.
|
||||
- Videos (mp4, ogv, m2ts) are a slightly purpler purple.
|
||||
- Music (mp3, m4a, ogg) is a deeper purple.
|
||||
|
|
|
@ -223,6 +223,36 @@ LIST OF CODES
|
|||
`mp`
|
||||
: a mount point
|
||||
|
||||
`im`
|
||||
: a regular file that is an image
|
||||
|
||||
`vi`
|
||||
: a regular file that is a video
|
||||
|
||||
`mu`
|
||||
: a regular file that is lossy music
|
||||
|
||||
`lo`
|
||||
: a regular file that is lossless music
|
||||
|
||||
`cr`
|
||||
: a regular file that is related to cryptography (ex: key or certificate)
|
||||
|
||||
`do`
|
||||
: a regular file that is a document (ex: office suite document or PDF)
|
||||
|
||||
`co`
|
||||
: a regular file this is compressed
|
||||
|
||||
`tm`
|
||||
: a regular file that is temporary (ex: a text editor's backup file)
|
||||
|
||||
`cm`
|
||||
: a regular file that is a compilation artifact (ex: Java class file)
|
||||
|
||||
`bu`
|
||||
: a regular file that is used to build a project (ex: Makefile)
|
||||
|
||||
Values in `EXA_COLORS` override those given in `LS_COLORS`, so you don’t need to re-write an existing `LS_COLORS` variable with proprietary extensions.
|
||||
|
||||
|
||||
|
@ -236,6 +266,12 @@ The codes accepted by eza are:
|
|||
`1`
|
||||
: for bold
|
||||
|
||||
`2`
|
||||
: for dimmed
|
||||
|
||||
`3`
|
||||
: for italic
|
||||
|
||||
`4`
|
||||
: for underline
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[toolchain]
|
||||
channel = "stable"
|
||||
channel = "1.70"
|
||||
components = [ "rustfmt", "rustc", "rust-src", "rust-analyzer", "cargo", "clippy" ]
|
||||
profile = "minimal"
|
||||
|
|
|
@ -42,6 +42,7 @@ impl Dir {
|
|||
.map(|result| result.map(|entry| entry.path()))
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
info!("Read directory success {:?}", &path);
|
||||
Ok(Self { contents, path })
|
||||
}
|
||||
|
||||
|
@ -129,8 +130,17 @@ impl<'dir, 'ig> Files<'dir, 'ig> {
|
|||
}
|
||||
}
|
||||
|
||||
return Some(File::from_args(path.clone(), self.dir, filename, self.deref_links)
|
||||
.map_err(|e| (path.clone(), e)))
|
||||
let file = File::from_args(path.clone(), self.dir, filename, self.deref_links)
|
||||
.map_err(|e| (path.clone(), e));
|
||||
|
||||
// Windows has its own concept of hidden files, when dotfiles are
|
||||
// hidden Windows hidden files should also be filtered out
|
||||
#[cfg(windows)]
|
||||
if !self.dotfiles && file.as_ref().is_ok_and(|f| f.attributes().hidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return Some(file);
|
||||
}
|
||||
|
||||
return None
|
||||
|
|
|
@ -6,17 +6,18 @@ use std::os::unix::fs::{FileTypeExt, MetadataExt, PermissionsExt};
|
|||
#[cfg(windows)]
|
||||
use std::os::windows::fs::MetadataExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use chrono::prelude::*;
|
||||
|
||||
use log::*;
|
||||
|
||||
use crate::ALL_MOUNTS;
|
||||
use crate::fs::dir::Dir;
|
||||
use crate::fs::feature::xattr;
|
||||
use crate::fs::feature::xattr::{FileAttributes, Attribute};
|
||||
use crate::fs::fields as f;
|
||||
|
||||
use super::mounts::all_mounts;
|
||||
use super::mounts::MountedFs;
|
||||
|
||||
|
||||
|
@ -79,11 +80,12 @@ pub struct File<'dir> {
|
|||
/// dereferencing is enabled, the size of the target will be displayed
|
||||
/// instead.
|
||||
pub deref_links: bool,
|
||||
|
||||
/// The extended attributes of this file.
|
||||
pub extended_attributes: Vec<Attribute>,
|
||||
extended_attributes: OnceLock<Vec<Attribute>>,
|
||||
|
||||
/// The absolute value of this path, used to look up mount points.
|
||||
pub absolute_path: Option<PathBuf>,
|
||||
absolute_path: OnceLock<Option<PathBuf>>,
|
||||
}
|
||||
|
||||
impl<'dir> File<'dir> {
|
||||
|
@ -98,8 +100,8 @@ impl<'dir> File<'dir> {
|
|||
debug!("Statting file {:?}", &path);
|
||||
let metadata = std::fs::symlink_metadata(&path)?;
|
||||
let is_all_all = false;
|
||||
let extended_attributes = File::gather_extended_attributes(&path);
|
||||
let absolute_path = std::fs::canonicalize(&path).ok();
|
||||
let extended_attributes = OnceLock::new();
|
||||
let absolute_path = OnceLock::new();
|
||||
|
||||
Ok(File { name, ext, path, metadata, parent_dir, is_all_all, deref_links, extended_attributes, absolute_path })
|
||||
}
|
||||
|
@ -112,8 +114,8 @@ impl<'dir> File<'dir> {
|
|||
let metadata = std::fs::symlink_metadata(&path)?;
|
||||
let is_all_all = true;
|
||||
let parent_dir = Some(parent_dir);
|
||||
let extended_attributes = File::gather_extended_attributes(&path);
|
||||
let absolute_path = std::fs::canonicalize(&path).ok();
|
||||
let extended_attributes = OnceLock::new();
|
||||
let absolute_path = OnceLock::new();
|
||||
|
||||
Ok(File { path, parent_dir, metadata, ext, name: ".".into(), is_all_all, deref_links: false, extended_attributes, absolute_path })
|
||||
}
|
||||
|
@ -125,8 +127,8 @@ impl<'dir> File<'dir> {
|
|||
let metadata = std::fs::symlink_metadata(&path)?;
|
||||
let is_all_all = true;
|
||||
let parent_dir = Some(parent_dir);
|
||||
let extended_attributes = File::gather_extended_attributes(&path);
|
||||
let absolute_path = std::fs::canonicalize(&path).ok();
|
||||
let extended_attributes = OnceLock::new();
|
||||
let absolute_path = OnceLock::new();
|
||||
|
||||
Ok(File { path, parent_dir, metadata, ext, name: "..".into(), is_all_all, deref_links: false, extended_attributes, absolute_path })
|
||||
}
|
||||
|
@ -176,6 +178,11 @@ impl<'dir> File<'dir> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the extended attributes of a file path on demand.
|
||||
pub fn extended_attributes(&self) -> &Vec<Attribute> {
|
||||
self.extended_attributes.get_or_init(||File::gather_extended_attributes(&self.path))
|
||||
}
|
||||
|
||||
/// Whether this file is a directory on the filesystem.
|
||||
pub fn is_directory(&self) -> bool {
|
||||
self.metadata.is_dir()
|
||||
|
@ -204,6 +211,7 @@ impl<'dir> File<'dir> {
|
|||
/// Returns an IO error upon failure, but this shouldn’t be used to check
|
||||
/// if a `File` is a directory or not! For that, just use `is_directory()`.
|
||||
pub fn to_dir(&self) -> io::Result<Dir> {
|
||||
trace!("to_dir: reading dir");
|
||||
Dir::read_dir(self.path.clone())
|
||||
}
|
||||
|
||||
|
@ -251,21 +259,22 @@ impl<'dir> File<'dir> {
|
|||
self.metadata.file_type().is_socket()
|
||||
}
|
||||
|
||||
/// Determine the full path resolving all symbolic links on demand.
|
||||
pub fn absolute_path(&self) -> Option<&PathBuf> {
|
||||
self.absolute_path.get_or_init(|| std::fs::canonicalize(&self.path).ok()).as_ref()
|
||||
}
|
||||
|
||||
/// Whether this file is a mount point
|
||||
pub fn is_mount_point(&self) -> bool {
|
||||
if cfg!(target_os = "linux") && self.is_directory() {
|
||||
return match self.absolute_path.as_ref() {
|
||||
Some(path) => ALL_MOUNTS.contains_key(path),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
false
|
||||
cfg!(any(target_os = "linux", target_os = "macos")) &&
|
||||
self.is_directory() &&
|
||||
self.absolute_path().is_some_and(|p| all_mounts().contains_key(p))
|
||||
}
|
||||
|
||||
/// The filesystem device and type for a mount point
|
||||
pub fn mount_point_info(&self) -> Option<&MountedFs> {
|
||||
if cfg!(target_os = "linux") {
|
||||
return self.absolute_path.as_ref().and_then(|p|ALL_MOUNTS.get(p));
|
||||
if cfg!(any(target_os = "linux",target_os = "macos")) {
|
||||
return self.absolute_path().and_then(|p| all_mounts().get(p));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -318,7 +327,8 @@ impl<'dir> File<'dir> {
|
|||
Ok(metadata) => {
|
||||
let ext = File::ext(&path);
|
||||
let name = File::filename(&path);
|
||||
let extended_attributes = File::gather_extended_attributes(&absolute_path);
|
||||
let extended_attributes = OnceLock::new();
|
||||
let absolute_path_cell = OnceLock::from(Some(absolute_path));
|
||||
let file = File {
|
||||
parent_dir: None,
|
||||
path,
|
||||
|
@ -328,7 +338,7 @@ impl<'dir> File<'dir> {
|
|||
is_all_all: false,
|
||||
deref_links: self.deref_links,
|
||||
extended_attributes,
|
||||
absolute_path: Some(absolute_path)
|
||||
absolute_path: absolute_path_cell,
|
||||
};
|
||||
FileTarget::Ok(Box::new(file))
|
||||
}
|
||||
|
@ -531,6 +541,7 @@ impl<'dir> File<'dir> {
|
|||
/// but as mentioned in the size function comment above, different filesystems
|
||||
/// make it difficult to get any info about a dir by it's size, so this may be it.
|
||||
fn is_empty_directory(&self) -> bool {
|
||||
trace!("is_empty_directory: reading dir");
|
||||
match Dir::read_dir(self.path.clone()) {
|
||||
// . & .. are skipped, if the returned iterator has .next(), it's not empty
|
||||
Ok(has_files) => has_files.files(super::DotFilter::Dotfiles, None, false, false).next().is_none(),
|
||||
|
@ -689,7 +700,7 @@ impl<'dir> File<'dir> {
|
|||
|
||||
/// This file’s security context field.
|
||||
pub fn security_context(&self) -> f::SecurityContext<'_> {
|
||||
let context = match &self.extended_attributes.iter().find(|a| a.name == "security.selinux") {
|
||||
let context = match self.extended_attributes().iter().find(|a| a.name == "security.selinux") {
|
||||
Some(attr) => f::SecurityContextType::SELinux(&attr.value),
|
||||
None => f::SecurityContextType::None
|
||||
};
|
||||
|
|
|
@ -8,4 +8,4 @@ pub mod dir_action;
|
|||
pub mod feature;
|
||||
pub mod fields;
|
||||
pub mod filter;
|
||||
pub mod mounts;
|
||||
pub mod mounts;
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
/// Details of a mounted filesystem.
|
||||
pub struct MountedFs {
|
||||
pub dest: String,
|
||||
pub fstype: String,
|
||||
pub source: String,
|
||||
}
|
16
src/fs/mounts/linux.rs
Normal file
16
src/fs/mounts/linux.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use proc_mounts::MountList;
|
||||
use crate::fs::mounts::{Error, MountedFs};
|
||||
|
||||
/// Get a list of all mounted filesystems
|
||||
pub fn mounts() -> Result<Vec<MountedFs>, Error> {
|
||||
Ok(MountList::new()
|
||||
.map_err(Error::IOError)?
|
||||
.0.iter()
|
||||
.map(|mount| MountedFs {
|
||||
dest: mount.dest.clone(),
|
||||
fstype: mount.fstype.clone(),
|
||||
source: mount.source.to_string_lossy().into()
|
||||
})
|
||||
.collect()
|
||||
)
|
||||
}
|
54
src/fs/mounts/macos.rs
Normal file
54
src/fs/mounts/macos.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use std::{mem, ptr};
|
||||
use std::ffi::{CStr, OsStr};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::path::PathBuf;
|
||||
use libc::{__error, getfsstat, MNT_NOWAIT, statfs};
|
||||
use crate::fs::mounts::{Error, MountedFs};
|
||||
|
||||
/// Get a list of all mounted filesystem
|
||||
pub fn mounts() -> Result<Vec<MountedFs>, Error> {
|
||||
// SAFETY:
|
||||
// Calling external "C" function getfsstat. Passing a null pointer and zero
|
||||
// bufsize will return the number of mounts.
|
||||
let mut count: i32 = unsafe { getfsstat(ptr::null_mut(), 0, MNT_NOWAIT) };
|
||||
let mut mntbuf = Vec::<statfs>::new();
|
||||
if count > 0 {
|
||||
// SAFETY: Zero out buffer memory as we allocate.
|
||||
mntbuf.resize_with(count as usize, || unsafe { mem::zeroed() });
|
||||
let bufsize = mntbuf.len() * mem::size_of::<statfs>();
|
||||
// SAFETY:
|
||||
// Calling external "C" function getfsstate with actual buffer now. The
|
||||
// function takes a buffer size to not overflow. If the mount table
|
||||
// changes size between calls we are protected by bufsize
|
||||
count = unsafe { getfsstat(mntbuf.as_mut_ptr(), bufsize as c_int, MNT_NOWAIT) };
|
||||
// Resize if the mount table has shrunk since last call
|
||||
if count >= 0 {
|
||||
mntbuf.truncate(count as usize);
|
||||
}
|
||||
}
|
||||
if count < 0 {
|
||||
// SAFETY: Calling external "C" errno function to get the error number
|
||||
return Err(Error::GetFSStatError(unsafe { *__error() }));
|
||||
}
|
||||
|
||||
let mut mounts = Vec::with_capacity(count as usize);
|
||||
for mnt in &mntbuf {
|
||||
let mount_point = OsStr::from_bytes(
|
||||
// SAFETY: Converting null terminated "C" string
|
||||
unsafe { CStr::from_ptr(mnt.f_mntonname.as_ptr().cast::<c_char>()) }.to_bytes()
|
||||
);
|
||||
let dest = PathBuf::from(mount_point);
|
||||
// SAFETY: Converting null terminated "C" string
|
||||
let fstype = unsafe { CStr::from_ptr(mnt.f_fstypename.as_ptr().cast::<c_char>()) }
|
||||
.to_string_lossy()
|
||||
.into();
|
||||
// SAFETY: Converting null terminated "C" string
|
||||
let source = unsafe { CStr::from_ptr(mnt.f_mntfromname.as_ptr().cast::<c_char>()) }
|
||||
.to_string_lossy()
|
||||
.into();
|
||||
mounts.push(MountedFs { dest, fstype, source });
|
||||
}
|
||||
|
||||
Ok(mounts)
|
||||
}
|
75
src/fs/mounts/mod.rs
Normal file
75
src/fs/mounts/mod.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
mod linux;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use linux::mounts;
|
||||
#[cfg(target_os = "macos")]
|
||||
use macos::mounts;
|
||||
|
||||
/// Details of a mounted filesystem.
|
||||
#[derive(Clone)]
|
||||
pub struct MountedFs {
|
||||
pub dest: PathBuf,
|
||||
pub fstype: String,
|
||||
pub source: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
#[cfg(target_os = "macos")]
|
||||
GetFSStatError(i32),
|
||||
#[cfg(target_os = "linux")]
|
||||
IOError(std::io::Error)
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// Allow unreachable_patterns for windows build
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
#[cfg(target_os = "macos")]
|
||||
Error::GetFSStatError(err) => write!(f, "getfsstat failed: {err}"),
|
||||
#[cfg(target_os = "linux")]
|
||||
Error::IOError(err) => write!(f, "failed to read /proc/mounts: {err}"),
|
||||
_ => write!(f, "Unknown error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A lazily initialised static map of all mounted file systems.
|
||||
//
|
||||
// The map contains a mapping from the mounted directory path to the
|
||||
// corresponding mount information. If there's an error retrieving the mount
|
||||
// list or if we're not running on Linux or Mac, the map will be empty.
|
||||
//
|
||||
// Initialise this at application start so we don't have to look the details
|
||||
// up for every directory. Ideally this would only be done if the --mounts
|
||||
// option is specified which will be significantly easier once the move
|
||||
// to `clap` is complete.
|
||||
pub(super) fn all_mounts() -> &'static HashMap<PathBuf, MountedFs> {
|
||||
static ALL_MOUNTS: OnceLock<HashMap<PathBuf, MountedFs>> = OnceLock::new();
|
||||
|
||||
ALL_MOUNTS.get_or_init(|| {
|
||||
// Allow unused_mut for windows build
|
||||
#[allow(unused_mut)]
|
||||
let mut mount_map: HashMap<PathBuf, MountedFs> = HashMap::new();
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
if let Ok(mounts) = mounts() {
|
||||
for mount in mounts {
|
||||
mount_map.insert(mount.dest.clone(), mount);
|
||||
}
|
||||
}
|
||||
|
||||
mount_map
|
||||
})
|
||||
}
|
|
@ -7,11 +7,9 @@
|
|||
//! # Contributors
|
||||
//! Please keep these lists sorted. If you're using vim, :sort i
|
||||
|
||||
use ansiterm::Style;
|
||||
use phf::{phf_map, Map};
|
||||
|
||||
use crate::fs::File;
|
||||
use crate::theme::FileColours;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FileType {
|
||||
|
@ -24,7 +22,7 @@ pub enum FileType {
|
|||
Compressed,
|
||||
Temp,
|
||||
Compiled,
|
||||
Immediate // An “immediate” file is something that can be run or activated somehow in order to
|
||||
Build // A “build file is something that can be run or activated somehow in order to
|
||||
// kick off the build of a project. It’s usually only present in directories full of
|
||||
// source code.
|
||||
}
|
||||
|
@ -32,47 +30,47 @@ pub enum FileType {
|
|||
/// Mapping from full filenames to file type.
|
||||
const FILENAME_TYPES: Map<&'static str, FileType> = phf_map! {
|
||||
/* Immediate file - kick off the build of a project */
|
||||
"Brewfile" => FileType::Immediate,
|
||||
"bsconfig.json" => FileType::Immediate,
|
||||
"BUILD" => FileType::Immediate,
|
||||
"BUILD.bazel" => FileType::Immediate,
|
||||
"build.gradle" => FileType::Immediate,
|
||||
"build.sbt" => FileType::Immediate,
|
||||
"build.xml" => FileType::Immediate,
|
||||
"Cargo.toml" => FileType::Immediate,
|
||||
"CMakeLists.txt" => FileType::Immediate,
|
||||
"composer.json" => FileType::Immediate,
|
||||
"configure" => FileType::Immediate,
|
||||
"Containerfile" => FileType::Immediate,
|
||||
"Dockerfile" => FileType::Immediate,
|
||||
"Earthfile" => FileType::Immediate,
|
||||
"flake.nix" => FileType::Immediate,
|
||||
"Gemfile" => FileType::Immediate,
|
||||
"GNUmakefile" => FileType::Immediate,
|
||||
"Gruntfile.coffee" => FileType::Immediate,
|
||||
"Gruntfile.js" => FileType::Immediate,
|
||||
"jsconfig.json" => FileType::Immediate,
|
||||
"Justfile" => FileType::Immediate,
|
||||
"justfile" => FileType::Immediate,
|
||||
"Makefile" => FileType::Immediate,
|
||||
"makefile" => FileType::Immediate,
|
||||
"meson.build" => FileType::Immediate,
|
||||
"mix.exs" => FileType::Immediate,
|
||||
"package.json" => FileType::Immediate,
|
||||
"Pipfile" => FileType::Immediate,
|
||||
"PKGBUILD" => FileType::Immediate,
|
||||
"Podfile" => FileType::Immediate,
|
||||
"pom.xml" => FileType::Immediate,
|
||||
"Procfile" => FileType::Immediate,
|
||||
"pyproject.toml" => FileType::Immediate,
|
||||
"Rakefile" => FileType::Immediate,
|
||||
"RoboFile.php" => FileType::Immediate,
|
||||
"SConstruct" => FileType::Immediate,
|
||||
"tsconfig.json" => FileType::Immediate,
|
||||
"Vagrantfile" => FileType::Immediate,
|
||||
"webpack.config.cjs" => FileType::Immediate,
|
||||
"webpack.config.js" => FileType::Immediate,
|
||||
"WORKSPACE" => FileType::Immediate,
|
||||
"Brewfile" => FileType::Build,
|
||||
"bsconfig.json" => FileType::Build,
|
||||
"BUILD" => FileType::Build,
|
||||
"BUILD.bazel" => FileType::Build,
|
||||
"build.gradle" => FileType::Build,
|
||||
"build.sbt" => FileType::Build,
|
||||
"build.xml" => FileType::Build,
|
||||
"Cargo.toml" => FileType::Build,
|
||||
"CMakeLists.txt" => FileType::Build,
|
||||
"composer.json" => FileType::Build,
|
||||
"configure" => FileType::Build,
|
||||
"Containerfile" => FileType::Build,
|
||||
"Dockerfile" => FileType::Build,
|
||||
"Earthfile" => FileType::Build,
|
||||
"flake.nix" => FileType::Build,
|
||||
"Gemfile" => FileType::Build,
|
||||
"GNUmakefile" => FileType::Build,
|
||||
"Gruntfile.coffee" => FileType::Build,
|
||||
"Gruntfile.js" => FileType::Build,
|
||||
"jsconfig.json" => FileType::Build,
|
||||
"Justfile" => FileType::Build,
|
||||
"justfile" => FileType::Build,
|
||||
"Makefile" => FileType::Build,
|
||||
"makefile" => FileType::Build,
|
||||
"meson.build" => FileType::Build,
|
||||
"mix.exs" => FileType::Build,
|
||||
"package.json" => FileType::Build,
|
||||
"Pipfile" => FileType::Build,
|
||||
"PKGBUILD" => FileType::Build,
|
||||
"Podfile" => FileType::Build,
|
||||
"pom.xml" => FileType::Build,
|
||||
"Procfile" => FileType::Build,
|
||||
"pyproject.toml" => FileType::Build,
|
||||
"Rakefile" => FileType::Build,
|
||||
"RoboFile.php" => FileType::Build,
|
||||
"SConstruct" => FileType::Build,
|
||||
"tsconfig.json" => FileType::Build,
|
||||
"Vagrantfile" => FileType::Build,
|
||||
"webpack.config.cjs" => FileType::Build,
|
||||
"webpack.config.js" => FileType::Build,
|
||||
"WORKSPACE" => FileType::Build,
|
||||
/* Cryptology files */
|
||||
"id_dsa" => FileType::Crypto,
|
||||
"id_ecdsa" => FileType::Crypto,
|
||||
|
@ -86,7 +84,7 @@ const FILENAME_TYPES: Map<&'static str, FileType> = phf_map! {
|
|||
/// extension is added also update the extension icon map.
|
||||
const EXTENSION_TYPES: Map<&'static str, FileType> = phf_map! {
|
||||
/* Immediate file - kick off the build of a project */
|
||||
"ninja" => FileType::Immediate,
|
||||
"ninja" => FileType::Build,
|
||||
/* Image files */
|
||||
"arw" => FileType::Image,
|
||||
"avif" => FileType::Image,
|
||||
|
@ -269,10 +267,10 @@ impl FileType {
|
|||
/// Lookup the file type based on the file's name, by the file name
|
||||
/// lowercase extension, or if the file could be compiled from related
|
||||
/// source code.
|
||||
fn get_file_type(file: &File<'_>) -> Option<FileType> {
|
||||
pub(crate) fn get_file_type(file: &File<'_>) -> Option<FileType> {
|
||||
// Case-insensitive readme is checked first for backwards compatibility.
|
||||
if file.name.to_lowercase().starts_with("readme") {
|
||||
return Some(Self::Immediate)
|
||||
return Some(Self::Build)
|
||||
}
|
||||
if let Some(file_type) = FILENAME_TYPES.get(&file.name) {
|
||||
return Some(file_type.clone())
|
||||
|
@ -291,27 +289,3 @@ impl FileType {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileTypeColor;
|
||||
|
||||
impl FileColours for FileTypeColor {
|
||||
/// Map from the file type to the display style/color for the file.
|
||||
fn colour_file(&self, file: &File<'_>) -> Option<Style> {
|
||||
use ansiterm::Colour::*;
|
||||
|
||||
match FileType::get_file_type(file) {
|
||||
Some(FileType::Compiled) => Some(Yellow.normal()),
|
||||
Some(FileType::Compressed) => Some(Red.normal()),
|
||||
Some(FileType::Crypto) => Some(Green.bold()),
|
||||
Some(FileType::Document) => Some(Green.normal()),
|
||||
Some(FileType::Image) => Some(Purple.normal()),
|
||||
Some(FileType::Immediate) => Some(Yellow.bold().underline()),
|
||||
Some(FileType::Lossless) => Some(Cyan.bold()),
|
||||
Some(FileType::Music) => Some(Cyan.normal()),
|
||||
Some(FileType::Temp) => Some(White.normal()),
|
||||
Some(FileType::Video) => Some(Purple.bold()),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
12
src/lib.rs
Normal file
12
src/lib.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
#[allow(unused)]
|
||||
pub mod fs;
|
||||
#[allow(unused)]
|
||||
pub mod info;
|
||||
#[allow(unused)]
|
||||
pub mod logger;
|
||||
#[allow(unused)]
|
||||
pub mod options;
|
||||
#[allow(unused)]
|
||||
pub mod output;
|
||||
#[allow(unused)]
|
||||
pub mod theme;
|
56
src/main.rs
56
src/main.rs
|
@ -22,23 +22,16 @@
|
|||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![allow(clippy::wildcard_imports)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::io::{self, Write, ErrorKind};
|
||||
use std::path::{Component, PathBuf};
|
||||
use std::process::exit;
|
||||
|
||||
use ansiterm::{ANSIStrings, Style};
|
||||
|
||||
use log::*;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use proc_mounts::MountList;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use crate::fs::mounts::MountedFs;
|
||||
use crate::fs::{Dir, File};
|
||||
use crate::fs::feature::git::GitCache;
|
||||
use crate::fs::filter::GitIgnore;
|
||||
|
@ -53,42 +46,7 @@ mod options;
|
|||
mod output;
|
||||
mod theme;
|
||||
|
||||
// A lazily initialised static map of all mounted file systems.
|
||||
//
|
||||
// The map contains a mapping from the mounted directory path to the
|
||||
// corresponding mount information. On Linux systems, this map is populated
|
||||
// using the `proc-mounts` crate. If there's an error retrieving the mount
|
||||
// list or if we're not running on Linux, the map will be empty.
|
||||
//
|
||||
// Initialise this at application start so we don't have to look the details
|
||||
// up for every directory. Ideally this would only be done if the --mounts
|
||||
// option is specified which will be significantly easier once the move
|
||||
// to `clap` is complete.
|
||||
lazy_static! {
|
||||
static ref ALL_MOUNTS: HashMap<PathBuf, MountedFs> = {
|
||||
#[cfg(target_os = "linux")]
|
||||
match MountList::new() {
|
||||
Ok(mount_list) => {
|
||||
let mut m = HashMap::new();
|
||||
mount_list.0.iter().for_each(|mount| {
|
||||
m.insert(mount.dest.clone(), MountedFs {
|
||||
dest: mount.dest.to_string_lossy().into_owned(),
|
||||
fstype: mount.fstype.clone(),
|
||||
source: mount.source.to_string_lossy().into(),
|
||||
});
|
||||
});
|
||||
m
|
||||
}
|
||||
Err(_) => HashMap::new()
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
HashMap::new()
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use std::process::exit;
|
||||
|
||||
#[cfg(unix)]
|
||||
unsafe {
|
||||
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
|
||||
|
@ -118,8 +76,11 @@ fn main() {
|
|||
let theme = options.theme.to_theme(terminal_size::terminal_size().is_some());
|
||||
let exa = Exa { options, writer, input_paths, theme, console_width, git };
|
||||
|
||||
|
||||
info!("matching on exa.run");
|
||||
match exa.run() {
|
||||
Ok(exit_status) => {
|
||||
trace!("exa.run: exit Ok(exit_status)");
|
||||
exit(exit_status);
|
||||
}
|
||||
|
||||
|
@ -130,6 +91,7 @@ fn main() {
|
|||
|
||||
Err(e) => {
|
||||
eprintln!("{e}");
|
||||
trace!("exa.run: exit RUNTIME_ERROR");
|
||||
exit(exits::RUNTIME_ERROR);
|
||||
}
|
||||
}
|
||||
|
@ -225,8 +187,13 @@ impl<'args> Exa<'args> {
|
|||
|
||||
Ok(f) => {
|
||||
if f.points_to_directory() && ! self.options.dir_action.treat_dirs_as_files() {
|
||||
trace!("matching on to_dir");
|
||||
match f.to_dir() {
|
||||
Ok(d) => dirs.push(d),
|
||||
Err(e) if e.kind() == ErrorKind::PermissionDenied => {
|
||||
warn!("Permission Denied: {e}");
|
||||
exit(exits::PERMISSION_DENIED);
|
||||
},
|
||||
Err(e) => writeln!(io::stderr(), "{file_path:?}: {e}")?,
|
||||
}
|
||||
}
|
||||
|
@ -378,4 +345,7 @@ mod exits {
|
|||
|
||||
/// Exit code for when the command-line options are invalid.
|
||||
pub const OPTIONS_ERROR: i32 = 3;
|
||||
|
||||
/// Exit code for missing file permissions
|
||||
pub const PERMISSION_DENIED: i32 = 13;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ LONG VIEW OPTIONS
|
|||
-H, --links list each file's number of hard links
|
||||
-i, --inode list each file's inode number
|
||||
-m, --modified use the modified timestamp field
|
||||
-M, --mounts show mount details (Linux only)
|
||||
-M, --mounts show mount details (Linux and MacOS only)
|
||||
-n, --numeric list numeric user and group IDs
|
||||
-S, --blocksize show size of allocated file system blocks
|
||||
-t, --time FIELD which timestamp field to list (modified, accessed, created)
|
||||
|
|
|
@ -68,6 +68,8 @@ use std::vec::IntoIter as VecIntoIter;
|
|||
use ansiterm::Style;
|
||||
use scoped_threadpool::Pool;
|
||||
|
||||
use log::*;
|
||||
|
||||
use crate::fs::{Dir, File};
|
||||
use crate::fs::dir_action::RecurseOptions;
|
||||
use crate::fs::feature::git::GitCache;
|
||||
|
@ -201,7 +203,7 @@ impl<'a> Render<'a> {
|
|||
pub fn show_xattr_hint(&self, file: &File<'_>) -> bool {
|
||||
// Do not show the hint '@' if the only extended attribute is the security
|
||||
// attribute and the security attribute column is active.
|
||||
let xattr_count = file.extended_attributes.len();
|
||||
let xattr_count = file.extended_attributes().len();
|
||||
let selinux_ctx_shown = self.opts.secattr && match file.security_context().context {
|
||||
SecurityContextType::SELinux(_) => true,
|
||||
SecurityContextType::None => false,
|
||||
|
@ -250,7 +252,7 @@ impl<'a> Render<'a> {
|
|||
// that they want to see them.
|
||||
|
||||
let xattrs: &[Attribute] = if xattr::ENABLED && self.opts.xattr {
|
||||
&file.extended_attributes
|
||||
file.extended_attributes()
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
|
@ -261,6 +263,7 @@ impl<'a> Render<'a> {
|
|||
let mut dir = None;
|
||||
if let Some(r) = self.recurse {
|
||||
if file.is_directory() && r.tree && ! r.is_too_deep(depth.0) {
|
||||
trace!("matching on to_dir");
|
||||
match file.to_dir() {
|
||||
Ok(d) => {
|
||||
dir = Some(d);
|
||||
|
|
|
@ -350,7 +350,8 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
|
|||
|
||||
let mut display_hyperlink = false;
|
||||
if self.options.embed_hyperlinks == EmbedHyperlinks::On {
|
||||
if let Some(abs_path) = self.file.absolute_path.as_ref().and_then(|p| p.as_os_str().to_str()) {
|
||||
if let Some(abs_path) = self.file.absolute_path().and_then(|p| p.as_os_str().to_str()) {
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
bits.insert(0, ANSIString::from(format!(
|
||||
"{}file://{}{}{}",
|
||||
HYPERLINK_START,
|
||||
|
@ -358,6 +359,14 @@ impl<'a, 'dir, C: Colours> FileName<'a, 'dir, C> {
|
|||
urlencoding::encode(abs_path).replace("%2F", "/"),
|
||||
HYPERLINK_END,
|
||||
)));
|
||||
#[cfg(target_os = "windows")]
|
||||
bits.insert(0, ANSIString::from(format!(
|
||||
"{}file://{}{}",
|
||||
HYPERLINK_START,
|
||||
abs_path.replace("\\\\?\\", ""),
|
||||
HYPERLINK_END,
|
||||
)));
|
||||
|
||||
display_hyperlink = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ impl f::SubdirGitRepo {
|
|||
let s = match self.status {
|
||||
f::SubdirGitRepoStatus::NoRepo => style.paint("- "),
|
||||
f::SubdirGitRepoStatus::GitClean => style.fg(Color::Green).paint("| "),
|
||||
f::SubdirGitRepoStatus::GitDirty => style.bold().fg(Color::Red).paint("- "),
|
||||
f::SubdirGitRepoStatus::GitUnknown => style.paint("- "),
|
||||
f::SubdirGitRepoStatus::GitDirty => style.bold().fg(Color::Red).paint("+ "),
|
||||
f::SubdirGitRepoStatus::GitUnknown => style.fg(Color::Green).bold().paint("~ "),
|
||||
};
|
||||
|
||||
TextCell {
|
||||
|
|
|
@ -78,6 +78,19 @@ impl UiStyles {
|
|||
},
|
||||
},
|
||||
|
||||
file_type: FileType {
|
||||
image: Purple.normal(),
|
||||
video: Purple.bold(),
|
||||
music: Cyan.normal(),
|
||||
lossless: Cyan.bold(),
|
||||
crypto: Green.bold(),
|
||||
document: Green.normal(),
|
||||
compressed: Red.normal(),
|
||||
temp: White.normal(),
|
||||
compiled: Yellow.normal(),
|
||||
build: Yellow.bold().underline()
|
||||
},
|
||||
|
||||
punctuation: DarkGray.bold(),
|
||||
date: Blue.normal(),
|
||||
inode: Purple.normal(),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use ansiterm::Style;
|
||||
|
||||
use crate::fs::File;
|
||||
use crate::info::filetype::FileType;
|
||||
use crate::output::file_name::Colours as FileNameColours;
|
||||
use crate::output::render;
|
||||
|
||||
|
@ -58,18 +59,16 @@ pub struct Definitions {
|
|||
|
||||
pub struct Theme {
|
||||
pub ui: UiStyles,
|
||||
pub exts: Box<dyn FileColours>,
|
||||
pub exts: Box<dyn FileStyle>,
|
||||
}
|
||||
|
||||
impl Options {
|
||||
|
||||
#[allow(trivial_casts)] // the `as Box<_>` stuff below warns about this for some reason
|
||||
pub fn to_theme(&self, isatty: bool) -> Theme {
|
||||
use crate::info::filetype::FileTypeColor;
|
||||
|
||||
if self.use_colours == UseColours::Never || (self.use_colours == UseColours::Automatic && ! isatty) {
|
||||
let ui = UiStyles::plain();
|
||||
let exts = Box::new(NoFileColours);
|
||||
let exts = Box::new(NoFileStyle);
|
||||
return Theme { ui, exts };
|
||||
}
|
||||
|
||||
|
@ -79,10 +78,10 @@ impl Options {
|
|||
|
||||
// Use between 0 and 2 file name highlighters
|
||||
let exts = match (exts.is_non_empty(), use_default_filetypes) {
|
||||
(false, false) => Box::new(NoFileColours) as Box<_>,
|
||||
(false, true) => Box::new(FileTypeColor) as Box<_>,
|
||||
( true, false) => Box::new(exts) as Box<_>,
|
||||
( true, true) => Box::new((exts, FileTypeColor)) as Box<_>,
|
||||
(false, false) => Box::new(NoFileStyle) as Box<_>,
|
||||
(false, true) => Box::new(FileTypes) as Box<_>,
|
||||
( true, false) => Box::new(exts) as Box<_>,
|
||||
( true, true) => Box::new((exts, FileTypes)) as Box<_>,
|
||||
};
|
||||
|
||||
Theme { ui, exts }
|
||||
|
@ -144,14 +143,18 @@ impl Definitions {
|
|||
}
|
||||
|
||||
|
||||
pub trait FileColours: std::marker::Sync {
|
||||
fn colour_file(&self, file: &File<'_>) -> Option<Style>;
|
||||
/// Determine the style to paint the text for the filename part of the output.
|
||||
pub trait FileStyle: Sync {
|
||||
/// Return the style to paint the filename text for `file` from the given
|
||||
/// `theme`.
|
||||
fn get_style(&self, file: &File<'_>, theme: &Theme) -> Option<Style>;
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct NoFileColours;
|
||||
impl FileColours for NoFileColours {
|
||||
fn colour_file(&self, _file: &File<'_>) -> Option<Style> {
|
||||
struct NoFileStyle;
|
||||
|
||||
impl FileStyle for NoFileStyle {
|
||||
fn get_style(&self, _file: &File<'_>, _theme: &Theme) -> Option<Style> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -160,13 +163,13 @@ impl FileColours for NoFileColours {
|
|||
// first one then try the second one. This lets the user provide their own
|
||||
// file type associations, while falling back to the default set if not set
|
||||
// explicitly.
|
||||
impl<A, B> FileColours for (A, B)
|
||||
where A: FileColours,
|
||||
B: FileColours,
|
||||
impl<A, B> FileStyle for (A, B)
|
||||
where A: FileStyle,
|
||||
B: FileStyle,
|
||||
{
|
||||
fn colour_file(&self, file: &File<'_>) -> Option<Style> {
|
||||
self.0.colour_file(file)
|
||||
.or_else(|| self.1.colour_file(file))
|
||||
fn get_style(&self, file: &File<'_>, theme: &Theme) -> Option<Style> {
|
||||
self.0.get_style(file, theme)
|
||||
.or_else(|| self.1.get_style(file, theme))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,17 +179,6 @@ struct ExtensionMappings {
|
|||
mappings: Vec<(glob::Pattern, Style)>,
|
||||
}
|
||||
|
||||
// Loop through backwards so that colours specified later in the list override
|
||||
// colours specified earlier, like we do with options and strict mode
|
||||
|
||||
impl FileColours for ExtensionMappings {
|
||||
fn colour_file(&self, file: &File<'_>) -> Option<Style> {
|
||||
self.mappings.iter().rev()
|
||||
.find(|t| t.0.matches(&file.name))
|
||||
.map (|t| t.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtensionMappings {
|
||||
fn is_non_empty(&self) -> bool {
|
||||
! self.mappings.is_empty()
|
||||
|
@ -197,8 +189,37 @@ impl ExtensionMappings {
|
|||
}
|
||||
}
|
||||
|
||||
// Loop through backwards so that colours specified later in the list override
|
||||
// colours specified earlier, like we do with options and strict mode
|
||||
|
||||
impl FileStyle for ExtensionMappings {
|
||||
fn get_style(&self, file: &File<'_>, _theme: &Theme) -> Option<Style> {
|
||||
self.mappings.iter().rev()
|
||||
.find(|t| t.0.matches(&file.name))
|
||||
.map (|t| t.1)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FileTypes;
|
||||
|
||||
impl FileStyle for FileTypes {
|
||||
fn get_style(&self, file: &File<'_>, theme: &Theme) -> Option<Style> {
|
||||
match FileType::get_file_type(file) {
|
||||
Some(FileType::Image) => Some(theme.ui.file_type.image),
|
||||
Some(FileType::Video) => Some(theme.ui.file_type.video),
|
||||
Some(FileType::Music) => Some(theme.ui.file_type.music),
|
||||
Some(FileType::Lossless) => Some(theme.ui.file_type.lossless),
|
||||
Some(FileType::Crypto) => Some(theme.ui.file_type.crypto),
|
||||
Some(FileType::Document) => Some(theme.ui.file_type.document),
|
||||
Some(FileType::Compressed) => Some(theme.ui.file_type.compressed),
|
||||
Some(FileType::Temp) => Some(theme.ui.file_type.temp),
|
||||
Some(FileType::Compiled) => Some(theme.ui.file_type.compiled),
|
||||
Some(FileType::Build) => Some(theme.ui.file_type.build),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl render::BlocksColours for Theme {
|
||||
|
@ -320,17 +341,17 @@ impl render::UserColours for Theme {
|
|||
}
|
||||
|
||||
impl FileNameColours for Theme {
|
||||
fn symlink_path(&self) -> Style { self.ui.symlink_path }
|
||||
fn normal_arrow(&self) -> Style { self.ui.punctuation }
|
||||
fn broken_symlink(&self) -> Style { self.ui.broken_symlink }
|
||||
fn broken_filename(&self) -> Style { apply_overlay(self.ui.broken_symlink, self.ui.broken_path_overlay) }
|
||||
fn broken_control_char(&self) -> Style { apply_overlay(self.ui.control_char, self.ui.broken_path_overlay) }
|
||||
fn control_char(&self) -> Style { self.ui.control_char }
|
||||
fn symlink_path(&self) -> Style { self.ui.symlink_path }
|
||||
fn broken_control_char(&self) -> Style { apply_overlay(self.ui.control_char, self.ui.broken_path_overlay) }
|
||||
fn executable_file(&self) -> Style { self.ui.filekinds.executable }
|
||||
fn mount_point(&self) -> Style { self.ui.filekinds.mount_point }
|
||||
|
||||
fn colour_file(&self, file: &File<'_>) -> Style {
|
||||
self.exts.colour_file(file).unwrap_or(self.ui.filekinds.normal)
|
||||
self.exts.get_style(file, self).unwrap_or(self.ui.filekinds.normal)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,6 +558,17 @@ mod customs_test {
|
|||
|
||||
test!(exa_mp: ls "", exa "mp=1;34;4" => colours c -> { c.filekinds.mount_point = Blue.bold().underline(); });
|
||||
|
||||
test!(exa_im: ls "", exa "im=38;5;128" => colours c -> { c.file_type.image = Fixed(128).normal(); });
|
||||
test!(exa_vi: ls "", exa "vi=38;5;129" => colours c -> { c.file_type.video = Fixed(129).normal(); });
|
||||
test!(exa_mu: ls "", exa "mu=38;5;130" => colours c -> { c.file_type.music = Fixed(130).normal(); });
|
||||
test!(exa_lo: ls "", exa "lo=38;5;131" => colours c -> { c.file_type.lossless = Fixed(131).normal(); });
|
||||
test!(exa_cr: ls "", exa "cr=38;5;132" => colours c -> { c.file_type.crypto = Fixed(132).normal(); });
|
||||
test!(exa_do: ls "", exa "do=38;5;133" => colours c -> { c.file_type.document = Fixed(133).normal(); });
|
||||
test!(exa_co: ls "", exa "co=38;5;134" => colours c -> { c.file_type.compressed = Fixed(134).normal(); });
|
||||
test!(exa_tm: ls "", exa "tm=38;5;135" => colours c -> { c.file_type.temp = Fixed(135).normal(); });
|
||||
test!(exa_cm: ls "", exa "cm=38;5;136" => colours c -> { c.file_type.compiled = Fixed(136).normal(); });
|
||||
test!(exa_ie: ls "", exa "bu=38;5;137" => colours c -> { c.file_type.build = Fixed(137).normal(); });
|
||||
|
||||
// All the while, LS_COLORS treats them as filenames:
|
||||
test!(ls_uu: ls "uu=38;5;117", exa "" => exts [ ("uu", Fixed(117).normal()) ]);
|
||||
test!(ls_un: ls "un=38;5;118", exa "" => exts [ ("un", Fixed(118).normal()) ]);
|
||||
|
|
|
@ -14,6 +14,7 @@ pub struct UiStyles {
|
|||
pub links: Links,
|
||||
pub git: Git,
|
||||
pub security_context: SecurityContext,
|
||||
pub file_type: FileType,
|
||||
|
||||
pub punctuation: Style,
|
||||
pub date: Style,
|
||||
|
@ -121,6 +122,21 @@ pub struct SecurityContext {
|
|||
pub selinux: SELinuxContext,
|
||||
}
|
||||
|
||||
/// Drawing styles based on the type of file (video, image, compressed, etc)
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
pub struct FileType {
|
||||
pub image: Style, // im - image file
|
||||
pub video: Style, // vi - video file
|
||||
pub music: Style, // mu - lossy music
|
||||
pub lossless: Style, // lo - lossless music
|
||||
pub crypto: Style, // cr - related to cryptography
|
||||
pub document: Style, // do - document file
|
||||
pub compressed: Style, // co - compressed file
|
||||
pub temp: Style, // tm - temporary file
|
||||
pub compiled: Style, // cm - compilation artifact
|
||||
pub build: Style, // bu - file that is used to build a project
|
||||
}
|
||||
|
||||
impl UiStyles {
|
||||
pub fn plain() -> Self {
|
||||
Self::default()
|
||||
|
@ -213,6 +229,17 @@ impl UiStyles {
|
|||
|
||||
"mp" => self.filekinds.mount_point = pair.to_style(),
|
||||
|
||||
"im" => self.file_type.image = pair.to_style(),
|
||||
"vi" => self.file_type.video = pair.to_style(),
|
||||
"mu" => self.file_type.music = pair.to_style(),
|
||||
"lo" => self.file_type.lossless = pair.to_style(),
|
||||
"cr" => self.file_type.crypto = pair.to_style(),
|
||||
"do" => self.file_type.document = pair.to_style(),
|
||||
"co" => self.file_type.compressed = pair.to_style(),
|
||||
"tm" => self.file_type.temp = pair.to_style(),
|
||||
"cm" => self.file_type.compiled = pair.to_style(),
|
||||
"bu" => self.file_type.build = pair.to_style(),
|
||||
|
||||
_ => return false,
|
||||
}
|
||||
|
||||
|
|
1
tests/cmd/inexistant_file_unix.stderr
Normal file
1
tests/cmd/inexistant_file_unix.stderr
Normal file
|
@ -0,0 +1 @@
|
|||
"nonexistentdir": No such file or directory (os error 2)
|
0
tests/cmd/inexistant_file_unix.stdout
Normal file
0
tests/cmd/inexistant_file_unix.stdout
Normal file
3
tests/cmd/inexistant_file_unix.toml
Normal file
3
tests/cmd/inexistant_file_unix.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
bin.name = "eza"
|
||||
args = "nonexistentdir"
|
||||
status.code = 2
|
0
tests/cmd/long_binary_bytes_unix.stderr
Normal file
0
tests/cmd/long_binary_bytes_unix.stderr
Normal file
21
tests/cmd/long_binary_bytes_unix.stdout
Normal file
21
tests/cmd/long_binary_bytes_unix.stdout
Normal file
|
@ -0,0 +1,21 @@
|
|||
0 a
|
||||
0 b
|
||||
0 c
|
||||
0 d
|
||||
0 e
|
||||
- exa
|
||||
0 f
|
||||
0 g
|
||||
0 h
|
||||
0 i
|
||||
0 image.jpg.img.c.rs.log.png
|
||||
19 index.svg
|
||||
0 j
|
||||
0 k
|
||||
0 l
|
||||
0 m
|
||||
0 n
|
||||
0 o
|
||||
0 p
|
||||
0 q
|
||||
- vagrant
|
2
tests/cmd/long_binary_bytes_unix.toml
Normal file
2
tests/cmd/long_binary_bytes_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --long --no-user --no-time --no-permissions --binary"
|
0
tests/cmd/long_file_size_unix.stderr
Normal file
0
tests/cmd/long_file_size_unix.stderr
Normal file
21
tests/cmd/long_file_size_unix.stdout
Normal file
21
tests/cmd/long_file_size_unix.stdout
Normal file
|
@ -0,0 +1,21 @@
|
|||
0 a
|
||||
0 b
|
||||
0 c
|
||||
0 d
|
||||
0 e
|
||||
- exa
|
||||
0 f
|
||||
0 g
|
||||
0 h
|
||||
0 i
|
||||
0 image.jpg.img.c.rs.log.png
|
||||
19 index.svg
|
||||
0 j
|
||||
0 k
|
||||
0 l
|
||||
0 m
|
||||
0 n
|
||||
0 o
|
||||
0 p
|
||||
0 q
|
||||
- vagrant
|
2
tests/cmd/long_file_size_unix.toml
Normal file
2
tests/cmd/long_file_size_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --long --no-user --no-time --no-permissions"
|
0
tests/cmd/long_header_unix.stderr
Normal file
0
tests/cmd/long_header_unix.stderr
Normal file
22
tests/cmd/long_header_unix.stdout
Normal file
22
tests/cmd/long_header_unix.stdout
Normal file
|
@ -0,0 +1,22 @@
|
|||
Size Name
|
||||
0 a
|
||||
0 b
|
||||
0 c
|
||||
0 d
|
||||
0 e
|
||||
- exa
|
||||
0 f
|
||||
0 g
|
||||
0 h
|
||||
0 i
|
||||
0 image.jpg.img.c.rs.log.png
|
||||
19 index.svg
|
||||
0 j
|
||||
0 k
|
||||
0 l
|
||||
0 m
|
||||
0 n
|
||||
0 o
|
||||
0 p
|
||||
0 q
|
||||
- vagrant
|
2
tests/cmd/long_header_unix.toml
Normal file
2
tests/cmd/long_header_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --long --no-user --no-time --header --no-permissions"
|
2
tests/cmd/long_links_recurse_unix.toml
Normal file
2
tests/cmd/long_links_recurse_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --long --no-user --no-time --no-filesize --no-permissions --recurse --links"
|
0
tests/cmd/long_recurse_with_level_unix.stderr
Normal file
0
tests/cmd/long_recurse_with_level_unix.stderr
Normal file
21
tests/cmd/long_recurse_with_level_unix.stdout
Normal file
21
tests/cmd/long_recurse_with_level_unix.stdout
Normal file
|
@ -0,0 +1,21 @@
|
|||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
exa
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
image.jpg.img.c.rs.log.png
|
||||
index.svg
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
vagrant
|
2
tests/cmd/long_recurse_with_level_unix.toml
Normal file
2
tests/cmd/long_recurse_with_level_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --long --no-user --no-permissions --no-time --no-filesize --recurse --level 2"
|
|
@ -1,21 +1,21 @@
|
|||
.rw-r--r-- a
|
||||
.rw-r--r-- b
|
||||
.rw-r--r-- c
|
||||
.rw-r--r-- d
|
||||
.rw-r--r-- e
|
||||
drwxr-xr-x exa
|
||||
.rw-r--r-- f
|
||||
.rw-r--r-- g
|
||||
.rw-r--r-- h
|
||||
.rw-r--r-- i
|
||||
.rw-r--r-- image.jpg.img.c.rs.log.png
|
||||
.rw-r--r-- index.svg
|
||||
.rw-r--r-- j
|
||||
.rw-r--r-- k
|
||||
.rw-r--r-- l
|
||||
.rw-r--r-- m
|
||||
.rw-r--r-- n
|
||||
.rw-r--r-- o
|
||||
.rw-r--r-- p
|
||||
.rw-r--r-- q
|
||||
drwxr-xr-x vagrant
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
exa
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
image.jpg.img.c.rs.log.png
|
||||
index.svg
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
vagrant
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --long --no-user --no-time --no-filesize"
|
||||
args = "tests/itest --long --no-user --no-time --no-filesize --no-permissions"
|
||||
|
|
0
tests/cmd/only_dir_recursive_long_unix.stderr
Normal file
0
tests/cmd/only_dir_recursive_long_unix.stderr
Normal file
21
tests/cmd/only_dir_recursive_long_unix.stdout
Normal file
21
tests/cmd/only_dir_recursive_long_unix.stdout
Normal file
|
@ -0,0 +1,21 @@
|
|||
exa
|
||||
vagrant
|
||||
|
||||
tests/itest/exa:
|
||||
sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
||||
|
||||
tests/itest/exa/sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss:
|
||||
|
||||
tests/itest/vagrant:
|
||||
debug
|
||||
dev
|
||||
log
|
||||
|
||||
tests/itest/vagrant/debug:
|
||||
|
||||
tests/itest/vagrant/dev:
|
||||
|
||||
tests/itest/vagrant/log:
|
||||
run
|
||||
|
||||
tests/itest/vagrant/log/run:
|
2
tests/cmd/only_dir_recursive_long_unix.toml
Normal file
2
tests/cmd/only_dir_recursive_long_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --recurse --long --no-user --no-time --no-filesize --no-permissions --only-dirs"
|
0
tests/cmd/only_dir_recursive_unix.stderr
Normal file
0
tests/cmd/only_dir_recursive_unix.stderr
Normal file
21
tests/cmd/only_dir_recursive_unix.stdout
Normal file
21
tests/cmd/only_dir_recursive_unix.stdout
Normal file
|
@ -0,0 +1,21 @@
|
|||
exa
|
||||
vagrant
|
||||
|
||||
tests/itest/exa:
|
||||
sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
||||
|
||||
tests/itest/exa/sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss:
|
||||
|
||||
tests/itest/vagrant:
|
||||
debug
|
||||
dev
|
||||
log
|
||||
|
||||
tests/itest/vagrant/debug:
|
||||
|
||||
tests/itest/vagrant/dev:
|
||||
|
||||
tests/itest/vagrant/log:
|
||||
run
|
||||
|
||||
tests/itest/vagrant/log/run:
|
2
tests/cmd/only_dir_recursive_unix.toml
Normal file
2
tests/cmd/only_dir_recursive_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --only-dirs --recurse"
|
0
tests/cmd/only_dir_unix.stderr
Normal file
0
tests/cmd/only_dir_unix.stderr
Normal file
2
tests/cmd/only_dir_unix.stdout
Normal file
2
tests/cmd/only_dir_unix.stdout
Normal file
|
@ -0,0 +1,2 @@
|
|||
exa
|
||||
vagrant
|
2
tests/cmd/only_dir_unix.toml
Normal file
2
tests/cmd/only_dir_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --only-dirs"
|
0
tests/cmd/recursive_long_unix.stderr
Normal file
0
tests/cmd/recursive_long_unix.stderr
Normal file
47
tests/cmd/recursive_long_unix.stdout
Normal file
47
tests/cmd/recursive_long_unix.stdout
Normal file
|
@ -0,0 +1,47 @@
|
|||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
exa
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
image.jpg.img.c.rs.log.png
|
||||
index.svg
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
vagrant
|
||||
|
||||
tests/itest/exa:
|
||||
file.c -> djihisudjuhfius
|
||||
sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
||||
|
||||
tests/itest/exa/sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss:
|
||||
Makefile
|
||||
|
||||
tests/itest/vagrant:
|
||||
debug
|
||||
dev
|
||||
log
|
||||
|
||||
tests/itest/vagrant/debug:
|
||||
symlinking -> a
|
||||
|
||||
tests/itest/vagrant/dev:
|
||||
main.bf
|
||||
|
||||
tests/itest/vagrant/log:
|
||||
file.png
|
||||
run
|
||||
|
||||
tests/itest/vagrant/log/run:
|
||||
run.log.text
|
||||
sps.log.text
|
2
tests/cmd/recursive_long_unix.toml
Normal file
2
tests/cmd/recursive_long_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --recurse --long --no-user --no-time --no-filesize --no-permissions"
|
0
tests/cmd/recursive_unix.stderr
Normal file
0
tests/cmd/recursive_unix.stderr
Normal file
47
tests/cmd/recursive_unix.stdout
Normal file
47
tests/cmd/recursive_unix.stdout
Normal file
|
@ -0,0 +1,47 @@
|
|||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
exa
|
||||
f
|
||||
g
|
||||
h
|
||||
i
|
||||
image.jpg.img.c.rs.log.png
|
||||
index.svg
|
||||
j
|
||||
k
|
||||
l
|
||||
m
|
||||
n
|
||||
o
|
||||
p
|
||||
q
|
||||
vagrant
|
||||
|
||||
tests/itest/exa:
|
||||
file.c -> djihisudjuhfius
|
||||
sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
||||
|
||||
tests/itest/exa/sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss:
|
||||
Makefile
|
||||
|
||||
tests/itest/vagrant:
|
||||
debug
|
||||
dev
|
||||
log
|
||||
|
||||
tests/itest/vagrant/debug:
|
||||
symlinking -> a
|
||||
|
||||
tests/itest/vagrant/dev:
|
||||
main.bf
|
||||
|
||||
tests/itest/vagrant/log:
|
||||
file.png
|
||||
run
|
||||
|
||||
tests/itest/vagrant/log/run:
|
||||
run.log.text
|
||||
sps.log.text
|
2
tests/cmd/recursive_unix.toml
Normal file
2
tests/cmd/recursive_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --recurse"
|
0
tests/cmd/tree_long_unix.stderr
Normal file
0
tests/cmd/tree_long_unix.stderr
Normal file
34
tests/cmd/tree_long_unix.stdout
Normal file
34
tests/cmd/tree_long_unix.stdout
Normal file
|
@ -0,0 +1,34 @@
|
|||
tests/itest
|
||||
├── a
|
||||
├── b
|
||||
├── c
|
||||
├── d
|
||||
├── e
|
||||
├── exa
|
||||
│ ├── file.c -> djihisudjuhfius
|
||||
│ └── sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
||||
│ └── Makefile
|
||||
├── f
|
||||
├── g
|
||||
├── h
|
||||
├── i
|
||||
├── image.jpg.img.c.rs.log.png
|
||||
├── index.svg
|
||||
├── j
|
||||
├── k
|
||||
├── l
|
||||
├── m
|
||||
├── n
|
||||
├── o
|
||||
├── p
|
||||
├── q
|
||||
└── vagrant
|
||||
├── debug
|
||||
│ └── symlinking -> a
|
||||
├── dev
|
||||
│ └── main.bf
|
||||
└── log
|
||||
├── file.png
|
||||
└── run
|
||||
├── run.log.text
|
||||
└── sps.log.text
|
2
tests/cmd/tree_long_unix.toml
Normal file
2
tests/cmd/tree_long_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --tree --long --no-user --no-time --no-filesize --no-permissions"
|
0
tests/cmd/tree_unix.stderr
Normal file
0
tests/cmd/tree_unix.stderr
Normal file
34
tests/cmd/tree_unix.stdout
Normal file
34
tests/cmd/tree_unix.stdout
Normal file
|
@ -0,0 +1,34 @@
|
|||
tests/itest
|
||||
├── a
|
||||
├── b
|
||||
├── c
|
||||
├── d
|
||||
├── e
|
||||
├── exa
|
||||
│ ├── file.c -> djihisudjuhfius
|
||||
│ └── sssssssssssssssssssssssssggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
|
||||
│ └── Makefile
|
||||
├── f
|
||||
├── g
|
||||
├── h
|
||||
├── i
|
||||
├── image.jpg.img.c.rs.log.png
|
||||
├── index.svg
|
||||
├── j
|
||||
├── k
|
||||
├── l
|
||||
├── m
|
||||
├── n
|
||||
├── o
|
||||
├── p
|
||||
├── q
|
||||
└── vagrant
|
||||
├── debug
|
||||
│ └── symlinking -> a
|
||||
├── dev
|
||||
│ └── main.bf
|
||||
└── log
|
||||
├── file.png
|
||||
└── run
|
||||
├── run.log.text
|
||||
└── sps.log.text
|
2
tests/cmd/tree_unix.toml
Normal file
2
tests/cmd/tree_unix.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bin.name = "eza"
|
||||
args = "tests/itest --tree"
|
|
@ -5,4 +5,7 @@
|
|||
rustfmt.enable = true;
|
||||
shellcheck.enable = true;
|
||||
};
|
||||
settings = {
|
||||
formatter.shellcheck.includes = ["*.sh" "./completions/bash/eza"];
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue