mirror of
https://github.com/zsh-users/zsh-syntax-highlighting.git
synced 2025-02-06 09:55:31 +08:00
136 lines
4.6 KiB
Plaintext
136 lines
4.6 KiB
Plaintext
![]() |
# Update ZLE buffer syntax highlighting.
|
||
|
#
|
||
|
# Invokes each highlighter that needs updating.
|
||
|
# This function is supposed to be called whenever the ZLE state changes.
|
||
|
_zsh_highlight_internal()
|
||
|
{
|
||
|
emulate -L zsh
|
||
|
setopt localoptions warncreateglobal nobashrematch
|
||
|
local REPLY # don't leak $REPLY into global scope
|
||
|
|
||
|
# Do not highlight if there are more than 300 chars in the buffer. It's most
|
||
|
# likely a pasted command or a huge list of files in that case..
|
||
|
[[ -n ${ZSH_HIGHLIGHT_MAXLENGTH:-} ]] && [[ $#BUFFER -gt $ZSH_HIGHLIGHT_MAXLENGTH ]] && return
|
||
|
|
||
|
# Do not highlight if there are pending inputs (copy/paste).
|
||
|
[[ $PENDING -gt 0 ]] && return
|
||
|
|
||
|
{
|
||
|
local cache_place
|
||
|
local -a region_highlight_copy
|
||
|
|
||
|
# Select which highlighters in ZSH_HIGHLIGHT_HIGHLIGHTERS need to be invoked.
|
||
|
local highlighter; for highlighter in $ZSH_HIGHLIGHT_HIGHLIGHTERS; do
|
||
|
|
||
|
# eval cache place for current highlighter and prepare it
|
||
|
cache_place="_zsh_highlight__highlighter_${highlighter}_cache"
|
||
|
typeset -ga ${cache_place}
|
||
|
|
||
|
# If highlighter needs to be invoked
|
||
|
if ! type "_zsh_highlight_highlighter_${highlighter}_predicate" >&/dev/null; then
|
||
|
echo "zsh-syntax-highlighting: warning: disabling the ${(qq)highlighter} highlighter as it has not been loaded" >&2
|
||
|
# TODO: use ${(b)} rather than ${(q)} if supported
|
||
|
ZSH_HIGHLIGHT_HIGHLIGHTERS=( ${ZSH_HIGHLIGHT_HIGHLIGHTERS:#${highlighter}} )
|
||
|
elif "_zsh_highlight_highlighter_${highlighter}_predicate"; then
|
||
|
|
||
|
# save a copy, and cleanup region_highlight
|
||
|
region_highlight_copy=("${region_highlight[@]}")
|
||
|
region_highlight=()
|
||
|
|
||
|
# Execute highlighter and save result
|
||
|
{
|
||
|
"_zsh_highlight_highlighter_${highlighter}_paint"
|
||
|
} always {
|
||
|
: ${(AP)cache_place::="${region_highlight[@]}"}
|
||
|
}
|
||
|
|
||
|
# Restore saved region_highlight
|
||
|
region_highlight=("${region_highlight_copy[@]}")
|
||
|
|
||
|
fi
|
||
|
|
||
|
# Use value form cache if any cached
|
||
|
region_highlight+=("${(@P)cache_place}")
|
||
|
|
||
|
done
|
||
|
|
||
|
# Re-apply zle_highlight settings
|
||
|
|
||
|
# region
|
||
|
() {
|
||
|
(( REGION_ACTIVE )) || return
|
||
|
integer min max
|
||
|
if (( MARK > CURSOR )) ; then
|
||
|
min=$CURSOR max=$MARK
|
||
|
else
|
||
|
min=$MARK max=$CURSOR
|
||
|
fi
|
||
|
if (( REGION_ACTIVE == 1 )); then
|
||
|
[[ $KEYMAP = vicmd ]] && (( max++ ))
|
||
|
elif (( REGION_ACTIVE == 2 )); then
|
||
|
local needle=$'\n'
|
||
|
# CURSOR and MARK are 0 indexed between letters like region_highlight
|
||
|
# Do not include the newline in the highlight
|
||
|
(( min = ${BUFFER[(Ib:min:)$needle]} ))
|
||
|
(( max = ${BUFFER[(ib:max:)$needle]} - 1 ))
|
||
|
fi
|
||
|
_zsh_highlight_apply_zle_highlight region standout "$min" "$max"
|
||
|
}
|
||
|
|
||
|
# yank / paste (zsh-5.1.1 and newer)
|
||
|
(( $+YANK_ACTIVE )) && (( YANK_ACTIVE )) && _zsh_highlight_apply_zle_highlight paste standout "$YANK_START" "$YANK_END"
|
||
|
|
||
|
# isearch
|
||
|
(( $+ISEARCHMATCH_ACTIVE )) && (( ISEARCHMATCH_ACTIVE )) && _zsh_highlight_apply_zle_highlight isearch underline "$ISEARCHMATCH_START" "$ISEARCHMATCH_END"
|
||
|
|
||
|
# suffix
|
||
|
(( $+SUFFIX_ACTIVE )) && (( SUFFIX_ACTIVE )) && _zsh_highlight_apply_zle_highlight suffix bold "$SUFFIX_START" "$SUFFIX_END"
|
||
|
|
||
|
} always {
|
||
|
typeset -g _ZSH_HIGHLIGHT_PRIOR_BUFFER="$BUFFER"
|
||
|
typeset -gi _ZSH_HIGHLIGHT_PRIOR_CURSOR=$CURSOR
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# Apply highlighting based on entries in the zle_highlight array.
|
||
|
# This function takes four arguments:
|
||
|
# 1. The exact entry (no patterns) in the zle_highlight array:
|
||
|
# region, paste, isearch, or suffix
|
||
|
# 2. The default highlighting that should be applied if the entry is unset
|
||
|
# 3. and 4. Two integer values describing the beginning and end of the
|
||
|
# range. The order does not matter.
|
||
|
_zsh_highlight_apply_zle_highlight() {
|
||
|
local entry="$1" default="$2"
|
||
|
integer first="$3" second="$4"
|
||
|
|
||
|
# read the relevant entry from zle_highlight
|
||
|
#
|
||
|
# ### In zsh≥5.0.8 we'd use ${(b)entry}, but we support older zsh's, so we don't
|
||
|
# ### add (b). The only effect is on the failure mode for callers that violate
|
||
|
# ### the precondition.
|
||
|
local region="${zle_highlight[(r)${entry}:*]-}"
|
||
|
|
||
|
if [[ -z "$region" ]]; then
|
||
|
# entry not specified at all, use default value
|
||
|
region=$default
|
||
|
else
|
||
|
# strip prefix
|
||
|
region="${region#${entry}:}"
|
||
|
|
||
|
# no highlighting when set to the empty string or to 'none'
|
||
|
if [[ -z "$region" ]] || [[ "$region" == none ]]; then
|
||
|
return
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
integer start end
|
||
|
if (( first < second )); then
|
||
|
start=$first end=$second
|
||
|
else
|
||
|
start=$second end=$first
|
||
|
fi
|
||
|
region_highlight+=("$start $end $region, memo=zsh-syntax-highlighting")
|
||
|
}
|
||
|
|
||
|
_zsh_highlight_internal "$@"
|