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.

721 Zeilen
28 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_main_highlighter_predicate()
  61. {
  62. # accept-* may trigger removal of path_prefix highlighting
  63. [[ $WIDGET == accept-* ]] ||
  64. _zsh_highlight_buffer_modified
  65. }
  66. # Helper to deal with tokens crossing line boundaries.
  67. _zsh_highlight_main_add_region_highlight() {
  68. integer start=$1 end=$2
  69. shift 2
  70. # The calculation was relative to $PREBUFFER$BUFFER, but region_highlight is
  71. # relative to $BUFFER.
  72. (( start -= $#PREBUFFER ))
  73. (( end -= $#PREBUFFER ))
  74. (( end < 0 )) && return # having end<0 would be a bug
  75. (( start < 0 )) && start=0 # having start<0 is normal with e.g. multiline strings
  76. _zsh_highlight_add_highlight $start $end "$@"
  77. }
  78. # Get the type of a command.
  79. #
  80. # Uses the zsh/parameter module if available to avoid forks, and a
  81. # wrapper around 'type -w' as fallback.
  82. #
  83. # Takes a single argument.
  84. #
  85. # The result will be stored in REPLY.
  86. _zsh_highlight_main__type() {
  87. if (( $+_zsh_highlight_main__command_type_cache )); then
  88. REPLY=$_zsh_highlight_main__command_type_cache[(e)$1]
  89. if [[ -n "$REPLY" ]]; then
  90. return
  91. fi
  92. fi
  93. if (( $#options_to_set )); then
  94. setopt localoptions $options_to_set;
  95. fi
  96. unset REPLY
  97. if zmodload -e zsh/parameter; then
  98. if (( $+aliases[(e)$1] )); then
  99. REPLY=alias
  100. elif (( $+saliases[(e)${1##*.}] )); then
  101. REPLY='suffix alias'
  102. elif (( $reswords[(Ie)$1] )); then
  103. REPLY=reserved
  104. elif (( $+functions[(e)$1] )); then
  105. REPLY=function
  106. elif (( $+builtins[(e)$1] )); then
  107. REPLY=builtin
  108. elif (( $+commands[(e)$1] )); then
  109. REPLY=command
  110. elif ! builtin type -w -- $1 >/dev/null 2>&1; then
  111. REPLY=none
  112. fi
  113. fi
  114. if ! (( $+REPLY )); then
  115. REPLY="${$(LC_ALL=C builtin type -w -- $1 2>/dev/null)#*: }"
  116. fi
  117. if (( $+_zsh_highlight_main__command_type_cache )); then
  118. _zsh_highlight_main__command_type_cache[(e)$1]=$REPLY
  119. fi
  120. }
  121. # Check whether the first argument is a redirection operator token.
  122. # Report result via the exit code.
  123. _zsh_highlight_main__is_redirection() {
  124. # A redirection operator token:
  125. # - starts with an optional single-digit number;
  126. # - then, has a '<' or '>' character;
  127. # - is not a process substitution [<(...) or >(...)].
  128. [[ $1 == (<0-9>|)(\<|\>)* ]] && [[ $1 != (\<|\>)$'\x28'* ]]
  129. }
  130. # Resolve alias.
  131. #
  132. # Takes a single argument.
  133. #
  134. # The result will be stored in REPLY.
  135. _zsh_highlight_main__resolve_alias() {
  136. if zmodload -e zsh/parameter; then
  137. REPLY=${aliases[$arg]}
  138. else
  139. REPLY="${"$(alias -- $arg)"#*=}"
  140. fi
  141. }
  142. # Main syntax highlighting function.
  143. _zsh_highlight_main_highlighter()
  144. {
  145. ## Before we even 'emulate -L', we must test a few options that would reset.
  146. if [[ -o interactive_comments ]]; then
  147. local interactive_comments= # set to empty
  148. fi
  149. if [[ -o path_dirs ]]; then
  150. integer path_dirs_was_set=1
  151. else
  152. integer path_dirs_was_set=0
  153. fi
  154. emulate -L zsh
  155. setopt localoptions extendedglob bareglobqual
  156. # At the PS3 prompt and in vared, highlight nothing.
  157. #
  158. # (We can't check this in _zsh_highlight_main_highlighter_predicate because
  159. # if the predicate returns false, the previous value of region_highlight
  160. # would be reused.)
  161. if [[ $CONTEXT == (select|vared) ]]; then
  162. return
  163. fi
  164. ## Variable declarations and initializations
  165. local start_pos=0 end_pos highlight_glob=true arg style
  166. local in_array_assignment=false # true between 'a=(' and the matching ')'
  167. typeset -a ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR
  168. typeset -a ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS
  169. typeset -a ZSH_HIGHLIGHT_TOKENS_CONTROL_FLOW
  170. local -a options_to_set # used in callees
  171. local buf="$PREBUFFER$BUFFER"
  172. integer len="${#buf}"
  173. if (( path_dirs_was_set )); then
  174. options_to_set+=( PATH_DIRS )
  175. fi
  176. unset path_dirs_was_set
  177. ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR=(
  178. '|' '||' ';' '&' '&&'
  179. '|&'
  180. '&!' '&|'
  181. # ### 'case' syntax, but followed by a pattern, not by a command
  182. # ';;' ';&' ';|'
  183. )
  184. ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS=(
  185. 'builtin' 'command' 'exec' 'nocorrect' 'noglob'
  186. 'pkexec' # immune to #121 because it's usually not passed --option flags
  187. )
  188. # Tokens that, at (naively-determined) "command position", are followed by
  189. # a de jure command position. All of these are reserved words.
  190. ZSH_HIGHLIGHT_TOKENS_CONTROL_FLOW=(
  191. $'\x7b' # block
  192. $'\x28' # subshell
  193. '()' # anonymous function
  194. 'while'
  195. 'until'
  196. 'if'
  197. 'then'
  198. 'elif'
  199. 'else'
  200. 'do'
  201. 'time'
  202. 'coproc'
  203. '!' # reserved word; unrelated to $histchars[1]
  204. )
  205. # State machine
  206. #
  207. # The states are:
  208. # - :start: Command word
  209. # - :sudo_opt: A leading-dash option to sudo (such as "-u" or "-i")
  210. # - :sudo_arg: The argument to a sudo leading-dash option that takes one,
  211. # when given as a separate word; i.e., "foo" in "-u foo" (two
  212. # words) but not in "-ufoo" (one word).
  213. # - :regular: "Not a command word", and command delimiters are permitted.
  214. # Mainly used to detect premature termination of commands.
  215. #
  216. # When the kind of a word is not yet known, $this_word / $next_word may contain
  217. # multiple states. For example, after "sudo -i", the next word may be either
  218. # another --flag or a command name, hence the state would include both :start:
  219. # and :sudo_opt:.
  220. #
  221. # The tokens are always added with both leading and trailing colons to serve as
  222. # word delimiters (an improvised array); [[ $x == *:foo:* ]] and x=${x//:foo:/}
  223. # will DTRT regardless of how many elements or repetitions $x has..
  224. #
  225. # Handling of redirections: upon seeing a redirection token, we must stall
  226. # the current state --- that is, the value of $this_word --- for two iterations
  227. # (one for the redirection operator, one for the word following it representing
  228. # the redirection target). Therefore, we set $in_redirection to 2 upon seeing a
  229. # redirection operator, decrement it each iteration, and stall the current state
  230. # when it is non-zero. Thus, upon reaching the next word (the one that follows
  231. # the redirection operator and target), $this_word will still contain values
  232. # appropriate for the word immediately following the word that preceded the
  233. # redirection operator.
  234. #
  235. # The "the previous word was a redirection operator" state is not communicated
  236. # to the next iteration via $next_word/$this_word as usual, but via
  237. # $in_redirection. The value of $next_word from the iteration that processed
  238. # the operator is discarded.
  239. #
  240. local this_word=':start:' next_word
  241. integer in_redirection
  242. # Processing buffer
  243. local proc_buf="$buf"
  244. for arg in ${interactive_comments-${(z)buf}} \
  245. ${interactive_comments+${(zZ+c+)buf}}; do
  246. if (( in_redirection )); then
  247. (( --in_redirection ))
  248. fi
  249. if (( in_redirection == 0 )); then
  250. # Initialize $next_word to its default value.
  251. next_word=':regular:'
  252. else
  253. # Stall $next_word.
  254. fi
  255. # $already_added is set to 1 to disable adding an entry to region_highlight
  256. # for this iteration. Currently, that is done for "" and $'' strings,
  257. # which add the entry early so escape sequences within the string override
  258. # the string's color.
  259. integer already_added=0
  260. style=unknown-token
  261. if [[ $this_word == *':start:'* ]]; then
  262. in_array_assignment=false
  263. if [[ $arg == 'noglob' ]]; then
  264. highlight_glob=false
  265. fi
  266. fi
  267. # advance $start_pos, skipping over whitespace in $buf.
  268. if [[ $arg == ';' ]] ; then
  269. # We're looking for either a semicolon or a newline, whichever comes
  270. # first. Both of these are rendered as a ";" (SEPER) by the ${(z)..}
  271. # flag.
  272. #
  273. # We can't use the (Z+n+) flag because that elides the end-of-command
  274. # token altogether, so 'echo foo\necho bar' (two commands) becomes
  275. # indistinguishable from 'echo foo echo bar' (one command with three
  276. # words for arguments).
  277. local needle=$'[;\n]'
  278. integer offset=$(( ${proc_buf[(i)$needle]} - 1 ))
  279. (( start_pos += offset ))
  280. (( end_pos = start_pos + $#arg ))
  281. else
  282. integer offset=$(((len-start_pos)-${#${proc_buf##([[:space:]]|\\[[:space:]])#}}))
  283. ((start_pos+=offset))
  284. ((end_pos=$start_pos+${#arg}))
  285. fi
  286. # Above `if` computes new start_pos and end_pos.
  287. # Here we compute new proc_buf. We advance it
  288. # (chop off characters from the beginning)
  289. # beyond what end_pos points to, by skipping
  290. # as many characters as end_pos was advanced.
  291. #
  292. # end_pos was advanced by $offset (via start_pos)
  293. # and by $#arg. Note the `start_pos=$end_pos`
  294. # below.
  295. #
  296. # As for the [,len]. We could use [,len-start_pos+offset]
  297. # here, but to make it easier on eyes, we use len and
  298. # rely on the fact that Zsh simply handles that. The
  299. # length of proc_buf is len-start_pos+offset because
  300. # we're chopping it to match current start_pos, so its
  301. # length matches the previous value of start_pos.
  302. #
  303. # Why [,-1] is slower than [,length] isn't clear.
  304. proc_buf="${proc_buf[offset + $#arg + 1,len]}"
  305. if [[ -n ${interactive_comments+'set'} && $arg[1] == $histchars[3] ]]; then
  306. if [[ $this_word == *(':regular:'|':start:')* ]]; then
  307. style=comment
  308. else
  309. style=unknown-token # prematurely terminated
  310. fi
  311. _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
  312. already_added=1
  313. continue
  314. fi
  315. # Parse the sudo command line
  316. if (( ! in_redirection )); then
  317. if [[ $this_word == *':sudo_opt:'* ]]; then
  318. case "$arg" in
  319. # Flag that requires an argument
  320. '-'[Cgprtu]) this_word=${this_word//:start:/};
  321. next_word=':sudo_arg:';;
  322. # This prevents misbehavior with sudo -u -otherargument
  323. '-'*) this_word=${this_word//:start:/};
  324. next_word+=':start:';
  325. next_word+=':sudo_opt:';;
  326. *) ;;
  327. esac
  328. elif [[ $this_word == *':sudo_arg:'* ]]; then
  329. next_word+=':sudo_opt:'
  330. next_word+=':start:'
  331. fi
  332. fi
  333. if [[ $this_word == *':start:'* ]] && (( in_redirection == 0 )); then # $arg is the command word
  334. if [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$arg"} ]]; then
  335. style=precommand
  336. elif [[ "$arg" = "sudo" ]]; then
  337. style=precommand
  338. next_word=${next_word//:regular:/}
  339. next_word+=':sudo_opt:'
  340. next_word+=':start:'
  341. else
  342. _zsh_highlight_main_highlighter_expand_path $arg
  343. local expanded_arg="$REPLY"
  344. _zsh_highlight_main__type ${expanded_arg}
  345. local res="$REPLY"
  346. () {
  347. # Special-case: command word is '$foo', like that, without braces or anything.
  348. #
  349. # That's not entirely correct --- if the parameter's value happens to be a reserved
  350. # word, the parameter expansion will be highlighted as a reserved word --- but that
  351. # incorrectness is outweighed by the usability improvement of permitting the use of
  352. # parameters that refer to commands, functions, and builtins.
  353. local -a match mbegin mend
  354. local MATCH; integer MBEGIN MEND
  355. if [[ $res == none ]] && (( ${+parameters} )) &&
  356. [[ ${arg[1]} == \$ ]] && [[ ${arg:1} =~ ^([A-Za-z_][A-Za-z0-9_]*|[0-9]+)$ ]] &&
  357. (( ${+parameters[${MATCH}]} ))
  358. then
  359. _zsh_highlight_main__type ${(P)MATCH}
  360. res=$REPLY
  361. fi
  362. }
  363. case $res in
  364. reserved) style=reserved-word;;
  365. 'suffix alias') style=suffix-alias;;
  366. alias) () {
  367. integer insane_alias
  368. case $arg in
  369. # Issue #263: aliases with '=' on their LHS.
  370. #
  371. # There are three cases:
  372. #
  373. # - Unsupported, breaks 'alias -L' output, but invokable:
  374. ('='*) :;;
  375. # - Unsupported, not invokable:
  376. (*'='*) insane_alias=1;;
  377. # - The common case:
  378. (*) :;;
  379. esac
  380. if (( insane_alias )); then
  381. style=unknown-token
  382. else
  383. style=alias
  384. _zsh_highlight_main__resolve_alias $arg
  385. local alias_target="$REPLY"
  386. [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$alias_target"} && -z ${(M)ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$arg"} ]] && ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS+=($arg)
  387. fi
  388. }
  389. ;;
  390. builtin) style=builtin;;
  391. function) style=function;;
  392. command) style=command;;
  393. hashed) style=hashed-command;;
  394. none) if _zsh_highlight_main_highlighter_check_assign; then
  395. style=assign
  396. if [[ $arg[-1] == '(' ]]; then
  397. in_array_assignment=true
  398. else
  399. # assignment to a scalar parameter.
  400. # (For array assignments, the command doesn't start until the ")" token.)
  401. next_word+=':start:'
  402. fi
  403. elif [[ $arg[0,1] = $histchars[0,1] ]] && (( $#arg[0,2] == 2 )); then
  404. style=history-expansion
  405. elif [[ $arg[0,1] == $histchars[2,2] ]]; then
  406. style=history-expansion
  407. elif [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]]; then
  408. if [[ $this_word == *':regular:'* ]]; then
  409. # This highlights empty commands (semicolon follows nothing) as an error.
  410. # Zsh accepts them, though.
  411. style=commandseparator
  412. else
  413. style=unknown-token
  414. fi
  415. elif _zsh_highlight_main__is_redirection $arg; then
  416. # A '<' or '>', possibly followed by a digit
  417. style=redirection
  418. (( in_redirection=2 ))
  419. elif [[ $arg[1,2] == '((' ]]; then
  420. # Arithmetic evaluation.
  421. #
  422. # Note: prior to zsh-5.1.1-52-g4bed2cf (workers/36669), the ${(z)...}
  423. # splitter would only output the '((' token if the matching '))' had
  424. # been typed. Therefore, under those versions of zsh, BUFFER="(( 42"
  425. # would be highlighted as an error until the matching "))" are typed.
  426. #
  427. # We highlight just the opening parentheses, as a reserved word; this
  428. # is how [[ ... ]] is highlighted, too.
  429. style=reserved-word
  430. _zsh_highlight_main_add_region_highlight $start_pos $((start_pos + 2)) $style
  431. already_added=1
  432. if [[ $arg[-2,-1] == '))' ]]; then
  433. _zsh_highlight_main_add_region_highlight $((end_pos - 2)) $end_pos $style
  434. already_added=1
  435. fi
  436. elif [[ $arg == '()' || $arg == $'\x28' ]]; then
  437. # anonymous function
  438. # subshell
  439. style=reserved-word
  440. else
  441. if _zsh_highlight_main_highlighter_check_path; then
  442. style=$REPLY
  443. else
  444. style=unknown-token
  445. fi
  446. fi
  447. ;;
  448. *) _zsh_highlight_main_add_region_highlight $start_pos $end_pos commandtypefromthefuture-$res
  449. already_added=1
  450. ;;
  451. esac
  452. fi
  453. fi
  454. if (( ! already_added )) && [[ $style == unknown-token ]] && # not handled by the 'command word' codepath
  455. { (( in_redirection )) || [[ $this_word == *':regular:'* ]] || [[ $this_word == *':sudo_opt:'* ]] || [[ $this_word == *':sudo_arg:'* ]] }
  456. then # $arg is a non-command word
  457. case $arg in
  458. $'\x29') # subshell or end of array assignment
  459. if $in_array_assignment; then
  460. style=assign
  461. in_array_assignment=false
  462. next_word+=':start:'
  463. else
  464. style=reserved-word
  465. fi;;
  466. $'\x7d') style=reserved-word;; # block
  467. '--'*) style=double-hyphen-option;;
  468. '-'*) style=single-hyphen-option;;
  469. "'"*) style=single-quoted-argument;;
  470. '"'*) style=double-quoted-argument
  471. _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
  472. _zsh_highlight_main_highlighter_highlight_string
  473. already_added=1
  474. ;;
  475. \$\'*) style=dollar-quoted-argument
  476. _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
  477. _zsh_highlight_main_highlighter_highlight_dollar_string
  478. already_added=1
  479. ;;
  480. '`'*) style=back-quoted-argument;;
  481. [*?]*|*[^\\][*?]*)
  482. $highlight_glob && style=globbing || style=default;;
  483. *) if false; then
  484. elif [[ $arg[0,1] = $histchars[0,1] ]] && (( $#arg[0,2] == 2 )); then
  485. style=history-expansion
  486. elif [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]]; then
  487. if [[ $this_word == *':regular:'* ]]; then
  488. style=commandseparator
  489. else
  490. style=unknown-token
  491. fi
  492. elif _zsh_highlight_main__is_redirection $arg; then
  493. style=redirection
  494. (( in_redirection=2 ))
  495. else
  496. if _zsh_highlight_main_highlighter_check_path; then
  497. style=$REPLY
  498. else
  499. style=default
  500. fi
  501. fi
  502. ;;
  503. esac
  504. fi
  505. if ! (( already_added )); then
  506. _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
  507. [[ $style == path || $style == path_prefix ]] && _zsh_highlight_main_highlighter_highlight_path_separators
  508. fi
  509. if [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]]; then
  510. next_word=':start:'
  511. highlight_glob=true
  512. elif
  513. [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_CONTROL_FLOW:#"$arg"} && $this_word == *':start:'* ]] ||
  514. [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_PRECOMMANDS:#"$arg"} && $this_word == *':start:'* ]]; then
  515. next_word=':start:'
  516. elif [[ $arg == "repeat" && $this_word == *':start:'* ]]; then
  517. # skip the repeat-count word
  518. in_redirection=2
  519. # The redirection mechanism assumes $this_word describes the word
  520. # following the redirection. Make it so.
  521. #
  522. # That word can be a command word with shortloops (`repeat 2 ls`)
  523. # or a command separator (`repeat 2; ls` or `repeat 2; do ls; done`).
  524. #
  525. # The repeat-count word will be handled like a redirection target.
  526. this_word=':start::regular:'
  527. fi
  528. start_pos=$end_pos
  529. (( in_redirection == 0 )) && this_word=$next_word
  530. done
  531. }
  532. # Check if $arg is variable assignment
  533. _zsh_highlight_main_highlighter_check_assign()
  534. {
  535. setopt localoptions extended_glob
  536. [[ $arg == [[:alpha:]_][[:alnum:]_]#(|\[*\])(|[+])=* ]] ||
  537. [[ $arg == [0-9]##(|[+])=* ]]
  538. }
  539. _zsh_highlight_main_highlighter_highlight_path_separators()
  540. {
  541. local pos style_pathsep
  542. style_pathsep=${style}_pathseparator
  543. [[ -z "$ZSH_HIGHLIGHT_STYLES[$style_pathsep]" || "$ZSH_HIGHLIGHT_STYLES[$style]" == "$ZSH_HIGHLIGHT_STYLES[$style_pathsep]" ]] && return 0
  544. for (( pos = start_pos; $pos <= end_pos; pos++ )) ; do
  545. if [[ $BUFFER[pos] == / ]]; then
  546. _zsh_highlight_main_add_region_highlight $((pos - 1)) $pos $style_pathsep
  547. fi
  548. done
  549. }
  550. # Check if $arg is a path.
  551. # If yes, return 0 and in $REPLY the style to use.
  552. # Else, return non-zero (and the contents of $REPLY is undefined).
  553. _zsh_highlight_main_highlighter_check_path()
  554. {
  555. _zsh_highlight_main_highlighter_expand_path $arg;
  556. local expanded_path="$REPLY"
  557. REPLY=path
  558. [[ -z $expanded_path ]] && return 1
  559. [[ -L $expanded_path ]] && return 0
  560. [[ -e $expanded_path ]] && return 0
  561. # Search the path in CDPATH
  562. local cdpath_dir
  563. for cdpath_dir in $cdpath ; do
  564. [[ -e "$cdpath_dir/$expanded_path" ]] && return 0
  565. done
  566. # If dirname($arg) doesn't exist, neither does $arg.
  567. [[ ! -d ${expanded_path:h} ]] && return 1
  568. # If this word ends the buffer, check if it's the prefix of a valid path.
  569. if [[ ${BUFFER[1]} != "-" && ${#BUFFER} == $end_pos ]] &&
  570. [[ $WIDGET != accept-* ]]; then
  571. local -a tmp
  572. tmp=( ${expanded_path}*(N) )
  573. (( $#tmp > 0 )) && REPLY=path_prefix && return 0
  574. fi
  575. # It's not a path.
  576. return 1
  577. }
  578. # Highlight special chars inside double-quoted strings
  579. _zsh_highlight_main_highlighter_highlight_string()
  580. {
  581. setopt localoptions noksharrays
  582. local -a match mbegin mend
  583. local MATCH; integer MBEGIN MEND
  584. local i j k style
  585. # Starting quote is at 1, so start parsing at offset 2 in the string.
  586. for (( i = 2 ; i < end_pos - start_pos ; i += 1 )) ; do
  587. (( j = i + start_pos - 1 ))
  588. (( k = j + 1 ))
  589. case "$arg[$i]" in
  590. '$' ) style=dollar-double-quoted-argument
  591. # Look for an alphanumeric parameter name.
  592. if [[ ${arg:$i} =~ ^([A-Za-z_][A-Za-z0-9_]*|[0-9]+) ]] ; then
  593. (( k += $#MATCH )) # highlight the parameter name
  594. (( i += $#MATCH )) # skip past it
  595. elif [[ ${arg:$i} =~ ^[{]([A-Za-z_][A-Za-z0-9_]*|[0-9]+)[}] ]] ; then
  596. (( k += $#MATCH )) # highlight the parameter name and braces
  597. (( i += $#MATCH )) # skip past it
  598. else
  599. continue
  600. fi
  601. ;;
  602. "\\") style=back-double-quoted-argument
  603. if [[ \\\`\"\$ == *$arg[$i+1]* ]]; then
  604. (( k += 1 )) # Color following char too.
  605. (( i += 1 )) # Skip parsing the escaped char.
  606. else
  607. continue
  608. fi
  609. ;;
  610. *) continue ;;
  611. esac
  612. _zsh_highlight_main_add_region_highlight $j $k $style
  613. done
  614. }
  615. # Highlight special chars inside dollar-quoted strings
  616. _zsh_highlight_main_highlighter_highlight_dollar_string()
  617. {
  618. setopt localoptions noksharrays
  619. local -a match mbegin mend
  620. local MATCH; integer MBEGIN MEND
  621. local i j k style
  622. local AA
  623. integer c
  624. # Starting dollar-quote is at 1:2, so start parsing at offset 3 in the string.
  625. for (( i = 3 ; i < end_pos - start_pos ; i += 1 )) ; do
  626. (( j = i + start_pos - 1 ))
  627. (( k = j + 1 ))
  628. case "$arg[$i]" in
  629. "\\") style=back-dollar-quoted-argument
  630. for (( c = i + 1 ; c <= end_pos - start_pos ; c += 1 )); do
  631. [[ "$arg[$c]" != ([0-9xXuUa-fA-F]) ]] && break
  632. done
  633. AA=$arg[$i+1,$c-1]
  634. # Matching for HEX and OCT values like \0xA6, \xA6 or \012
  635. if [[ "$AA" =~ "^(x|X)[0-9a-fA-F]{1,2}"
  636. || "$AA" =~ "^[0-7]{1,3}"
  637. || "$AA" =~ "^u[0-9a-fA-F]{1,4}"
  638. || "$AA" =~ "^U[0-9a-fA-F]{1,8}"
  639. ]]; then
  640. (( k += $#MATCH ))
  641. (( i += $#MATCH ))
  642. else
  643. if (( $#arg > $i+1 )) && [[ $arg[$i+1] == [xXuU] ]]; then
  644. # \x not followed by hex digits is probably an error
  645. style=unknown-token
  646. fi
  647. (( k += 1 )) # Color following char too.
  648. (( i += 1 )) # Skip parsing the escaped char.
  649. fi
  650. ;;
  651. *) continue ;;
  652. esac
  653. _zsh_highlight_main_add_region_highlight $j $k $style
  654. done
  655. }
  656. # Called with a single positional argument.
  657. # Perform filename expansion (tilde expansion) on the argument and set $REPLY to the expanded value.
  658. #
  659. # Does not perform filename generation (globbing).
  660. _zsh_highlight_main_highlighter_expand_path()
  661. {
  662. (( $# == 1 )) || print -r -- >&2 "zsh-syntax-highlighting: BUG: _zsh_highlight_main_highlighter_expand_path: called without argument"
  663. # The $~1 syntax normally performs filename generation, but not when it's on the right-hand side of ${x:=y}.
  664. setopt localoptions nonomatch
  665. unset REPLY
  666. : ${REPLY:=${(Q)~1}}
  667. }
  668. # -------------------------------------------------------------------------------------------------
  669. # Main highlighter initialization
  670. # -------------------------------------------------------------------------------------------------
  671. _zsh_highlight_main__precmd_hook() {
  672. _zsh_highlight_main__command_type_cache=()
  673. }
  674. autoload -U add-zsh-hook
  675. if add-zsh-hook precmd _zsh_highlight_main__precmd_hook 2>/dev/null; then
  676. # Initialize command type cache
  677. typeset -gA _zsh_highlight_main__command_type_cache
  678. else
  679. print -r -- >&2 'zsh-syntax-highlighting: Failed to load add-zsh-hook. Some speed optimizations will not be used.'
  680. # Make sure the cache is unset
  681. unset _zsh_highlight_main__command_type_cache
  682. fi