diff options
author | Chester Liu <skyline75489@outlook.com> | 2021-10-29 15:50:54 +0800 |
---|---|---|
committer | Chester Liu <skyline75489@outlook.com> | 2021-10-29 15:50:54 +0800 |
commit | 99d653b7fa3d6f29efe8c8e4506b3c97a2afa234 (patch) | |
tree | 547bf9850801fa9780d386b7e339203f2c790b51 | |
parent | 9881d00d00e1575229c47570017e386bdc202f6a (diff) | |
parent | b32f441851fdad8b5e3a6aa8cf23e276d7cc1278 (diff) |
Merge branch 'master' into chesterliu/dev/win-support
-rw-r--r-- | .github/workflows/unit-tests.yml | 54 | ||||
-rw-r--r-- | .travis.yml | 19 | ||||
-rw-r--r-- | Cargo.lock | 10 | ||||
-rw-r--r-- | Cargo.toml | 11 | ||||
-rw-r--r-- | README.md | 12 | ||||
-rw-r--r-- | build.rs | 3 | ||||
-rw-r--r-- | completions/bash/exa (renamed from completions/completions.bash) | 20 | ||||
-rwxr-xr-x | completions/fish/exa.fish (renamed from completions/completions.fish) | 22 | ||||
-rw-r--r-- | completions/zsh/_exa (renamed from completions/completions.zsh) | 4 | ||||
-rw-r--r-- | devtools/dev-bash.sh | 23 | ||||
-rwxr-xr-x | devtools/dev-create-test-filesystem.sh | 20 | ||||
-rw-r--r-- | devtools/dev-package-for-linux.sh | 13 | ||||
-rw-r--r-- | devtools/local-package-for-macos.sh | 13 | ||||
-rw-r--r-- | src/fs/dir_action.rs | 2 | ||||
-rw-r--r-- | src/fs/feature/git.rs | 8 | ||||
-rw-r--r-- | src/info/filetype.rs | 14 | ||||
-rw-r--r-- | src/main.rs | 1 | ||||
-rw-r--r-- | src/options/parser.rs | 2 | ||||
-rw-r--r-- | src/output/grid_details.rs | 4 | ||||
-rw-r--r-- | src/output/icons.rs | 14 | ||||
-rw-r--r-- | src/output/render/size.rs | 2 | ||||
-rw-r--r-- | xtests/git.toml | 12 | ||||
-rw-r--r-- | xtests/outputs/git4_long.ansitxt | 1 |
23 files changed, 195 insertions, 89 deletions
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml new file mode 100644 index 0000000..4071b3a --- /dev/null +++ b/.github/workflows/unit-tests.yml @@ -0,0 +1,54 @@ +name: Unit tests + +on: + push: + branches: [ master ] + paths: + - '.github/workflows/*' + - 'src/**' + - 'Cargo.*' + - build.rs + pull_request: + branches: [ master ] + paths: + - '.github/workflows/*' + - 'src/**' + - 'Cargo.*' + - build.rs + +env: + CARGO_TERM_COLOR: always + +jobs: + unit-tests: + runs-on: ${{ matrix.os }} + + continue-on-error: ${{ matrix.rust == 'nightly' }} + + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + rust: [1.48.0, stable, beta, nightly] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + + - name: Install cargo-hack + uses: actions-rs/cargo@v1 + with: + command: install + args: cargo-hack + + - name: Run unit tests + uses: actions-rs/cargo@v1 + with: + command: hack + args: test --feature-powerset diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1f08108..0000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: rust -rust: - - 1.45.2 - - stable - - beta - - nightly - -jobs: - fast_finish: true - allow_failures: - - rust: nightly - - include: - - name: 'Rust: test with all features' - rust: stable - install: - - cargo install cargo-hack - script: - - cargo hack test --feature-powerset @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "ansi_term" version = "0.12.1" @@ -90,9 +92,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.13.18" +version = "0.13.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b483c6c2145421099df1b4efd50e0f6205479a072199460eff852fa15e5603c7" +checksum = "d9831e983241f8c5591ed53f17d874833e2fa82cac2625f3888c50cbfe136cba" dependencies = [ "bitflags", "libc", @@ -151,9 +153,9 @@ checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" [[package]] name = "libgit2-sys" -version = "0.12.19+1.1.0" +version = "0.12.21+1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f322155d574c8b9ebe991a04f6908bb49e68a79463338d24a43d6274cb6443e6" +checksum = "86271bacd72b2b9e854c3dcfb82efd538f15f870e4c11af66900effb462f6825" dependencies = [ "cc", "libc", @@ -1,11 +1,11 @@ [package] name = "exa" description = "A modern replacement for ls" - authors = ["Benjamin Sago <ogham@bsago.me>"] categories = ["command-line-utilities"] edition = "2018" exclude = ["/devtools/*", "/Justfile", "/Vagrantfile", "/screenshots.png"] +readme = "README.md" homepage = "https://the.exa.website/" license = "MIT" repository = "https://github.com/ogham/exa" @@ -65,7 +65,7 @@ lto = true [package.metadata.deb] -license-file = [ "LICENCE" ] +license-file = [ "LICENCE", "4" ] depends = "$auto" extended-description = """ exa is a replacement for ls written in Rust. @@ -74,6 +74,9 @@ section = "utils" priority = "optional" assets = [ [ "target/release/exa", "/usr/bin/exa", "0755" ], - [ "contrib/man/exa.1", "/usr/share/man/man1/exa.1", "0644" ], - [ "contrib/completions.bash", "/etc/bash_completion.d/exa", "0644" ], + [ "target/release/../man/exa.1", "/usr/share/man/man1/exa.1", "0644" ], + [ "target/release/../man/exa_colors.5", "/usr/share/man/man5/exa_colors.5", "0644" ], + [ "completions/bash/exa", "/usr/share/bash-completion/completions/exa", "0644" ], + [ "completions/zsh/_exa", "/usr/share/zsh/site-functions/_exa", "0644" ], + [ "completions/fish/exa.fish", "/usr/share/fish/vendor_completions.d/exa.fish", "0644" ], ] @@ -1,17 +1,13 @@ <div align="center"> -<h1>exa</h1> + +# exa [exa](https://the.exa.website/) is a modern replacement for _ls_. **README Sections:** [Options](#options) — [Installation](#installation) — [Development](#development) -<a href="https://travis-ci.org/github/ogham/exa"> - <img src="https://travis-ci.org/ogham/exa.svg?branch=master" alt="Build status" /> -</a> - -<a href="https://saythanks.io/to/ogham%40bsago.me"> - <img src="https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg" alt="Say thanks!" /> -</a> +[![Unit tests](https://github.com/ogham/exa/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/ogham/exa/actions/workflows/unit-tests.yml) +[![Say thanks!](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/ogham%40bsago.me) </div> ![Screenshots of exa](screenshots.png) @@ -38,9 +38,10 @@ fn main() -> io::Result<()> { // We need to create these files in the Cargo output directory. let out = PathBuf::from(env::var("OUT_DIR").unwrap()); + let path = &out.join("version_string.txt"); // Bland version text - let mut f = File::create(&out.join("version_string.txt"))?; + let mut f = File::create(path).expect(&path.to_string_lossy()); writeln!(f, "{}", strip_codes(&ver))?; Ok(()) diff --git a/completions/completions.bash b/completions/bash/exa index 4a370f3..d044727 100644 --- a/completions/completions.bash +++ b/completions/bash/exa @@ -8,6 +8,11 @@ _exa() return ;; + --colour) + COMPREPLY=( $( compgen -W 'always auto never' -- "$cur" ) ) + return + ;; + -L|--level) COMPREPLY=( $( compgen -W '{0..9}' -- "$cur" ) ) return @@ -19,19 +24,28 @@ _exa() ;; -t|--time) - COMPREPLY=( $( compgen -W 'modified changed accessed created --' -- $cur ) ) + COMPREPLY=( $( compgen -W 'modified changed accessed created --' -- "$cur" ) ) return ;; --time-style) - COMPREPLY=( $( compgen -W 'default iso long-iso full-iso --' -- $cur ) ) + COMPREPLY=( $( compgen -W 'default iso long-iso full-iso --' -- "$cur" ) ) return ;; esac case "$cur" in + # _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=$( exa --help | grep -oE ' (\-\-[[:alnum:]@-]+)' | tr -d ' ' | grep -v '\-\-colo' ) + completions=$( echo '--color --colour --color-scale --colour-scale' $parse_help ) + COMPREPLY=( $( compgen -W "$completions" -- "$cur" ) ) + ;; + -*) - COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) ) + completions=$( exa --help | grep -oE ' (\-[[:alnum:]@])' | tr -d ' ' ) + COMPREPLY=( $( compgen -W "$completions" -- "$cur" ) ) ;; *) diff --git a/completions/completions.fish b/completions/fish/exa.fish index d261196..daf6a4b 100755 --- a/completions/completions.fish +++ b/completions/fish/exa.fish @@ -10,10 +10,14 @@ complete -c exa -s 'x' -l 'across' -d "Sort the grid across, rather than d complete -c exa -s 'R' -l 'recurse' -d "Recurse into directories" complete -c exa -s 'T' -l 'tree' -d "Recurse into directories as a tree" complete -c exa -s 'F' -l 'classify' -d "Display type indicator by file names" -complete -c exa -l 'color' -d "When to use terminal colours" -complete -c exa -l 'colour' -d "When to use terminal colours" -complete -c exa -l 'color-scale' -d "Highlight levels of file sizes distinctly" -complete -c exa -l 'colour-scale' -d "Highlight levels of file sizes distinctly" +complete -c exa -l 'color' \ + -l 'colour' -d "When to use terminal colours" -x -a " + always\t'Always use colour' + auto\t'Use colour if standard output is a terminal' + never\t'Never use colour' +" +complete -c exa -l 'color-scale' \ + -l 'colour-scale' -d "Highlight levels of file sizes distinctly" complete -c exa -l 'icons' -d "Display icons" complete -c exa -l 'no-icons' -d "Don't display icons" @@ -22,9 +26,9 @@ complete -c exa -l 'group-directories-first' -d "Sort directories before other f complete -c exa -l 'git-ignore' -d "Ignore files mentioned in '.gitignore'" complete -c exa -s 'a' -l 'all' -d "Show hidden and 'dot' files" complete -c exa -s 'd' -l 'list-dirs' -d "List directories like regular files" -complete -c exa -s 'L' -l 'level' -d "Limit the depth of recursion" -a "1 2 3 4 5 6 7 8 9" +complete -c exa -s 'L' -l 'level' -d "Limit the depth of recursion" -x -a "1 2 3 4 5 6 7 8 9" complete -c exa -s 'r' -l 'reverse' -d "Reverse the sort order" -complete -c exa -s 's' -l 'sort' -x -d "Which field to sort by" -a " +complete -c exa -s 's' -l 'sort' -d "Which field to sort by" -x -a " accessed\t'Sort by file accessed time' age\t'Sort by file modified time (newest first)' changed\t'Sort by changed time' @@ -56,10 +60,10 @@ complete -c exa -s 'b' -l 'binary' -d "List file sizes with binary prefixes" complete -c exa -s 'B' -l 'bytes' -d "List file sizes in bytes, without any prefixes" complete -c exa -s 'g' -l 'group' -d "List each file's group" complete -c exa -s 'h' -l 'header' -d "Add a header row to each column" -complete -c exa -s 'h' -l 'links' -d "List each file's number of hard links" +complete -c exa -s 'H' -l 'links' -d "List each file's number of hard links" complete -c exa -s 'g' -l 'group' -d "List each file's inode number" complete -c exa -s 'S' -l 'blocks' -d "List each file's number of filesystem blocks" -complete -c exa -s 't' -l 'time' -x -d "Which timestamp field to list" -a " +complete -c exa -s 't' -l 'time' -d "Which timestamp field to list" -x -a " modified\t'Display modified time' changed\t'Display changed time' accessed\t'Display accessed time' @@ -70,7 +74,7 @@ complete -c exa -s 'n' -l 'numeric' -d "List numeric user and group IDs." complete -c exa -l 'changed' -d "Use the changed timestamp field" complete -c exa -s 'u' -l 'accessed' -d "Use the accessed timestamp field" complete -c exa -s 'U' -l 'created' -d "Use the created timestamp field" -complete -c exa -l 'time-style' -x -d "How to format timestamps" -a " +complete -c exa -l 'time-style' -d "How to format timestamps" -x -a " default\t'Use the default time style' iso\t'Display brief ISO timestamps' long-iso\t'Display longer ISO timestaps, up to the minute' diff --git a/completions/completions.zsh b/completions/zsh/_exa index f339289..b915a5d 100644 --- a/completions/completions.zsh +++ b/completions/zsh/_exa @@ -1,7 +1,7 @@ #compdef exa # Save this file as _exa in /usr/local/share/zsh/site-functions or in any -# other folder in $fpath. E. g. save it in a folder called ~/.zfunc and add a +# other folder in $fpath. E.g. save it in a folder called ~/.zfunc and add a # line containing `fpath=(~/.zfunc $fpath)` somewhere before `compinit` in your # ~/.zshrc. @@ -19,7 +19,7 @@ __exa() { {-R,--recurse}"[Recurse into directories]" \ {-T,--tree}"[Recurse into directories as a tree]" \ {-F,--classify}"[Display type indicator by file names]" \ - --colo{,u}r"[When to use terminal colours]" \ + --colo{,u}r="[When to use terminal colours]:(when):(always auto never)" \ --colo{,u}r-scale"[Highlight levels of file sizes distinctly]" \ --icons"[Display icons]" \ --no-icons"[Hide icons]" \ diff --git a/devtools/dev-bash.sh b/devtools/dev-bash.sh index 95a48a4..8a9073b 100644 --- a/devtools/dev-bash.sh +++ b/devtools/dev-bash.sh @@ -11,17 +11,17 @@ bash /vagrant/devtools/dev-versions.sh # Configure the Cool Prompt™ (not actually trademarked). # The Cool Prompt tells you whether you’re in debug or strict mode, whether # you have colours configured, and whether your last command failed. -function nonzero_return() { RETVAL=$?; [ $RETVAL -ne 0 ] && echo "$RETVAL "; } -function debug_mode() { [ "$EXA_DEBUG" == "trace" ] && echo -n "trace-"; [ -n "$EXA_DEBUG" ] && echo "debug "; } -function strict_mode() { [ -n "$EXA_STRICT" ] && echo "strict "; } -function lsc_mode() { [ -n "$LS_COLORS" ] && echo "lsc "; } -function exac_mode() { [ -n "$EXA_COLORS" ] && echo "exac "; } +nonzero_return() { RETVAL=$?; [ "$RETVAL" -ne 0 ] && echo "$RETVAL "; } +debug_mode() { [ "$EXA_DEBUG" == "trace" ] && echo -n "trace-"; [ -n "$EXA_DEBUG" ] && echo "debug "; } +strict_mode() { [ -n "$EXA_STRICT" ] && echo "strict "; } +lsc_mode() { [ -n "$LS_COLORS" ] && echo "lsc "; } +exac_mode() { [ -n "$EXA_COLORS" ] && echo "exac "; } export PS1="\[\e[1;36m\]\h \[\e[32m\]\w \[\e[31m\]\`nonzero_return\`\[\e[35m\]\`debug_mode\`\[\e[32m\]\`lsc_mode\`\[\e[1;32m\]\`exac_mode\`\[\e[33m\]\`strict_mode\`\[\e[36m\]\\$\[\e[0m\] " # The ‘debug’ function lets you switch debug mode on and off. # Turn it on if you need to see exa’s debugging logs. -function debug () { +debug() { case "$1" in ""|"on") export EXA_DEBUG=1 ;; "off") export EXA_DEBUG= ;; @@ -33,11 +33,12 @@ function debug () { # The ‘strict’ function lets you switch strict mode on and off. # Turn it on if you’d like exa’s command-line arguments checked. -function strict () { - case "$1" in "on") export EXA_STRICT=1 ;; +strict() { + case "$1" in + "on") export EXA_STRICT=1 ;; "off") export EXA_STRICT= ;; - "") [ -n "$EXA_STRICT" ] && echo "strict on" || echo "strict off" ;; - *) echo "Usage: strict on|off"; return 1 ;; + "") [ -n "$EXA_STRICT" ] && echo "strict on" || echo "strict off" ;; + *) echo "Usage: strict on|off"; return 1 ;; esac; } @@ -45,7 +46,7 @@ function strict () { # environment variables. There’s also a ‘hacker’ theme which turns everything # green, which is usually used for checking that all colour codes work, and # for looking cool while you phreak some mainframes or whatever. -function colors () { +colors() { case "$1" in "ls") export LS_COLORS="di=34:ln=35:so=32:pi=33:ex=31:bd=34;46:cd=34;43:su=30;41:sg=30;46:tw=30;42:ow=30;43" diff --git a/devtools/dev-create-test-filesystem.sh b/devtools/dev-create-test-filesystem.sh index 112b569..74d5e2e 100755 --- a/devtools/dev-create-test-filesystem.sh +++ b/devtools/dev-create-test-filesystem.sh @@ -252,7 +252,7 @@ sudo chown $FIXED_USER:$FIXED_USER -R "$TEST_ROOT/attributes" # A sample Git repository # This uses cd because it's easier than telling Git where to go each time -echo -e "\033[1m[10/13]\033[0m Creating Git testcases (1/3)" +echo -e "\033[1m[10/13]\033[0m Creating Git testcases (1/4)" mkdir "$TEST_ROOT/git" cd "$TEST_ROOT/git" git init >/dev/null @@ -281,7 +281,7 @@ sudo chown $FIXED_USER:$FIXED_USER -R "$TEST_ROOT/git" # A second Git repository # for testing two at once -echo -e "\033[1m[11/13]\033[0m Creating Git testcases (2/3)" +echo -e "\033[1m[11/13]\033[0m Creating Git testcases (2/4)" mkdir -p "$TEST_ROOT/git2/deeply/nested/directory" cd "$TEST_ROOT/git2" git init >/dev/null @@ -321,7 +321,7 @@ sudo chown $FIXED_USER:$FIXED_USER -R "$TEST_ROOT/git2" # A third Git repository # Regression test for https://github.com/ogham/exa/issues/526 -echo -e "\033[1m[12/13]\033[0m Creating Git testcases (3/3)" +echo -e "\033[1m[12/13]\033[0m Creating Git testcases (3/4)" mkdir -p "$TEST_ROOT/git3" cd "$TEST_ROOT/git3" git init >/dev/null @@ -334,6 +334,20 @@ find "$TEST_ROOT/git3" -exec touch {} -h -t $FIXED_DATE \; sudo chown $FIXED_USER:$FIXED_USER -R "$TEST_ROOT/git3" +# A fourth Git repository +# Regression test for https://github.com/ogham/exa/issues/698 +echo -e "\033[1m[12/13]\033[0m Creating Git testcases (4/4)" +mkdir -p "$TEST_ROOT/git4" +cd "$TEST_ROOT/git4" +git init >/dev/null + +# Create a non UTF-8 file +touch 'P'$'\b\211''UUU' + +find "$TEST_ROOT/git4" -exec touch {} -h -t $FIXED_DATE \; +sudo chown $FIXED_USER:$FIXED_USER -R "$TEST_ROOT/git4" + + # Hidden and dot file testcases. # We need to set the permissions of `.` and `..` because they actually # get displayed in the output here, so this has to come last. diff --git a/devtools/dev-package-for-linux.sh b/devtools/dev-package-for-linux.sh index 2e79e00..4497df0 100644 --- a/devtools/dev-package-for-linux.sh +++ b/devtools/dev-package-for-linux.sh @@ -9,7 +9,7 @@ set -e # Linux check! -uname=`uname -s` +uname=$(uname -s) if [[ "$uname" != "Linux" ]]; then echo "Gotta be on Linux to run this (detected '$uname')!" exit 1 @@ -29,8 +29,8 @@ fi # Weekly builds have a bit more information in their version number (see build.rs). if [[ "$1" == "--weekly" ]]; then - git_hash=`GIT_DIR=/vagrant/.git git rev-parse --short --verify HEAD` - date=`date +"%Y-%m-%d"` + git_hash=$(GIT_DIR=/vagrant/.git git rev-parse --short --verify HEAD) + date=$(date +"%Y-%m-%d") echo "Building exa weekly v$exa_version, date $date, Git hash $git_hash" else echo "Building exa v$exa_version" @@ -57,9 +57,10 @@ strip -v "$exa_linux_binary" # the binaries can have consistent names, and it’s still possible to tell # different *downloads* apart. echo -e "\n\033[4mZipping binary...\033[0m" -if [[ "$1" == "--weekly" ]] - then exa_linux_zip="/vagrant/exa-linux-x86_64-${exa_version}-${date}-${git_hash}.zip" - else exa_linux_zip="/vagrant/exa-linux-x86_64.zip" +if [[ "$1" == "--weekly" ]]; then + exa_linux_zip="/vagrant/exa-linux-x86_64-${exa_version}-${date}-${git_hash}.zip" +else + exa_linux_zip="/vagrant/exa-linux-x86_64.zip" fi rm -vf "$exa_linux_zip" zip -j "$exa_linux_zip" "$exa_linux_binary" diff --git a/devtools/local-package-for-macos.sh b/devtools/local-package-for-macos.sh index 57dfbe6..f82841c 100644 --- a/devtools/local-package-for-macos.sh +++ b/devtools/local-package-for-macos.sh @@ -11,7 +11,7 @@ set -e # Virtualising macOS is a legal minefield, so this script is ‘local’ instead # of ‘dev’: I run it from my actual machine, rather than from a VM. -uname=`uname -s` +uname=$(uname -s) if [[ "$uname" != "Darwin" ]]; then echo "Gotta be on Darwin to run this (detected '$uname')!" exit 1 @@ -36,8 +36,8 @@ fi # Weekly builds have a bit more information in their version number (see build.rs). if [[ "$1" == "--weekly" ]]; then - git_hash=`GIT_DIR=$exa_root/.git git rev-parse --short --verify HEAD` - date=`date +"%Y-%m-%d"` + git_hash=$(GIT_DIR=$exa_root/.git git rev-parse --short --verify HEAD) + date=$(date +"%Y-%m-%d") echo "Building exa weekly v$exa_version, date $date, Git hash $git_hash" else echo "Building exa v$exa_version" @@ -65,9 +65,10 @@ echo "strip $exa_macos_binary" # the binaries can have consistent names, and it’s still possible to tell # different *downloads* apart. echo -e "\n\033[4mZipping binary...\033[0m" -if [[ "$1" == "--weekly" ]] - then exa_macos_zip="$exa_root/exa-macos-x86_64-${exa_version}-${date}-${git_hash}.zip" - else exa_macos_zip="$exa_root/exa-macos-x86_64-${exa_version}.zip" +if [[ "$1" == "--weekly" ]]; then + exa_macos_zip="$exa_root/exa-macos-x86_64-${exa_version}-${date}-${git_hash}.zip" +else + exa_macos_zip="$exa_root/exa-macos-x86_64-${exa_version}.zip" fi rm -vf "$exa_macos_zip" | sed 's/^/removing /' zip -j "$exa_macos_zip" "$exa_macos_binary" diff --git a/src/fs/dir_action.rs b/src/fs/dir_action.rs index 26e78d3..ab8ceda 100644 --- a/src/fs/dir_action.rs +++ b/src/fs/dir_action.rs @@ -51,7 +51,7 @@ impl DirAction { match self { Self::AsFile => true, Self::Recurse(o) => o.tree, - _ => false, + Self::List => false, } } } diff --git a/src/fs/feature/git.rs b/src/fs/feature/git.rs index f6e37ab..c700730 100644 --- a/src/fs/feature/git.rs +++ b/src/fs/feature/git.rs @@ -1,5 +1,8 @@ //! Getting the Git status of files and directories. +use std::ffi::OsStr; +#[cfg(target_family = "unix")] +use std::os::unix::ffi::OsStrExt; use std::path::{Path, PathBuf}; use std::sync::Mutex; @@ -205,6 +208,11 @@ fn repo_to_statuses(repo: &git2::Repository, workdir: &Path) -> Git { match repo.statuses(None) { Ok(es) => { for e in es.iter() { + #[cfg(target_family = "unix")] + let path = workdir.join(Path::new(OsStr::from_bytes(e.path_bytes()))); + // TODO: handle non Unix systems better: + // https://github.com/ogham/exa/issues/698 + #[cfg(not(target_family = "unix"))] let path = workdir.join(Path::new(e.path().unwrap())); let elem = (path, e.status()); statuses.push(elem); diff --git a/src/info/filetype.rs b/src/info/filetype.rs index 1def7a2..3011d5f 100644 --- a/src/info/filetype.rs +++ b/src/info/filetype.rs @@ -26,7 +26,7 @@ impl FileExtensions { file.name_is_one_of( &[ "Makefile", "Cargo.toml", "SConstruct", "CMakeLists.txt", "build.gradle", "pom.xml", "Rakefile", "package.json", "Gruntfile.js", - "Gruntfile.coffee", "BUILD", "BUILD.bazel", "WORKSPACE", "build.xml", + "Gruntfile.coffee", "BUILD", "BUILD.bazel", "WORKSPACE", "build.xml", "Podfile", "webpack.config.js", "meson.build", "composer.json", "RoboFile.php", "PKGBUILD", "Justfile", "Procfile", "Dockerfile", "Containerfile", "Vagrantfile", "Brewfile", "Gemfile", "Pipfile", "build.sbt", "mix.exs", "bsconfig.json", "tsconfig.json", @@ -35,10 +35,10 @@ impl FileExtensions { fn is_image(&self, file: &File<'_>) -> bool { file.extension_is_one_of( &[ - "png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif", - "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw", - "svg", "stl", "eps", "dvi", "ps", "cbr", "jpf", - "cbz", "xpm", "ico", "cr2", "orf", "nef", "heif", + "png", "jfi", "jfif", "jif", "jpe", "jpeg", "jpg", "gif", "bmp", + "tiff", "tif", "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw", + "svg", "stl", "eps", "dvi", "ps", "cbr", "jpf", "cbz", "xpm", + "ico", "cr2", "orf", "nef", "heif", "avif", "jxl", ]) } @@ -80,14 +80,14 @@ impl FileExtensions { file.extension_is_one_of( &[ "zip", "tar", "Z", "z", "gz", "bz2", "a", "ar", "7z", "iso", "dmg", "tc", "rar", "par", "tgz", "xz", "txz", - "lz", "tlz", "lzma", "deb", "rpm", "zst", + "lz", "tlz", "lzma", "deb", "rpm", "zst", "lz4", ]) } fn is_temp(&self, file: &File<'_>) -> bool { file.name.ends_with('~') || (file.name.starts_with('#') && file.name.ends_with('#')) - || file.extension_is_one_of( &[ "tmp", "swp", "swo", "swn", "bak", "bk" ]) + || file.extension_is_one_of( &[ "tmp", "swp", "swo", "swn", "bak", "bkp", "bk" ]) } fn is_compiled(&self, file: &File<'_>) -> bool { diff --git a/src/main.rs b/src/main.rs index c3cdd2d..7bb193a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ #![allow(clippy::non_ascii_literal)] #![allow(clippy::option_if_let_else)] #![allow(clippy::too_many_lines)] +#![allow(clippy::unnested_or_patterns)] // TODO: remove this when we support Rust 1.53.0 #![allow(clippy::unused_self)] #![allow(clippy::upper_case_acronyms)] #![allow(clippy::wildcard_imports)] diff --git a/src/options/parser.rs b/src/options/parser.rs index 1a765b6..63a1606 100644 --- a/src/options/parser.rs +++ b/src/options/parser.rs @@ -430,7 +430,7 @@ impl<'a> MatchedFlags<'a> { .filter(|tuple| tuple.1.is_some() && predicate(&tuple.0)) .collect::<Vec<_>>(); - if those.len() < 2 { Ok(those.first().cloned().map(|t| t.1.unwrap())) } + if those.len() < 2 { Ok(those.first().copied().map(|t| t.1.unwrap())) } else { Err(OptionsError::Duplicate(those[0].0, those[1].0)) } } else { diff --git a/src/output/grid_details.rs b/src/output/grid_details.rs index 35ff023..088d7a8 100644 --- a/src/output/grid_details.rs +++ b/src/output/grid_details.rs @@ -158,7 +158,7 @@ impl<'a> Render<'a> { .collect::<Vec<_>>(); let mut last_working_grid = self.make_grid(1, options, &file_names, rows.clone(), &drender); - + if file_names.len() == 1 { return Some((last_working_grid, 1)); } @@ -176,7 +176,7 @@ impl<'a> Render<'a> { if the_grid_fits { last_working_grid = grid; } - + if !the_grid_fits || column_count == file_names.len() { let last_column_count = if the_grid_fits { column_count } else { column_count - 1 }; // If we’ve figured out how many columns can fit in the user’s terminal, diff --git a/src/output/icons.rs b/src/output/icons.rs index eea0286..eb7666a 100644 --- a/src/output/icons.rs +++ b/src/output/icons.rs @@ -80,7 +80,7 @@ lazy_static! { m.insert("include", '\u{e5fc}'); // m.insert("lib", '\u{f121}'); // m.insert("localized", '\u{f179}'); // - m.insert("Makefile", '\u{e779}'); // + m.insert("Makefile", '\u{f489}'); // m.insert("node_modules", '\u{e718}'); // m.insert("npmignore", '\u{e71e}'); // m.insert("rubydoc", '\u{e73b}'); // @@ -110,6 +110,7 @@ pub fn icon_for_file(file: &File<'_>) -> char { "apk" => '\u{e70e}', // "apple" => '\u{f179}', // "avi" => '\u{f03d}', // + "avif" => '\u{f1c5}', // "avro" => '\u{e60b}', // "awk" => '\u{f489}', // "bash" => '\u{f489}', // @@ -206,11 +207,16 @@ pub fn icon_for_file(file: &File<'_>) -> char { "jad" => '\u{e256}', // "jar" => '\u{e204}', // "java" => '\u{e204}', // + "jfi" => '\u{f1c5}', // + "jfif" => '\u{f1c5}', // + "jif" => '\u{f1c5}', // + "jpe" => '\u{f1c5}', // "jpeg" => '\u{f1c5}', // "jpg" => '\u{f1c5}', // "js" => '\u{e74e}', // "json" => '\u{e60b}', // "jsx" => '\u{e7ba}', // + "jxl" => '\u{f1c5}', // "ksh" => '\u{f489}', // "latex" => '\u{f034}', // "less" => '\u{e758}', // @@ -221,6 +227,7 @@ pub fn icon_for_file(file: &File<'_>) -> char { "log" => '\u{f18d}', // "lua" => '\u{e620}', // "lz" => '\u{f410}', // + "lz4" => '\u{f410}', // "lzh" => '\u{f410}', // "lzma" => '\u{f410}', // "lzo" => '\u{f410}', // @@ -230,6 +237,7 @@ pub fn icon_for_file(file: &File<'_>) -> char { "markdown" => '\u{f48a}', // "md" => '\u{f48a}', // "mjs" => '\u{e74e}', // + "mk" => '\u{f489}', // "mkd" => '\u{f48a}', // "mkv" => '\u{f03d}', // "mobi" => '\u{e28b}', // @@ -292,6 +300,7 @@ pub fn icon_for_file(file: &File<'_>) -> char { "so" => '\u{f17c}', // "sql" => '\u{f1c0}', // "sqlite3" => '\u{e7c4}', // + "sty" => '\u{f034}', // "styl" => '\u{e600}', // "stylus" => '\u{e600}', // "svg" => '\u{f1c5}', // @@ -301,7 +310,9 @@ pub fn icon_for_file(file: &File<'_>) -> char { "tbz" => '\u{f410}', // "tbz2" => '\u{f410}', // "tex" => '\u{f034}', // + "tgz" => '\u{f410}', // "tiff" => '\u{f1c5}', // + "tlz" => '\u{f410}', // "toml" => '\u{e615}', // "ts" => '\u{e628}', // "tsv" => '\u{f1c3}', // @@ -309,6 +320,7 @@ pub fn icon_for_file(file: &File<'_>) -> char { "ttf" => '\u{f031}', // "twig" => '\u{e61c}', // "txt" => '\u{f15c}', // + "txz" => '\u{f410}', // "tz" => '\u{f410}', // "tzo" => '\u{f410}', // "video" => '\u{f03d}', // diff --git a/src/output/render/size.rs b/src/output/render/size.rs index 94f751b..5a3ad72 100644 --- a/src/output/render/size.rs +++ b/src/output/render/size.rs @@ -46,7 +46,7 @@ impl f::Size { } else { numerics.format_int(n.round() as isize) }; - + TextCell { // symbol is guaranteed to be ASCII since unit prefixes are hardcoded. width: DisplayWidth::from(&*number) + symbol.len(), diff --git a/xtests/git.toml b/xtests/git.toml index c262e9e..ea64cad 100644 --- a/xtests/git.toml +++ b/xtests/git.toml @@ -144,6 +144,18 @@ status = 0 tags = [ 'long', 'git' ] + +# The forth Git repo: non UTF-8 file + +[[cmd]] +name = "‘exa --git -l’ handles non UTF8 file in Git repositories" +shell = "exa --git -l /testcases/git4" +stdout = { file = "outputs/git4_long.ansitxt" } +stderr = { empty = true } |