@andespindola/crow-term-linux-x64 0.0.0-bootstrap.1 → 0.1.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/LICENSE +55 -0
  2. package/NOTICE.md +25 -0
  3. package/README.md +5 -0
  4. package/THIRD_PARTY_LICENSES.txt +71128 -0
  5. package/assets/fonts/OFL.txt +96 -0
  6. package/assets/theme-license.txt +21 -0
  7. package/bin/crow-term +4 -0
  8. package/bin/shell/README.md +37 -0
  9. package/bin/shell/plugins.lock.json +63 -0
  10. package/bin/shell/setup.py +241 -0
  11. package/bin/shell/vendor/fisher/LICENSE.md +7 -0
  12. package/bin/shell/vendor/fisher/completions/fisher.fish +7 -0
  13. package/bin/shell/vendor/fisher/functions/fisher.fish +251 -0
  14. package/bin/shell/vendor/z/LICENSE +21 -0
  15. package/bin/shell/vendor/z/conf.d/z.fish +63 -0
  16. package/bin/shell/vendor/z/functions/__z.fish +178 -0
  17. package/bin/shell/vendor/z/functions/__z_add.fish +49 -0
  18. package/bin/shell/vendor/z/functions/__z_clean.fish +11 -0
  19. package/bin/shell/vendor/z/functions/__z_complete.fish +13 -0
  20. package/bin/shell/vendor/zsh-autosuggestions/LICENSE +23 -0
  21. package/bin/shell/vendor/zsh-autosuggestions/zsh-autosuggestions.zsh +867 -0
  22. package/bin/shell/vendor/zsh-syntax-highlighting/.revision-hash +1 -0
  23. package/bin/shell/vendor/zsh-syntax-highlighting/.version +1 -0
  24. package/bin/shell/vendor/zsh-syntax-highlighting/COPYING.md +23 -0
  25. package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/brackets/brackets-highlighter.zsh +107 -0
  26. package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/cursor/cursor-highlighter.zsh +47 -0
  27. package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/line/line-highlighter.zsh +44 -0
  28. package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/main/main-highlighter.zsh +1853 -0
  29. package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/pattern/pattern-highlighter.zsh +60 -0
  30. package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/regexp/regexp-highlighter.zsh +62 -0
  31. package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/root/root-highlighter.zsh +44 -0
  32. package/bin/shell/vendor/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh +587 -0
  33. package/package.json +35 -1
@@ -0,0 +1,1853 @@
1
+ # -------------------------------------------------------------------------------------------------
2
+ # Copyright (c) 2010-2020 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
+
30
+
31
+ # Define default styles.
32
+ : ${ZSH_HIGHLIGHT_STYLES[default]:=none}
33
+ : ${ZSH_HIGHLIGHT_STYLES[unknown-token]:=fg=red,bold}
34
+ : ${ZSH_HIGHLIGHT_STYLES[reserved-word]:=fg=yellow}
35
+ : ${ZSH_HIGHLIGHT_STYLES[suffix-alias]:=fg=green,underline}
36
+ : ${ZSH_HIGHLIGHT_STYLES[global-alias]:=fg=cyan}
37
+ : ${ZSH_HIGHLIGHT_STYLES[precommand]:=fg=green,underline}
38
+ : ${ZSH_HIGHLIGHT_STYLES[commandseparator]:=none}
39
+ : ${ZSH_HIGHLIGHT_STYLES[autodirectory]:=fg=green,underline}
40
+ : ${ZSH_HIGHLIGHT_STYLES[path]:=underline}
41
+ : ${ZSH_HIGHLIGHT_STYLES[path_pathseparator]:=}
42
+ : ${ZSH_HIGHLIGHT_STYLES[path_prefix_pathseparator]:=}
43
+ : ${ZSH_HIGHLIGHT_STYLES[globbing]:=fg=blue}
44
+ : ${ZSH_HIGHLIGHT_STYLES[history-expansion]:=fg=blue}
45
+ : ${ZSH_HIGHLIGHT_STYLES[command-substitution]:=none}
46
+ : ${ZSH_HIGHLIGHT_STYLES[command-substitution-delimiter]:=fg=magenta}
47
+ : ${ZSH_HIGHLIGHT_STYLES[process-substitution]:=none}
48
+ : ${ZSH_HIGHLIGHT_STYLES[process-substitution-delimiter]:=fg=magenta}
49
+ : ${ZSH_HIGHLIGHT_STYLES[single-hyphen-option]:=none}
50
+ : ${ZSH_HIGHLIGHT_STYLES[double-hyphen-option]:=none}
51
+ : ${ZSH_HIGHLIGHT_STYLES[back-quoted-argument]:=none}
52
+ : ${ZSH_HIGHLIGHT_STYLES[back-quoted-argument-delimiter]:=fg=magenta}
53
+ : ${ZSH_HIGHLIGHT_STYLES[single-quoted-argument]:=fg=yellow}
54
+ : ${ZSH_HIGHLIGHT_STYLES[double-quoted-argument]:=fg=yellow}
55
+ : ${ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]:=fg=yellow}
56
+ : ${ZSH_HIGHLIGHT_STYLES[rc-quote]:=fg=cyan}
57
+ : ${ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument]:=fg=cyan}
58
+ : ${ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument]:=fg=cyan}
59
+ : ${ZSH_HIGHLIGHT_STYLES[back-dollar-quoted-argument]:=fg=cyan}
60
+ : ${ZSH_HIGHLIGHT_STYLES[assign]:=none}
61
+ : ${ZSH_HIGHLIGHT_STYLES[redirection]:=fg=yellow}
62
+ : ${ZSH_HIGHLIGHT_STYLES[comment]:=fg=black,bold}
63
+ : ${ZSH_HIGHLIGHT_STYLES[named-fd]:=none}
64
+ : ${ZSH_HIGHLIGHT_STYLES[numeric-fd]:=none}
65
+ : ${ZSH_HIGHLIGHT_STYLES[arg0]:=fg=green}
66
+
67
+ # Whether the highlighter should be called or not.
68
+ _zsh_highlight_highlighter_main_predicate()
69
+ {
70
+ # may need to remove path_prefix highlighting when the line ends
71
+ [[ $WIDGET == zle-line-finish ]] || _zsh_highlight_buffer_modified
72
+ }
73
+
74
+ # Helper to deal with tokens crossing line boundaries.
75
+ _zsh_highlight_main_add_region_highlight() {
76
+ integer start=$1 end=$2
77
+ shift 2
78
+
79
+ if (( $#in_alias )); then
80
+ [[ $1 == unknown-token ]] && alias_style=unknown-token
81
+ return
82
+ fi
83
+ if (( in_param )); then
84
+ if [[ $1 == unknown-token ]]; then
85
+ param_style=unknown-token
86
+ fi
87
+ if [[ -n $param_style ]]; then
88
+ return
89
+ fi
90
+ param_style=$1
91
+ return
92
+ fi
93
+
94
+ # The calculation was relative to $buf but region_highlight is relative to $BUFFER.
95
+ (( start += buf_offset ))
96
+ (( end += buf_offset ))
97
+
98
+ list_highlights+=($start $end $1)
99
+ }
100
+
101
+ _zsh_highlight_main_add_many_region_highlights() {
102
+ for 1 2 3; do
103
+ _zsh_highlight_main_add_region_highlight $1 $2 $3
104
+ done
105
+ }
106
+
107
+ _zsh_highlight_main_calculate_fallback() {
108
+ local -A fallback_of; fallback_of=(
109
+ alias arg0
110
+ suffix-alias arg0
111
+ global-alias dollar-double-quoted-argument
112
+ builtin arg0
113
+ function arg0
114
+ command arg0
115
+ precommand arg0
116
+ hashed-command arg0
117
+ autodirectory arg0
118
+ arg0_\* arg0
119
+
120
+ # TODO: Maybe these? —
121
+ # named-fd file-descriptor
122
+ # numeric-fd file-descriptor
123
+
124
+ path_prefix path
125
+ # The path separator fallback won't ever be used, due to the optimisation
126
+ # in _zsh_highlight_main_highlighter_highlight_path_separators().
127
+ path_pathseparator path
128
+ path_prefix_pathseparator path_prefix
129
+
130
+ single-quoted-argument{-unclosed,}
131
+ double-quoted-argument{-unclosed,}
132
+ dollar-quoted-argument{-unclosed,}
133
+ back-quoted-argument{-unclosed,}
134
+
135
+ command-substitution{-quoted,,-unquoted,}
136
+ command-substitution-delimiter{-quoted,,-unquoted,}
137
+
138
+ command-substitution{-delimiter,}
139
+ process-substitution{-delimiter,}
140
+ back-quoted-argument{-delimiter,}
141
+ )
142
+ local needle=$1 value
143
+ reply=($1)
144
+ while [[ -n ${value::=$fallback_of[(k)$needle]} ]]; do
145
+ unset "fallback_of[$needle]" # paranoia against infinite loops
146
+ reply+=($value)
147
+ needle=$value
148
+ done
149
+ }
150
+
151
+ # Get the type of a command.
152
+ #
153
+ # Uses the zsh/parameter module if available to avoid forks, and a
154
+ # wrapper around 'type -w' as fallback.
155
+ #
156
+ # If $2 is 0, do not consider aliases.
157
+ #
158
+ # The result will be stored in REPLY.
159
+ _zsh_highlight_main__type() {
160
+ integer -r aliases_allowed=${2-1}
161
+ # We won't cache replies of anything that exists as an alias at all, to
162
+ # ensure the cached value is correct regardless of $aliases_allowed.
163
+ #
164
+ # ### We probably _should_ cache them in a cache that's keyed on the value of
165
+ # ### $aliases_allowed, on the assumption that aliases are the common case.
166
+ integer may_cache=1
167
+
168
+ # Cache lookup
169
+ if (( $+_zsh_highlight_main__command_type_cache )); then
170
+ REPLY=$_zsh_highlight_main__command_type_cache[(e)$1]
171
+ if [[ -n "$REPLY" ]]; then
172
+ return
173
+ fi
174
+ fi
175
+
176
+ # Main logic
177
+ if (( $#options_to_set )); then
178
+ setopt localoptions $options_to_set;
179
+ fi
180
+ unset REPLY
181
+ if zmodload -e zsh/parameter; then
182
+ if (( $+aliases[(e)$1] )); then
183
+ may_cache=0
184
+ fi
185
+ if (( ${+galiases[(e)$1]} )) && (( aliases_allowed )); then
186
+ REPLY='global alias'
187
+ elif (( $+aliases[(e)$1] )) && (( aliases_allowed )); then
188
+ REPLY=alias
189
+ elif [[ $1 == *.* && -n ${1%.*} ]] && (( $+saliases[(e)${1##*.}] )); then
190
+ REPLY='suffix alias'
191
+ elif (( $reswords[(Ie)$1] )); then
192
+ REPLY=reserved
193
+ elif (( $+functions[(e)$1] )); then
194
+ REPLY=function
195
+ elif (( $+builtins[(e)$1] )); then
196
+ REPLY=builtin
197
+ elif (( $+commands[(e)$1] )); then
198
+ REPLY=command
199
+ # None of the special hashes had a match, so fall back to 'type -w', for
200
+ # forward compatibility with future versions of zsh that may add new command
201
+ # types.
202
+ #
203
+ # zsh 5.2 and older have a bug whereby running 'type -w ./sudo' implicitly
204
+ # runs 'hash ./sudo=/usr/local/bin/./sudo' (assuming /usr/local/bin/sudo
205
+ # exists and is in $PATH). Avoid triggering the bug, at the expense of
206
+ # falling through to the $() below, incurring a fork. (Issue #354.)
207
+ #
208
+ # The first disjunct mimics the isrelative() C call from the zsh bug.
209
+ elif { [[ $1 != */* ]] || is-at-least 5.3 } &&
210
+ # Add a subshell to avoid a zsh upstream bug; see issue #606.
211
+ # ### Remove the subshell when we stop supporting zsh 5.7.1 (I assume 5.8 will have the bugfix).
212
+ ! (builtin type -w -- "$1") >/dev/null 2>&1; then
213
+ REPLY=none
214
+ fi
215
+ fi
216
+ if ! (( $+REPLY )); then
217
+ # zsh/parameter not available or had no matches.
218
+ #
219
+ # Note that 'type -w' will run 'rehash' implicitly.
220
+ #
221
+ # We 'unalias' in a subshell, so the parent shell is not affected.
222
+ #
223
+ # The colon command is there just to avoid a command substitution that
224
+ # starts with an arithmetic expression [«((…))» as the first thing inside
225
+ # «$(…)»], which is area that has had some parsing bugs before 5.6
226
+ # (approximately).
227
+ REPLY="${$(:; (( aliases_allowed )) || unalias -- "$1" 2>/dev/null; LC_ALL=C builtin type -w -- "$1" 2>/dev/null)##*: }"
228
+ if [[ $REPLY == 'alias' ]]; then
229
+ may_cache=0
230
+ fi
231
+ fi
232
+
233
+ # Cache population
234
+ if (( may_cache )) && (( $+_zsh_highlight_main__command_type_cache )); then
235
+ _zsh_highlight_main__command_type_cache[(e)$1]=$REPLY
236
+ fi
237
+ [[ -n $REPLY ]]
238
+ return $?
239
+ }
240
+
241
+ # Checks whether $1 is something that can be run.
242
+ #
243
+ # Return 0 if runnable, 1 if not runnable, 2 if trouble.
244
+ _zsh_highlight_main__is_runnable() {
245
+ if _zsh_highlight_main__type "$1"; then
246
+ [[ $REPLY != none ]]
247
+ else
248
+ return 2
249
+ fi
250
+ }
251
+
252
+ # Check whether the first argument is a redirection operator token.
253
+ # Report result via the exit code.
254
+ _zsh_highlight_main__is_redirection() {
255
+ # A redirection operator token:
256
+ # - starts with an optional single-digit number;
257
+ # - is one of the tokens listed in zshmisc(1)
258
+ # - however (z) normalizes ! to |
259
+ [[ ${1#[0-9]} == (\<|\<\>|(\>|\>\>)(|\|)|\<\<(|-)|\<\<\<|\<\&|\&\<|(\>|\>\>)\&(|\|)|\&(\>|\>\>)(|\||\!)) ]]
260
+ }
261
+
262
+ # Resolve alias.
263
+ #
264
+ # Takes a single argument.
265
+ #
266
+ # The result will be stored in REPLY.
267
+ _zsh_highlight_main__resolve_alias() {
268
+ if zmodload -e zsh/parameter; then
269
+ REPLY=${aliases[$arg]}
270
+ else
271
+ REPLY="${"$(alias -- $arg)"#*=}"
272
+ fi
273
+ }
274
+
275
+ # Return true iff $1 is a global alias
276
+ _zsh_highlight_main__is_global_alias() {
277
+ if zmodload -e zsh/parameter; then
278
+ (( ${+galiases[$arg]} ))
279
+ elif [[ $arg == '='* ]]; then
280
+ # avoid running into «alias -L '=foo'» erroring out with 'bad assignment'
281
+ return 1
282
+ else
283
+ alias -L -g -- "$1" >/dev/null
284
+ fi
285
+ }
286
+
287
+ # Check that the top of $braces_stack has the expected value. If it does, set
288
+ # the style according to $2; otherwise, set style=unknown-token.
289
+ #
290
+ # $1: character expected to be at the top of $braces_stack
291
+ # $2: optional assignment to style it if matches
292
+ # return value is 0 if there is a match else 1
293
+ _zsh_highlight_main__stack_pop() {
294
+ if [[ $braces_stack[1] == $1 ]]; then
295
+ braces_stack=${braces_stack:1}
296
+ if (( $+2 )); then
297
+ style=$2
298
+ fi
299
+ return 0
300
+ else
301
+ style=unknown-token
302
+ return 1
303
+ fi
304
+ }
305
+
306
+ # Main syntax highlighting function.
307
+ _zsh_highlight_highlighter_main_paint()
308
+ {
309
+ setopt localoptions extendedglob
310
+
311
+ # At the PS3 prompt and in vared, highlight nothing.
312
+ #
313
+ # (We can't check this in _zsh_highlight_highlighter_main_predicate because
314
+ # if the predicate returns false, the previous value of region_highlight
315
+ # would be reused.)
316
+ if [[ $CONTEXT == (select|vared) ]]; then
317
+ return
318
+ fi
319
+
320
+ typeset -a ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR
321
+ typeset -a ZSH_HIGHLIGHT_TOKENS_CONTROL_FLOW
322
+ local -a options_to_set reply # used in callees
323
+ local REPLY
324
+
325
+ # $flags_with_argument is a set of letters, corresponding to the option letters
326
+ # that would be followed by a colon in a getopts specification.
327
+ local flags_with_argument
328
+ # $flags_sans_argument is a set of letters, corresponding to the option letters
329
+ # that wouldn't be followed by a colon in a getopts specification.
330
+ local flags_sans_argument
331
+ # $flags_solo is a set of letters, corresponding to option letters that, if
332
+ # present, mean the precommand will not be acting as a precommand, i.e., will
333
+ # not be followed by a :start: word.
334
+ local flags_solo
335
+ # $precommand_options maps precommand name to values of $flags_with_argument,
336
+ # $flags_sans_argument, and flags_solo for that precommand, joined by a
337
+ # colon. (The value is NOT a getopt(3) spec, although it resembles one.)
338
+ #
339
+ # Currently, setting $flags_sans_argument is only important for commands that
340
+ # have a non-empty $flags_with_argument; see test-data/precommand4.zsh.
341
+ local -A precommand_options
342
+ precommand_options=(
343
+ # Precommand modifiers as of zsh 5.6.2 cf. zshmisc(1).
344
+ '-' ''
345
+ 'builtin' ''
346
+ 'command' :pvV
347
+ 'exec' a:cl
348
+ 'noglob' ''
349
+ # 'time' and 'nocorrect' shouldn't be added here; they're reserved words, not precommands.
350
+
351
+ # miscellaneous commands
352
+ 'doas' aCu:Lns # as of OpenBSD's doas(1) dated September 4, 2016
353
+ 'nice' n: # as of current POSIX spec
354
+ 'pkexec' '' # doesn't take short options; immune to #121 because it's usually not passed --option flags
355
+ # Not listed: -h, which has two different meanings.
356
+ 'sudo' Cgprtu:AEHPSbilns:eKkVv # as of sudo 1.8.21p2
357
+ 'run0' ugD:h # systemd 256.6
358
+ 'stdbuf' ioe:
359
+ 'eatmydata' ''
360
+ 'catchsegv' ''
361
+ 'nohup' ''
362
+ 'setsid' :wc
363
+ 'env' u:i
364
+ 'ionice' cn:t:pPu # util-linux 2.33.1-0.1
365
+ 'strace' IbeaosXPpEuOS:ACdfhikqrtTvVxyDc # strace 4.26-0.2
366
+ 'proxychains' f:q # proxychains 4.4.0
367
+ 'torsocks' idq:upaP # Torsocks 2.3.0
368
+ 'torify' idq:upaP # Torsocks 2.3.0
369
+ 'ssh-agent' aEPt:csDd:k # As of OpenSSH 8.1p1
370
+ 'tabbed' gnprtTuU:cdfhs:v # suckless-tools v44
371
+ 'chronic' :ev # moreutils 0.62-1
372
+ 'ifne' :n # moreutils 0.62-1
373
+ 'grc' :se # grc - a "generic colouriser" (that's their spelling, not mine)
374
+ 'cpulimit' elp:ivz # cpulimit 0.2
375
+ 'ktrace' fgpt:aBCcdiT
376
+ 'caffeinate' tw:dimsu # as of macOS's caffeinate(8) dated November 9, 2012
377
+ )
378
+ # Commands that would need to skip one positional argument:
379
+ # flock
380
+ # ssh
381
+ # _wanted (skip two)
382
+
383
+ if [[ $zsyh_user_options[ignorebraces] == on || ${zsyh_user_options[ignoreclosebraces]:-off} == on ]]; then
384
+ local right_brace_is_recognised_everywhere=false
385
+ else
386
+ local right_brace_is_recognised_everywhere=true
387
+ fi
388
+
389
+ if [[ $zsyh_user_options[pathdirs] == on ]]; then
390
+ options_to_set+=( PATH_DIRS )
391
+ fi
392
+
393
+ ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR=(
394
+ '|' '||' ';' '&' '&&'
395
+ $'\n' # ${(z)} returns ';' but we convert it to $'\n'
396
+ '|&'
397
+ '&!' '&|'
398
+ # ### 'case' syntax, but followed by a pattern, not by a command
399
+ # ';;' ';&' ';|'
400
+ )
401
+
402
+ # Tokens that, at (naively-determined) "command position", are followed by
403
+ # a de jure command position. All of these are reserved words.
404
+ ZSH_HIGHLIGHT_TOKENS_CONTROL_FLOW=(
405
+ $'\x7b' # block
406
+ $'\x28' # subshell
407
+ '()' # anonymous function
408
+ 'while'
409
+ 'until'
410
+ 'if'
411
+ 'then'
412
+ 'elif'
413
+ 'else'
414
+ 'do'
415
+ 'time'
416
+ 'coproc'
417
+ '!' # reserved word; unrelated to $histchars[1]
418
+ )
419
+
420
+ if (( $+X_ZSH_HIGHLIGHT_DIRS_BLACKLIST )); then
421
+ print >&2 'zsh-syntax-highlighting: X_ZSH_HIGHLIGHT_DIRS_BLACKLIST is deprecated. Please use ZSH_HIGHLIGHT_DIRS_BLACKLIST.'
422
+ ZSH_HIGHLIGHT_DIRS_BLACKLIST=($X_ZSH_HIGHLIGHT_DIRS_BLACKLIST)
423
+ unset X_ZSH_HIGHLIGHT_DIRS_BLACKLIST
424
+ fi
425
+
426
+ _zsh_highlight_main_highlighter_highlight_list -$#PREBUFFER '' 1 "$PREBUFFER$BUFFER"
427
+
428
+ # end is a reserved word
429
+ local start end_ style
430
+ for start end_ style in $reply; do
431
+ (( start >= end_ )) && { print -r -- >&2 "zsh-syntax-highlighting: BUG: _zsh_highlight_highlighter_main_paint: start($start) >= end($end_)"; return }
432
+ (( end_ <= 0 )) && continue
433
+ (( start < 0 )) && start=0 # having start<0 is normal with e.g. multiline strings
434
+ _zsh_highlight_main_calculate_fallback $style
435
+ _zsh_highlight_add_highlight $start $end_ $reply
436
+ done
437
+ }
438
+
439
+ # Try to expand $1, if it's possible to do so safely.
440
+ #
441
+ # Uses two parameters from the caller: $parameter_name_pattern and $res.
442
+ #
443
+ # If expansion was done, set $reply to the expansion and return true.
444
+ # Otherwise, return false.
445
+ _zsh_highlight_main_highlighter__try_expand_parameter()
446
+ {
447
+ local arg="$1"
448
+ unset reply
449
+ {
450
+ # ### For now, expand just '$foo' or '${foo}', possibly with braces, but with
451
+ # ### no other features of the parameter expansion syntax. (No ${(x)foo},
452
+ # ### no ${foo[x]}, no ${foo:-x}.)
453
+ {
454
+ local -a match mbegin mend
455
+ local MATCH; integer MBEGIN MEND
456
+ local parameter_name
457
+ local -a words
458
+ if [[ $arg[1] != '$' ]]; then
459
+ return 1
460
+ fi
461
+ if [[ ${arg[2]} == '{' ]] && [[ ${arg[-1]} == '}' ]]; then
462
+ parameter_name=${${arg:2}%?}
463
+ else
464
+ parameter_name=${arg:1}
465
+ fi
466
+ if [[ $res == none ]] &&
467
+ [[ ${parameter_name} =~ ^${~parameter_name_pattern}$ ]] &&
468
+ [[ ${(tP)MATCH} != *special* ]]
469
+ then
470
+ # Set $arg and update $res.
471
+ case ${(tP)MATCH} in
472
+ (*array*|*assoc*)
473
+ words=( ${(P)MATCH} )
474
+ ;;
475
+ ("")
476
+ # not set
477
+ words=( )
478
+ ;;
479
+ (*)
480
+ # scalar, presumably
481
+ if [[ $zsyh_user_options[shwordsplit] == on ]]; then
482
+ words=( ${(P)=MATCH} )
483
+ else
484
+ words=( ${(P)MATCH} )
485
+ fi
486
+ ;;
487
+ esac
488
+ reply=( "${words[@]}" )
489
+ else
490
+ return 1
491
+ fi
492
+ }
493
+ }
494
+ }
495
+
496
+ # $1 is the offset of $4 from the parent buffer. Added to the returned highlights.
497
+ # $2 is the initial braces_stack (for a closing paren).
498
+ # $3 is 1 if $4 contains the end of $BUFFER, else 0.
499
+ # $4 is the buffer to highlight.
500
+ # Returns:
501
+ # $REPLY: $buf[REPLY] is the last character parsed.
502
+ # $reply is an array of region_highlight additions.
503
+ # exit code is 0 if the braces_stack is empty, 1 otherwise.
504
+ _zsh_highlight_main_highlighter_highlight_list()
505
+ {
506
+ integer start_pos end_pos=0 buf_offset=$1 has_end=$3
507
+ # alias_style is the style to apply to an alias once $#in_alias == 0
508
+ # Usually 'alias' but set to 'unknown-token' if any word expanded from
509
+ # the alias would be highlighted as unknown-token
510
+ # param_style is analogous for parameter expansions
511
+ local alias_style param_style last_arg arg buf=$4 highlight_glob=true saw_assignment=false style
512
+ local in_array_assignment=false # true between 'a=(' and the matching ')'
513
+ # in_alias is an array of integers with each element equal to the number
514
+ # of shifts needed until arg=args[1] pops an arg from the next level up
515
+ # alias or from BUFFER.
516
+ # in_param is analogous for parameter expansions
517
+ integer in_param=0 len=$#buf
518
+ local -a in_alias match mbegin mend list_highlights
519
+ # seen_alias is a map of aliases already seen to avoid loops like alias a=b b=a
520
+ local -A seen_alias
521
+ # Pattern for parameter names
522
+ readonly parameter_name_pattern='([A-Za-z_][A-Za-z0-9_]*|[0-9]+)'
523
+ list_highlights=()
524
+
525
+ # "R" for round
526
+ # "Q" for square
527
+ # "Y" for curly
528
+ # "T" for [[ ]]
529
+ # "S" for $( ), =( ), <( ), >( )
530
+ # "D" for do/done
531
+ # "$" for 'end' (matches 'foreach' always; also used with cshjunkiequotes in repeat/while)
532
+ # "?" for 'if'/'fi'; also checked by 'elif'/'else'
533
+ # ":" for 'then'
534
+ local braces_stack=$2
535
+
536
+ # State machine
537
+ #
538
+ # The states are:
539
+ # - :start: Command word
540
+ # - :start_of_pipeline: Start of a 'pipeline' as defined in zshmisc(1).
541
+ # Only valid when :start: is present
542
+ # - :sudo_opt: A leading-dash option to a precommand, whether it takes an
543
+ # argument or not. (Example: sudo's "-u" or "-i".)
544
+ # - :sudo_arg: The argument to a precommand's leading-dash option,
545
+ # when given as a separate word; i.e., "foo" in "-u foo" (two
546
+ # words) but not in "-ufoo" (one word).
547
+ # Note: :sudo_opt: and :sudo_arg: are used for any precommand
548
+ # declared in ${precommand_options}, not just for sudo(8).
549
+ # The naming is historical.
550
+ # - :regular: "Not a command word", and command delimiters are permitted.
551
+ # Mainly used to detect premature termination of commands.
552
+ # - :always: The word 'always' in the «{ foo } always { bar }» syntax.
553
+ #
554
+ # When the kind of a word is not yet known, $this_word / $next_word may contain
555
+ # multiple states. For example, after "sudo -i", the next word may be either
556
+ # another --flag or a command name, hence the state would include both ':start:'
557
+ # and ':sudo_opt:'.
558
+ #
559
+ # The tokens are always added with both leading and trailing colons to serve as
560
+ # word delimiters (an improvised array); [[ $x == *':foo:'* ]] and x=${x//:foo:/}
561
+ # will DTRT regardless of how many elements or repetitions $x has.
562
+ #
563
+ # Handling of redirections: upon seeing a redirection token, we must stall
564
+ # the current state --- that is, the value of $this_word --- for two iterations
565
+ # (one for the redirection operator, one for the word following it representing
566
+ # the redirection target). Therefore, we set $in_redirection to 2 upon seeing a
567
+ # redirection operator, decrement it each iteration, and stall the current state
568
+ # when it is non-zero. Thus, upon reaching the next word (the one that follows
569
+ # the redirection operator and target), $this_word will still contain values
570
+ # appropriate for the word immediately following the word that preceded the
571
+ # redirection operator.
572
+ #
573
+ # The "the previous word was a redirection operator" state is not communicated
574
+ # to the next iteration via $next_word/$this_word as usual, but via
575
+ # $in_redirection. The value of $next_word from the iteration that processed
576
+ # the operator is discarded.
577
+ #
578
+ # $in_redirection is currently used for:
579
+ # - comments
580
+ # - aliases
581
+ # - redirections
582
+ # - parameter elision in command position
583
+ # - 'repeat' loops
584
+ #
585
+ local this_word next_word=':start::start_of_pipeline:'
586
+ integer in_redirection
587
+ # Processing buffer
588
+ local proc_buf="$buf"
589
+ local -a args
590
+ if [[ $zsyh_user_options[interactivecomments] == on ]]; then
591
+ args=(${(zZ+c+)buf})
592
+ else
593
+ args=(${(z)buf})
594
+ fi
595
+
596
+ # Special case: $(<*) isn't globbing.
597
+ if [[ $braces_stack == 'S' ]] && (( $+args[3] && ! $+args[4] )) && [[ $args[3] == $'\x29' ]] &&
598
+ [[ $args[1] == *'<'* ]] && _zsh_highlight_main__is_redirection $args[1]; then
599
+ highlight_glob=false
600
+ fi
601
+
602
+ while (( $#args )); do
603
+ last_arg=$arg
604
+ arg=$args[1]
605
+ shift args
606
+ if (( $#in_alias )); then
607
+ (( in_alias[1]-- ))
608
+ # Remove leading 0 entries
609
+ in_alias=($in_alias[$in_alias[(i)<1->],-1])
610
+ if (( $#in_alias == 0 )); then
611
+ seen_alias=()
612
+ # start_pos and end_pos are of the alias (previous $arg) here
613
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos $alias_style
614
+ else
615
+ # We can't unset keys that contain special characters (] \ and some others).
616
+ # More details: https://www.zsh.org/workers/43269
617
+ (){
618
+ local alias_name
619
+ for alias_name in ${(k)seen_alias[(R)<$#in_alias->]}; do
620
+ seen_alias=("${(@kv)seen_alias[(I)^$alias_name]}")
621
+ done
622
+ }
623
+ fi
624
+ fi
625
+ if (( in_param )); then
626
+ (( in_param-- ))
627
+ if (( in_param == 0 )); then
628
+ # start_pos and end_pos are of the '$foo' word (previous $arg) here
629
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos $param_style
630
+ param_style=""
631
+ fi
632
+ fi
633
+
634
+ # Initialize this_word and next_word.
635
+ if (( in_redirection == 0 )); then
636
+ this_word=$next_word
637
+ next_word=':regular:'
638
+ elif (( !in_param )); then
639
+ # Stall $next_word.
640
+ (( --in_redirection ))
641
+ fi
642
+
643
+ # Initialize per-"simple command" [zshmisc(1)] variables:
644
+ #
645
+ # $style how to highlight $arg
646
+ # $in_array_assignment boolean flag for "between '(' and ')' of array assignment"
647
+ # $highlight_glob boolean flag for "'noglob' is in effect"
648
+ # $saw_assignment boolean flag for "was preceded by an assignment"
649
+ #
650
+ style=unknown-token
651
+ if [[ $this_word == *':start:'* ]]; then
652
+ in_array_assignment=false
653
+ if [[ $arg == 'noglob' ]]; then
654
+ highlight_glob=false
655
+ fi
656
+ fi
657
+
658
+ if (( $#in_alias == 0 && in_param == 0 )); then
659
+ # Compute the new $start_pos and $end_pos, skipping over whitespace in $buf.
660
+ [[ "$proc_buf" = (#b)(#s)(''([ $'\t']|[\\]$'\n')#)(?|)* ]]
661
+ # The first, outer parenthesis
662
+ integer offset="${#match[1]}"
663
+ (( start_pos = end_pos + offset ))
664
+ (( end_pos = start_pos + $#arg ))
665
+
666
+ # The zsh lexer considers ';' and newline to be the same token, so
667
+ # ${(z)} converts all newlines to semicolons. Convert them back here to
668
+ # make later processing simpler.
669
+ [[ $arg == ';' && ${match[3]} == $'\n' ]] && arg=$'\n'
670
+
671
+ # Compute the new $proc_buf. We advance it
672
+ # (chop off characters from the beginning)
673
+ # beyond what end_pos points to, by skipping
674
+ # as many characters as end_pos was advanced.
675
+ #
676
+ # end_pos was advanced by $offset (via start_pos)
677
+ # and by $#arg. Note the `start_pos=$end_pos`
678
+ # below.
679
+ #
680
+ # As for the [,len]. We could use [,len-start_pos+offset]
681
+ # here, but to make it easier on eyes, we use len and
682
+ # rely on the fact that Zsh simply handles that. The
683
+ # length of proc_buf is len-start_pos+offset because
684
+ # we're chopping it to match current start_pos, so its
685
+ # length matches the previous value of start_pos.
686
+ #
687
+ # Why [,-1] is slower than [,length] isn't clear.
688
+ proc_buf="${proc_buf[offset + $#arg + 1,len]}"
689
+ fi
690
+
691
+ # Handle the INTERACTIVE_COMMENTS option.
692
+ #
693
+ # We use the (Z+c+) flag so the entire comment is presented as one token in $arg.
694
+ if [[ $zsyh_user_options[interactivecomments] == on && $arg[1] == $histchars[3] ]]; then
695
+ if [[ $this_word == *(':regular:'|':start:')* ]]; then
696
+ style=comment
697
+ else
698
+ style=unknown-token # prematurely terminated
699
+ fi
700
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
701
+ # Stall this arg
702
+ in_redirection=1
703
+ continue
704
+ fi
705
+
706
+ if [[ $this_word == *':start:'* ]] && ! (( in_redirection )); then
707
+ # Expand aliases.
708
+ # An alias is ineligible for expansion while it's being expanded (see #652/#653).
709
+ _zsh_highlight_main__type "$arg" "$(( ! ${+seen_alias[$arg]} ))"
710
+ local res="$REPLY"
711
+ if [[ $res == "alias" ]]; then
712
+ # Mark insane aliases as unknown-token (cf. #263).
713
+ if [[ $arg == ?*=* ]]; then
714
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos unknown-token
715
+ continue
716
+ fi
717
+ seen_alias[$arg]=$#in_alias
718
+ _zsh_highlight_main__resolve_alias $arg
719
+ local -a alias_args
720
+ # Elision is desired in case alias x=''
721
+ if [[ $zsyh_user_options[interactivecomments] == on ]]; then
722
+ alias_args=(${(zZ+c+)REPLY})
723
+ else
724
+ alias_args=(${(z)REPLY})
725
+ fi
726
+ args=( $alias_args $args )
727
+ if (( $#in_alias == 0 )); then
728
+ alias_style=alias
729
+ else
730
+ # Transfer the count of this arg to the new element about to be appended.
731
+ (( in_alias[1]-- ))
732
+ fi
733
+ # Add one because we will in_alias[1]-- on the next loop iteration so
734
+ # this iteration should be considered in in_alias as well
735
+ in_alias=( $(($#alias_args + 1)) $in_alias )
736
+ (( in_redirection++ )) # Stall this arg
737
+ continue
738
+ else
739
+ _zsh_highlight_main_highlighter_expand_path $arg
740
+ _zsh_highlight_main__type "$REPLY" 0
741
+ res="$REPLY"
742
+ fi
743
+ fi
744
+
745
+ # Analyse the current word.
746
+ if _zsh_highlight_main__is_redirection $arg ; then
747
+ if (( in_redirection == 1 )); then
748
+ # Two consecutive redirection operators is an error.
749
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos unknown-token
750
+ else
751
+ in_redirection=2
752
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos redirection
753
+ fi
754
+ continue
755
+ elif [[ $arg == '{'${~parameter_name_pattern}'}' ]] && _zsh_highlight_main__is_redirection $args[1]; then
756
+ # named file descriptor: {foo}>&2
757
+ in_redirection=3
758
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos named-fd
759
+ continue
760
+ fi
761
+
762
+ # Expand parameters.
763
+ if (( ! in_param )) && _zsh_highlight_main_highlighter__try_expand_parameter "$arg"; then
764
+ # That's not entirely correct --- if the parameter's value happens to be a reserved
765
+ # word, the parameter expansion will be highlighted as a reserved word --- but that
766
+ # incorrectness is outweighed by the usability improvement of permitting the use of
767
+ # parameters that refer to commands, functions, and builtins.
768
+ () {
769
+ local -a words; words=( "${reply[@]}" )
770
+ if (( $#words == 0 )) && (( ! in_redirection )); then
771
+ # Parameter elision is happening
772
+ (( ++in_redirection ))
773
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos comment
774
+ continue
775
+ else
776
+ (( in_param = 1 + $#words ))
777
+ args=( $words $args )
778
+ arg=$args[1]
779
+ _zsh_highlight_main__type "$arg" 0
780
+ res=$REPLY
781
+ fi
782
+ }
783
+ fi
784
+
785
+ # Parse the sudo command line
786
+ if (( ! in_redirection )); then
787
+ if [[ $this_word == *':sudo_opt:'* ]]; then
788
+ if [[ -n $flags_with_argument ]] &&
789
+ {
790
+ # Trenary
791
+ if [[ -n $flags_sans_argument ]]
792
+ then [[ $arg == '-'[$flags_sans_argument]#[$flags_with_argument] ]]
793
+ else [[ $arg == '-'[$flags_with_argument] ]]
794
+ fi
795
+ } then
796
+ # Flag that requires an argument
797
+ this_word=${this_word//:start:/}
798
+ next_word=':sudo_arg:'
799
+ elif [[ -n $flags_with_argument ]] &&
800
+ {
801
+ # Trenary
802
+ if [[ -n $flags_sans_argument ]]
803
+ then [[ $arg == '-'[$flags_sans_argument]#[$flags_with_argument]* ]]
804
+ else [[ $arg == '-'[$flags_with_argument]* ]]
805
+ fi
806
+ } then
807
+ # Argument attached in the same word
808
+ this_word=${this_word//:start:/}
809
+ next_word+=':start:'
810
+ next_word+=':sudo_opt:'
811
+ elif [[ -n $flags_sans_argument ]] &&
812
+ [[ $arg == '-'[$flags_sans_argument]# ]]; then
813
+ # Flag that requires no argument
814
+ this_word=':sudo_opt:'
815
+ next_word+=':start:'
816
+ next_word+=':sudo_opt:'
817
+ elif [[ -n $flags_solo ]] &&
818
+ {
819
+ # Trenary
820
+ if [[ -n $flags_sans_argument ]]
821
+ then [[ $arg == '-'[$flags_sans_argument]#[$flags_solo]* ]]
822
+ else [[ $arg == '-'[$flags_solo]* ]]
823
+ fi
824
+ } then
825
+ # Solo flags
826
+ this_word=':sudo_opt:'
827
+ next_word=':regular:' # no :start:, nor :sudo_opt: since we don't know whether the solo flag takes an argument or not
828
+ elif [[ $arg == '-'* ]]; then
829
+ # Unknown flag. We don't know whether it takes an argument or not,
830
+ # so modify $next_word as we do for flags that require no argument.
831
+ # With that behaviour, if the flag in fact takes no argument we'll
832
+ # highlight the inner command word correctly, and if it does take an
833
+ # argument we'll highlight the command word correctly if the argument
834
+ # was given in the same shell word as the flag (as in '-uphy1729' or
835
+ # '--user=phy1729' without spaces).
836
+ this_word=':sudo_opt:'
837
+ next_word+=':start:'
838
+ next_word+=':sudo_opt:'
839
+ else
840
+ # Not an option flag; nothing to do. (If the command line is
841
+ # syntactically valid, ${this_word//:sudo_opt:/} should be
842
+ # non-empty now.)
843
+ this_word=${this_word//:sudo_opt:/}
844
+ fi
845
+ elif [[ $this_word == *':sudo_arg:'* ]]; then
846
+ next_word+=':sudo_opt:'
847
+ next_word+=':start:'
848
+ fi
849
+ fi
850
+
851
+ # The Great Fork: is this a command word? Is this a non-command word?
852
+ if [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_COMMANDSEPARATOR:#"$arg"} ]] &&
853
+ [[ $braces_stack != *T* || $arg != ('||'|'&&') ]]; then
854
+
855
+ # First, determine the style of the command separator itself.
856
+ if _zsh_highlight_main__stack_pop T || _zsh_highlight_main__stack_pop Q; then
857
+ # Missing closing square bracket(s)
858
+ style=unknown-token
859
+ elif $in_array_assignment; then
860
+ case $arg in
861
+ # Literal newlines are just fine.
862
+ ($'\n') style=commandseparator;;
863
+ # Semicolons are parsed the same way as literal newlines. Nevertheless,
864
+ # highlight them as errors since they're probably unintended. Compare
865
+ # issue #691.
866
+ (';') style=unknown-token;;
867
+ # Other command separators aren't allowed.
868
+ (*) style=unknown-token;;
869
+ esac
870
+ elif [[ $this_word == *':regular:'* ]]; then
871
+ style=commandseparator
872
+ elif [[ $this_word == *':start:'* ]] && [[ $arg == $'\n' ]]; then
873
+ style=commandseparator
874
+ elif [[ $this_word == *':start:'* ]] && [[ $arg == ';' ]] && (( $#in_alias )); then
875
+ style=commandseparator
876
+ else
877
+ # Empty commands (semicolon follows nothing) are valid syntax.
878
+ # However, in interactive use they are likely to be erroneous;
879
+ # therefore, we highlight them as errors.
880
+ #
881
+ # Alias definitions are exempted from this check to allow multiline aliases
882
+ # with explicit (redundant) semicolons: «alias foo=$'bar;\nbaz'» (issue #677).
883
+ #
884
+ # See also #691 about possibly changing the style used here.
885
+ style=unknown-token
886
+ fi
887
+
888
+ # Second, determine the style of next_word.
889
+ if [[ $arg == $'\n' ]] && $in_array_assignment; then
890
+ # literal newline inside an array assignment
891
+ next_word=':regular:'
892
+ elif [[ $arg == ';' ]] && $in_array_assignment; then
893
+ # literal semicolon inside an array assignment
894
+ next_word=':regular:'
895
+ else
896
+ next_word=':start:'
897
+ highlight_glob=true
898
+ saw_assignment=false
899
+ (){
900
+ local alias_name
901
+ for alias_name in ${(k)seen_alias[(R)<$#in_alias->]}; do
902
+ # We can't unset keys that contain special characters (] \ and some others).
903
+ # More details: https://www.zsh.org/workers/43269
904
+ seen_alias=("${(@kv)seen_alias[(I)^$alias_name]}")
905
+ done
906
+ }
907
+ if [[ $arg != '|' && $arg != '|&' ]]; then
908
+ next_word+=':start_of_pipeline:'
909
+ fi
910
+ fi
911
+
912
+ elif ! (( in_redirection)) && [[ $this_word == *':always:'* && $arg == 'always' ]]; then
913
+ # try-always construct
914
+ style=reserved-word # de facto a reserved word, although not de jure
915
+ highlight_glob=true
916
+ saw_assignment=false
917
+ next_word=':start::start_of_pipeline:' # only left brace is allowed, apparently
918
+ elif ! (( in_redirection)) && [[ $this_word == *':start:'* ]]; then # $arg is the command word
919
+ if (( ${+precommand_options[$arg]} )) && _zsh_highlight_main__is_runnable $arg; then
920
+ style=precommand
921
+ () {
922
+ set -- "${(@s.:.)precommand_options[$arg]}"
923
+ flags_with_argument=$1
924
+ flags_sans_argument=$2
925
+ flags_solo=$3
926
+ }
927
+ next_word=${next_word//:regular:/}
928
+ next_word+=':sudo_opt:'
929
+ next_word+=':start:'
930
+ if [[ $arg == 'exec' || $arg == 'env' ]]; then
931
+ # To allow "exec 2>&1;" and "env | grep" where there's no command word
932
+ next_word+=':regular:'
933
+ fi
934
+ else
935
+ case $res in
936
+ (reserved) # reserved word
937
+ style=reserved-word
938
+ # Match braces and handle special cases.
939
+ case $arg in
940
+ (time|nocorrect)
941
+ next_word=${next_word//:regular:/}
942
+ next_word+=':start:'
943
+ ;;
944
+ ($'\x7b')
945
+ braces_stack='Y'"$braces_stack"
946
+ ;;
947
+ ($'\x7d')
948
+ # We're at command word, so no need to check $right_brace_is_recognised_everywhere
949
+ _zsh_highlight_main__stack_pop 'Y' reserved-word
950
+ if [[ $style == reserved-word ]]; then
951
+ next_word+=':always:'
952
+ fi
953
+ ;;
954
+ ($'\x5b\x5b')
955
+ braces_stack='T'"$braces_stack"
956
+ ;;
957
+ ('do')
958
+ braces_stack='D'"$braces_stack"
959
+ ;;
960
+ ('done')
961
+ _zsh_highlight_main__stack_pop 'D' reserved-word
962
+ ;;
963
+ ('if')
964
+ braces_stack=':?'"$braces_stack"
965
+ ;;
966
+ ('then')
967
+ _zsh_highlight_main__stack_pop ':' reserved-word
968
+ ;;
969
+ ('elif')
970
+ if [[ ${braces_stack[1]} == '?' ]]; then
971
+ braces_stack=':'"$braces_stack"
972
+ else
973
+ style=unknown-token
974
+ fi
975
+ ;;
976
+ ('else')
977
+ if [[ ${braces_stack[1]} == '?' ]]; then
978
+ :
979
+ else
980
+ style=unknown-token
981
+ fi
982
+ ;;
983
+ ('fi')
984
+ _zsh_highlight_main__stack_pop '?'
985
+ ;;
986
+ ('foreach')
987
+ braces_stack='$'"$braces_stack"
988
+ ;;
989
+ ('end')
990
+ _zsh_highlight_main__stack_pop '$' reserved-word
991
+ ;;
992
+ ('repeat')
993
+ # skip the repeat-count word
994
+ in_redirection=2
995
+ # The redirection mechanism assumes $this_word describes the word
996
+ # following the redirection. Make it so.
997
+ #
998
+ # That word can be a command word with shortloops (`repeat 2 ls`)
999
+ # or a command separator (`repeat 2; ls` or `repeat 2; do ls; done`).
1000
+ #
1001
+ # The repeat-count word will be handled like a redirection target.
1002
+ this_word=':start::regular:'
1003
+ ;;
1004
+ ('!')
1005
+ if [[ $this_word != *':start_of_pipeline:'* ]]; then
1006
+ style=unknown-token
1007
+ else
1008
+ # '!' reserved word at start of pipeline; style already set above
1009
+ fi
1010
+ ;;
1011
+ esac
1012
+ if $saw_assignment && [[ $style != unknown-token ]]; then
1013
+ style=unknown-token
1014
+ fi
1015
+ ;;
1016
+ ('suffix alias')
1017
+ style=suffix-alias
1018
+ ;;
1019
+ ('global alias')
1020
+ style=global-alias
1021
+ ;;
1022
+ (alias) :;;
1023
+ (builtin) style=builtin
1024
+ [[ $arg == $'\x5b' ]] && braces_stack='Q'"$braces_stack"
1025
+ ;;
1026
+ (function) style=function;;
1027
+ (command) style=command;;
1028
+ (hashed) style=hashed-command;;
1029
+ (none) if (( ! in_param )) && _zsh_highlight_main_highlighter_check_assign; then
1030
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos assign
1031
+ local i=$(( arg[(i)=] + 1 ))
1032
+ saw_assignment=true
1033
+ if [[ $arg[i] == '(' ]]; then
1034
+ in_array_assignment=true
1035
+ _zsh_highlight_main_add_region_highlight start_pos+i-1 start_pos+i reserved-word
1036
+ else
1037
+ # assignment to a scalar parameter.
1038
+ # (For array assignments, the command doesn't start until the ")" token.)
1039
+ #
1040
+ # Discard :start_of_pipeline:, if present, as '!' is not valid
1041
+ # after assignments.
1042
+ next_word+=':start:'
1043
+ if (( i <= $#arg )); then
1044
+ () {
1045
+ local highlight_glob=false
1046
+ [[ $zsyh_user_options[globassign] == on ]] && highlight_glob=true
1047
+ _zsh_highlight_main_highlighter_highlight_argument $i
1048
+ }
1049
+ fi
1050
+ fi
1051
+ continue
1052
+ elif (( ! in_param )) &&
1053
+ [[ $arg[0,1] = $histchars[0,1] ]] && (( $#arg[0,2] == 2 )); then
1054
+ style=history-expansion
1055
+ elif (( ! in_param )) &&
1056
+ [[ $arg[0,1] == $histchars[2,2] ]]; then
1057
+ style=history-expansion
1058
+ elif (( ! in_param )) &&
1059
+ ! $saw_assignment &&
1060
+ [[ $arg[1,2] == '((' ]]; then
1061
+ # Arithmetic evaluation.
1062
+ #
1063
+ # Note: prior to zsh-5.1.1-52-g4bed2cf (workers/36669), the ${(z)...}
1064
+ # splitter would only output the '((' token if the matching '))' had
1065
+ # been typed. Therefore, under those versions of zsh, BUFFER="(( 42"
1066
+ # would be highlighted as an error until the matching "))" are typed.
1067
+ #
1068
+ # We highlight just the opening parentheses, as a reserved word; this
1069
+ # is how [[ ... ]] is highlighted, too.
1070
+ _zsh_highlight_main_add_region_highlight $start_pos $((start_pos + 2)) reserved-word
1071
+ if [[ $arg[-2,-1] == '))' ]]; then
1072
+ _zsh_highlight_main_add_region_highlight $((end_pos - 2)) $end_pos reserved-word
1073
+ fi
1074
+ continue
1075
+ elif (( ! in_param )) &&
1076
+ [[ $arg == '()' ]]; then
1077
+ # anonymous function
1078
+ style=reserved-word
1079
+ elif (( ! in_param )) &&
1080
+ ! $saw_assignment &&
1081
+ [[ $arg == $'\x28' ]]; then
1082
+ # subshell
1083
+ style=reserved-word
1084
+ braces_stack='R'"$braces_stack"
1085
+ elif (( ! in_param )) &&
1086
+ [[ $arg == $'\x29' ]]; then
1087
+ # end of subshell or command substitution
1088
+ if _zsh_highlight_main__stack_pop 'S'; then
1089
+ REPLY=$start_pos
1090
+ reply=($list_highlights)
1091
+ return 0
1092
+ fi
1093
+ _zsh_highlight_main__stack_pop 'R' reserved-word
1094
+ else
1095
+ if _zsh_highlight_main_highlighter_check_path $arg 1; then
1096
+ style=$REPLY
1097
+ else
1098
+ style=unknown-token
1099
+ fi
1100
+ fi
1101
+ ;;
1102
+ (*) _zsh_highlight_main_add_region_highlight $start_pos $end_pos arg0_$res
1103
+ continue
1104
+ ;;
1105
+ esac
1106
+ fi
1107
+ if [[ -n ${(M)ZSH_HIGHLIGHT_TOKENS_CONTROL_FLOW:#"$arg"} ]]; then
1108
+ next_word=':start::start_of_pipeline:'
1109
+ fi
1110
+ elif _zsh_highlight_main__is_global_alias "$arg"; then # $arg is a global alias that isn't in command position
1111
+ style=global-alias
1112
+ else # $arg is a non-command word
1113
+ case $arg in
1114
+ ($'\x29')
1115
+ # subshell or end of array assignment
1116
+ if $in_array_assignment; then
1117
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos assign
1118
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos reserved-word
1119
+ in_array_assignment=false
1120
+ next_word+=':start:'
1121
+ continue
1122
+ elif (( in_redirection )); then
1123
+ style=unknown-token
1124
+ else
1125
+ if _zsh_highlight_main__stack_pop 'S'; then
1126
+ REPLY=$start_pos
1127
+ reply=($list_highlights)
1128
+ return 0
1129
+ fi
1130
+ _zsh_highlight_main__stack_pop 'R' reserved-word
1131
+ fi
1132
+ ;;
1133
+ ($'\x28\x29')
1134
+ # possibly a function definition
1135
+ if (( in_redirection )) || $in_array_assignment; then
1136
+ style=unknown-token
1137
+ else
1138
+ if [[ $zsyh_user_options[multifuncdef] == on ]] || false # TODO: or if the previous word was a command word
1139
+ then
1140
+ next_word+=':start::start_of_pipeline:'
1141
+ fi
1142
+ style=reserved-word
1143
+ fi
1144
+ ;;
1145
+ (*) if false; then
1146
+ elif [[ $arg = $'\x7d' ]] && $right_brace_is_recognised_everywhere; then
1147
+ # Parsing rule: {
1148
+ #
1149
+ # Additionally, `tt(})' is recognized in any position if neither the
1150
+ # tt(IGNORE_BRACES) option nor the tt(IGNORE_CLOSE_BRACES) option is set.
1151
+ if (( in_redirection )) || $in_array_assignment; then
1152
+ style=unknown-token
1153
+ else
1154
+ _zsh_highlight_main__stack_pop 'Y' reserved-word
1155
+ if [[ $style == reserved-word ]]; then
1156
+ next_word+=':always:'
1157
+ fi
1158
+ fi
1159
+ elif [[ $arg[0,1] = $histchars[0,1] ]] && (( $#arg[0,2] == 2 )); then
1160
+ style=history-expansion
1161
+ elif [[ $arg == $'\x5d\x5d' ]] && _zsh_highlight_main__stack_pop 'T' reserved-word; then
1162
+ :
1163
+ elif [[ $arg == $'\x5d' ]] && _zsh_highlight_main__stack_pop 'Q' builtin; then
1164
+ :
1165
+ else
1166
+ _zsh_highlight_main_highlighter_highlight_argument 1 $(( 1 != in_redirection ))
1167
+ continue
1168
+ fi
1169
+ ;;
1170
+ esac
1171
+ fi
1172
+ _zsh_highlight_main_add_region_highlight $start_pos $end_pos $style
1173
+ done
1174
+ (( $#in_alias )) && in_alias=() _zsh_highlight_main_add_region_highlight $start_pos $end_pos $alias_style
1175
+ (( in_param == 1 )) && in_param=0 _zsh_highlight_main_add_region_highlight $start_pos $end_pos $param_style
1176
+ [[ "$proc_buf" = (#b)(#s)(([[:space:]]|\\$'\n')#) ]]
1177
+ REPLY=$(( end_pos + ${#match[1]} - 1 ))
1178
+ reply=($list_highlights)
1179
+ return $(( $#braces_stack > 0 ))
1180
+ }
1181
+
1182
+ # Check if $arg is variable assignment
1183
+ _zsh_highlight_main_highlighter_check_assign()
1184
+ {
1185
+ setopt localoptions extended_glob
1186
+ [[ $arg == [[:alpha:]_][[:alnum:]_]#(|\[*\])(|[+])=* ]] ||
1187
+ [[ $arg == [0-9]##(|[+])=* ]]
1188
+ }
1189
+
1190
+ _zsh_highlight_main_highlighter_highlight_path_separators()
1191
+ {
1192
+ local pos style_pathsep
1193
+ style_pathsep=$1_pathseparator
1194
+ reply=()
1195
+ [[ -z "$ZSH_HIGHLIGHT_STYLES[$style_pathsep]" || "$ZSH_HIGHLIGHT_STYLES[$1]" == "$ZSH_HIGHLIGHT_STYLES[$style_pathsep]" ]] && return 0
1196
+ for (( pos = start_pos; $pos <= end_pos; pos++ )) ; do
1197
+ if [[ $BUFFER[pos] == / ]]; then
1198
+ reply+=($((pos - 1)) $pos $style_pathsep)
1199
+ fi
1200
+ done
1201
+ }
1202
+
1203
+ # Check if $1 is a path.
1204
+ # If yes, return 0 and in $REPLY the style to use.
1205
+ # Else, return non-zero (and the contents of $REPLY is undefined).
1206
+ #
1207
+ # $2 should be non-zero iff we're in command position.
1208
+ _zsh_highlight_main_highlighter_check_path()
1209
+ {
1210
+ _zsh_highlight_main_highlighter_expand_path "$1"
1211
+ local expanded_path="$REPLY" tmp_path
1212
+ integer in_command_position=$2
1213
+
1214
+ if [[ $zsyh_user_options[autocd] == on ]]; then
1215
+ integer autocd=1
1216
+ else
1217
+ integer autocd=0
1218
+ fi
1219
+
1220
+ if (( in_command_position )); then
1221
+ # ### Currently, this value is never returned: either it's overwritten
1222
+ # ### below, or the return code is non-zero
1223
+ REPLY=arg0
1224
+ else
1225
+ REPLY=path
1226
+ fi
1227
+
1228
+ if [[ ${1[1]} == '=' && $1 == ??* && ${1[2]} != $'\x28' && $zsyh_user_options[equals] == 'on' && $expanded_path[1] != '/' ]]; then
1229
+ REPLY=unknown-token # will error out if executed
1230
+ return 0
1231
+ fi
1232
+
1233
+ [[ -z $expanded_path ]] && return 1
1234
+
1235
+ # Check if this is a blacklisted path
1236
+ if [[ $expanded_path[1] == / ]]; then
1237
+ tmp_path=$expanded_path
1238
+ else
1239
+ tmp_path=$PWD/$expanded_path
1240
+ fi
1241
+ tmp_path=$tmp_path:a
1242
+
1243
+ local candidate_new_tmp_path
1244
+ while [[ $tmp_path != / ]]; do
1245
+ [[ -n ${(M)ZSH_HIGHLIGHT_DIRS_BLACKLIST:#$tmp_path} ]] && return 1
1246
+ candidate_new_tmp_path=${tmp_path:h}
1247
+ if [[ $candidate_new_tmp_path == $tmp_path ]]; then
1248
+ break
1249
+ fi
1250
+ tmp_path=${candidate_new_tmp_path}
1251
+ done
1252
+
1253
+ if (( in_command_position )); then
1254
+ if [[ -x $expanded_path ]]; then
1255
+ if (( autocd )); then
1256
+ if [[ -d $expanded_path ]]; then
1257
+ REPLY=autodirectory
1258
+ fi
1259
+ return 0
1260
+ elif [[ ! -d $expanded_path ]]; then
1261
+ # ### This seems unreachable for the current callers
1262
+ return 0
1263
+ fi
1264
+ fi
1265
+ else
1266
+ if [[ -L $expanded_path || -e $expanded_path ]]; then
1267
+ return 0
1268
+ fi
1269
+ fi
1270
+
1271
+ # Search the path in CDPATH
1272
+ if [[ $expanded_path != /* ]] && (( autocd || ! in_command_position )); then
1273
+ # TODO: When we've dropped support for pre-5.0.6 zsh, use the *(Y1) glob qualifier here.
1274
+ local cdpath_dir
1275
+ for cdpath_dir in $cdpath ; do
1276
+ if [[ -d "$cdpath_dir/$expanded_path" && -x "$cdpath_dir/$expanded_path" ]]; then
1277
+ if (( in_command_position && autocd )); then
1278
+ REPLY=autodirectory
1279
+ fi
1280
+ return 0
1281
+ fi
1282
+ done
1283
+ fi
1284
+
1285
+ # If dirname($1) doesn't exist, neither does $1.
1286
+ [[ ! -d ${expanded_path:h} ]] && return 1
1287
+
1288
+ # If this word ends the buffer, check if it's the prefix of a valid path.
1289
+ if (( has_end && (len == end_pos) )) &&
1290
+ (( ! $#in_alias )) &&
1291
+ [[ $WIDGET != zle-line-finish ]]; then
1292
+ # TODO: When we've dropped support for pre-5.0.6 zsh, use the *(Y1) glob qualifier here.
1293
+ local -a tmp
1294
+ if (( in_command_position )); then
1295
+ # We include directories even when autocd is enabled, because those
1296
+ # directories might contain executable files: e.g., BUFFER="/bi" en route
1297
+ # to typing "/bin/sh".
1298
+ tmp=( ${expanded_path}*(N-*,N-/) )
1299
+ else
1300
+ tmp=( ${expanded_path}*(N) )
1301
+ fi
1302
+ (( ${+tmp[1]} )) && REPLY=path_prefix && return 0
1303
+ fi
1304
+
1305
+ # It's not a path.
1306
+ return 1
1307
+ }
1308
+
1309
+ # Highlight an argument and possibly special chars in quotes starting at $1 in $arg
1310
+ # This command will at least highlight $1 to end_pos with the default style
1311
+ # If $2 is set to 0, the argument cannot be highlighted as an option.
1312
+ #
1313
+ # This function currently assumes it's never called for the command word.
1314
+ _zsh_highlight_main_highlighter_highlight_argument()
1315
+ {
1316
+ local base_style=default i=$1 option_eligible=${2:-1} path_eligible=1 ret start style
1317
+ local -a highlights
1318
+
1319
+ local -a match mbegin mend
1320
+ local MATCH; integer MBEGIN MEND
1321
+
1322
+ case "$arg[i]" in
1323
+ '%')
1324
+ if [[ $arg[i+1] == '?' ]]; then
1325
+ (( i += 2 ))
1326
+ fi
1327
+ ;;
1328
+ '-')
1329
+ if (( option_eligible )); then
1330
+ if [[ $arg[i+1] == - ]]; then
1331
+ base_style=double-hyphen-option
1332
+ else
1333
+ base_style=single-hyphen-option
1334
+ fi
1335
+ path_eligible=0
1336
+ fi
1337
+ ;;
1338
+ '=')
1339
+ if [[ $arg[i+1] == $'\x28' ]]; then
1340
+ (( i += 2 ))
1341
+ _zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,-1]
1342
+ ret=$?
1343
+ (( i += REPLY ))
1344
+ highlights+=(
1345
+ $(( start_pos + $1 - 1 )) $(( start_pos + i )) process-substitution
1346
+ $(( start_pos + $1 - 1 )) $(( start_pos + $1 + 1 )) process-substitution-delimiter
1347
+ $reply
1348
+ )
1349
+ if (( ret == 0 )); then
1350
+ highlights+=($(( start_pos + i - 1 )) $(( start_pos + i )) process-substitution-delimiter)
1351
+ fi
1352
+ fi
1353
+ esac
1354
+
1355
+ # This loop is a hot path. Keep it fast!
1356
+ (( --i ))
1357
+ while (( ++i <= $#arg )); do
1358
+ i=${arg[(ib.i.)[\\\'\"\`\$\<\>\*\?]]}
1359
+ case "$arg[$i]" in
1360
+ "") break;;
1361
+ "\\") (( i += 1 )); continue;;
1362
+ "'")
1363
+ _zsh_highlight_main_highlighter_highlight_single_quote $i
1364
+ (( i = REPLY ))
1365
+ highlights+=($reply)
1366
+ ;;
1367
+ '"')
1368
+ _zsh_highlight_main_highlighter_highlight_double_quote $i
1369
+ (( i = REPLY ))
1370
+ highlights+=($reply)
1371
+ ;;
1372
+ '`')
1373
+ _zsh_highlight_main_highlighter_highlight_backtick $i
1374
+ (( i = REPLY ))
1375
+ highlights+=($reply)
1376
+ ;;
1377
+ '$')
1378
+ if [[ $arg[i+1] != "'" ]]; then
1379
+ path_eligible=0
1380
+ fi
1381
+ if [[ $arg[i+1] == "'" ]]; then
1382
+ _zsh_highlight_main_highlighter_highlight_dollar_quote $i
1383
+ (( i = REPLY ))
1384
+ highlights+=($reply)
1385
+ continue
1386
+ elif [[ $arg[i+1] == $'\x28' ]]; then
1387
+ if [[ $arg[i+2] == $'\x28' ]] && _zsh_highlight_main_highlighter_highlight_arithmetic $i; then
1388
+ # Arithmetic expansion
1389
+ (( i = REPLY ))
1390
+ highlights+=($reply)
1391
+ continue
1392
+ fi
1393
+ start=$i
1394
+ (( i += 2 ))
1395
+ _zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,-1]
1396
+ ret=$?
1397
+ (( i += REPLY ))
1398
+ highlights+=(
1399
+ $(( start_pos + start - 1)) $(( start_pos + i )) command-substitution-unquoted
1400
+ $(( start_pos + start - 1)) $(( start_pos + start + 1)) command-substitution-delimiter-unquoted
1401
+ $reply
1402
+ )
1403
+ if (( ret == 0 )); then
1404
+ highlights+=($(( start_pos + i - 1)) $(( start_pos + i )) command-substitution-delimiter-unquoted)
1405
+ fi
1406
+ continue
1407
+ fi
1408
+ while [[ $arg[i+1] == [=~#+'^'] ]]; do
1409
+ (( i += 1 ))
1410
+ done
1411
+ if [[ $arg[i+1] == [*@#?$!-] ]]; then
1412
+ (( i += 1 ))
1413
+ fi;;
1414
+ [\<\>])
1415
+ if [[ $arg[i+1] == $'\x28' ]]; then # \x28 = open paren
1416
+ start=$i
1417
+ (( i += 2 ))
1418
+ _zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,-1]
1419
+ ret=$?
1420
+ (( i += REPLY ))
1421
+ highlights+=(
1422
+ $(( start_pos + start - 1)) $(( start_pos + i )) process-substitution
1423
+ $(( start_pos + start - 1)) $(( start_pos + start + 1 )) process-substitution-delimiter
1424
+ $reply
1425
+ )
1426
+ if (( ret == 0 )); then
1427
+ highlights+=($(( start_pos + i - 1)) $(( start_pos + i )) process-substitution-delimiter)
1428
+ fi
1429
+ continue
1430
+ fi
1431
+ ;|
1432
+ *)
1433
+ if $highlight_glob &&
1434
+ [[ $zsyh_user_options[multios] == on || $in_redirection -eq 0 ]] &&
1435
+ [[ ${arg[$i]} =~ ^[*?] || ${arg:$i-1} =~ ^\<[0-9]*-[0-9]*\> ]]; then
1436
+ highlights+=($(( start_pos + i - 1 )) $(( start_pos + i + $#MATCH - 1)) globbing)
1437
+ (( i += $#MATCH - 1 ))
1438
+ path_eligible=0
1439
+ else
1440
+ continue
1441
+ fi
1442
+ ;;
1443
+ esac
1444
+ done
1445
+
1446
+ if (( path_eligible )); then
1447
+ if (( in_redirection )) && [[ $last_arg == *['<>']['&'] && $arg[$1,-1] == (<0->|p|-) ]]; then
1448
+ if [[ $arg[$1,-1] == (p|-) ]]; then
1449
+ base_style=redirection
1450
+ else
1451
+ base_style=numeric-fd
1452
+ fi
1453
+ # This function is currently never called for the command word, so $2 is hard-coded as 0.
1454
+ elif _zsh_highlight_main_highlighter_check_path $arg[$1,-1] 0; then
1455
+ base_style=$REPLY
1456
+ _zsh_highlight_main_highlighter_highlight_path_separators $base_style
1457
+ highlights+=($reply)
1458
+ fi
1459
+ fi
1460
+
1461
+ highlights=($(( start_pos + $1 - 1 )) $end_pos $base_style $highlights)
1462
+ _zsh_highlight_main_add_many_region_highlights $highlights
1463
+ }
1464
+
1465
+ # Quote Helper Functions
1466
+ #
1467
+ # $arg is expected to be set to the current argument
1468
+ # $start_pos is expected to be set to the start of $arg in $BUFFER
1469
+ # $1 is the index in $arg which starts the quote
1470
+ # $REPLY is returned as the end of quote index in $arg
1471
+ # $reply is returned as an array of region_highlight additions
1472
+
1473
+ # Highlight single-quoted strings
1474
+ _zsh_highlight_main_highlighter_highlight_single_quote()
1475
+ {
1476
+ local arg1=$1 i q=\' style
1477
+ i=$arg[(ib:arg1+1:)$q]
1478
+ reply=()
1479
+
1480
+ if [[ $zsyh_user_options[rcquotes] == on ]]; then
1481
+ while [[ $arg[i+1] == "'" ]]; do
1482
+ reply+=($(( start_pos + i - 1 )) $(( start_pos + i + 1 )) rc-quote)
1483
+ (( i++ ))
1484
+ i=$arg[(ib:i+1:)$q]
1485
+ done
1486
+ fi
1487
+
1488
+ if [[ $arg[i] == "'" ]]; then
1489
+ style=single-quoted-argument
1490
+ else
1491
+ # If unclosed, i points past the end
1492
+ (( i-- ))
1493
+ style=single-quoted-argument-unclosed
1494
+ fi
1495
+ reply=($(( start_pos + arg1 - 1 )) $(( start_pos + i )) $style $reply)
1496
+ REPLY=$i
1497
+ }
1498
+
1499
+ # Highlight special chars inside double-quoted strings
1500
+ _zsh_highlight_main_highlighter_highlight_double_quote()
1501
+ {
1502
+ local -a breaks match mbegin mend saved_reply
1503
+ local MATCH; integer last_break=$(( start_pos + $1 - 1 )) MBEGIN MEND
1504
+ local i j k ret style
1505
+ reply=()
1506
+
1507
+ for (( i = $1 + 1 ; i <= $#arg ; i += 1 )) ; do
1508
+ (( j = i + start_pos - 1 ))
1509
+ (( k = j + 1 ))
1510
+ case "$arg[$i]" in
1511
+ ('"') break;;
1512
+ ('`') saved_reply=($reply)
1513
+ _zsh_highlight_main_highlighter_highlight_backtick $i
1514
+ (( i = REPLY ))
1515
+ reply=($saved_reply $reply)
1516
+ continue
1517
+ ;;
1518
+ ('$') style=dollar-double-quoted-argument
1519
+ # Look for an alphanumeric parameter name.
1520
+ if [[ ${arg:$i} =~ ^([A-Za-z_][A-Za-z0-9_]*|[0-9]+) ]] ; then
1521
+ (( k += $#MATCH )) # highlight the parameter name
1522
+ (( i += $#MATCH )) # skip past it
1523
+ elif [[ ${arg:$i} =~ ^[{]([A-Za-z_][A-Za-z0-9_]*|[0-9]+)[}] ]] ; then
1524
+ (( k += $#MATCH )) # highlight the parameter name and braces
1525
+ (( i += $#MATCH )) # skip past it
1526
+ elif [[ $arg[i+1] == '$' ]]; then
1527
+ # $$ - pid
1528
+ (( k += 1 )) # highlight both dollar signs
1529
+ (( i += 1 )) # don't consider the second one as introducing another parameter expansion
1530
+ elif [[ $arg[i+1] == [-#*@?] ]]; then
1531
+ # $#, $*, $@, $?, $- - like $$ above
1532
+ (( k += 1 )) # highlight both dollar signs
1533
+ (( i += 1 )) # don't consider the second one as introducing another parameter expansion
1534
+ elif [[ $arg[i+1] == $'\x28' ]]; then
1535
+ saved_reply=($reply)
1536
+ if [[ $arg[i+2] == $'\x28' ]] && _zsh_highlight_main_highlighter_highlight_arithmetic $i; then
1537
+ # Arithmetic expansion
1538
+ (( i = REPLY ))
1539
+ reply=($saved_reply $reply)
1540
+ continue
1541
+ fi
1542
+
1543
+ breaks+=( $last_break $(( start_pos + i - 1 )) )
1544
+ (( i += 2 ))
1545
+ _zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,-1]
1546
+ ret=$?
1547
+ (( i += REPLY ))
1548
+ last_break=$(( start_pos + i ))
1549
+ reply=(
1550
+ $saved_reply
1551
+ $j $(( start_pos + i )) command-substitution-quoted
1552
+ $j $(( j + 2 )) command-substitution-delimiter-quoted
1553
+ $reply
1554
+ )
1555
+ if (( ret == 0 )); then
1556
+ reply+=($(( start_pos + i - 1 )) $(( start_pos + i )) command-substitution-delimiter-quoted)
1557
+ fi
1558
+ continue
1559
+ else
1560
+ continue
1561
+ fi
1562
+ ;;
1563
+ "\\") style=back-double-quoted-argument
1564
+ if [[ \\\`\"\$${histchars[1]} == *$arg[$i+1]* ]]; then
1565
+ (( k += 1 )) # Color following char too.
1566
+ (( i += 1 )) # Skip parsing the escaped char.
1567
+ else
1568
+ continue
1569
+ fi
1570
+ ;;
1571
+ ($histchars[1]) # ! - may be a history expansion
1572
+ if [[ $arg[i+1] != ('='|$'\x28'|$'\x7b'|[[:blank:]]) ]]; then
1573
+ style=history-expansion
1574
+ else
1575
+ continue
1576
+ fi
1577
+ ;;
1578
+ *) continue ;;
1579
+
1580
+ esac
1581
+ reply+=($j $k $style)
1582
+ done
1583
+
1584
+ if [[ $arg[i] == '"' ]]; then
1585
+ style=double-quoted-argument
1586
+ else
1587
+ # If unclosed, i points past the end
1588
+ (( i-- ))
1589
+ style=double-quoted-argument-unclosed
1590
+ fi
1591
+ (( last_break != start_pos + i )) && breaks+=( $last_break $(( start_pos + i )) )
1592
+ saved_reply=($reply)
1593
+ reply=()
1594
+ for 1 2 in $breaks; do
1595
+ (( $1 != $2 )) && reply+=($1 $2 $style)
1596
+ done
1597
+ reply+=($saved_reply)
1598
+ REPLY=$i
1599
+ }
1600
+
1601
+ # Highlight special chars inside dollar-quoted strings
1602
+ _zsh_highlight_main_highlighter_highlight_dollar_quote()
1603
+ {
1604
+ local -a match mbegin mend
1605
+ local MATCH; integer MBEGIN MEND
1606
+ local i j k style
1607
+ local AA
1608
+ integer c
1609
+ reply=()
1610
+
1611
+ for (( i = $1 + 2 ; i <= $#arg ; i += 1 )) ; do
1612
+ (( j = i + start_pos - 1 ))
1613
+ (( k = j + 1 ))
1614
+ case "$arg[$i]" in
1615
+ "'") break;;
1616
+ "\\") style=back-dollar-quoted-argument
1617
+ for (( c = i + 1 ; c <= $#arg ; c += 1 )); do
1618
+ [[ "$arg[$c]" != ([0-9xXuUa-fA-F]) ]] && break
1619
+ done
1620
+ AA=$arg[$i+1,$c-1]
1621
+ # Matching for HEX and OCT values like \0xA6, \xA6 or \012
1622
+ if [[ "$AA" =~ "^(x|X)[0-9a-fA-F]{1,2}"
1623
+ || "$AA" =~ "^[0-7]{1,3}"
1624
+ || "$AA" =~ "^u[0-9a-fA-F]{1,4}"
1625
+ || "$AA" =~ "^U[0-9a-fA-F]{1,8}"
1626
+ ]]; then
1627
+ (( k += $#MATCH ))
1628
+ (( i += $#MATCH ))
1629
+ else
1630
+ if (( $#arg > $i+1 )) && [[ $arg[$i+1] == [xXuU] ]]; then
1631
+ # \x not followed by hex digits is probably an error
1632
+ style=unknown-token
1633
+ fi
1634
+ (( k += 1 )) # Color following char too.
1635
+ (( i += 1 )) # Skip parsing the escaped char.
1636
+ fi
1637
+ ;;
1638
+ *) continue ;;
1639
+
1640
+ esac
1641
+ reply+=($j $k $style)
1642
+ done
1643
+
1644
+ if [[ $arg[i] == "'" ]]; then
1645
+ style=dollar-quoted-argument
1646
+ else
1647
+ # If unclosed, i points past the end
1648
+ (( i-- ))
1649
+ style=dollar-quoted-argument-unclosed
1650
+ fi
1651
+ reply=($(( start_pos + $1 - 1 )) $(( start_pos + i )) $style $reply)
1652
+ REPLY=$i
1653
+ }
1654
+
1655
+ # Highlight backtick substitutions
1656
+ _zsh_highlight_main_highlighter_highlight_backtick()
1657
+ {
1658
+ # buf is the contents of the backticks with a layer of backslashes removed.
1659
+ # last is the index of arg for the start of the string to be copied into buf.
1660
+ # It is either one past the beginning backtick or one past the last backslash.
1661
+ # offset is a count of consumed \ (the delta between buf and arg).
1662
+ # offsets is an array indexed by buf offset of when the delta between buf and arg changes.
1663
+ # It is sparse, so search backwards to the last value
1664
+ local buf highlight style=back-quoted-argument-unclosed style_end
1665
+ local -i arg1=$1 end_ i=$1 last offset=0 start subshell_has_end=0
1666
+ local -a highlight_zone highlights offsets
1667
+ reply=()
1668
+
1669
+ last=$(( arg1 + 1 ))
1670
+ # Remove one layer of backslashes and find the end
1671
+ while i=$arg[(ib:i+1:)[\\\\\`]]; do # find the next \ or `
1672
+ if (( i > $#arg )); then
1673
+ buf=$buf$arg[last,i]
1674
+ offsets[i-arg1-offset]='' # So we never index past the end
1675
+ (( i-- ))
1676
+ subshell_has_end=$(( has_end && (start_pos + i == len) ))
1677
+ break
1678
+ fi
1679
+
1680
+ if [[ $arg[i] == '\' ]]; then
1681
+ (( i++ ))
1682
+ # POSIX XCU 2.6.3
1683
+ if [[ $arg[i] == ('$'|'`'|'\') ]]; then
1684
+ buf=$buf$arg[last,i-2]
1685
+ (( offset++ ))
1686
+ # offsets is relative to buf, so adjust by -arg1
1687
+ offsets[i-arg1-offset]=$offset
1688
+ else
1689
+ buf=$buf$arg[last,i-1]
1690
+ fi
1691
+ else # it's an unquoted ` and this is the end
1692
+ style=back-quoted-argument
1693
+ style_end=back-quoted-argument-delimiter
1694
+ buf=$buf$arg[last,i-1]
1695
+ offsets[i-arg1-offset]='' # So we never index past the end
1696
+ break
1697
+ fi
1698
+ last=$i
1699
+ done
1700
+
1701
+ _zsh_highlight_main_highlighter_highlight_list 0 '' $subshell_has_end $buf
1702
+
1703
+ # Munge the reply to account for removed backslashes
1704
+ for start end_ highlight in $reply; do
1705
+ start=$(( start_pos + arg1 + start + offsets[(Rb:start:)?*] ))
1706
+ end_=$(( start_pos + arg1 + end_ + offsets[(Rb:end_:)?*] ))
1707
+ highlights+=($start $end_ $highlight)
1708
+ if [[ $highlight == back-quoted-argument-unclosed && $style == back-quoted-argument ]]; then
1709
+ # An inner backtick command substitution is unclosed, but this level is closed
1710
+ style_end=unknown-token
1711
+ fi
1712
+ done
1713
+
1714
+ reply=(
1715
+ $(( start_pos + arg1 - 1 )) $(( start_pos + i )) $style
1716
+ $(( start_pos + arg1 - 1 )) $(( start_pos + arg1 )) back-quoted-argument-delimiter
1717
+ $highlights
1718
+ )
1719
+ if (( $#style_end )); then
1720
+ reply+=($(( start_pos + i - 1)) $(( start_pos + i )) $style_end)
1721
+ fi
1722
+ REPLY=$i
1723
+ }
1724
+
1725
+ # Highlight special chars inside arithmetic expansions
1726
+ _zsh_highlight_main_highlighter_highlight_arithmetic()
1727
+ {
1728
+ local -a saved_reply
1729
+ local style
1730
+ integer i j k paren_depth ret
1731
+ reply=()
1732
+
1733
+ for (( i = $1 + 3 ; i <= end_pos - start_pos ; i += 1 )) ; do
1734
+ (( j = i + start_pos - 1 ))
1735
+ (( k = j + 1 ))
1736
+ case "$arg[$i]" in
1737
+ [\'\"\\@{}])
1738
+ style=unknown-token
1739
+ ;;
1740
+ '(')
1741
+ (( paren_depth++ ))
1742
+ continue
1743
+ ;;
1744
+ ')')
1745
+ if (( paren_depth )); then
1746
+ (( paren_depth-- ))
1747
+ continue
1748
+ fi
1749
+ [[ $arg[i+1] == ')' ]] && { (( i++ )); break; }
1750
+ # Special case ) at the end of the buffer to avoid flashing command substitution for a character
1751
+ (( has_end && (len == k) )) && break
1752
+ # This is a single paren and there are no open parens, so this isn't an arithmetic expansion
1753
+ return 1
1754
+ ;;
1755
+ '`')
1756
+ saved_reply=($reply)
1757
+ _zsh_highlight_main_highlighter_highlight_backtick $i
1758
+ (( i = REPLY ))
1759
+ reply=($saved_reply $reply)
1760
+ continue
1761
+ ;;
1762
+ '$' )
1763
+ if [[ $arg[i+1] == $'\x28' ]]; then
1764
+ saved_reply=($reply)
1765
+ if [[ $arg[i+2] == $'\x28' ]] && _zsh_highlight_main_highlighter_highlight_arithmetic $i; then
1766
+ # Arithmetic expansion
1767
+ (( i = REPLY ))
1768
+ reply=($saved_reply $reply)
1769
+ continue
1770
+ fi
1771
+
1772
+ (( i += 2 ))
1773
+ _zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,end_pos]
1774
+ ret=$?
1775
+ (( i += REPLY ))
1776
+ reply=(
1777
+ $saved_reply
1778
+ $j $(( start_pos + i )) command-substitution-quoted
1779
+ $j $(( j + 2 )) command-substitution-delimiter-quoted
1780
+ $reply
1781
+ )
1782
+ if (( ret == 0 )); then
1783
+ reply+=($(( start_pos + i - 1 )) $(( start_pos + i )) command-substitution-delimiter)
1784
+ fi
1785
+ continue
1786
+ else
1787
+ continue
1788
+ fi
1789
+ ;;
1790
+ ($histchars[1]) # ! - may be a history expansion
1791
+ if [[ $arg[i+1] != ('='|$'\x28'|$'\x7b'|[[:blank:]]) ]]; then
1792
+ style=history-expansion
1793
+ else
1794
+ continue
1795
+ fi
1796
+ ;;
1797
+ *)
1798
+ continue
1799
+ ;;
1800
+
1801
+ esac
1802
+ reply+=($j $k $style)
1803
+ done
1804
+
1805
+ if [[ $arg[i] != ')' ]]; then
1806
+ # If unclosed, i points past the end
1807
+ (( i-- ))
1808
+ fi
1809
+ style=arithmetic-expansion
1810
+ reply=($(( start_pos + $1 - 1)) $(( start_pos + i )) arithmetic-expansion $reply)
1811
+ REPLY=$i
1812
+ }
1813
+
1814
+
1815
+ # Called with a single positional argument.
1816
+ # Perform filename expansion (tilde expansion) on the argument and set $REPLY to the expanded value.
1817
+ #
1818
+ # Does not perform filename generation (globbing).
1819
+ _zsh_highlight_main_highlighter_expand_path()
1820
+ {
1821
+ (( $# == 1 )) || print -r -- >&2 "zsh-syntax-highlighting: BUG: _zsh_highlight_main_highlighter_expand_path: called without argument"
1822
+
1823
+ # The $~1 syntax normally performs filename generation, but not when it's on the right-hand side of ${x:=y}.
1824
+ setopt localoptions nonomatch
1825
+ unset REPLY
1826
+ : ${REPLY:=${(Q)${~1}}}
1827
+ }
1828
+
1829
+ # -------------------------------------------------------------------------------------------------
1830
+ # Main highlighter initialization
1831
+ # -------------------------------------------------------------------------------------------------
1832
+
1833
+ _zsh_highlight_main__precmd_hook() {
1834
+ # Unset the WARN_NESTED_VAR option, taking care not to error if the option
1835
+ # doesn't exist (zsh older than zsh-5.3.1-test-2).
1836
+ setopt localoptions
1837
+ if eval '[[ -o warnnestedvar ]]' 2>/dev/null; then
1838
+ unsetopt warnnestedvar
1839
+ fi
1840
+
1841
+ _zsh_highlight_main__command_type_cache=()
1842
+ }
1843
+
1844
+ autoload -Uz add-zsh-hook
1845
+ if add-zsh-hook precmd _zsh_highlight_main__precmd_hook 2>/dev/null; then
1846
+ # Initialize command type cache
1847
+ typeset -gA _zsh_highlight_main__command_type_cache
1848
+ else
1849
+ print -r -- >&2 'zsh-syntax-highlighting: Failed to load add-zsh-hook. Some speed optimizations will not be used.'
1850
+ # Make sure the cache is unset
1851
+ unset _zsh_highlight_main__command_type_cache
1852
+ fi
1853
+ typeset -ga ZSH_HIGHLIGHT_DIRS_BLACKLIST