From 12b879caf7a6f96921d1c03ab9b839a7f6c8eb1e Mon Sep 17 00:00:00 2001 From: m0viefreak Date: Mon, 28 Mar 2016 23:42:31 +0200 Subject: [PATCH] '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. --- highlighters/main/main-highlighter.zsh | 61 +++++++++++++------ .../main/test-data/hashed-command.zsh | 2 +- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/highlighters/main/main-highlighter.zsh b/highlighters/main/main-highlighter.zsh index 225866a..47d3b6e 100644 --- a/highlighters/main/main-highlighter.zsh +++ b/highlighters/main/main-highlighter.zsh @@ -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 diff --git a/highlighters/main/test-data/hashed-command.zsh b/highlighters/main/test-data/hashed-command.zsh index 83b0ed6..2983ef8 100644 --- a/highlighters/main/test-data/hashed-command.zsh +++ b/highlighters/main/test-data/hashed-command.zsh @@ -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'" )