'main': Use zsh/parameter instead of type -w

If possible, try to use the zsh/parameter module to get
information about a shell words.

This avoids subshells and is a huge speed improvement
on systems such as cygwin.

Note 1:
$commands does not know about PATH_DIRS. So in case
PATH_DIRS is set, 'type -w' is still used if nothing
else matches.

Note 2:
zsh/parameter can't distinguish between 'command' and
'hashed'. Adjusted the test for that case to XFAIL.

The ideal solution would be if whence had an option to
put the result in REPLY instead of printing it to stdout.
This commit is contained in:
m0viefreak 2016-03-28 23:42:31 +02:00
parent 61f43255ab
commit 12b879caf7
2 changed files with 44 additions and 19 deletions

View File

@ -80,17 +80,39 @@ _zsh_highlight_main_add_region_highlight() {
_zsh_highlight_add_highlight $start $end "$@" _zsh_highlight_add_highlight $start $end "$@"
} }
# Wrapper around 'type -w'. # Get the type of a command.
# #
# Takes a single argument and outputs the output of 'type -w $1'. # Uses the zsh/parameter module if available to avoid forks, and a
# wrapper around 'type -w' as fallback.
# #
# NOTE: This runs 'setopt', but that should be safe since it'll only ever be # Takes a single argument.
# called inside a $(...) subshell, so the effects will be local. #
# The result will be stored in REPLY.
_zsh_highlight_main__type() { _zsh_highlight_main__type() {
if (( $#options_to_set )); then if (( $#options_to_set )); then
setopt localoptions $options_to_set; setopt localoptions $options_to_set;
fi fi
LC_ALL=C builtin type -w -- $1 2>/dev/null unset REPLY
if zmodload -e zsh/parameter; then
if (( $+aliases[(e)$1] )); then
REPLY=alias
elif (( $+saliases[(e)${1##*.}] )); then
REPLY='suffix alias'
elif (( $reswords[(Ie)$1] )); then
REPLY=reserved
elif (( $+functions[(e)$1] )); then
REPLY=function
elif (( $+builtins[(e)$1] )); then
REPLY=builtin
elif (( $+commands[(e)$1] )); then
REPLY=command
elif ! builtin type -w -- $1 >/dev/null 2>&1; then
REPLY=none
fi
fi
if ! (( $+REPLY )); then
REPLY="${$(LC_ALL=C builtin type -w -- $1 2>/dev/null)#*: }"
fi
} }
# Check whether the first argument is a redirection operator token. # Check whether the first argument is a redirection operator token.
@ -329,7 +351,8 @@ _zsh_highlight_main_highlighter()
else else
_zsh_highlight_main_highlighter_expand_path $arg _zsh_highlight_main_highlighter_expand_path $arg
local expanded_arg="$REPLY" local expanded_arg="$REPLY"
local res="$(_zsh_highlight_main__type ${expanded_arg})" _zsh_highlight_main__type ${expanded_arg}
local res="$REPLY"
() { () {
# Special-case: command word is '$foo', like that, without braces or anything. # Special-case: command word is '$foo', like that, without braces or anything.
# #
@ -339,17 +362,16 @@ _zsh_highlight_main_highlighter()
# parameters that refer to commands, functions, and builtins. # parameters that refer to commands, functions, and builtins.
local -a match mbegin mend local -a match mbegin mend
local MATCH; integer MBEGIN MEND local MATCH; integer MBEGIN MEND
if [[ $res == *': none' ]] && (( ${+parameters} )) && if [[ $res == none ]] && (( ${+parameters} )) &&
[[ ${arg[1]} == \$ ]] && [[ ${arg:1} =~ ^([A-Za-z_][A-Za-z0-9_]*|[0-9]+)$ ]]; then [[ ${arg[1]} == \$ ]] && [[ ${arg:1} =~ ^([A-Za-z_][A-Za-z0-9_]*|[0-9]+)$ ]]; then
res="$(_zsh_highlight_main__type ${(P)MATCH})" _zsh_highlight_main__type ${(P)MATCH}
res=$REPLY
fi fi
} }
case $res in case $res in
*': reserved') style=reserved-word;; reserved) style=reserved-word;;
*': suffix alias') 'suffix alias') style=suffix-alias;;
style=suffix-alias alias) () {
;;
*': alias') () {
integer insane_alias integer insane_alias
case $arg in case $arg in
# Issue #263: aliases with '=' on their LHS. # Issue #263: aliases with '=' on their LHS.
@ -373,11 +395,11 @@ _zsh_highlight_main_highlighter()
fi fi
} }
;; ;;
*': builtin') style=builtin;; builtin) style=builtin;;
*': function') style=function;; function) style=function;;
*': command') style=command;; command) style=command;;
*': hashed') style=hashed-command;; hashed) style=hashed-command;;
*) if _zsh_highlight_main_highlighter_check_assign; then none) if _zsh_highlight_main_highlighter_check_assign; then
style=assign style=assign
if [[ $arg[-1] == '(' ]]; then if [[ $arg[-1] == '(' ]]; then
in_array_assignment=true in_array_assignment=true
@ -431,6 +453,9 @@ _zsh_highlight_main_highlighter()
fi fi
fi fi
;; ;;
*) _zsh_highlight_main_add_region_highlight commandtypefromthefuture-$res
already_added=1
;;
esac esac
fi fi
else # $arg is a non-command word else # $arg is a non-command word

View File

@ -31,5 +31,5 @@ hash zsh_syntax_highlighting_hash=/doesnotexist
BUFFER='zsh_syntax_highlighting_hash' BUFFER='zsh_syntax_highlighting_hash'
expected_region_highlight=( expected_region_highlight=(
"1 28 hashed-command" "1 28 hashed-command 'zsh/parameter cannot distinguish between hashed and command'"
) )