diff --git a/highlighters/main/main-highlighter.zsh b/highlighters/main/main-highlighter.zsh index 061e2a4..a76e64f 100644 --- a/highlighters/main/main-highlighter.zsh +++ b/highlighters/main/main-highlighter.zsh @@ -706,7 +706,18 @@ _zsh_highlight_main_highlighter_highlight_list() if [[ $this_word == *':start:'* ]] && ! (( in_redirection )); then # Expand aliases. # An alias is ineligible for expansion while it's being expanded (see #652/#653). - _zsh_highlight_main__type "$arg" "$(( ! ${+seen_alias[$arg]} ))" + () { + # :sudo_opt: marks every word from a recognised precommand (sudo, + # env, nice, ...) up to and including its actual command word. Those + # precommands spawn their target via execvp(3)-style lookup, which + # (unlike the shell's own PATH_DIRS option) never searches $path for + # a name containing a slash -- so PATH_DIRS must not be honoured + # while classifying this word, or e.g. "sudo foo/bar" gets + # highlighted as a valid command when sudo itself would fail to find + # it (issue #595). + [[ $this_word == *':sudo_opt:'* ]] && local -a options_to_set=( ${options_to_set:#PATH_DIRS} ) + _zsh_highlight_main__type "$arg" "$(( ! ${+seen_alias[$arg]} ))" + } local res="$REPLY" if [[ $res == "alias" ]]; then # Mark insane aliases as unknown-token (cf. #263). @@ -737,7 +748,10 @@ _zsh_highlight_main_highlighter_highlight_list() continue else _zsh_highlight_main_highlighter_expand_path $arg - _zsh_highlight_main__type "$REPLY" 0 + () { + [[ $this_word == *':sudo_opt:'* ]] && local -a options_to_set=( ${options_to_set:#PATH_DIRS} ) + _zsh_highlight_main__type "$REPLY" 0 + } res="$REPLY" fi fi diff --git a/highlighters/main/test-data/sudo-path_dirs.zsh b/highlighters/main/test-data/sudo-path_dirs.zsh new file mode 100644 index 0000000..598bfae --- /dev/null +++ b/highlighters/main/test-data/sudo-path_dirs.zsh @@ -0,0 +1,50 @@ +# ------------------------------------------------------------------------------------------------- +# Copyright (c) 2015 zsh-syntax-highlighting contributors +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted +# provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this list of conditions +# and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, this list of +# conditions and the following disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of the zsh-syntax-highlighting contributors nor the names of its contributors +# may be used to endorse or promote products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ------------------------------------------------------------------------------------------------- +# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*- +# vim: ft=zsh sw=2 ts=2 et +# ------------------------------------------------------------------------------------------------- + +# sudo(8) resolves its target command via execvp(3)-style lookup, which never +# searches $path for a name containing a slash -- unlike the shell's own +# PATH_DIRS option (see option-path_dirs.zsh). So even though PATH_DIRS makes +# 'bar/testing-issue-228' resolve to a real command when run directly, the +# same word after 'sudo' should not, since sudo itself wouldn't find it (#595). +if [[ $OSTYPE == msys ]]; then + skip_test='Cannot chmod +x in msys2' +else + setopt PATH_DIRS + mkdir -p foo/bar + touch foo/bar/testing-issue-228 + chmod +x foo/bar/testing-issue-228 + path+=( "$PWD"/foo ) + + BUFFER='sudo bar/testing-issue-228' + + expected_region_highlight=( + "1 4 precommand" # sudo + "6 26 unknown-token" # bar/testing-issue-228 -- not found via sudo's own lookup + ) +fi