diff options
author | Kevin Ballard <kevin@sb.org> | 2014-07-09 23:38:33 -0700 |
---|---|---|
committer | Kevin Ballard <kevin@sb.org> | 2014-07-13 19:11:29 -0700 |
commit | bfd3a47380f65e24ff568efd1570338298d56200 (patch) | |
tree | 6b9aab751d324512314e07067e7fd20817c7f4e8 /share/functions/type.fish | |
parent | 0933e5cab470125fc3757dc146173551a4cad177 (diff) |
Fix `type` function to work better
Stop using getopt to parse flags. It's far more expensive than
necessary, and results in long flags not being parsed on OS X. This also
allows args starting with - after the options list to be properly
interpreted as a value to test.
Print the error message to stderr as is appropriate.
Use the new `command -p` functionality when the -a flag has not been
provided (`command` does not have any equivalent to the -a flag),
instead of using `which`. This is faster and also avoids any possible
disagreement between `which` and what fish thinks is valid.
Stop testing every path to see if it's executable, that test has already
been done by `which` or `command -p`.
The end result is `type -P ls` is roughly 250% faster, according to
profiling, on my OS X machine.
Diffstat (limited to 'share/functions/type.fish')
-rw-r--r-- | share/functions/type.fish | 114 |
1 files changed, 43 insertions, 71 deletions
diff --git a/share/functions/type.fish b/share/functions/type.fish index 4a4c7703..2ddcc622 100644 --- a/share/functions/type.fish +++ b/share/functions/type.fish @@ -5,74 +5,48 @@ function type --description "Print the type of a command" set -l res 1 set -l mode normal set -l selection all - - # - # Get options - # - set -l options - set -l shortopt tpPafh - if not getopt -T > /dev/null - # GNU getopt - set -l longopt type,path,force-path,all,no-functions,help - set options -o $shortopt -l $longopt -- - # Verify options - if not getopt -n type $options $argv >/dev/null - return 1 - end - else - # Old getopt, used on OS X - set options $shortopt - # Verify options - if not getopt $options $argv >/dev/null - return 1 - end - end - # Do the real getopt invocation - set -l tmp (getopt $options $argv) + # Parse options + set -l names + if test (count $argv) -gt 0 + for i in (seq (count $argv)) + switch $argv[$i] + case -t --type + set mode type - # Break tmp up into an array - set -l opt - eval set opt $tmp - - for i in $opt - switch $i - case -t --type - set mode type + case -p --path + set mode path - case -p --path - set mode path + case -P --force-path + set mode path + set selection files - case -P --force-path - set mode path - set selection files + case -a --all + set selection multi - case -a --all - set selection multi + case -f --no-functions + set selection files - case -f --no-functions - set selection files + case -h --help + __fish_print_help type + return 0 - case -h --help - __fish_print_help type - return 0 - - case -- - break + case -- + set names $argv[$i..-1] + set -e names[1] + break + case '*' + set names $argv[$i..-1] + break + end end end # Check all possible types for the remaining arguments - for i in $argv - - switch $i - case '-*' - continue - end - + for i in $names # Found will be set to 1 if a match is found - set found 0 + set -l found 0 if test $selection != files @@ -119,32 +93,30 @@ function type --description "Print the type of a command" set -l paths if test $selection != multi - set paths (which $i ^/dev/null) + set paths (command -p $i) else set paths (which -a $i ^/dev/null) end for path in $paths - if test -x (echo $path) - set res 0 - set found 1 - switch $mode - case normal - printf (_ '%s is %s\n') $i $path + set res 0 + set found 1 + switch $mode + case normal + printf (_ '%s is %s\n') $i $path - case type - echo (_ 'file') + case type + echo (_ 'file') - case path - echo $path - end - if test $selection != multi - continue - end + case path + echo $path + end + if test $selection != multi + continue end end if test $found = 0 - printf (_ "%s: Could not find '%s'\n") type $i + printf (_ "%s: Could not find '%s'\n") type $i >&2 end end |