Skip to content

Commit 3423a97

Browse files
committed
driver: Split out autoloadable part of _zsh_highlight
1 parent 120433e commit 3423a97

File tree

2 files changed

+140
-129
lines changed

2 files changed

+140
-129
lines changed

_zsh_highlight_internal

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Update ZLE buffer syntax highlighting.
2+
#
3+
# Invokes each highlighter that needs updating.
4+
# This function is supposed to be called whenever the ZLE state changes.
5+
_zsh_highlight_internal()
6+
{
7+
emulate -L zsh
8+
setopt localoptions warncreateglobal nobashrematch
9+
local REPLY # don't leak $REPLY into global scope
10+
11+
# Do not highlight if there are more than 300 chars in the buffer. It's most
12+
# likely a pasted command or a huge list of files in that case..
13+
[[ -n ${ZSH_HIGHLIGHT_MAXLENGTH:-} ]] && [[ $#BUFFER -gt $ZSH_HIGHLIGHT_MAXLENGTH ]] && return
14+
15+
# Do not highlight if there are pending inputs (copy/paste).
16+
[[ $PENDING -gt 0 ]] && return
17+
18+
{
19+
local cache_place
20+
local -a region_highlight_copy
21+
22+
# Select which highlighters in ZSH_HIGHLIGHT_HIGHLIGHTERS need to be invoked.
23+
local highlighter; for highlighter in $ZSH_HIGHLIGHT_HIGHLIGHTERS; do
24+
25+
# eval cache place for current highlighter and prepare it
26+
cache_place="_zsh_highlight__highlighter_${highlighter}_cache"
27+
typeset -ga ${cache_place}
28+
29+
# If highlighter needs to be invoked
30+
if ! type "_zsh_highlight_highlighter_${highlighter}_predicate" >&/dev/null; then
31+
echo "zsh-syntax-highlighting: warning: disabling the ${(qq)highlighter} highlighter as it has not been loaded" >&2
32+
# TODO: use ${(b)} rather than ${(q)} if supported
33+
ZSH_HIGHLIGHT_HIGHLIGHTERS=( ${ZSH_HIGHLIGHT_HIGHLIGHTERS:#${highlighter}} )
34+
elif "_zsh_highlight_highlighter_${highlighter}_predicate"; then
35+
36+
# save a copy, and cleanup region_highlight
37+
region_highlight_copy=("${region_highlight[@]}")
38+
region_highlight=()
39+
40+
# Execute highlighter and save result
41+
{
42+
"_zsh_highlight_highlighter_${highlighter}_paint"
43+
} always {
44+
: ${(AP)cache_place::="${region_highlight[@]}"}
45+
}
46+
47+
# Restore saved region_highlight
48+
region_highlight=("${region_highlight_copy[@]}")
49+
50+
fi
51+
52+
# Use value form cache if any cached
53+
region_highlight+=("${(@P)cache_place}")
54+
55+
done
56+
57+
# Re-apply zle_highlight settings
58+
59+
# region
60+
() {
61+
(( REGION_ACTIVE )) || return
62+
integer min max
63+
if (( MARK > CURSOR )) ; then
64+
min=$CURSOR max=$MARK
65+
else
66+
min=$MARK max=$CURSOR
67+
fi
68+
if (( REGION_ACTIVE == 1 )); then
69+
[[ $KEYMAP = vicmd ]] && (( max++ ))
70+
elif (( REGION_ACTIVE == 2 )); then
71+
local needle=$'\n'
72+
# CURSOR and MARK are 0 indexed between letters like region_highlight
73+
# Do not include the newline in the highlight
74+
(( min = ${BUFFER[(Ib:min:)$needle]} ))
75+
(( max = ${BUFFER[(ib:max:)$needle]} - 1 ))
76+
fi
77+
_zsh_highlight_apply_zle_highlight region standout "$min" "$max"
78+
}
79+
80+
# yank / paste (zsh-5.1.1 and newer)
81+
(( $+YANK_ACTIVE )) && (( YANK_ACTIVE )) && _zsh_highlight_apply_zle_highlight paste standout "$YANK_START" "$YANK_END"
82+
83+
# isearch
84+
(( $+ISEARCHMATCH_ACTIVE )) && (( ISEARCHMATCH_ACTIVE )) && _zsh_highlight_apply_zle_highlight isearch underline "$ISEARCHMATCH_START" "$ISEARCHMATCH_END"
85+
86+
# suffix
87+
(( $+SUFFIX_ACTIVE )) && (( SUFFIX_ACTIVE )) && _zsh_highlight_apply_zle_highlight suffix bold "$SUFFIX_START" "$SUFFIX_END"
88+
89+
} always {
90+
typeset -g _ZSH_HIGHLIGHT_PRIOR_BUFFER="$BUFFER"
91+
typeset -gi _ZSH_HIGHLIGHT_PRIOR_CURSOR=$CURSOR
92+
}
93+
}
94+
95+
# Apply highlighting based on entries in the zle_highlight array.
96+
# This function takes four arguments:
97+
# 1. The exact entry (no patterns) in the zle_highlight array:
98+
# region, paste, isearch, or suffix
99+
# 2. The default highlighting that should be applied if the entry is unset
100+
# 3. and 4. Two integer values describing the beginning and end of the
101+
# range. The order does not matter.
102+
_zsh_highlight_apply_zle_highlight() {
103+
local entry="$1" default="$2"
104+
integer first="$3" second="$4"
105+
106+
# read the relevant entry from zle_highlight
107+
#
108+
# ### In zsh≥5.0.8 we'd use ${(b)entry}, but we support older zsh's, so we don't
109+
# ### add (b). The only effect is on the failure mode for callers that violate
110+
# ### the precondition.
111+
local region="${zle_highlight[(r)${entry}:*]-}"
112+
113+
if [[ -z "$region" ]]; then
114+
# entry not specified at all, use default value
115+
region=$default
116+
else
117+
# strip prefix
118+
region="${region#${entry}:}"
119+
120+
# no highlighting when set to the empty string or to 'none'
121+
if [[ -z "$region" ]] || [[ "$region" == none ]]; then
122+
return
123+
fi
124+
fi
125+
126+
integer start end
127+
if (( first < second )); then
128+
start=$first end=$second
129+
else
130+
start=$second end=$first
131+
fi
132+
region_highlight+=("$start $end $region, memo=zsh-syntax-highlighting")
133+
}
134+
135+
_zsh_highlight_internal

zsh-syntax-highlighting.zsh

Lines changed: 5 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ builtin unalias -m '[^+]*'
3737

3838
# Set $0 to the expected value, regardless of functionargzero.
3939
0=${(%):-%N}
40+
fpath+=(${0:a:h})
4041
if true; then
4142
# $0 is reliable
4243
typeset -g ZSH_HIGHLIGHT_VERSION=$(<"${0:A:h}"/.version)
@@ -210,136 +211,9 @@ _zsh_highlight()
210211
fi
211212
typeset -r zsyh_user_options
212213

213-
emulate -L zsh
214-
setopt localoptions warncreateglobal nobashrematch
215-
local REPLY # don't leak $REPLY into global scope
214+
_zsh_highlight_internal
216215

217-
# Do not highlight if there are more than 300 chars in the buffer. It's most
218-
# likely a pasted command or a huge list of files in that case..
219-
[[ -n ${ZSH_HIGHLIGHT_MAXLENGTH:-} ]] && [[ $#BUFFER -gt $ZSH_HIGHLIGHT_MAXLENGTH ]] && return $ret
220-
221-
# Do not highlight if there are pending inputs (copy/paste).
222-
[[ $PENDING -gt 0 ]] && return $ret
223-
224-
{
225-
local cache_place
226-
local -a region_highlight_copy
227-
228-
# Select which highlighters in ZSH_HIGHLIGHT_HIGHLIGHTERS need to be invoked.
229-
local highlighter; for highlighter in $ZSH_HIGHLIGHT_HIGHLIGHTERS; do
230-
231-
# eval cache place for current highlighter and prepare it
232-
cache_place="_zsh_highlight__highlighter_${highlighter}_cache"
233-
typeset -ga ${cache_place}
234-
235-
# If highlighter needs to be invoked
236-
if ! type "_zsh_highlight_highlighter_${highlighter}_predicate" >&/dev/null; then
237-
echo "zsh-syntax-highlighting: warning: disabling the ${(qq)highlighter} highlighter as it has not been loaded" >&2
238-
# TODO: use ${(b)} rather than ${(q)} if supported
239-
ZSH_HIGHLIGHT_HIGHLIGHTERS=( ${ZSH_HIGHLIGHT_HIGHLIGHTERS:#${highlighter}} )
240-
elif "_zsh_highlight_highlighter_${highlighter}_predicate"; then
241-
242-
# save a copy, and cleanup region_highlight
243-
region_highlight_copy=("${region_highlight[@]}")
244-
region_highlight=()
245-
246-
# Execute highlighter and save result
247-
{
248-
"_zsh_highlight_highlighter_${highlighter}_paint"
249-
} always {
250-
: ${(AP)cache_place::="${region_highlight[@]}"}
251-
}
252-
253-
# Restore saved region_highlight
254-
region_highlight=("${region_highlight_copy[@]}")
255-
256-
fi
257-
258-
# Use value form cache if any cached
259-
region_highlight+=("${(@P)cache_place}")
260-
261-
done
262-
263-
# Re-apply zle_highlight settings
264-
265-
# region
266-
() {
267-
(( REGION_ACTIVE )) || return
268-
integer min max
269-
if (( MARK > CURSOR )) ; then
270-
min=$CURSOR max=$MARK
271-
else
272-
min=$MARK max=$CURSOR
273-
fi
274-
if (( REGION_ACTIVE == 1 )); then
275-
[[ $KEYMAP = vicmd ]] && (( max++ ))
276-
elif (( REGION_ACTIVE == 2 )); then
277-
local needle=$'\n'
278-
# CURSOR and MARK are 0 indexed between letters like region_highlight
279-
# Do not include the newline in the highlight
280-
(( min = ${BUFFER[(Ib:min:)$needle]} ))
281-
(( max = ${BUFFER[(ib:max:)$needle]} - 1 ))
282-
fi
283-
_zsh_highlight_apply_zle_highlight region standout "$min" "$max"
284-
}
285-
286-
# yank / paste (zsh-5.1.1 and newer)
287-
(( $+YANK_ACTIVE )) && (( YANK_ACTIVE )) && _zsh_highlight_apply_zle_highlight paste standout "$YANK_START" "$YANK_END"
288-
289-
# isearch
290-
(( $+ISEARCHMATCH_ACTIVE )) && (( ISEARCHMATCH_ACTIVE )) && _zsh_highlight_apply_zle_highlight isearch underline "$ISEARCHMATCH_START" "$ISEARCHMATCH_END"
291-
292-
# suffix
293-
(( $+SUFFIX_ACTIVE )) && (( SUFFIX_ACTIVE )) && _zsh_highlight_apply_zle_highlight suffix bold "$SUFFIX_START" "$SUFFIX_END"
294-
295-
296-
return $ret
297-
298-
299-
} always {
300-
typeset -g _ZSH_HIGHLIGHT_PRIOR_BUFFER="$BUFFER"
301-
typeset -gi _ZSH_HIGHLIGHT_PRIOR_CURSOR=$CURSOR
302-
}
303-
}
304-
305-
# Apply highlighting based on entries in the zle_highlight array.
306-
# This function takes four arguments:
307-
# 1. The exact entry (no patterns) in the zle_highlight array:
308-
# region, paste, isearch, or suffix
309-
# 2. The default highlighting that should be applied if the entry is unset
310-
# 3. and 4. Two integer values describing the beginning and end of the
311-
# range. The order does not matter.
312-
_zsh_highlight_apply_zle_highlight() {
313-
local entry="$1" default="$2"
314-
integer first="$3" second="$4"
315-
316-
# read the relevant entry from zle_highlight
317-
#
318-
# ### In zsh≥5.0.8 we'd use ${(b)entry}, but we support older zsh's, so we don't
319-
# ### add (b). The only effect is on the failure mode for callers that violate
320-
# ### the precondition.
321-
local region="${zle_highlight[(r)${entry}:*]-}"
322-
323-
if [[ -z "$region" ]]; then
324-
# entry not specified at all, use default value
325-
region=$default
326-
else
327-
# strip prefix
328-
region="${region#${entry}:}"
329-
330-
# no highlighting when set to the empty string or to 'none'
331-
if [[ -z "$region" ]] || [[ "$region" == none ]]; then
332-
return
333-
fi
334-
fi
335-
336-
integer start end
337-
if (( first < second )); then
338-
start=$first end=$second
339-
else
340-
start=$second end=$first
341-
fi
342-
region_highlight+=("$start $end $region, memo=zsh-syntax-highlighting")
216+
return ret
343217
}
344218

345219

@@ -561,6 +435,8 @@ _zsh_highlight_load_highlighters()
561435
# Setup
562436
# -------------------------------------------------------------------------------------------------
563437

438+
autoload -Uz _zsh_highlight_internal
439+
564440
# Try binding widgets.
565441
_zsh_highlight_bind_widgets || {
566442
print -r -- >&2 'zsh-syntax-highlighting: failed binding ZLE widgets, exiting.'

0 commit comments

Comments
 (0)