Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

799 Zeilen
32 KiB

minor: Fix WARN_CREATE_GLOBAL warnings issued by zsh 5.1.1-dev-0. The following warnings are issued by zsh as of zsh-workers/37018 (commit de9effbce601 to zsh itself): _zsh_highlight_main_highlighter_highlight_dollar_string:17: array parameter match created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: array parameter mbegin created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: array parameter mend created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: numeric parameter parameter MBEGIN created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: numeric parameter parameter MEND created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: scalar parameter MATCH created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_string:11: array parameter match created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: array parameter mbegin created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: array parameter mend created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: numeric parameter parameter MBEGIN created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: numeric parameter parameter MEND created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: scalar parameter MATCH created globally in function _zsh_highlight_main_highlighter_highlight_string
vor 9 Jahren
minor: Fix WARN_CREATE_GLOBAL warnings issued by zsh 5.1.1-dev-0. The following warnings are issued by zsh as of zsh-workers/37018 (commit de9effbce601 to zsh itself): _zsh_highlight_main_highlighter_highlight_dollar_string:17: array parameter match created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: array parameter mbegin created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: array parameter mend created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: numeric parameter parameter MBEGIN created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: numeric parameter parameter MEND created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_dollar_string:17: scalar parameter MATCH created globally in function _zsh_highlight_main_highlighter_highlight_dollar_string _zsh_highlight_main_highlighter_highlight_string:11: array parameter match created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: array parameter mbegin created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: array parameter mend created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: numeric parameter parameter MBEGIN created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: numeric parameter parameter MEND created globally in function _zsh_highlight_main_highlighter_highlight_string _zsh_highlight_main_highlighter_highlight_string:11: scalar parameter MATCH created globally in function _zsh_highlight_main_highlighter_highlight_string
vor 9 Jahren
  1. # -------------------------------------------------------------------------------------------------
  2. # Copyright (c) 2010-2016 zsh-syntax-highlighting contributors
  3. # All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without modification, are permitted
  6. # provided that the following conditions are met:
  7. #
  8. # * Redistributions of source code must retain the above copyright notice, this list of conditions
  9. # and the following disclaimer.
  10. # * Redistributions in binary form must reproduce the above copyright notice, this list of
  11. # conditions and the following disclaimer in the documentation and/or other materials provided
  12. # with the distribution.
  13. # * Neither the name of the zsh-syntax-highlighting contributors nor the names of its contributors
  14. # may be used to endorse or promote products derived from this software without specific prior
  15. # written permission.
  16. #
  17. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  18. # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  19. # FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  20. # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  23. # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  24. # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. # -------------------------------------------------------------------------------------------------
  26. # -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
  27. # vim: ft=zsh sw=2 ts=2 et
  28. # -------------------------------------------------------------------------------------------------
  29. # Define default styles.
  30. : ${ZSH_HIGHLIGHT_STYLES[default]:=none}
  31. : ${ZSH_HIGHLIGHT_STYLES[unknown-token]:=fg=red,bold}
  32. : ${ZSH_HIGHLIGHT_STYLES[reserved-word]:=fg=yellow}
  33. : ${ZSH_HIGHLIGHT_STYLES[alias]:=fg=green}
  34. : ${ZSH_HIGHLIGHT_STYLES[suffix-alias]:=fg=green,underline}
  35. : ${ZSH_HIGHLIGHT_STYLES[builtin]:=fg=green}
  36. : ${ZSH_HIGHLIGHT_STYLES[function]:=fg=green}
  37. : ${ZSH_HIGHLIGHT_STYLES[command]:=fg=green}
  38. : ${ZSH_HIGHLIGHT_STYLES[precommand]:=fg=green,underline}
  39. : ${ZSH_HIGHLIGHT_STYLES[commandseparator]:=none}
  40. : ${ZSH_HIGHLIGHT_STYLES[hashed-command]:=fg=green}
  41. : ${ZSH_HIGHLIGHT_STYLES[path]:=underline}
  42. : ${ZSH_HIGHLIGHT_STYLES[path_pathseparator]:=}
  43. : ${ZSH_HIGHLIGHT_STYLES[path_prefix]:=underline}
  44. : ${ZSH_HIGHLIGHT_STYLES[path_prefix_pathseparator]:=}
  45. : ${ZSH_HIGHLIGHT_STYLES[globbing]:=fg=blue}
  46. : ${ZSH_HIGHLIGHT_STYLES[history-expansion]:=fg=blue}
  47. : ${ZSH_HIGHLIGHT_STYLES[single-hyphen-option]:=none}
  48. : ${ZSH_HIGHLIGHT_STYLES[double-hyphen-option]:=none}
  49. : ${ZSH_HIGHLIGHT_STYLES[back-quoted-argument]:=none}
  50. : ${ZSH_HIGHLIGHT_STYLES[single-quoted-argument]:=fg=yellow}
  51. : ${ZSH_HIGHLIGHT_STYLES[double-quoted-argument]:=fg=yellow}
  52. : ${ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]:=fg=yellow}
  53. : ${ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument]:=fg=cyan}
  54. : ${ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument]:=fg=cyan}
  55. : ${ZSH_HIGHLIGHT_STYLES[back-dollar-quoted-argument]:=fg=cyan}
  56. : ${ZSH_HIGHLIGHT_STYLES[assign]:=none}
  57. : ${ZSH_HIGHLIGHT_STYLES[redirection]:=none}
  58. : ${ZSH_HIGHLIGHT_STYLES[comment]:=fg=black,bold}
  59. # Whether the highlighter should be called or not.
  60. _zsh_highlight_highlighter_main_predicate()
  61. {
  62. # may need to remove path_prefix highlighting when the line ends
  63. [[ $WIDGET == zle-line-finish ]] || _zsh_highlight_buffer_modified
  64. }
  65. # Helper to deal with tokens crossing line boundaries.
  66. _zsh_highlight_main_add_region_highlight() {
  67. integer start=$1 end=$2
  68. shift 2
  69. # The calculation was relative to $PREBUFFER$BUFFER, but region_highlight is
  70. # relative to $BUFFER.
  71. (( start -= $#PREBUFFER ))
  72. (( end -= $#PREBUFFER ))
  73. (( end < 0 )) && return # having end<0 would be a bug
  74. (( start < 0 )) && start=0 # having start<0 is normal with e.g. multiline strings
  75. _zsh_highlight_add_highlight $start $end "$@"
  76. }
  77. # Get the type of a command.
  78. #
  79. # Uses the zsh/parameter module if available to avoid forks, and a
  80. # wrapper around 'type -w' as fallback.
  81. #
  82. # Takes a single argument.
  83. #
  84. # The result will be stored in REPLY.
  85. _zsh_highlight_main__type() {
  86. if (( $+_zsh_highlight_main__command_type_cache )); then
  87. REPLY=$_zsh_highlight_main__command_type_cache[(e)$1]
  88. if [[ -n "$REPLY" ]]; then
  89. return
  90. fi
  91. fi
  92. if (( $#options_to_set )); then
  93. setopt localoptions $options_to_set;
  94. fi
  95. unset REPLY
  96. if zmodload -e zsh/parameter; then
  97. if (( $+aliases[(e)$1] )); then
  98. REPLY=alias
  99. elif (( $+saliases[(e)${1##*.}] )); then
  100. REPLY='suffix alias'
  101. elif (( $reswords[(Ie)$1] )); then
  102. REPLY=reserved
  103. elif (( $+functions[(e)$1] )); then
  104. REPLY=function
  105. elif (( $+builtins[(e)$1] )); then
  106. REPLY=builtin
  107. elif (( $+commands[(e)$1] )); then
  108. REPLY=command
  109. # zsh 5.2 and older have a bug whereby running 'type -w ./sudo' implicitly
  110. # runs 'hash ./sudo=/usr/local/bin/./sudo' (assuming /usr/local/bin/sudo
  111. # exists and is in $PATH). Avoid triggering the bug, at the expense of
  112. # falling through to the $() below, incurring a fork. (Issue #354.)
  113. #
  114. # The second disjunct mimics the isrelative() C call from the zsh bug.
  115. elif { [[ $1 != */* ]] || is-at-least 5.3 } &&
  116. ! builtin type -w -- $1 >/dev/null 2>&1; then
  117. REPLY=none
  118. fi
  119. fi
  120. if ! (( $+REPLY )); then
  121. REPLY="${$(LC_ALL=C builtin type -w -- $1 2>/dev/null)#*: }"
  122. fi
  123. if (( $+_zsh_highlight_main__command_type_cache )); then
  124. _zsh_highlight_main__command_type_cache[(e)$1]=$REPLY
  125. fi
  126. }
  127. # Check whether the first argument is a redirection operator token.
  128. # Report result via the exit code.
  129. _zsh_highlight_main__is_redirection() {
  130. # A redirection operator token:
  131. # - starts with an optional single-digit number;
  132. # - then, has a '<' or '>' character;
  133. # - is not a process substitution [<(...) or >(...)].
  134. [[ $1 == (<0-9>|)(\<|\>)* ]] && [[ $1 != (\<|\>)$'\x28'* ]]
  135. }
  136. # Resolve alias.
  137. #
  138. # Takes a single argument.
  139. #
  140. # The result will be stored in REPLY.
  141. _zsh_highlight_main__resolve_alias() {
  142. if zmodload -e zsh/parameter; then
  143. REPLY=${aliases[$arg]}
  144. else
  145. REPLY="${"$(alias -- $arg)"#*=}"
  146. fi
  147. }
  148. # Check that the top of $braces_stack has the expected value. If it does, set
  149. # the style according to $2; otherwise, set style=unknown-token.
  150. #
  151. # $1: character expected to be at the top of $braces_stack
  152. # $2: assignment to execute it if matches
  153. _zsh_highlight_main__stack_pop() {
  154. if [[ $braces_stack[1] == $1 ]]; then
  155. braces_stack=${braces_stack:1}
  156. eval "$2"
  157. else
  158. style=unknown-token
  159. fi
  160. }
  161. # Main syntax highlighting function.
  162. _zsh_highlight_highlighter_main_paint()
  163. {
  164. ## Before we even 'emulate -L', we must test a few options that would reset.
  165. if [[ -o interactive_comments ]]; then
  166. local interactive_comments= # set to empty
  167. fi
  168. if [[ -o ignore_braces ]] || [[ -o ignore_close_braces ]]; then
  169. local right_brace_is_recognised_everywhere=false
  170. else
  171. local right_brace_is_recognised_everywhere=true
  172. fi
  173. if [[ -o path_dirs ]]; then
  174. integer path_dirs_was_set=1
  175. else
  176. integer path_dirs_was_set=0
  177. fi
  178. emulate -L zsh
  179. setopt localoptions extendedglob bareglobqual
  180. # At the PS3 prompt and in vared, highlight nothing.
  181. #
  182. # (We can't check this in _zsh_highlight_highlighter_main_predicate because
  183. # if the predicate returns false, the previous value of region_highlight
  184. # would be reused.)
  185. if [[ $CONTEXT == (select|vared) ]]; then
  186. return
  187. fi
  188. ## Variable declarations and initializations
  189. local start_pos=0 end_pos highlight_glob=true arg style
  190. local in_array_assignment=false # true between 'a=(' and the matching ')'
  191. typeset -a ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR
  192. typeset -a ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS
  193. typeset -a ZSH_HIGHLIGHT_TOKENS_CONTROL_FLOW
  194. local -a options_to_set # used in callees
  195. local buf="$PREBUFFER$BUFFER"
  196. integer len="${#buf}"
  197. local braces_stack # "R" for round, "Q" for square, "Y" for curly
  198. if (( path_dirs_was_set )); then
  199. options_to_set+=( PATH_DIRS )
  200. fi
  201. unset path_dirs_was_set
  202. ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR=(
  203. '|' '||' ';' '&' '&&'
  204. '|&'
  205. '&!' '&|'
  206. # ### 'case' syntax, but followed by a pattern, not by a command
  207. # ';;' ';&' ';|'
  208. )
  209. ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS=(
  210. 'builtin' 'command' 'exec' 'nocorrect' 'noglob'
  211. 'pkexec' # immune to #121 because it's usually not passed --option flags
  212. )
  213. # Tokens that, at (naively-determined) "command position", are followed by
  214. # a de jure command position. All of these are reserved words.
  215. ZSH_HIGHLIGHT_TOKENS_CONTROL_FLOW=(
  216. $'\x7b' # block
  217. $'\x28' # subshell
  218. '()' # anonymous function
  219. 'while'
  220. 'until'
  221. 'if'
  222. 'then'
  223. 'elif'
  224. 'else'
  225. 'do'
  226. 'time'
  227. 'coproc'
  228. '!' # reserved word; unrelated to $histchars[1]
  229. )
  230. # State machine
  231. #
  232. # The states are:
  233. # - :start: Command word
  234. # - :sudo_opt: A leading-dash option to sudo (such as "-u" or "-i")
  235. # - :sudo_arg: The argument to a sudo leading-dash option that takes one,
  236. # when given as a separate word; i.e., "foo" in "-u foo" (two
  237. # words) but not in "-ufoo" (one word).
  238. # - :regular: "Not a command word", and command delimiters are permitted.
  239. # Mainly used to detect premature termination of commands.
  240. #
  241. # When the kind of a word is not yet known, $this_word / $next_word may contain
  242. # multiple states. For example, after "sudo -i", the next word may be either
  243. # another --flag or a command name, hence the state would include both :start:
  244. # and :sudo_opt:.
  245. #
  246. # The tokens are always added with both leading and trailing colons to serve as
  247. # word delimiters (an improvised array); [[ $x == *:foo:* ]] and x=${x//:foo:/}
  248. # will DTRT regardless of how many elements or repetitions $x has..
  249. #
  250. # Handling of redirections: upon seeing a redirection token, we must stall
  251. # the current state --- that is, the value of $this_word --- for two iterations
  252. # (one for the redirection operator, one for the word following it representing
  253. # the redirection target). Therefore, we set $in_redirection to 2 upon seeing a
  254. # redirection operator, decrement it each iteration, and stall the current state
  255. # when it is non-zero. Thus, upon reaching the next word (the one that follows
  256. # the redirection operator and target), $this_word will still contain values
  257. # appropriate for the word immediately following the word that preceded the
  258. # redirection operator.
  259. #
  260. # The "the previous word was a redirection operator" state is not communicated
  261. # to the next iteration via $next_word/$this_word as usual, but via
  262. # $in_redirection. The value of $next_word from the iteration that processed
  263. # the operator is discarded.
  264. #
  265. local this_word=':start:' next_word
  266. integer in_redirection
  267. # Processing buffer
  268. local proc_buf="$buf"
  269. for arg in ${interactive_comments-${(z)buf}} \
  270. ${interactive_comments+${(zZ+c+)buf}}; do
  271. # Initialize $next_word.
  272. if (( in_redirection )); then
  273. (( --in_redirection ))
  274. fi
  275. if (( in_redirection == 0 )); then
  276. # Initialize $next_word to its default value.
  277. next_word=':regular:'
  278. else
  279. # Stall $next_word.
  280. fi
  281. # Initialize per-"simple command" [zshmisc(1)] variables:
  282. #
  283. # $already_added (see next paragraph)
  284. # $style how to highlight $arg
  285. # $in_array_assignment boolean flag for "between '(' and ')' of array assignment"
  286. # $highlight_glob boolean flag for "'noglob' is in effect"
  287. #
  288. # $already_added is set to 1 to disable adding an entry to region_highlight
  289. # for this iteration. Currently, that is done for "" and $'' strings,
  290. # which add the entry early so escape sequences within the string override
  291. # the string's color.
  292. integer already_added=0
  293. style=unknown-token
  294. if [[ $this_word == *':start:'* ]]; then
  295. in_array_assignment=false
  296. if [[ $arg == 'noglob' ]]; then
  297. highlight_glob=false
  298. fi
  299. fi
  300. # Compute the new $start_pos and $end_pos, skipping over whitespace in $buf.
  301. if [[ $arg == ';' ]] ; then
  302. # We're looking for either a semicolon or a newline, whichever comes
  303. # first. Both of these are rendered as a ";" (SEPER) by the ${(z)..}
  304. # flag.
  305. #
  306. # We can't use the (Z+n+) flag because that elides the end-of-command
  307. # token altogether, so 'echo foo\necho bar' (two commands) becomes
  308. # indistinguishable from 'echo foo echo bar' (one command with three
  309. # words for arguments).
  310. local needle=$'[;\n]'
  311. integer offset=$(( ${proc_buf[(i)$needle]} - 1 ))
  312. (( start_pos += offset ))
  313. (( end_pos = start_pos + $#arg ))
  314. else
  315. integer offset=$(((len-start_pos)-${#${proc_buf##([[:space:]]|\\[[:space:]])#}}))
  316. ((start_pos+=offset))
  317. ((end_pos=$start_pos+${#arg}))
  318. fi
  319. # Compute the new $proc_buf. We advance it
  320. # (chop off characters from the beginning)
  321. # beyond what end_pos points to, by skipping
  322. # as many characters as end_pos was advanced.
  323. #
  324. # end_pos was advanced by $offset (via start_pos)
  325. # and by $#arg. Note the `start_pos=$end_pos`
  326. # below.
  327. #
  328. # As for the [,len]. We could use [,len-start_pos+offset]
  329. # here, but to make it easier on eyes, we use len and
  330. # rely on the fact that Zsh simply handles that. The
  331. # length of proc_buf is len-start_pos+offset because
  332. # we're chopping it to match current start_pos, so its
  333. # length matches the previous value of start_pos.
  334. #
  335. # Why [,-1] is slower than [,length] isn't clear.
  336. proc_buf="${proc_buf[offset + $#arg + 1,len]}"
  337. # Handle the INTERACTIVE_COMMENTS option.
  338. #
  339. # We use the (Z+c+) flag so the entire comment is presented as one token in $arg.
  340. if [[ -n ${interactive_comments+'set'} && $arg[1] == $histchars[3] ]]; then
  341. if [[ $this_word == *(':regular:'|':start:')* ]]; then
  342. style=comment
  343. else
  344. style=unknown-token # prematurely terminated
  345. fi
  346. _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
  347. already_added=1
  348. continue
  349. fi
  350. # Analyse the current word.
  351. if _zsh_highlight_main__is_redirection $arg ; then
  352. # A '<' or '>', possibly followed by a digit
  353. in_redirection=2
  354. fi
  355. # Special-case the first word after 'sudo'.
  356. if (( ! in_redirection )); then
  357. if [[ $this_word == *':sudo_opt:'* ]] && [[ $arg != -* ]]; then
  358. this_word=${this_word//:sudo_opt:/}
  359. fi
  360. fi
  361. # Parse the sudo command line
  362. if (( ! in_redirection )); then
  363. if [[ $this_word == *':sudo_opt:'* ]]; then
  364. case "$arg" in
  365. # Flag that requires an argument
  366. '-'[Cgprtu]) this_word=${this_word//:start:/};
  367. next_word=':sudo_arg:';;
  368. # This prevents misbehavior with sudo -u -otherargument
  369. '-'*) this_word=${this_word//:start:/};
  370. next_word+=':start:';
  371. next_word+=':sudo_opt:';;
  372. *) ;;
  373. esac
  374. elif [[ $this_word == *':sudo_arg:'* ]]; then
  375. next_word+=':sudo_opt:'
  376. next_word+=':start:'
  377. fi
  378. fi
  379. # The Great Fork: is this a command word? Is this a non-command word?
  380. if [[ $this_word == *':start:'* ]] && (( in_redirection == 0 )); then # $arg is the command word
  381. if [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$arg"} ]]; then
  382. style=precommand
  383. elif [[ "$arg" = "sudo" ]]; then
  384. style=precommand
  385. next_word=${next_word//:regular:/}
  386. next_word+=':sudo_opt:'
  387. next_word+=':start:'
  388. else
  389. _zsh_highlight_main_highlighter_expand_path $arg
  390. local expanded_arg="$REPLY"
  391. _zsh_highlight_main__type ${expanded_arg}
  392. local res="$REPLY"
  393. () {
  394. # Special-case: command word is '$foo', like that, without braces or anything.
  395. #
  396. # That's not entirely correct --- if the parameter's value happens to be a reserved
  397. # word, the parameter expansion will be highlighted as a reserved word --- but that
  398. # incorrectness is outweighed by the usability improvement of permitting the use of
  399. # parameters that refer to commands, functions, and builtins.
  400. local -a match mbegin mend
  401. local MATCH; integer MBEGIN MEND
  402. if [[ $res == none ]] && (( ${+parameters} )) &&
  403. [[ ${arg[1]} == \$ ]] && [[ ${arg:1} =~ ^([A-Za-z_][A-Za-z0-9_]*|[0-9]+)$ ]] &&
  404. (( ${+parameters[${MATCH}]} ))
  405. then
  406. _zsh_highlight_main__type ${(P)MATCH}
  407. res=$REPLY
  408. fi
  409. }
  410. case $res in
  411. reserved) # reserved word
  412. style=reserved-word
  413. if [[ $arg == $'\x7b' ]]; then
  414. braces_stack='Y'"$braces_stack"
  415. elif [[ $arg == $'\x7d' ]]; then
  416. # We're at command word, so no need to check $right_brace_is_recognised_everywhere
  417. _zsh_highlight_main__stack_pop 'Y' style=reserved-word
  418. fi
  419. ;;
  420. 'suffix alias') style=suffix-alias;;
  421. alias) () {
  422. integer insane_alias
  423. case $arg in
  424. # Issue #263: aliases with '=' on their LHS.
  425. #
  426. # There are three cases:
  427. #
  428. # - Unsupported, breaks 'alias -L' output, but invokable:
  429. ('='*) :;;
  430. # - Unsupported, not invokable:
  431. (*'='*) insane_alias=1;;
  432. # - The common case:
  433. (*) :;;
  434. esac
  435. if (( insane_alias )); then
  436. style=unknown-token
  437. else
  438. style=alias
  439. _zsh_highlight_main__resolve_alias $arg
  440. local alias_target="$REPLY"
  441. [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$alias_target"} && -z ${(M)ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$arg"} ]] && ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS+=($arg)
  442. fi
  443. }
  444. ;;
  445. builtin) style=builtin;;
  446. function) style=function;;
  447. command) style=command;;
  448. hashed) style=hashed-command;;
  449. none) if _zsh_highlight_main_highlighter_check_assign; then
  450. style=assign
  451. if [[ $arg[-1] == '(' ]]; then
  452. in_array_assignment=true
  453. else
  454. # assignment to a scalar parameter.
  455. # (For array assignments, the command doesn't start until the ")" token.)
  456. next_word+=':start:'
  457. fi
  458. elif [[ $arg[0,1] = $histchars[0,1] ]] && (( $#arg[0,2] == 2 )); then
  459. style=history-expansion
  460. elif [[ $arg[0,1] == $histchars[2,2] ]]; then
  461. style=history-expansion
  462. elif [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]]; then
  463. if [[ $this_word == *':regular:'* ]]; then
  464. # This highlights empty commands (semicolon follows nothing) as an error.
  465. # Zsh accepts them, though.
  466. style=commandseparator
  467. else
  468. style=unknown-token
  469. fi
  470. elif (( in_redirection == 2 )); then
  471. style=redirection
  472. elif [[ $arg[1,2] == '((' ]]; then
  473. # Arithmetic evaluation.
  474. #
  475. # Note: prior to zsh-5.1.1-52-g4bed2cf (workers/36669), the ${(z)...}
  476. # splitter would only output the '((' token if the matching '))' had
  477. # been typed. Therefore, under those versions of zsh, BUFFER="(( 42"
  478. # would be highlighted as an error until the matching "))" are typed.
  479. #
  480. # We highlight just the opening parentheses, as a reserved word; this
  481. # is how [[ ... ]] is highlighted, too.
  482. style=reserved-word
  483. _zsh_highlight_main_add_region_highlight $start_pos $((start_pos + 2)) $style
  484. already_added=1
  485. if [[ $arg[-2,-1] == '))' ]]; then
  486. _zsh_highlight_main_add_region_highlight $((end_pos - 2)) $end_pos $style
  487. already_added=1
  488. fi
  489. elif [[ $arg == '()' ]]; then
  490. # anonymous function
  491. style=reserved-word
  492. elif [[ $arg == $'\x28' ]]; then
  493. # subshell
  494. style=reserved-word
  495. braces_stack='R'"$braces_stack"
  496. else
  497. if _zsh_highlight_main_highlighter_check_path; then
  498. style=$REPLY
  499. else
  500. style=unknown-token
  501. fi
  502. fi
  503. ;;
  504. *) _zsh_highlight_main_add_region_highlight $start_pos $end_pos commandtypefromthefuture-$res
  505. already_added=1
  506. ;;
  507. esac
  508. fi
  509. fi
  510. if (( ! already_added )) && [[ $style == unknown-token ]] && # not handled by the 'command word' codepath
  511. { (( in_redirection )) || [[ $this_word == *':regular:'* ]] || [[ $this_word == *':sudo_opt:'* ]] || [[ $this_word == *':sudo_arg:'* ]] }
  512. then # $arg is a non-command word
  513. case $arg in
  514. $'\x29') # subshell or end of array assignment
  515. if $in_array_assignment; then
  516. style=assign
  517. in_array_assignment=false
  518. next_word+=':start:'
  519. else
  520. _zsh_highlight_main__stack_pop 'R' style=reserved-word
  521. fi;;
  522. $'\x7d') # right brace
  523. #
  524. # Parsing rule: # {
  525. #
  526. # Additionally, `tt(})' is recognized in any position if neither the
  527. # tt(IGNORE_BRACES) option nor the tt(IGNORE_CLOSE_BRACES) option is set."""
  528. if $right_brace_is_recognised_everywhere; then
  529. _zsh_highlight_main__stack_pop 'Y' style=reserved-word
  530. else
  531. # Fall through to the catchall case at the end.
  532. fi
  533. ;|
  534. '--'*) style=double-hyphen-option;;
  535. '-'*) style=single-hyphen-option;;
  536. "'"*) style=single-quoted-argument;;
  537. '"'*) style=double-quoted-argument
  538. _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
  539. _zsh_highlight_main_highlighter_highlight_string
  540. already_added=1
  541. ;;
  542. \$\'*) style=dollar-quoted-argument
  543. _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
  544. _zsh_highlight_main_highlighter_highlight_dollar_string
  545. already_added=1
  546. ;;
  547. '`'*) style=back-quoted-argument;;
  548. [*?]*|*[^\\][*?]*)
  549. $highlight_glob && style=globbing || style=default;;
  550. *) if false; then
  551. elif [[ $arg = $'\x7d' ]] && $right_brace_is_recognised_everywhere; then
  552. # was handled by the $'\x7d' case above
  553. elif [[ $arg[0,1] = $histchars[0,1] ]] && (( $#arg[0,2] == 2 )); then
  554. style=history-expansion
  555. elif [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]]; then
  556. if [[ $this_word == *':regular:'* ]]; then
  557. style=commandseparator
  558. else
  559. style=unknown-token
  560. fi
  561. elif (( in_redirection == 2 )); then
  562. style=redirection
  563. else
  564. if _zsh_highlight_main_highlighter_check_path; then
  565. style=$REPLY
  566. else
  567. style=default
  568. fi
  569. fi
  570. ;;
  571. esac
  572. fi
  573. if ! (( already_added )); then
  574. _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
  575. [[ $style == path || $style == path_prefix ]] && _zsh_highlight_main_highlighter_highlight_path_separators
  576. fi
  577. if [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]]; then
  578. next_word=':start:'
  579. highlight_glob=true
  580. elif
  581. [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_CONTROL_FLOW:#"$arg"} && $this_word == *':start:'* ]] ||
  582. [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$arg"} && $this_word == *':start:'* ]]; then
  583. next_word=':start:'
  584. elif [[ $arg == "repeat" && $this_word == *':start:'* ]]; then
  585. # skip the repeat-count word
  586. in_redirection=2
  587. # The redirection mechanism assumes $this_word describes the word
  588. # following the redirection. Make it so.
  589. #
  590. # That word can be a command word with shortloops (`repeat 2 ls`)
  591. # or a command separator (`repeat 2; ls` or `repeat 2; do ls; done`).
  592. #
  593. # The repeat-count word will be handled like a redirection target.
  594. this_word=':start::regular:'
  595. fi
  596. start_pos=$end_pos
  597. if (( in_redirection == 0 )); then
  598. # This is the default/common codepath.
  599. this_word=$next_word
  600. else
  601. # Stall $this_word.
  602. fi
  603. done
  604. }
  605. # Check if $arg is variable assignment
  606. _zsh_highlight_main_highlighter_check_assign()
  607. {
  608. setopt localoptions extended_glob
  609. [[ $arg == [[:alpha:]_][[:alnum:]_]#(|\[*\])(|[+])=* ]] ||
  610. [[ $arg == [0-9]##(|[+])=* ]]
  611. }
  612. _zsh_highlight_main_highlighter_highlight_path_separators()
  613. {
  614. local pos style_pathsep
  615. style_pathsep=${style}_pathseparator
  616. [[ -z "$ZSH_HIGHLIGHT_STYLES[$style_pathsep]" || "$ZSH_HIGHLIGHT_STYLES[$style]" == "$ZSH_HIGHLIGHT_STYLES[$style_pathsep]" ]] && return 0
  617. for (( pos = start_pos; $pos <= end_pos; pos++ )) ; do
  618. if [[ $BUFFER[pos] == / ]]; then
  619. _zsh_highlight_main_add_region_highlight $((pos - 1)) $pos $style_pathsep
  620. fi
  621. done
  622. }
  623. # Check if $arg is a path.
  624. # If yes, return 0 and in $REPLY the style to use.
  625. # Else, return non-zero (and the contents of $REPLY is undefined).
  626. _zsh_highlight_main_highlighter_check_path()
  627. {
  628. _zsh_highlight_main_highlighter_expand_path $arg;
  629. local expanded_path="$REPLY"
  630. REPLY=path
  631. [[ -z $expanded_path ]] && return 1
  632. [[ -L $expanded_path ]] && return 0
  633. [[ -e $expanded_path ]] && return 0
  634. # Search the path in CDPATH
  635. local cdpath_dir
  636. for cdpath_dir in $cdpath ; do
  637. [[ -e "$cdpath_dir/$expanded_path" ]] && return 0
  638. done
  639. # If dirname($arg) doesn't exist, neither does $arg.
  640. [[ ! -d ${expanded_path:h} ]] && return 1
  641. # If this word ends the buffer, check if it's the prefix of a valid path.
  642. if [[ ${BUFFER[1]} != "-" && ${#BUFFER} == $end_pos ]] &&
  643. [[ $WIDGET != zle-line-finish ]]; then
  644. local -a tmp
  645. tmp=( ${expanded_path}*(N) )
  646. (( $#tmp > 0 )) && REPLY=path_prefix && return 0
  647. fi
  648. # It's not a path.
  649. return 1
  650. }
  651. # Highlight special chars inside double-quoted strings
  652. _zsh_highlight_main_highlighter_highlight_string()
  653. {
  654. setopt localoptions noksharrays
  655. local -a match mbegin mend
  656. local MATCH; integer MBEGIN MEND
  657. local i j k style
  658. # Starting quote is at 1, so start parsing at offset 2 in the string.
  659. for (( i = 2 ; i < end_pos - start_pos ; i += 1 )) ; do
  660. (( j = i + start_pos - 1 ))
  661. (( k = j + 1 ))
  662. case "$arg[$i]" in
  663. '$' ) style=dollar-double-quoted-argument
  664. # Look for an alphanumeric parameter name.
  665. if [[ ${arg:$i} =~ ^([A-Za-z_][A-Za-z0-9_]*|[0-9]+) ]] ; then
  666. (( k += $#MATCH )) # highlight the parameter name
  667. (( i += $#MATCH )) # skip past it
  668. elif [[ ${arg:$i} =~ ^[{]([A-Za-z_][A-Za-z0-9_]*|[0-9]+)[}] ]] ; then
  669. (( k += $#MATCH )) # highlight the parameter name and braces
  670. (( i += $#MATCH )) # skip past it
  671. else
  672. continue
  673. fi
  674. ;;
  675. "\\") style=back-double-quoted-argument
  676. if [[ \\\`\"\$ == *$arg[$i+1]* ]]; then
  677. (( k += 1 )) # Color following char too.
  678. (( i += 1 )) # Skip parsing the escaped char.
  679. else
  680. continue
  681. fi
  682. ;;
  683. *) continue ;;
  684. esac
  685. _zsh_highlight_main_add_region_highlight $j $k $style
  686. done
  687. }
  688. # Highlight special chars inside dollar-quoted strings
  689. _zsh_highlight_main_highlighter_highlight_dollar_string()
  690. {
  691. setopt localoptions noksharrays
  692. local -a match mbegin mend
  693. local MATCH; integer MBEGIN MEND
  694. local i j k style
  695. local AA
  696. integer c
  697. # Starting dollar-quote is at 1:2, so start parsing at offset 3 in the string.
  698. for (( i = 3 ; i < end_pos - start_pos ; i += 1 )) ; do
  699. (( j = i + start_pos - 1 ))
  700. (( k = j + 1 ))
  701. case "$arg[$i]" in
  702. "\\") style=back-dollar-quoted-argument
  703. for (( c = i + 1 ; c <= end_pos - start_pos ; c += 1 )); do
  704. [[ "$arg[$c]" != ([0-9xXuUa-fA-F]) ]] && break
  705. done
  706. AA=$arg[$i+1,$c-1]
  707. # Matching for HEX and OCT values like \0xA6, \xA6 or \012
  708. if [[ "$AA" =~ "^(x|X)[0-9a-fA-F]{1,2}"
  709. || "$AA" =~ "^[0-7]{1,3}"
  710. || "$AA" =~ "^u[0-9a-fA-F]{1,4}"
  711. || "$AA" =~ "^U[0-9a-fA-F]{1,8}"
  712. ]]; then
  713. (( k += $#MATCH ))
  714. (( i += $#MATCH ))
  715. else
  716. if (( $#arg > $i+1 )) && [[ $arg[$i+1] == [xXuU] ]]; then
  717. # \x not followed by hex digits is probably an error
  718. style=unknown-token
  719. fi
  720. (( k += 1 )) # Color following char too.
  721. (( i += 1 )) # Skip parsing the escaped char.
  722. fi
  723. ;;
  724. *) continue ;;
  725. esac
  726. _zsh_highlight_main_add_region_highlight $j $k $style
  727. done
  728. }
  729. # Called with a single positional argument.
  730. # Perform filename expansion (tilde expansion) on the argument and set $REPLY to the expanded value.
  731. #
  732. # Does not perform filename generation (globbing).
  733. _zsh_highlight_main_highlighter_expand_path()
  734. {
  735. (( $# == 1 )) || print -r -- >&2 "zsh-syntax-highlighting: BUG: _zsh_highlight_main_highlighter_expand_path: called without argument"
  736. # The $~1 syntax normally performs filename generation, but not when it's on the right-hand side of ${x:=y}.
  737. setopt localoptions nonomatch
  738. unset REPLY
  739. : ${REPLY:=${(Q)~1}}
  740. }
  741. # -------------------------------------------------------------------------------------------------
  742. # Main highlighter initialization
  743. # -------------------------------------------------------------------------------------------------
  744. _zsh_highlight_main__precmd_hook() {
  745. _zsh_highlight_main__command_type_cache=()
  746. }
  747. autoload -U add-zsh-hook
  748. if add-zsh-hook precmd _zsh_highlight_main__precmd_hook 2>/dev/null; then
  749. # Initialize command type cache
  750. typeset -gA _zsh_highlight_main__command_type_cache
  751. else
  752. print -r -- >&2 'zsh-syntax-highlighting: Failed to load add-zsh-hook. Some speed optimizations will not be used.'
  753. # Make sure the cache is unset
  754. unset _zsh_highlight_main__command_type_cache
  755. fi