main: Recurse into backtick command substitutions
This commit is contained in:
parent
c40c72c386
commit
9db393309e
@ -1084,21 +1084,67 @@ _zsh_highlight_main_highlighter_highlight_dollar_quote()
|
||||
REPLY=$i
|
||||
}
|
||||
|
||||
# Highlight backtick subshells
|
||||
# Highlight backtick substitutions
|
||||
_zsh_highlight_main_highlighter_highlight_backtick()
|
||||
{
|
||||
local arg1=$1 i=$1 q=\` style
|
||||
# buf is the contents of the backticks with a layer of backslashes removed.
|
||||
# last is the index of arg for the start of the string to be copied into buf.
|
||||
# It is either one past the beginning backtick or one past the last backslash.
|
||||
# offset is a count of consumed \ (the delta between buf and arg).
|
||||
# offsets is an array indexed by buf offset of when the delta between buf and arg changes.
|
||||
# It is sparse, so search backwards to the last value
|
||||
# unclosed is an array of one highlight to append to reply if this back-quoted-argument
|
||||
# is closed and there is an unclosed back-quoted-argument in buf.
|
||||
local buf highlight style=back-quoted-argument-unclosed
|
||||
local -i arg1=$1 end_ i=$1 last offset=0 start subshell_has_end=0
|
||||
local -a highlight_zone highlights offsets unclosed
|
||||
reply=()
|
||||
while i=$arg[(ib:i+1:)$q]; [[ $arg[i-1] == '\' && $i -lt $(( end_pos - start_pos )) ]]; do done
|
||||
|
||||
if [[ $arg[i] == '`' ]]; then
|
||||
style=back-quoted-argument
|
||||
else
|
||||
# If unclosed, i points past the end
|
||||
(( i-- ))
|
||||
style=back-quoted-argument-unclosed
|
||||
fi
|
||||
reply=($(( start_pos + arg1 - 1 )) $(( start_pos + i )) $style)
|
||||
last=$(( arg1 + 1 ))
|
||||
# Remove one layer of backslashes and find the end
|
||||
while i=$arg[(ib:i+1:)[\\\\\`]]; do # find the next \ or `
|
||||
if (( i > end_pos - start_pos )); then
|
||||
buf=$buf$arg[last,i]
|
||||
offsets[i-arg1-offset]='' # So we never index past the end
|
||||
(( i-- ))
|
||||
subshell_has_end=$(( has_end && (start_pos + i == len) ))
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ $arg[i] == '\' ]]; then
|
||||
(( i++ ))
|
||||
# POSIX XCU 2.6.3
|
||||
if [[ $arg[i] == ('$'|'`'|'\') ]]; then
|
||||
buf=$buf$arg[last,i-2]
|
||||
(( offset++ ))
|
||||
# offsets is relative to buf, so adjust by -arg1
|
||||
offsets[i-arg1-offset]=$offset
|
||||
else
|
||||
buf=$buf$arg[last,i-1]
|
||||
fi
|
||||
else # it's an unquoted ` and this is the end
|
||||
style=back-quoted-argument
|
||||
buf=$buf$arg[last,i-1]
|
||||
offsets[i-arg1-offset]='' # So we never index past the end
|
||||
break
|
||||
fi
|
||||
last=$i
|
||||
done
|
||||
|
||||
_zsh_highlight_main_highlighter_highlight_list 0 '' $subshell_has_end $buf
|
||||
|
||||
# Munge the reply to account for removed backslashes
|
||||
for start end_ highlight in $reply; do
|
||||
start=$(( start_pos + arg1 + start + offsets[(Rb:start:)?*] ))
|
||||
end_=$(( start_pos + arg1 + end_ + offsets[(Rb:end_:)?*] ))
|
||||
highlights+=($start $end_ $highlight)
|
||||
if [[ $highlight == back-quoted-argument-unclosed && $style == back-quoted-argument ]]; then
|
||||
# An inner backtick command substitution is unclosed, but this level is closed
|
||||
unclosed=($(( start_pos + i - 1)) $(( start_pos + i )) unknown-token)
|
||||
fi
|
||||
done
|
||||
|
||||
reply=($(( start_pos + arg1 - 1 )) $(( start_pos + i )) $style $highlights $unclosed)
|
||||
REPLY=$i
|
||||
}
|
||||
|
||||
|
@ -27,16 +27,25 @@
|
||||
# vim: ft=zsh sw=2 ts=2 et
|
||||
# -------------------------------------------------------------------------------------------------
|
||||
|
||||
# 42 is in the command position in a nested subshell.
|
||||
BUFFER='echo `echo \`42\`` "is `echo equal` to" `echo 6 times 9'
|
||||
|
||||
expected_region_highlight=(
|
||||
"1 4 builtin" # echo
|
||||
"6 18 default" # `echo \`42\``
|
||||
"6 18 back-quoted-argument" # `echo \`42\``
|
||||
"7 10 builtin" # echo
|
||||
"12 17 default" # \`42\`
|
||||
"12 17 back-quoted-argument" # \`42\`
|
||||
"14 15 unknown-token" # 42
|
||||
"20 39 default" # "is `echo equal` to"
|
||||
"20 39 double-quoted-argument" # "is `echo equal` to"
|
||||
"24 35 back-quoted-argument" # `echo equal`
|
||||
"25 28 builtin" # echo
|
||||
"30 34 default" # equal
|
||||
"41 55 default" # `echo 6 times 9
|
||||
"41 55 back-quoted-argument-unclosed" # `echo 6 times 9
|
||||
"42 45 builtin" # echo
|
||||
"47 47 default" # 6
|
||||
"49 53 default" # times
|
||||
"55 55 default" # 9
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user