'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 "$@"
}
# 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
# called inside a $(...) subshell, so the effects will be local.
# Takes a single argument.
#
# The result will be stored in REPLY.
_zsh_highlight_main__type() {
if (( $#options_to_set )); then
setopt localoptions $options_to_set;
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.
@ -329,7 +351,8 @@ _zsh_highlight_main_highlighter()
else
_zsh_highlight_main_highlighter_expand_path $arg
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.
#
@ -339,17 +362,16 @@ _zsh_highlight_main_highlighter()
# parameters that refer to commands, functions, and builtins.
local -a match 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
res="$(_zsh_highlight_main__type ${(P)MATCH})"
_zsh_highlight_main__type ${(P)MATCH}
res=$REPLY
fi
}
case $res in
*': reserved') style=reserved-word;;
*': suffix alias')
style=suffix-alias
;;
*': alias') () {
reserved) style=reserved-word;;
'suffix alias') style=suffix-alias;;
alias) () {
integer insane_alias
case $arg in
# Issue #263: aliases with '=' on their LHS.
@ -373,11 +395,11 @@ _zsh_highlight_main_highlighter()
fi
}
;;
*': builtin') style=builtin;;
*': function') style=function;;
*': command') style=command;;
*': hashed') style=hashed-command;;
*) if _zsh_highlight_main_highlighter_check_assign; then
builtin) style=builtin;;
function) style=function;;
command) style=command;;
hashed) style=hashed-command;;
none) if _zsh_highlight_main_highlighter_check_assign; then
style=assign
if [[ $arg[-1] == '(' ]]; then
in_array_assignment=true
@ -431,6 +453,9 @@ _zsh_highlight_main_highlighter()
fi
fi
;;
*) _zsh_highlight_main_add_region_highlight commandtypefromthefuture-$res
already_added=1
;;
esac
fi
else # $arg is a non-command word

View File

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