diff --git a/Makefile.in b/Makefile.in index 9fe0f8e05..4995dddcc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -284,7 +284,7 @@ doc/refman.pdf: doc test: $(PROGRAMS) fish_tests ./fish_tests - cd tests; ../fish 0) + { + wcstring chars(bufflen+(bufflen-1), ARRAY_SEP); + for (size_t j=0; jcommand COMMANDNAME [OPTIONS...] +command [OPTIONS] COMMANDNAME [ARGS...] \subsection command-description Description \c command forces the shell to execute the program \c COMMANDNAME and ignore any functions or builtins with the same name. -\subsection command-example Example +The following options are available: +- \c -h or \c --help prints help and then exits. +- \c -s or \c --search returns the name of the disk file that would be executed, or nothing if no file with the specified name could be found in the $PATH. + +With the \c -s option, \c command treats every argument as a separate command to look up and sets the exit status to 0 if any of the specified commands were found, or 1 if no commands could be found. + +For basic compatibility with POSIX command, the \c -v flag is recognized as an alias for -s. + +\subsection command-example Examples command ls causes fish to execute the \c ls program, even if an 'ls' function exists. + +command -s ls returns the path to the \c ls program. diff --git a/doc_src/read.txt b/doc_src/read.txt index ca7a4d145..4f1760a56 100644 --- a/doc_src/read.txt +++ b/doc_src/read.txt @@ -19,11 +19,17 @@ The following options are available: - -u or --unexport prevents the variables from being exported to child processes (default behaviour). - -U or --universal causes the specified shell variable to be made universal. - -x or --export exports the variables to child processes. +- -a or --array stores the result as an array. \c read reads a single line of input from stdin, breaks it into tokens based on the IFS shell variable, and then assigns one token to each variable specified in VARIABLES. If there are more tokens than variables, the complete remainder is assigned to the last variable. +As a special case, if \c IFS is set to the empty string, each character of the +input is considered a separate token. + +If \c -a or \c --array is provided, only one variable name is allowed and the +tokens are stored as an array in this variable. See the documentation for \c set for more details on the scoping rules for variables. diff --git a/doc_src/type.txt b/doc_src/type.txt index 9b5699f35..8945102ca 100644 --- a/doc_src/type.txt +++ b/doc_src/type.txt @@ -12,9 +12,10 @@ The following options are available: - \c -h or \c --help prints help and then exits. - \c -a or \c --all prints all of possible definitions of the specified names. - \c -f or \c --no-functions suppresses function and builtin lookup. -- \c -t or \c --type prints keyword, function, builtin, or file if \c NAME is a shell reserved word, function, builtin, or disk file, respectively. +- \c -t or \c --type prints function, builtin, or file if \c NAME is a shell function, builtin, or disk file, respectively. - \c -p or \c --path returns the name of the disk file that would be executed, or nothing if 'type -t name' would not return 'file'. -- \c -P or \c --force-path returns the name of the disk file that would be executed, or nothing no file with the specified name could be found in the $PATH. +- \c -P or \c --force-path returns the name of the disk file that would be executed, or nothing if no file with the specified name could be found in the $PATH. +- \c -q or \c --quiet suppresses all output; this is useful when testing the exit status. \c type sets the exit status to 0 if the specified command was found, and 1 if it could not be found. diff --git a/share/functions/__fish_complete_cabal.fish b/share/functions/__fish_complete_cabal.fish index b5b8c0c00..484710a84 100644 --- a/share/functions/__fish_complete_cabal.fish +++ b/share/functions/__fish_complete_cabal.fish @@ -1,5 +1,5 @@ function __fish_complete_cabal - if type -f cabal >/dev/null + if type -q -f cabal set cmd (commandline -poc) if test (count $cmd) -gt 1 cabal $cmd[2..-1] --list-options diff --git a/share/functions/__fish_complete_vi.fish b/share/functions/__fish_complete_vi.fish index 8a07ffd2e..51009d8b8 100644 --- a/share/functions/__fish_complete_vi.fish +++ b/share/functions/__fish_complete_vi.fish @@ -2,7 +2,7 @@ function __fish_complete_vi -d "Compleletions for vi and its aliases" --argument-names cmd set -l is_vim - if type $cmd > /dev/null + if type -q $cmd eval command $cmd --version >/dev/null ^/dev/null; and set -l is_vim vim end diff --git a/share/functions/__fish_config_interactive.fish b/share/functions/__fish_config_interactive.fish index 46b6ca248..1d3a1bea2 100644 --- a/share/functions/__fish_config_interactive.fish +++ b/share/functions/__fish_config_interactive.fish @@ -248,7 +248,7 @@ function __fish_config_interactive -d "Initializations that should be performed # First check if we are on OpenSUSE since SUSE's handler has no options # and expects first argument to be a command and second database # also check if there is command-not-found command. - if begin; test -f /etc/SuSE-release; and type -p command-not-found > /dev/null 2> /dev/null; end + if begin; test -f /etc/SuSE-release; and type -q -p command-not-found; end function __fish_command_not_found_handler --on-event fish_command_not_found /usr/bin/command-not-found $argv end @@ -263,7 +263,7 @@ function __fish_config_interactive -d "Initializations that should be performed /usr/lib/command-not-found -- $argv end # Ubuntu Feisty places this command in the regular path instead - else if type -p command-not-found > /dev/null 2> /dev/null + else if type -q -p command-not-found function __fish_command_not_found_handler --on-event fish_command_not_found command-not-found -- $argv end diff --git a/share/functions/__fish_print_packages.fish b/share/functions/__fish_print_packages.fish index 6755dd6ae..050fcac28 100644 --- a/share/functions/__fish_print_packages.fish +++ b/share/functions/__fish_print_packages.fish @@ -18,7 +18,7 @@ function __fish_print_packages end mkdir -m 700 -p $XDG_CACHE_HOME - if type -f apt-cache >/dev/null + if type -q -f apt-cache # Do not generate the cache as apparently sometimes this is slow. # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=547550 apt-cache --no-generate pkgnames (commandline -tc) ^/dev/null | sed -e 's/$/'\t$package'/' @@ -28,7 +28,7 @@ function __fish_print_packages # Pkg is fast on FreeBSD and provides versioning info which we want for # installed packages if begin - type -f pkg > /dev/null + type -q -f pkg and test (uname) = "FreeBSD" end pkg query "%n-%v" @@ -36,7 +36,7 @@ function __fish_print_packages end # Caches for 5 minutes - if type -f pacman >/dev/null + if type -q -f pacman set cache_file $XDG_CACHE_HOME/.pac-cache.$USER if test -f $cache_file cat $cache_file @@ -53,7 +53,7 @@ function __fish_print_packages end # yum is slow, just like rpm, so go to the background - if type -f /usr/share/yum-cli/completion-helper.py >/dev/null + if type -q -f /usr/share/yum-cli/completion-helper.py # If the cache is less than six hours old, we do not recalculate it @@ -75,7 +75,7 @@ function __fish_print_packages # Rpm is too slow for this job, so we set it up to do completions # as a background job and cache the results. - if type -f rpm >/dev/null + if type -q -f rpm # If the cache is less than five minutes old, we do not recalculate it @@ -99,12 +99,12 @@ function __fish_print_packages # installed on the system packages is in completions/emerge.fish # eix is MUCH faster than emerge so use it if it is available - if type -f eix > /dev/null + if type -q -f eix eix --only-names "^"(commandline -tc) | cut -d/ -f2 return else # FIXME? Seems to be broken - if type -f emerge >/dev/null + if type -q -f emerge emerge -s \^(commandline -tc) |sgrep "^*" |cut -d\ -f3 |cut -d/ -f2 return end diff --git a/share/functions/funced.fish b/share/functions/funced.fish index ca2e27721..074e3c435 100644 --- a/share/functions/funced.fish +++ b/share/functions/funced.fish @@ -51,7 +51,7 @@ function funced --description 'Edit function definition' if test -n "$editor" set -l editor_cmd eval set editor_cmd $editor - if not type -f "$editor_cmd[1]" >/dev/null + if not type -q -f "$editor_cmd[1]" _ "funced: The value for \$EDITOR '$editor' could not be used because the command '$editor_cmd[1]' could not be found " set editor fish diff --git a/share/functions/help.fish b/share/functions/help.fish index 04992e35d..a04add53f 100644 --- a/share/functions/help.fish +++ b/share/functions/help.fish @@ -25,7 +25,7 @@ function help --description 'Show help for the fish shell' set -l graphical_browsers htmlview x-www-browser firefox galeon mozilla konqueror epiphany opera netscape rekonq google-chrome chromium-browser set -l text_browsers htmlview www-browser links elinks lynx w3m - if type "$BROWSER" >/dev/null + if type -q "$BROWSER" # User has manually set a preferred browser, so we respect that set fish_browser $BROWSER @@ -36,7 +36,7 @@ function help --description 'Show help for the fish shell' else # Check for a text-based browser. for i in $text_browsers - if type -f $i >/dev/null + if type -q -f $i set fish_browser $i break end @@ -46,7 +46,7 @@ function help --description 'Show help for the fish shell' # browser to use instead. if test "$DISPLAY" -a \( "$XAUTHORITY" = "$HOME/.Xauthority" -o "$XAUTHORITY" = "" \) for i in $graphical_browsers - if type -f $i >/dev/null + if type -q -f $i set fish_browser $i set fish_browser_bg 1 break @@ -55,17 +55,17 @@ function help --description 'Show help for the fish shell' end # If the OS appears to be Windows (graphical), try to use cygstart - if type cygstart > /dev/null + if type -q cygstart set fish_browser cygstart # If xdg-open is available, just use that - else if type xdg-open > /dev/null + else if type -q xdg-open set fish_browser xdg-open end # On OS X, we go through osascript by default if test (uname) = Darwin - if type osascript >/dev/null + if type -q osascript set fish_browser osascript end end @@ -92,7 +92,7 @@ function help --description 'Show help for the fish shell' case $help_topics set fish_help_page "index.html\#$fish_help_item" case "*" - if type -f $fish_help_item >/dev/null + if type -q -f $fish_help_item # Prefer to use fish's man pages, to avoid # the annoying useless "builtin" man page bash # installs on OS X diff --git a/share/functions/ls.fish b/share/functions/ls.fish index dd4fb3a67..4824e1c1d 100644 --- a/share/functions/ls.fish +++ b/share/functions/ls.fish @@ -13,7 +13,7 @@ if command ls --version 1>/dev/null 2>/dev/null end if not set -q LS_COLORS - if type -f dircolors >/dev/null + if type -q -f dircolors eval (dircolors -c | sed 's/>&\/dev\/null$//') end end diff --git a/share/functions/open.fish b/share/functions/open.fish index 63d562371..7a1e7bcec 100644 --- a/share/functions/open.fish +++ b/share/functions/open.fish @@ -14,11 +14,11 @@ if not test (uname) = Darwin end end - if type -f cygstart >/dev/null + if type -q -f cygstart for i in $argv cygstart $i end - else if type -f xdg-open >/dev/null + else if type -q -f xdg-open for i in $argv xdg-open $i end diff --git a/share/functions/seq.fish b/share/functions/seq.fish index 0f5f8534c..4229f0c5a 100644 --- a/share/functions/seq.fish +++ b/share/functions/seq.fish @@ -2,7 +2,7 @@ # test -x in /usr/bin/seq because that's where it usually is and # that's substantially cheaper than the type function -if begin ; not test -x /usr/bin/seq ; and not type -f seq > /dev/null; end +if begin ; not test -x /usr/bin/seq ; and not type -q -f seq; end # No seq command function seq --description "Print sequences of numbers" __fish_fallback_seq $argv diff --git a/share/functions/type.fish b/share/functions/type.fish index 4a4c77031..e7bc7b288 100644 --- a/share/functions/type.fish +++ b/share/functions/type.fish @@ -4,79 +4,84 @@ function type --description "Print the type of a command" # Initialize set -l res 1 set -l mode normal + set -l multi no 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)) + set -l arg $argv[$i] + set -l needbreak 0 + while test -n $arg + set -l flag $arg + set arg '' + switch $flag + case '--*' + # do nothing; this just prevents it matching the next case + case '-??*' + # combined flags + set -l IFS + echo -n $flag | read _ flag arg + set flag -$flag + set arg -$arg + end + switch $flag + case -t --type + if test $mode != quiet + set mode type + end - # 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 + if test $mode != quiet + set mode path + end - case -p --path - set mode path + case -P --force-path + if test $mode != quiet + set mode path + end + set selection files - case -P --force-path - set mode path - set selection files + case -a --all + set multi yes - case -a --all - set selection multi + case -f --no-functions + set selection files - case -f --no-functions - set selection files + case -q --quiet + set mode quiet - 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] + set needbreak 1 + break + case '*' + set names $argv[$i..-1] + set needbreak 1 + break + end + end + if test $needbreak -eq 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 - if contains -- $i (functions -na) + if functions -q -- $i set res 0 set found 1 switch $mode @@ -86,12 +91,8 @@ function type --description "Print the type of a command" case type echo (_ 'function') - - case path - echo - end - if test $selection != multi + if test $multi != yes continue end end @@ -106,11 +107,8 @@ function type --description "Print the type of a command" case type echo (_ 'builtin') - - case path - echo end - if test $selection != multi + if test $multi != yes continue end end @@ -118,33 +116,31 @@ function type --description "Print the type of a command" end set -l paths - if test $selection != multi - set paths (which $i ^/dev/null) + if test $multi != yes + set paths (command -s -- $i) else - set paths (which -a $i ^/dev/null) + 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 $multi != yes + continue end end - if test $found = 0 - printf (_ "%s: Could not find '%s'\n") type $i + if begin; test $found = 0; and test $mode != quiet; end + printf (_ "%s: Could not find '%s'\n") type $i >&2 end end diff --git a/tests/read.err b/tests/read.err new file mode 100644 index 000000000..e69de29bb diff --git a/tests/read.in b/tests/read.in new file mode 100644 index 000000000..53f9873b6 --- /dev/null +++ b/tests/read.in @@ -0,0 +1,72 @@ +# +# Test read builtin and IFS +# + +count (echo one\ntwo) +set -l IFS \t +count (echo one\ntwo) +set -l IFS +count (echo one\ntwo) +set -le IFS + +function print_vars --no-scope-shadowing + set -l space + set -l IFS \n # ensure our command substitution works right + for var in $argv + echo -n $space (count $$var) \'$$var\' + set space '' + end + echo +end + +echo +echo 'hello there' | read -l one two +print_vars one two +echo 'hello there' | read -l one +print_vars one +echo '' | read -l one +print_vars one +echo '' | read -l one two +print_vars one two +echo 'test' | read -l one two three +print_vars one two three + +echo +set -l IFS +echo 'hello' | read -l one +print_vars one +echo 'hello' | read -l one two +print_vars one two +echo 'hello' | read -l one two three +print_vars one two three +echo '' | read -l one +print_vars one +echo 't' | read -l one two +print_vars one two +echo 't' | read -l one two three +print_vars one two three +echo ' t' | read -l one two +print_vars one two +set -le IFS + +echo +echo 'hello there' | read -la ary +print_vars ary +echo 'hello' | read -la ary +print_vars ary +echo 'this is a bunch of words' | read -la ary +print_vars ary +echo ' one two three' | read -la ary +print_vars ary +echo '' | read -la ary +print_vars ary + +echo +set -l IFS +echo 'hello' | read -la ary +print_vars ary +echo 'h' | read -la ary +print_vars ary +echo '' | read -la ary +print_vars ary +set -le IFS diff --git a/tests/read.out b/tests/read.out new file mode 100644 index 000000000..6d90fc0e7 --- /dev/null +++ b/tests/read.out @@ -0,0 +1,27 @@ +2 +2 +1 + +1 'hello' 1 'there' +1 'hello there' +1 '' +1 '' 1 '' +1 'test' 1 '' 1 '' + +1 'hello' +1 'h' 1 'ello' +1 'h' 1 'e' 1 'llo' +1 '' +1 't' 1 '' +1 't' 1 '' 1 '' +1 ' ' 1 't' + +2 'hello' 'there' +1 'hello' +6 'this' 'is' 'a' 'bunch' 'of' 'words' +3 'one' 'two' 'three' +0 + +5 'h' 'e' 'l' 'l' 'o' +1 'h' +0 diff --git a/tests/read.status b/tests/read.status new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/tests/read.status @@ -0,0 +1 @@ +0 diff --git a/tests/test7.in b/tests/test7.in index a3ae8360c..322982756 100644 --- a/tests/test7.in +++ b/tests/test7.in @@ -110,6 +110,6 @@ function fish_test_type_zzz true end # Should succeed -type fish_test_type_zzz >/dev/null ; echo $status +type -q fish_test_type_zzz ; echo $status # Should fail -type -f fish_test_type_zzz >/dev/null ; echo $status +type -q -f fish_test_type_zzz ; echo $status diff --git a/tests/top.out b/tests/top.out index 768526c66..f2873b153 100644 --- a/tests/top.out +++ b/tests/top.out @@ -1,5 +1,6 @@ Testing high level script functionality File printf.in tested ok +File read.in tested ok File test1.in tested ok File test2.in tested ok File test3.in tested ok