Skip to content

Commit

Permalink
Merge branch 'command-line'
Browse files Browse the repository at this point in the history
Provides shell completion and makes all the command-line options consistent and complete.

Fixes #150, which tracked shell completion.
  • Loading branch information
ogham committed May 6, 2017
2 parents 1546994 + e2f7392 commit 897d6ff
Show file tree
Hide file tree
Showing 8 changed files with 301 additions and 118 deletions.
54 changes: 27 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,45 +14,45 @@ exa’s options are similar, but not exactly the same, as `ls`.
### Display Options

- **-1**, **--oneline**: display one entry per line
- **-G**, **--grid**: display entries in a grid view (default)
- **-G**, **--grid**: display entries as a grid (default)
- **-l**, **--long**: display extended details and attributes
- **-R**, **--recurse**: recurse into directories
- **-T**, **--tree**: recurse into subdirectories in a tree view
- **-x**, **--across**: sort multi-column view entries across
- **--color**, **--colour**: when to colourise the output
- **--color-scale**, **--colour-scale**: colour file sizes according to their magnitude
- **-T**, **--tree**: recurse into directories as a tree
- **-x**, **--across**: sort the grid across, rather than downwards
- **--colo[u]r**: when to use terminal colours
- **--colo[u]r-scale**: highlight levels of file sizes distinctly

### Filtering Options

- **-a**, **--all**: show dot files
- **-d**, **--list-dirs**: list directories as regular files
- **-L**, **--level=(depth)**: maximum depth of recursion
- **-r**, **--reverse**: reverse sort order
- **-s**, **--sort=(field)**: field to sort by
- **-a**, **--all**: don't hide hidden and 'dot' files
- **-d**, **--list-dirs**: list directories like regular files
- **-L**, **--level=(depth)**: limit the depth of recursion
- **-r**, **--reverse**: reverse the sort order
- **-s**, **--sort=(field)**: which field to sort by
- **--group-directories-first**: list directories before other files
- **-I**, **--ignore-glob=(globs)**: glob patterns (pipe-separated) of files to ignore

### Long View Options

These options are available when running with --long (`-l`):

- **-b**, **--binary**: use binary (power of two) file sizes
- **-B**, **--bytes**: list file sizes in bytes, without prefixes
- **-g**, **--group**: show group as well as user
- **-h**, **--header**: show a header row
- **-H**, **--links**: show number of hard links column
- **-i**, **--inode**: show inode number column
- **-m**, **--modified**: display timestamp of most recent modification
- **-S**, **--blocks**: show number of file system blocks
- **-t**, **--time=(field)**: which timestamp to show for a file
- **-u**, **--accessed**: display timestamp of last access for a file
- **-U**, **--created**: display timestamp of creation of a file
- **-@**, **--extended**: display extended attribute keys and sizes
- **--git**: show Git status for a file

Accepted **--color** options are **always**, **automatic**, and **never**.
Valid sort fields are **name**, **size**, **extension**, **modified**, **accessed**, **created**, **inode**, and **none**.
Valid time fields are **modified**, **accessed**, and **created**.
- **-b**, **--binary**: list file sizes with binary prefixes
- **-B**, **--bytes**: list file sizes in bytes, without any prefixes
- **-g**, **--group**: list each file's group
- **-h**, **--header**: add a header row to each column
- **-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
- **-S**, **--blocks**: list each file's number of file system blocks
- **-t**, **--time=(field)**: which timestamp field to use
- **-u**, **--accessed**: use the accessed timestamp field
- **-U**, **--created**: use the created timestamp field
- **-@**, **--extended**: list each file's extended attributes and sizes
- **--git**: list each file's Git status, if tracked

- Valid **--color** options are **always**, **automatic**, and **never**.
- Valid sort fields are **accessed**, **created**, **extension**, **Extension**, **inode**, **modified**, **name**, **Name**, **size**, and **none**. Fields starting with a capital letter are case-sensitive.
- Valid time fields are **modified**, **accessed**, and **created**.


## Installation
Expand Down
44 changes: 38 additions & 6 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Vagrant.configure(2) do |config|
v.cpus = 1
end

developer = 'ubuntu'


# We use Ubuntu instead of Debian because the image comes with two-way
# shared folder support by default.
Expand All @@ -16,8 +18,11 @@ Vagrant.configure(2) do |config|

# Install the dependencies needed for exa to build, as quietly as
# apt can do.
config.vm.provision :shell, privileged: true, inline:
%[apt-get install -qq -o=Dpkg::Use-Pty=0 -y git cmake libgit2-dev curl attr pkg-config]
config.vm.provision :shell, privileged: true, inline: <<-EOF
apt-get install -qq -o=Dpkg::Use-Pty=0 -y \
git cmake curl attr pkg-config libgit2-dev \
fish zsh bash bash-completion
EOF


# Guarantee that the timezone is UTC -- some of the tests
Expand All @@ -38,13 +43,40 @@ Vagrant.configure(2) do |config|
# By default it just uses the one in /vagrant/target, which can
# cause problems if it has different permissions than the other
# directories, or contains object files compiled for the host.
config.vm.provision :shell, privileged: false, inline:
%[echo "export CARGO_TARGET_DIR=/home/ubuntu/target" >> ~/.bashrc]
config.vm.provision :shell, privileged: false, inline: <<-EOF
function put_line() {
grep -q -F "$2" $1 || echo "$2" >> $1
}
put_line ~/.bashrc 'export CARGO_TARGET_DIR=/home/#{developer}/target'
EOF


# Create "dexa" and "rexa" scripts that run the debug and release
# compiled versions of exa.
config.vm.provision :shell, privileged: true, inline: <<-EOF
echo -e "#!/bin/sh\n/home/#{developer}/target/debug/exa \\$*" > /usr/bin/exa
echo -e "#!/bin/sh\n/home/#{developer}/target/release/exa \\$*" > /usr/bin/rexa
chmod +x /usr/bin/{exa,rexa}
EOF


# Link the completion files so they’re “installed”.
config.vm.provision :shell, privileged: true, inline: <<-EOF
test -h /etc/bash_completion.d/exa \
|| ln -s /vagrant/contrib/completions.bash /etc/bash_completion.d/exa
test -h /usr/share/zsh/vendor-completions/_exa \
|| ln -s /vagrant/contrib/completions.zsh /usr/share/zsh/vendor-completions/_exa
test -h /usr/share/fish/completions/exa.fish \
|| ln -s /vagrant/contrib/completions.fish /usr/share/fish/completions/exa.fish
EOF


# We create two users that own the test files.
# The first one just owns the ordinary ones, because we don’t want to
# depend on “vagrant” or “ubuntu” existing.
# The first one just owns the ordinary ones, because we don’t want the
# test outputs to depend on “vagrant” or “ubuntu” existing.
user = "cassowary"
config.vm.provision :shell, privileged: true, inline:
%[id -u #{user} &>/dev/null || useradd #{user}]
Expand Down
37 changes: 37 additions & 0 deletions contrib/completions.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
_exa()
{
cur=${COMP_WORDS[COMP_CWORD]}
prev=${COMP_WORDS[COMP_CWORD-1]}

case "$prev" in
-'?'|--help|-v|--version)
return
;;

-L|--level)
COMPREPLY=( $( compgen -W '{0..9}' -- "$cur" ) )
return
;;

-s|--sort)
COMPREPLY=( $( compgen -W 'name filename Name Filename size filesize extension Extension modified accessed created none inode --' -- "$cur" ) )
return
;;

-t|--time)
COMPREPLY=( $( compgen -W 'accessed modified created --' -- $cur ) )
return
;;
esac

case "$cur" in
-*)
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) )
;;

*)
_filedir
;;
esac
} &&
complete -o filenames -o bashdefault -F _exa exa
62 changes: 62 additions & 0 deletions contrib/completions.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Meta-stuff
complete -c exa -s 'v' -l 'version' -d "Show version of exa"
complete -c exa -s '?' -l 'help' -d "Show list of command-line options"

# Display options
complete -c exa -s '1' -l 'oneline' -d "Display one entry per line"
complete -c exa -s 'l' -l 'long' -d "Display extended file metadata as a table"
complete -c exa -s 'G' -l 'grid' -d "Display entries in a grid"
complete -c exa -s 'x' -l 'across' -d "Sort the grid across, rather than downwards"
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"

# Filtering and sorting options
complete -c exa -l 'group-directories-first' -d "Sort directories before other files"
complete -c exa -s 'a' -l 'all' -d "Don't hide 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 'r' -l 'reverse' -d "Reverse the sort order"
complete -c exa -s 's' -l 'sort' -x -d "Which field to sort by" -a "
accessed\t'Sort by file accessed time'
created\t'Sort by file modified time'
ext\t'Sort by file extension'
Ext\t'Sort by file extension (case-insensitive)'
extension\t'Sort by file extension'
Extension\t'Sort by file extension (case-insensitive)'
filename\t'Sort by filename'
Filename\t'Sort by filename (case-insensitive)'
inode\t'Sort by file inode'
modified\t'Sort by file modified time'
name\t'Sort by filename'
Name\t'Sort by filename (case-insensitive)'
none\t'Do not sort files at all'
size\t'Sort by file size'
"

complete -c exa -s 'I' -l 'ignore-glob' -d "Ignore files that match these glob patterns" -r

# Long view options
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 'g' -l 'group' -d "List each file's inode number"
complete -c exa -s 'm' -l 'modified' -d "Use the modified timestamp field"
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 "
accessed\t'Display accessed time'
created\t'Display created time'
modified\t'Display modified time'
"
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"

# Optional extras
complete -c exa -s 'g' -l 'git' -d "List each file's Git status, if tracked"
complete -c exa -s '@' -l 'extended' -d "List each file's extended attributes and sizes"
39 changes: 39 additions & 0 deletions contrib/completions.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#compdef exa

__exa() {
_arguments \
"(- 1 *)"{-v,--version}"[Show version of exa]" \
"(- 1 *)"{-\?,--help}"[Show list of command-line options]" \
{-1,--oneline}"[Display one entry per line]" \
{-l,--long}"[Display extended file metadata as a table]" \
{-G,--grid}"[Display entries as a grid]" \
{-x,--across}"[Sort the grid across, rather than downwards]" \
{-R,--recurse}"[Recurse into directories]" \
{-T,--tree}"[Recurse into directories as a tree]" \
{-F,--classify}"[Display type indicator by file names]" \
{--color,--colour}"[When to use terminal colours]" \
{--color,--colour}-scale"[Highlight levels of file sizes distinctly]" \
--group-directories-first"[Sort directories before other files]" \
{-a,--all}"[Don't hide hidden and 'dot' files]" \
{-d,--list-dirs}"[List directories like regular files]" \
{-L,--level}"+[Limit the depth of recursion]" \
{-r,--reverse}"[Reverse the sort order]" \
{-s,--sort}"[Which field to sort by]:(sort field):(accessed created extension Extension filename Filename inode modified name Name none size)" \
{-I,--ignore-glob}"[Ignore files that match these glob patterns]" \
{-b,--binary}"[List file sizes with binary prefixes]" \
{-B,--bytes}"[List file sizes in bytes, without any prefixes]" \
{-g,--group}"[List each file's group]" \
{-h,--header}"[Add a header row to each column]" \
{-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]" \
{-S,--blocks}"[List each file's number of filesystem blocks]" \
{-t,--time}"[Which time field to show]:(time field):(accessed created modified)" \
{-u,--accessed}"[Use the accessed timestamp field]" \
{-U,--created}"[Use the created timestamp field]" \
--git"[List each file's Git status, if tracked]" \
{-@,--extended}"[List each file's extended attributes and sizes]" \
'*:filename:_files'
}

__exa
Loading

0 comments on commit 897d6ff

Please sign in to comment.