Skip to content

Commit 178039e

Browse files
committed
main: Add arithmetic substitution highlighting
Closes #607 #649 #704
1 parent d1802e3 commit 178039e

File tree

3 files changed

+121
-15
lines changed

3 files changed

+121
-15
lines changed

highlighters/main/main-highlighter.zsh

Lines changed: 110 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,8 +1300,13 @@ _zsh_highlight_main_highlighter_highlight_argument()
13001300
(( i = REPLY ))
13011301
highlights+=($reply)
13021302
continue
1303-
elif [[ $arg[i+1] == $'\x28' && ${arg:$i} != $'\x28\x28'*$'\x29\x29'* ]]; then
1304-
# command substitution that doesn't look like an arithmetic expansion
1303+
elif [[ $arg[i+1] == $'\x28' ]]; then
1304+
if [[ $arg[i+2] == $'\x28' ]] && _zsh_highlight_main_highlighter_highlight_arithmetic $i; then
1305+
# Arithmetic substitution
1306+
(( i = REPLY ))
1307+
highlights+=($reply)
1308+
continue
1309+
fi
13051310
start=$i
13061311
(( i += 2 ))
13071312
_zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,-1]
@@ -1447,11 +1452,17 @@ _zsh_highlight_main_highlighter_highlight_double_quote()
14471452
# $#, $*, $@, $?, $- - like $$ above
14481453
(( k += 1 )) # highlight both dollar signs
14491454
(( i += 1 )) # don't consider the second one as introducing another parameter expansion
1450-
elif [[ $arg[i+1] == $'\x28' && ${arg:$i} != $'\x28\x28'*$'\x29\x29'* ]]; then
1451-
# command substitution that doesn't look like an arithmetic expansion
1455+
elif [[ $arg[i+1] == $'\x28' ]]; then
1456+
saved_reply=($reply)
1457+
if [[ $arg[i+2] == $'\x28' ]] && _zsh_highlight_main_highlighter_highlight_arithmetic $i; then
1458+
# Arithmetic substitution
1459+
(( i = REPLY ))
1460+
reply=($saved_reply $reply)
1461+
continue
1462+
fi
1463+
14521464
breaks+=( $last_break $(( start_pos + i - 1 )) )
14531465
(( i += 2 ))
1454-
saved_reply=($reply)
14551466
_zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,-1]
14561467
ret=$?
14571468
(( i += REPLY ))
@@ -1632,6 +1643,100 @@ _zsh_highlight_main_highlighter_highlight_backtick()
16321643
REPLY=$i
16331644
}
16341645

1646+
# Highlight special chars inside arithmetic substitutions
1647+
_zsh_highlight_main_highlighter_highlight_arithmetic()
1648+
{
1649+
local -a match mbegin mend saved_reply
1650+
local MATCH; integer MBEGIN MEND
1651+
local i j k ret style
1652+
integer paren_depth
1653+
reply=()
1654+
1655+
for (( i = $1 + 3 ; i <= end_pos - start_pos ; i += 1 )) ; do
1656+
(( j = i + start_pos - 1 ))
1657+
(( k = j + 1 ))
1658+
case "$arg[$i]" in
1659+
')')
1660+
if (( paren_depth )); then
1661+
(( paren_depth-- ))
1662+
continue
1663+
fi
1664+
[[ $arg[i+1] == ')' ]] && break
1665+
# Special case ) at the end of the buffer to avoid flashing command substitution for a character
1666+
(( has_end && (len == k) )) && break
1667+
# This is a single paren and there are no open parens, so this isn't an arithmetic substitution
1668+
return 1
1669+
;;
1670+
'(')
1671+
(( paren_depth++ ))
1672+
continue
1673+
;;
1674+
[\'\"\\])
1675+
style=unknown-token
1676+
;;
1677+
'`')
1678+
saved_reply=($reply)
1679+
_zsh_highlight_main_highlighter_highlight_backtick $i
1680+
(( i = REPLY ))
1681+
reply=($saved_reply $reply)
1682+
continue
1683+
;;
1684+
'$' )
1685+
if [[ $arg[i+1] == $'\x28' ]]; then
1686+
saved_reply=($reply)
1687+
if [[ $arg[i+2] == $'\x28' ]] && _zsh_highlight_main_highlighter_highlight_arithmetic $i; then
1688+
# Arithmetic substitution
1689+
(( i = REPLY ))
1690+
reply=($saved_reply $reply)
1691+
continue
1692+
fi
1693+
1694+
(( i += 2 ))
1695+
_zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,end_pos]
1696+
ret=$?
1697+
(( i += REPLY ))
1698+
reply=(
1699+
$saved_reply
1700+
$j $(( start_pos + i )) command-substitution-quoted
1701+
$j $(( j + 2 )) command-substitution-delimiter-quoted
1702+
$reply
1703+
)
1704+
if (( ret == 0 )); then
1705+
reply+=($(( start_pos + i - 1 )) $(( start_pos + i )) command-substitution-delimiter)
1706+
fi
1707+
continue
1708+
else
1709+
continue
1710+
fi
1711+
;;
1712+
($histchars[1]) # ! - may be a history expansion
1713+
if [[ $arg[i+1] != ('='|$'\x28'|$'\x7b'|[[:blank:]]) ]]; then
1714+
style=history-expansion
1715+
else
1716+
continue
1717+
fi
1718+
;;
1719+
*)
1720+
continue
1721+
;;
1722+
1723+
esac
1724+
reply+=($j $k $style)
1725+
done
1726+
1727+
if [[ $arg[i,i+1] == '))' ]]; then
1728+
style=arithmetic-expansion
1729+
(( i++ ))
1730+
else
1731+
# If unclosed, i points past the end
1732+
(( i-- ))
1733+
style=arithmetic-expansion-unclosed
1734+
fi
1735+
reply=($(( start_pos + $1 - 1)) $(( start_pos + i )) $style $reply)
1736+
REPLY=$i
1737+
}
1738+
1739+
16351740
# Called with a single positional argument.
16361741
# Perform filename expansion (tilde expansion) on the argument and set $REPLY to the expanded value.
16371742
#

highlighters/main/test-data/arith-cmdsubst-mess.zsh

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ BUFFER=$': $((ls); (ls))'
3333
expected_region_highlight=(
3434
'1 1 builtin' # :
3535
'3 15 default' # $((ls); (ls))
36-
'3 15 command-substitution-unquoted "issue #704"' # $((ls); (ls))
37-
'3 4 command-substitution-delimiter-unquoted "issue #704"' # $(
38-
'5 5 reserved-word "issue #704"' # (
39-
'6 7 command "issue #704"' # ls
40-
'8 8 reserved-word "issue #704"' # )
41-
'9 9 commandseparator "issue #704"' # ;
42-
'11 11 reserved-word "issue #704"' # (
43-
'12 13 command "issue #704"' # ls
44-
'14 14 reserved-word "issue #704"' # )
45-
'15 15 command-substitution-delimiter-unquoted "issue #704"' # )
36+
'3 15 command-substitution-unquoted' # $((ls); (ls))
37+
'3 4 command-substitution-delimiter-unquoted' # $(
38+
'5 5 reserved-word' # (
39+
'6 7 command' # ls
40+
'8 8 reserved-word' # )
41+
'9 9 commandseparator' # ;
42+
'11 11 reserved-word' # (
43+
'12 13 command' # ls
44+
'14 14 reserved-word' # )
45+
'15 15 command-substitution-delimiter-unquoted' # )
4646
)

highlighters/main/test-data/arith2.zsh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@ expected_region_highlight=(
3434
'1 1 builtin' # :
3535
'3 16 default' # "$(( 6 * 9 ))"
3636
'3 16 double-quoted-argument' # "$(( 6 * 9 ))"
37+
'4 15 arithmetic-expansion' # $(( 6 * 9 ))
3738
)

0 commit comments

Comments
 (0)