From e86f75a840e739652b337729c14d16c2f5f71553 Mon Sep 17 00:00:00 2001 From: Matthew Martin Date: Sat, 14 Apr 2018 14:00:03 -0500 Subject: [PATCH] main: Highlight {command,process} substitution delimiters --- docs/highlighters/main.md | 3 + highlighters/main/main-highlighter.zsh | 74 +++++++++++++++---- .../main/test-data/back-quoted-argument.zsh | 7 ++ .../command-substitution-in-assignment.zsh | 2 + .../command-substitution-unclosed.zsh | 1 + highlighters/main/test-data/cthulhu.zsh | 8 ++ highlighters/main/test-data/dollar-paren.zsh | 2 + ...substitution-redirection-isnt-globbing.zsh | 2 + .../main/test-data/process-substitution.zsh | 2 + .../main/test-data/process-substitution2.zsh | 5 +- .../test-data/redirection-in-cmdsubst.zsh | 2 + highlighters/main/test-data/redirection2.zsh | 2 + 12 files changed, 95 insertions(+), 15 deletions(-) diff --git a/docs/highlighters/main.md b/docs/highlighters/main.md index af7815e..188da07 100644 --- a/docs/highlighters/main.md +++ b/docs/highlighters/main.md @@ -33,11 +33,14 @@ This highlighter defines the following styles: * `globbing` - globbing expressions (`*.txt`) * `history-expansion` - history expansion expressions (`!foo` and `^foo^bar`) * `command-substitution` - command substitutions (`$(echo foo)`) +* `command-substitution-delimiter` - command substitution delimiters (`$(` and `)`) * `process-substitution` - process substitutions (`<(echo foo)`) +* `process-substitution-delimiter` - process substitution delimiters (`<(` and `)`) * `single-hyphen-option` - single-hyphen options (`-o`) * `double-hyphen-option` - double-hyphen options (`--option`) * `back-quoted-argument` - backtick command substitution (`` `foo` ``) * `back-quoted-argument-unclosed` - unclosed backtick command substitution (`` `foo ``) +* `back-quoted-argument-delimiter` - backtick command substitution delimiters (`` ` ``) * `single-quoted-argument` - single-quoted arguments (`` 'foo' ``) * `single-quoted-argument-unclosed` - unclosed single-quoted arguments (`` 'foo ``) * `double-quoted-argument` - double-quoted arguments (`` "foo" ``) diff --git a/highlighters/main/main-highlighter.zsh b/highlighters/main/main-highlighter.zsh index cce0317..5f23357 100644 --- a/highlighters/main/main-highlighter.zsh +++ b/highlighters/main/main-highlighter.zsh @@ -40,11 +40,14 @@ : ${ZSH_HIGHLIGHT_STYLES[path_prefix_pathseparator]:=} : ${ZSH_HIGHLIGHT_STYLES[globbing]:=fg=blue} : ${ZSH_HIGHLIGHT_STYLES[history-expansion]:=fg=blue} -: ${ZSH_HIGHLIGHT_STYLES[command-substitution]:=fg=magenta} -: ${ZSH_HIGHLIGHT_STYLES[process-substitution]:=fg=magenta} +: ${ZSH_HIGHLIGHT_STYLES[command-substitution]:=none} +: ${ZSH_HIGHLIGHT_STYLES[command-substitution-delimiter]:=fg=magenta} +: ${ZSH_HIGHLIGHT_STYLES[process-substitution]:=none} +: ${ZSH_HIGHLIGHT_STYLES[process-substitution-delimiter]:=fg=magenta} : ${ZSH_HIGHLIGHT_STYLES[single-hyphen-option]:=none} : ${ZSH_HIGHLIGHT_STYLES[double-hyphen-option]:=none} : ${ZSH_HIGHLIGHT_STYLES[back-quoted-argument]:=none} +: ${ZSH_HIGHLIGHT_STYLES[back-quoted-argument-delimiter]:=fg=magenta} : ${ZSH_HIGHLIGHT_STYLES[single-quoted-argument]:=fg=yellow} : ${ZSH_HIGHLIGHT_STYLES[double-quoted-argument]:=fg=yellow} : ${ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]:=fg=yellow} @@ -103,6 +106,10 @@ _zsh_highlight_main_calculate_fallback() { double-quoted-argument{-unclosed,} dollar-quoted-argument{-unclosed,} back-quoted-argument{-unclosed,} + + command-substitution{-delimiter,} + process-substitution{-delimiter,} + back-quoted-argument{-delimiter,} ) local needle=$1 value reply=($1) @@ -853,7 +860,7 @@ _zsh_highlight_main_highlighter_check_path() # This command will at least highlight $1 to end_pos with the default style _zsh_highlight_main_highlighter_highlight_argument() { - local base_style=default i=$1 path_eligible=1 start style + local base_style=default i=$1 path_eligible=1 ret start style local -a highlights local -a match mbegin mend @@ -872,8 +879,16 @@ _zsh_highlight_main_highlighter_highlight_argument() if [[ $arg[i+1] == $'\x28' ]]; then (( i += 2 )) _zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,end_pos] + ret=$? (( i += REPLY )) - highlights+=($(( start_pos + $1 - 1 )) $(( start_pos + i )) process-substitution $reply) + highlights+=( + $(( start_pos + $1 - 1 )) $(( start_pos + i )) process-substitution + $(( start_pos + $1 - 1 )) $(( start_pos + $1 + 1 )) process-substitution-delimiter + $reply + ) + if (( ret == 0 )); then + highlights+=($(( start_pos + i - 1 )) $(( start_pos + i )) process-substitution-delimiter) + fi fi esac @@ -907,8 +922,16 @@ _zsh_highlight_main_highlighter_highlight_argument() start=$i (( i += 2 )) _zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,end_pos] + ret=$? (( i += REPLY )) - highlights+=($(( start_pos + start - 1)) $(( start_pos + i )) command-substitution $reply) + highlights+=( + $(( start_pos + start - 1)) $(( start_pos + i )) command-substitution + $(( start_pos + start - 1)) $(( start_pos + start + 1)) command-substitution-delimiter + $reply + ) + if (( ret == 0 )); then + highlights+=($(( start_pos + i - 1)) $(( start_pos + i )) command-substitution-delimiter) + fi continue fi while [[ $arg[i+1] == [\^=~#+] ]]; do @@ -922,8 +945,16 @@ _zsh_highlight_main_highlighter_highlight_argument() start=$i (( i += 2 )) _zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,end_pos] + ret=$? (( i += REPLY )) - highlights+=($(( start_pos + start - 1)) $(( start_pos + i )) process-substitution $reply) + highlights+=( + $(( start_pos + start - 1)) $(( start_pos + i )) process-substitution + $(( start_pos + start - 1)) $(( start_pos + start + 1 )) process-substitution-delimiter + $reply + ) + if (( ret == 0 )); then + highlights+=($(( start_pos + i - 1)) $(( start_pos + i )) process-substitution-delimiter) + fi continue fi ;| @@ -988,7 +1019,7 @@ _zsh_highlight_main_highlighter_highlight_double_quote() { local -a match mbegin mend saved_reply local MATCH; integer MBEGIN MEND - local i j k style + local i j k ret style reply=() for (( i = $1 + 1 ; i <= end_pos - start_pos ; i += 1 )) ; do @@ -1022,8 +1053,17 @@ _zsh_highlight_main_highlighter_highlight_double_quote() (( i += 2 )) saved_reply=($reply) _zsh_highlight_main_highlighter_highlight_list $(( start_pos + i - 1 )) S $has_end $arg[i,end_pos] + ret=$? (( i += REPLY )) - reply=($saved_reply $j $(( start_pos + i )) command-substitution $reply) + reply=( + $saved_reply + $j $(( start_pos + i )) command-substitution + $j $(( j + 2 )) command-substitution-delimiter + $reply + ) + if (( ret == 0 )); then + reply+=($(( start_pos + i - 1 )) $(( start_pos + i )) command-substitution-delimiter) + fi continue else continue @@ -1124,11 +1164,9 @@ _zsh_highlight_main_highlighter_highlight_backtick() # 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 buf highlight style=back-quoted-argument-unclosed style_end local -i arg1=$1 end_ i=$1 last offset=0 start subshell_has_end=0 - local -a highlight_zone highlights offsets unclosed + local -a highlight_zone highlights offsets reply=() last=$(( arg1 + 1 )) @@ -1155,6 +1193,7 @@ _zsh_highlight_main_highlighter_highlight_backtick() fi else # it's an unquoted ` and this is the end style=back-quoted-argument + style_end=back-quoted-argument-delimiter buf=$buf$arg[last,i-1] offsets[i-arg1-offset]='' # So we never index past the end break @@ -1171,11 +1210,18 @@ _zsh_highlight_main_highlighter_highlight_backtick() 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) + style_end=unknown-token fi done - reply=($(( start_pos + arg1 - 1 )) $(( start_pos + i )) $style $highlights $unclosed) + reply=( + $(( start_pos + arg1 - 1 )) $(( start_pos + i )) $style + $(( start_pos + arg1 - 1 )) $(( start_pos + arg1 )) back-quoted-argument-delimiter + $highlights + ) + if (( $#style_end )); then + reply+=($(( start_pos + i - 1)) $(( start_pos + i )) $style_end) + fi REPLY=$i } diff --git a/highlighters/main/test-data/back-quoted-argument.zsh b/highlighters/main/test-data/back-quoted-argument.zsh index 8b13729..d504a2c 100644 --- a/highlighters/main/test-data/back-quoted-argument.zsh +++ b/highlighters/main/test-data/back-quoted-argument.zsh @@ -33,17 +33,24 @@ expected_region_highlight=( "1 4 builtin" # echo "6 18 default" # `echo \`42\`` "6 18 back-quoted-argument" # `echo \`42\`` + "6 6 back-quoted-argument-delimiter" # ` "7 10 builtin" # echo "12 17 default" # \`42\` "12 17 back-quoted-argument" # \`42\` + "12 13 back-quoted-argument-delimiter" # \` "14 15 unknown-token" # 42 + "16 17 back-quoted-argument-delimiter" # \` + "18 18 back-quoted-argument-delimiter" # ` "20 39 default" # "is `echo equal` to" "20 39 double-quoted-argument" # "is `echo equal` to" "24 35 back-quoted-argument" # `echo equal` + "24 24 back-quoted-argument-delimiter" # ` "25 28 builtin" # echo "30 34 default" # equal + "35 35 back-quoted-argument-delimiter" # ` "41 55 default" # `echo 6 times 9 "41 55 back-quoted-argument-unclosed" # `echo 6 times 9 + "41 41 back-quoted-argument-delimiter" # ` "42 45 builtin" # echo "47 47 default" # 6 "49 53 default" # times diff --git a/highlighters/main/test-data/command-substitution-in-assignment.zsh b/highlighters/main/test-data/command-substitution-in-assignment.zsh index db82b7c..010df7f 100644 --- a/highlighters/main/test-data/command-substitution-in-assignment.zsh +++ b/highlighters/main/test-data/command-substitution-in-assignment.zsh @@ -34,7 +34,9 @@ expected_region_highlight=( '1 15 assign' # foo=$(echo bar) '5 15 default' # $(echo bar) '5 15 command-substitution' # $(echo bar) + '5 6 command-substitution-delimiter' # $( '7 10 builtin' # echo '12 14 default' # bar + '15 15 command-substitution-delimiter' # ) '17 17 builtin' # : ) diff --git a/highlighters/main/test-data/command-substitution-unclosed.zsh b/highlighters/main/test-data/command-substitution-unclosed.zsh index 198e710..570471b 100644 --- a/highlighters/main/test-data/command-substitution-unclosed.zsh +++ b/highlighters/main/test-data/command-substitution-unclosed.zsh @@ -34,6 +34,7 @@ expected_region_highlight=( '1 1 builtin' # : '3 15 default' # foo$(echo bar '6 15 command-substitution' # $(echo bar + '6 7 command-substitution-delimiter' # $( '8 11 builtin' # echo '13 15 default' # bar ) diff --git a/highlighters/main/test-data/cthulhu.zsh b/highlighters/main/test-data/cthulhu.zsh index 0350640..7a1b7f1 100644 --- a/highlighters/main/test-data/cthulhu.zsh +++ b/highlighters/main/test-data/cthulhu.zsh @@ -36,27 +36,35 @@ expected_region_highlight=( '1 4 builtin' # echo '6 113 default' # Ph\'ng`echo lui "mg"\`echo lw\'nafh \\\`echo Cthu"lhu\\\` R\\'ly$(echo eh wag\\\`echo h\'nag\\\`'l' fht)agn` '12 113 back-quoted-argument' # `echo lui "mg"\`echo lw\'nafh \\\`echo Cthu"lhu\\\` R\\'ly$(echo eh wag\\\`echo h\'nag\\\`'l' fht)agn` + '12 12 back-quoted-argument-delimiter' # ` '13 16 builtin' # echo '18 20 default' # lui '22 112 default' # "mg"\`echo lw\'nafh \\\`echo Cthu"lhu\\\` R\\'ly$(echo eh wag\\\`echo h\'nag\\\`'l' fht)agn '22 25 double-quoted-argument' # "mg" '26 112 back-quoted-argument-unclosed' # \`echo lw\'nafh \\\`echo Cthu"lhu\\\` R\\'ly$(echo eh wag\\\`echo h\'nag\\\`'l' fht)agn + '26 27 back-quoted-argument-delimiter' # \` '28 31 builtin' # echo '33 40 default' # lw\'nafh '42 62 default' # \\\`echo Cthu"lhu\\\` '42 62 back-quoted-argument' # \\\`echo Cthu"lhu\\\` + '42 45 back-quoted-argument-delimiter' # \\\` '46 49 builtin' # echo '51 58 default' # Cthu"lhu '55 58 double-quoted-argument-unclosed' # "lhu + '59 62 back-quoted-argument-delimiter' # \\\` '64 112 default' # R\\'ly$(echo eh wag\\\`echo h\'nag\\\`'l' fht)agn '70 109 command-substitution' # $(echo eh wag\\\`echo h\'nag\\\`'l' fht) + '70 71 command-substitution-delimiter' # $( '72 75 builtin' # echo '77 78 default' # eh '80 104 default' # wag\\\`echo h\'nag\\\`'l' '83 101 back-quoted-argument' # \\\`echo h\'nag\\\` + '83 86 back-quoted-argument-delimiter' # \\\` '87 90 builtin' # echo '92 97 default' # h\'nag + '98 101 back-quoted-argument-delimiter' # \\\` '102 104 single-quoted-argument' # 'l' '106 108 default' # fht + '109 109 command-substitution-delimiter' # ) '113 113 unknown-token' # ` ) diff --git a/highlighters/main/test-data/dollar-paren.zsh b/highlighters/main/test-data/dollar-paren.zsh index c64a764..f051e4a 100644 --- a/highlighters/main/test-data/dollar-paren.zsh +++ b/highlighters/main/test-data/dollar-paren.zsh @@ -35,5 +35,7 @@ expected_region_highlight=( '3 8 default' # "$(:)" '3 8 double-quoted-argument' # "$(:)" '4 7 command-substitution' # $(:) + '4 5 command-substitution-delimiter' # $( '6 6 builtin' # : + '7 7 command-substitution-delimiter' # ) ) diff --git a/highlighters/main/test-data/process-substitution-redirection-isnt-globbing.zsh b/highlighters/main/test-data/process-substitution-redirection-isnt-globbing.zsh index d5de3fd..f8dbd6b 100644 --- a/highlighters/main/test-data/process-substitution-redirection-isnt-globbing.zsh +++ b/highlighters/main/test-data/process-substitution-redirection-isnt-globbing.zsh @@ -34,6 +34,8 @@ expected_region_highlight=( '1 1 builtin' # : '3 9 default' # =((wc) "4 8 process-substitution" # >(wc) + "4 5 process-substitution-delimiter" # >( "6 7 command" # wc + "8 8 process-substitution-delimiter" # ) "10 10 commandseparator" # | "12 13 command" # nl )