runtime(vim): Update syntax file, improve :substitute matching (#14093)
Commit:
https://github.com/vim/vim/commit/2c51e15b66a4be9b5134c495ef546479aaa89ce9
Author: dkearns <[email protected]>
Date: Tue Feb 27 07:10:18 2024 +1100
runtime(vim): Update syntax file, improve :substitute matching
(https://github.com/vim/vim/issues/14093)
- Differentiate between :substitute and substitute(), fixes
https://github.com/vim/vim/issues/13883.
- Match all allowed :substitute delimiters.
- Remove leading context from :substitute matches.
Signed-off-by: Doug Kearns <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
diff --git a/runtime/syntax/generator/vim.vim.base
b/runtime/syntax/generator/vim.vim.base
index 99a0488b3..6527fe178 100644
--- a/runtime/syntax/generator/vim.vim.base
+++ b/runtime/syntax/generator/vim.vim.base
@@ -157,16 +157,16 @@ endif
" Numbers {{{2
" =======
-syn match vimNumber '\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '-\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '\<0[xX]\x\+' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '\%(^\|\A\)\zs#\x\{6}'
skipwhite nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '\<0[zZ][a-zA-Z0-9.]\+' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '0[0-7]\+' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '0[bB][01]\+' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '-\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\<0[xX]\x\+' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\%(^\|\A\)\zs#\x\{6}'
skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\<0[zZ][a-zA-Z0-9.]\+' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '0[0-7]\+' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '0[bB][01]\+' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
" All vimCommands are contained by vimIsCommand. {{{2
-syn match vimCmdSep "[:|]\+" skipwhite
nextgroup=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimEcho,vimEchoHL,vimExecute,vimIsCommand,vimExtCmd,vimFilter,vimGlobal,vimHighlight,vimLet,vimMap,vimMark,vimNorm,vimSet,vimSyntax,vimUnlet,vimUnmap,vimUserCmd
+syn match vimCmdSep "[:|]\+" skipwhite
nextgroup=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimEcho,vimEchoHL,vimExecute,vimIsCommand,vimExtCmd,vimFilter,vimGlobal,vimHighlight,vimLet,vimMap,vimMark,vimNorm,vimSet,vimSubst1,vimSyntax,vimUnlet,vimUnmap,vimUserCmd
syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand
syn match vimVar contained "\<\h[a-zA-Z0-9#_]*\>"
syn match vimVar "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>"
@@ -194,7 +194,6 @@ syn match vimBehave "\<be\%[have]\>"
nextgroup=vimBehaveBang,vimBehaveModel,vi
syn match vimBehaveBang contained " \@1<=!"
nextgroup=vimBehaveModel skipwhite
syn keyword vimBehaveModel contained mswin xterm
-hi def link vimBehaveBang vimBang
" Filetypes {{{2
" =========
syn match vimFiletype "\<filet\%[ype]\(\s\+\I\i*\)*" skipwhite
contains=vimFTCmd,vimFTOption,vimFTError
@@ -270,12 +269,12 @@ syn region vimKeymap matchgroup=vimCommand
start="\<loadk\%[eymap]\>" end="\%$"
" Special Filenames, Modifiers, Extension Removal: {{{2
" ===============================================
-syn match vimSpecFile "<c\(word\|WORD\)>"
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "<\([acs]file\|amatch\|abuf\)>"
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "\s%[ :]"ms=s+1,me=e-1
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "\s%$"ms=s+1
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "\s%<"ms=s+1,me=e-1
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "#\d\+\|[#%]<\>"
nextgroup=vimSpecFileMod,vimSubst
+syn match vimSpecFile "<c\(word\|WORD\)>"
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "<\([acs]file\|amatch\|abuf\)>"
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "\s%[ :]"ms=s+1,me=e-1
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "\s%$"ms=s+1
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "\s%<"ms=s+1,me=e-1
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "#\d\+\|[#%]<\>"
nextgroup=vimSpecFileMod,vimSubst1
syn match vimSpecFileMod "\(:[phtre]\)\+" contained
" User-Specified Commands: {{{2
@@ -356,33 +355,34 @@ syn match vimStringInterpolationBrace "}}"
syn cluster vimSubstList
contains=vimPatSep,vimPatRegion,vimPatSepErr,vimSubstTwoBS,vimSubstRange,vimNotation
syn cluster vimSubstRepList
contains=vimSubstSubstr,vimSubstTwoBS,vimNotation
syn cluster vimSubstList add=vimCollection
-syn match vimSubst
"\(:\+\s*\|^\s*\||\s*\)\<\%(\<s\%[ubstitute]\>\|\<sm\%[agic]\>\|\<sno\%[magic]\>\)[:#[:alpha:]]\@!"
nextgroup=vimSubstPat
-"syn match vimSubst
"\%(^\|[^\]\)\<s\%[ubstitute]\>[:#[:alpha:]]\@!" nextgroup=vimSubstPat
contained
-syn match vimSubst
"\%(^\|[^\\"']\)\<s\%[ubstitute]\>[:#[:alpha:]\"']\@!" nextgroup=vimSubstPat
contained
-syn match vimSubst "/\zs\<s\%[ubstitute]\>\ze/"
nextgroup=vimSubstPat
-syn match vimSubst "\(:\+\s*\|^\s*\)s\ze#.\{-}#.\{-}#"
nextgroup=vimSubstPat
-syn match vimSubst1 contained "\<s\%[ubstitute]\>"
nextgroup=vimSubstPat
-syn match vimSubst2 contained "s\%[ubstitute]\>"
nextgroup=vimSubstPat
-syn region vimSubstPat contained matchgroup=vimSubstDelim
start="\z([^a-zA-Z( [\]&]\)"rs=s+1 skip="\\\|\\z1" end="\z1"re=e-1,me=e-1
contains=@vimSubstList nextgroup=vimSubstRep4 oneline
-syn region vimSubstRep4 contained matchgroup=vimSubstDelim
start="\z(.\)" skip="\\\|\\z1" end="\z1" matchgroup=vimNotation
end="<[cC][rR]>" contains=@vimSubstRepList nextgroup=vimSubstFlagErr
oneline
-syn region vimCollection contained transparent start="\\@<!\["
skip="\\[" end="\]" contains=vimCollClass
-syn match vimCollClassErr contained "\[:.\{-\}:\]"
-syn match vimCollClass contained transparent
"\%#=1\[:\(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\|retu\%[rn]\|tab\|escape\|backspace\):\]"
-syn match vimSubstSubstr contained "\z\=\d"
-syn match vimSubstTwoBS contained "\\"
-syn match vimSubstFlagErr contained "[^<
|]\+" contains=vimSubstFlags
-syn match vimSubstFlags contained "[&cegiIlnpr#]\+"
+syn match vimSubst
"^\s*\%(s\%[ubstitute]\|sm\%[agic]\|sno\%[magic]\)\>[\"#|]\@!"
nextgroup=vimSubstPat
+syn match vimSubst
"^\s*\%(s\%[ubstitute]\|sm\%[agic]\|sno\%[magic]\)_\@=" nextgroup=vimSubstPat
+syn match vimSubst
"^\s*\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)\ze#.\{-}#.\{-}#"
nextgroup=vimSubstPat
+syn match vimSubst1 contained
"\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)\>[\"#|]\@!"
nextgroup=vimSubstPat
+syn match vimSubst1 contained
"\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)_\@="
nextgroup=vimSubstPat
+syn match vimSubst1 contained
"\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)\ze#.\{-}#.\{-}#"
nextgroup=vimSubstPat
+" TODO: Vim9 illegal separators for abbreviated :s form are [-.:], :su\%[...]
required
+" : # is allowed but "not recommended" (see :h pattern-delimiter)
+syn region vimSubstPat contained matchgroup=vimSubstDelim
start="\z([!#$%&'()*+,-./:;<=>?@[\]^_`{}~]\)"rs=s+1 skip="\\\|\\z1"
end="\z1"re=e-1,me=e-1 contains=@vimSubstList nextgroup=vimSubstRep4
oneline
+syn region vimSubstRep4 contained matchgroup=vimSubstDelim
start="\z(.\)" skip="\\\|\\z1" end="\z1" matchgroup=vimNotation
end="<[cC][rR]>" contains=@vimSubstRepList
nextgroup=vimSubstFlagErr oneline
+syn region vimCollection contained transparent start="\\@<!\["
skip="\\[" end="\]" contains=vimCollClass
+syn match vimCollClassErr contained "\[:.\{-\}:\]"
+syn match vimCollClass contained transparent
"\%#=1\[:\(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\|retu\%[rn]\|tab\|escape\|backspace\):\]"
+syn match vimSubstSubstr contained "\z\=\d"
+syn match vimSubstTwoBS contained "\\"
+syn match vimSubstFlagErr contained "[^<
|]\+" contains=vimSubstFlags
+syn match vimSubstFlags contained "[&cegiIlnpr#]\+"
" 'String': {{{2
syn match vimString "[^(,]'[^']\{-}\zs'"
" Marks, Registers, Addresses, Filters: {{{2
-syn match vimMark "'[a-zA-Z0-9]\ze[-+,!]"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark "'[<>]\ze[-+,!]"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark ",\zs'[<>]\ze"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark "[!,:]\zs'[a-zA-Z0-9]"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark "\<norm\%[al]\s\zs'[a-zA-Z0-9]"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMarkNumber "[-+]\d\+" contained
contains=vimOper nextgroup=vimSubst2
+syn match vimMark "'[a-zA-Z0-9]\ze[-+,!]"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark "'[<>]\ze[-+,!]"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark ",\zs'[<>]\ze"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark "[!,:]\zs'[a-zA-Z0-9]"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark "\<norm\%[al]\s\zs'[a-zA-Z0-9]"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMarkNumber "[-+]\d\+" contained
contains=vimOper nextgroup=vimSubst1
syn match vimPlainMark contained "'[a-zA-Z0-9]"
syn match vimRange "[`'][a-zA-Z0-9],[`'][a-zA-Z0-9]"
contains=vimMark skipwhite nextgroup=vimFilter
@@ -713,8 +713,8 @@ syn match vimCommentTitleLeader '"\s\+'ms=s+1
contained
" ====================
syn match vimSearch '^\s*[/?].*' contains=vimSearchDelim
syn match vimSearchDelim '^\s*\zs[/?]\|[/?]$' contained
-syn region vimGlobal matchgroup=Statement start='\<g\%[lobal]!\=/'
skip='\.' end='/' skipwhite nextgroup=vimSubst
-syn region vimGlobal matchgroup=Statement start='\<v\%[global]!\=/'
skip='\.' end='/' skipwhite nextgroup=vimSubst
+syn region vimGlobal matchgroup=Statement start='\<g\%[lobal]!\=/'
skip='\.' end='/' skipwhite nextgroup=vimSubst1
+syn region vimGlobal matchgroup=Statement start='\<v\%[global]!\=/'
skip='\.' end='/' skipwhite nextgroup=vimSubst1
" Embedded Scripts: {{{2
" ================
@@ -934,7 +934,7 @@ if !exists("skip_vim_syntax_inits")
hi def link vimAutoCmdMod Special
hi def link vimAutoSet vimCommand
hi def link vimBang vimOper
- hi def link vimBehaveBang vimBang
+ hi def link vimBehaveBang vimBang
hi def link vimBehaveModel vimBehave
hi def link vimBehave vimCommand
hi def link vimBracket Delimiter
diff --git a/runtime/syntax/testdir/dumps/vim_ex_commands_23.dump
b/runtime/syntax/testdir/dumps/vim_ex_commands_23.dump
index d75c4b008..6baf838d1 100644
--- a/runtime/syntax/testdir/dumps/vim_ex_commands_23.dump
+++ b/runtime/syntax/testdir/dumps/vim_ex_commands_23.dump
@@ -15,6 +15,6 @@
|:|r+0#af5f00255&|u|n|d|o| +0#0000000&@68
|:|r+0#af5f00255&|u|n|t|i|m|e| +0#0000000&@66
|:|r+0#af5f00255&|v|i|m|i|n|f|o| +0#0000000&@65
-|:+0#af5f00255&|s|u|b|s|t|i|t|u|t|e| +0#0000000&@63
+|:|s+0#af5f00255&|u|b|s|t|i|t|u|t|e| +0#0000000&@63
|:|s+0#af5f00255&|N|e|x|t| +0#0000000&@68
@57|4|1|5|,|1| @8|3|4|%|
diff --git a/runtime/syntax/testdir/dumps/vim_ex_commands_25.dump
b/runtime/syntax/testdir/dumps/vim_ex_commands_25.dump
index 746b0d80a..6b40f2cac 100644
--- a/runtime/syntax/testdir/dumps/vim_ex_commands_25.dump
+++ b/runtime/syntax/testdir/dumps/vim_ex_commands_25.dump
@@ -11,7 +11,7 @@
|:|s+0#af5f00255&|l|e@1|p| +0#0000000&@68
|:|s+0#af5f00255&|l|e@1|p|!| +0#0000000&@67
|:|s+0#af5f00255&|l|a|s|t| +0#0000000&@68
-|:+0#af5f00255&|s|m|a|g|i|c| +0#0000000&@67
+|:|s+0#af5f00255&|m|a|g|i|c| +0#0000000&@67
|:|s+0#af5f00255&|m|a|p| +0#0000000&@69
|:|s+0#af5f00255&|m|a|p|c|l|e|a|r| +0#0000000&@64
|:|s+0#af5f00255&|m|e|n|u| +0#0000000&@68
diff --git a/runtime/syntax/testdir/dumps/vim_ex_commands_26.dump
b/runtime/syntax/testdir/dumps/vim_ex_commands_26.dump
index db27187c1..f388e4fe3 100644
--- a/runtime/syntax/testdir/dumps/vim_ex_commands_26.dump
+++ b/runtime/syntax/testdir/dumps/vim_ex_commands_26.dump
@@ -1,5 +1,5 @@
|:+0&#ffffff0|s+0#af5f00255&|n|e|x|t| +0#0000000&@68
-|:+0#af5f00255&|s|n|o|m|a|g|i|c| +0#0000000&@65
+|:|s+0#af5f00255&|n|o|m|a|g|i|c| +0#0000000&@65
|:|s+0#af5f00255&|n|o|r|e|m|a|p| +0#0000000&@65
|:|s+0#af5f00255&|n|o|r|e|m|e|n|u| +0#0000000&@64
|:|s+0#af5f00255&|o|r|t| +0#0000000&@69
diff --git a/runtime/syntax/testdir/dumps/vim_ex_commands_56.dump
b/runtime/syntax/testdir/dumps/vim_ex_commands_56.dump
index 89b1df7a4..ba5754108 100644
--- a/runtime/syntax/testdir/dumps/vim_ex_commands_56.dump
+++ b/runtime/syntax/testdir/dumps/vim_ex_commands_56.dump
@@ -15,6 +15,6 @@
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|r+0#af5f00255&|u|n|d|o| +0#0000000&@56
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|r+0#af5f00255&|u|n|t|i|m|e| +0#0000000&@54
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|r+0#af5f00255&|v|i|m|i|n|f|o| +0#0000000&@53
-|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)|
+0#0000000&||+0#af5f00255&| |s|u|b|s|t|i|t|u|t|e| +0#0000000&@51
+|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|u|b|s|t|i|t|u|t|e| +0#0000000&@51
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|N|e|x|t| +0#0000000&@56
@57|1|0@1|9|,|1| @7|8|5|%|
diff --git a/runtime/syntax/testdir/dumps/vim_ex_commands_58.dump
b/runtime/syntax/testdir/dumps/vim_ex_commands_58.dump
index 28f0d8918..1d24fd510 100644
--- a/runtime/syntax/testdir/dumps/vim_ex_commands_58.dump
+++ b/runtime/syntax/testdir/dumps/vim_ex_commands_58.dump
@@ -11,7 +11,7 @@
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|l|e@1|p| +0#0000000&@56
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|l|e@1|p|!| +0#0000000&@55
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|l|a|s|t| +0#0000000&@56
-|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)|
+0#0000000&||+0#af5f00255&| |s|m|a|g|i|c| +0#0000000&@55
+|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|m|a|g|i|c| +0#0000000&@55
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|m|a|p| +0#0000000&@57
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|m|a|p|c|l|e|a|r| +0#0000000&@52
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|m|e|n|u| +0#0000000&@56
diff --git a/runtime/syntax/testdir/dumps/vim_ex_commands_59.dump
b/runtime/syntax/testdir/dumps/vim_ex_commands_59.dump
index d346f93a5..920861c52 100644
--- a/runtime/syntax/testdir/dumps/vim_ex_commands_59.dump
+++ b/runtime/syntax/testdir/dumps/vim_ex_commands_59.dump
@@ -1,5 +1,5 @@
|c+0#af5f00255#ffffff0|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|n|e|x|t| +0#0000000&@56
-|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)|
+0#0000000&||+0#af5f00255&| |s|n|o|m|a|g|i|c| +0#0000000&@53
+|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|n|o|m|a|g|i|c| +0#0000000&@53
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|n|o|r|e|m|a|p| +0#0000000&@53
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|n|o|r|e|m|e|n|u| +0#0000000&@52
|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|o|r|t| +0#0000000&@57
diff --git a/runtime/syntax/testdir/dumps/vim_ex_substitute_00.dump
b/runtime/syntax/testdir/dumps/vim_ex_substitute_00.dump
new file mode 100644
index 000000000..31094c952
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_substitute_00.dump
@@ -0,0 +1,20 @@
+>s+0#af5f00255#ffffff0|u|b|s|t|i|t|u|t|e|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@54
+|s+0#af5f00255&|u|b|s|t|i|t|u|t|e|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@45
+@75
+|s+0#af5f00255&|n|o|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@56
+|s+0#af5f00255&|n|o|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@47
+@75
+|s+0#af5f00255&|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@58
+|s+0#af5f00255&|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@49
+@75
+|:|s+0#af5f00255&|u|b|s|t|i|t|u|t|e|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@53
+|:|s+0#af5f00255&|u|b|s|t|i|t|u|t|e|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@44
+@75
+|:|s+0#af5f00255&|n|o|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@55
+|:|s+0#af5f00255&|n|o|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@46
+@75
+|:|s+0#af5f00255&|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@57
+|:|s+0#af5f00255&|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@48
+@75
+|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|u|b|s|t|i|t|u|t|e|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@41
+|"|i|n|p|u|t|/|v|i|m|_|e|x|_|s|u|b|s|t|i|t|u|t|e|.|v|i|m|"| |8|6|L|,|
|1|5|1|0|B| @16|1|,|1| @10|T|o|p|
diff --git a/runtime/syntax/testdir/dumps/vim_ex_substitute_01.dump
b/runtime/syntax/testdir/dumps/vim_ex_substitute_01.dump
new file mode 100644
index 000000000..806101c29
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_substitute_01.dump
@@ -0,0 +1,20 @@
+|:+0&#ffffff0|s+0#af5f00255&|n|o|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@46
+@75
+|:|s+0#af5f00255&|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@57
+|:|s+0#af5f00255&|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@48
+@75
+>c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|u|b|s|t|i|t|u|t|e|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@41
+|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|u|b|s|t|i|t|u|t|e|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@32
+@75
+|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|n|o|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@43
+|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|n|o|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@34
+@75
+|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|&|
+0#0000000&@45
+|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&|||
|s+0#af5f00255&|m|a|g|i|c|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|c|e|g|i|I|n|p|#|l|r|
+0#0000000&@36
+@75
+|l+0#af5f00255&|e|t| +0#0000000&|f+0#00e0e07&|o@1| +0#0000000&|=+0#af5f00255&|
+0#0000000&|s|t|r|-+0#af5f00255&|>|s+0#00e0e07&|u|b|s|t|i|t|u|t|e|(+0#e000e06&|s+0#00e0e07&|t|r|,+0#0000000&|
|p+0#00e0e07&|a|t|,+0#0000000&| |s+0#00e0e07&|u|b|,+0#0000000&|
|f+0#00e0e07&|l|a|g|s|)+0#e000e06&| +0#0000000&@27
+@75
+|f+0#af5f00255&|u|n|c|t|i|o|n| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&@60
+|
+0#af5f00255&@1|s|u|b|s|t|i|t|u|t|e|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|
+0#0000000&@53
+@2|l+0#af5f00255&|e|t| +0#0000000&|b+0#00e0e07&|a|r|
+0#0000000&|=+0#af5f00255&|
+0#0000000&|s|t|r|-+0#af5f00255&|>|s+0#00e0e07&|u|b|s|t|i|t|u|t|e|(+0#e000e06&|s+0#00e0e07&|t|r|,+0#0000000&|
|p+0#00e0e07&|a|t|,+0#0000000&| |s+0#00e0e07&|u|b|,+0#0000000&|
|f+0#00e0e07&|l|a|g|s|)+0#e000e06&| +0#0000000&@25
+@57|1|9|,|1| @9|1|9|%|
diff --git a/runtime/syntax/testdir/dumps/vim_ex_substitute_02.dump
b/runtime/syntax/testdir/dumps/vim_ex_substitute_02.dump
new file mode 100644
index 000000000..b0e722d26
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_substitute_02.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@1|l+0#af5f00255&|e|t| +0#0000000&|b+0#00e0e07&|a|r|
+0#0000000&|=+0#af5f00255&|
+0#0000000&|s|t|r|-+0#af5f00255&|>|s+0#00e0e07&|u|b|s|t|i|t|u|t|e|(+0#e000e06&|s+0#00e0e07&|t|r|,+0#0000000&|
|p+0#00e0e07&|a|t|,+0#0000000&| |s+0#00e0e07&|u|b|,+0#0000000&|
|f+0#00e0e07&|l|a|g|s|)+0#e000e06&| +0#0000000&@25
+|e+0#af5f00255&|n|d|f|u|n|c|t|i|o|n| +0#0000000&@63
+@75
+|d+0#af5f00255&|e|f| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&@65
+|
+0#af5f00255&@1|s|u|b|s|t|i|t|u|t|e|/+0#e000e06&|f+0#0000000&|o@1|/+0#e000e06&|b+0#0000000&|a|r|/+0#e000e06&|
+0#0000000&@53
+@2>l+0#af5f00255&|e|t| +0#0000000&|b+0#00e0e07&|a|r|
+0#0000000&|=+0#af5f00255&|
+0#0000000&|s|t|r|-+0#af5f00255&|>|s+0#00e0e07&|u|b|s|t|i|t|u|t|e|(+0#e000e06&|s+0#00e0e07&|t|r|,+0#0000000&|
|p+0#00e0e07&|a|t|,+0#0000000&| |s+0#00e0e07&|u|b|,+0#0000000&|
|f+0#00e0e07&|l|a|g|s|)+0#e000e06&| +0#0000000&@25
+|e+0#af5f00255&|n|d@1|e|f| +0#0000000&@68
+@75
+|"+0#0000e05&| |v|a|r|i|o|u|s| |d|e|l|i|m|i|t|e|r|s| +0#0000000&@54
+@75
+|s+0#af5f00255&|!+0#e000e06&|/+0#0000000&|!+0#e000e06&|/+0#0000000&@1|!+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|"+0#0000e05&| |s|"|/|"|/@1|"| |"| |c|o|m@1|e|n|t| |(|w|o|r|k|s| |b|u|t|
|d|i|s|a|l@1|o|w|e|d|)| +0#0000000&@32
+|s+0#af5f00255&|#+0#e000e06&|/+0#0000000&|#+0#e000e06&|/+0#0000000&@1|#+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|$+0#e000e06&|/+0#0000000&|$+0#e000e06&|/+0#0000000&@1|$+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|%+0#e000e06&|/+0#0000000&|%+0#e000e06&|/+0#0000000&@1|%+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|&+0#e000e06&|/+0#0000000&|&+0#e000e06&|/+0#0000000&@1|&+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|'+0#e000e06&|/+0#0000000&|'+0#e000e06&|/+0#0000000&@1|'+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|"+0#0000e05&| |F+0#0000001#ffff4012|I|X|M|E| +0#0000e05#ffffff0|-|
|m|a|t|c|h|e|s| |v|i|m|U|s|e|r|F|u|n|c| +0#0000000&@45
+|"+0#0000e05&| |s|(|/|(|/@1|(| |"| |c|o|m@1|e|n|t| +0#0000000&@55
+@57|3|7|,|3| @9|4|6|%|
diff --git a/runtime/syntax/testdir/dumps/vim_ex_substitute_03.dump
b/runtime/syntax/testdir/dumps/vim_ex_substitute_03.dump
new file mode 100644
index 000000000..cb12bb38a
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_substitute_03.dump
@@ -0,0 +1,20 @@
+|"+0#0000e05#ffffff0| |s|(|/|(|/@1|(| |"| |c|o|m@1|e|n|t| +0#0000000&@55
+|s+0#af5f00255&|)+0#e000e06&|/+0#0000000&|)+0#e000e06&|/+0#0000000&@1|)+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|*+0#e000e06&|/+0#0000000&|*+0#e000e06&|/+0#0000000&@1|*+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|++0#e000e06&|/+0#0000000&|++0#e000e06&|/+0#0000000&@1|++0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|,+0#e000e06&|/+0#0000000&|,+0#e000e06&|/+0#0000000&@1|,+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+>s+0#af5f00255&|-+0#e000e06&|/+0#0000000&|-+0#e000e06&|/+0#0000000&@1|-+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|.+0#e000e06&|/+0#0000000&|.+0#e000e06&|/+0#0000000&@1|.+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|/+0#e000e06&|X+0#0000000&|/+0#e000e06&|X+0#0000000&@1|/+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|:+0#e000e06&|/+0#0000000&|:+0#e000e06&|/+0#0000000&@1|:+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|;+0#e000e06&|/+0#0000000&|;+0#e000e06&|/+0#0000000&@1|;+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|<+0#e000e06&|/+0#0000000&|<+0#e000e06&|/+0#0000000&@1|<+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|=+0#e000e06&|/+0#0000000&|=+0#e000e06&|/+0#0000000&@1|=+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|>+0#e000e06&|/+0#0000000&|>+0#e000e06&|/+0#0000000&@1|>+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|?+0#e000e06&|/+0#0000000&|?+0#e000e06&|/+0#0000000&@1|?+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|@+0#e000e06&|/+0#0000000&|@+0#e000e06&|/+0#0000000&@1|@+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|[+0#e000e06&|/+0#0000000&|[+0#e000e06&|/+0#0000000&@1|[+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|"+0#0000e05&| |s|\|/|\|/@1|\| |"| |c|o|m@1|e|n|t| |(|d|i|s|a|l@1|o|w|e|d|)|
+0#0000000&@42
+|s+0#af5f00255&|]+0#e000e06&|/+0#0000000&|]+0#e000e06&|/+0#0000000&@1|]+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|^+0#e000e06&|/+0#0000000&|^+0#e000e06&|/+0#0000000&@1|^+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+@57|5@1|,|1| @9|7|3|%|
diff --git a/runtime/syntax/testdir/dumps/vim_ex_substitute_04.dump
b/runtime/syntax/testdir/dumps/vim_ex_substitute_04.dump
new file mode 100644
index 000000000..b37826020
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_substitute_04.dump
@@ -0,0 +1,20 @@
+|s+0#af5f00255#ffffff0|^+0#e000e06&|/+0#0000000&|^+0#e000e06&|/+0#0000000&@1|^+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|_+0#e000e06&|/+0#0000000&|_+0#e000e06&|/+0#0000000&@1|_+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|`+0#e000e06&|/+0#0000000&|`+0#e000e06&|/+0#0000000&@1|`+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|{+0#e000e06&|/+0#0000000&|{+0#e000e06&|/+0#0000000&@1|{+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|"+0#0000e05&| |s|||/|||/@1||| |"| |c|o|m@1|e|n|t| |(|d|i|s|a|l@1|o|w|e|d|)|
+0#0000000&@42
+>s+0#af5f00255&|}+0#e000e06&|/+0#0000000&|}+0#e000e06&|/+0#0000000&@1|}+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|~+0#e000e06&|/+0#0000000&|~+0#e000e06&|/+0#0000000&@1|~+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+@75
+@75
+|"+0#0000e05&| |I|s@1|u|e| |#|1|3|8@1|3| +0#0000000&@60
+@75
+|s|t|r|[|s|]| @68
+|s|t|r|(+0#e000e06&|s+0#00e0e07&|)+0#e000e06&| +0#0000000&@68
+@75
+|d+0#af5f00255&|e|f| +0#0000000&|T|e|s|t|(+0#e000e06&|)| +0#0000000&@64
+@2|s|t|r|[|s|]| @66
+@2|s|t|r|(+0#e000e06&|s+0#00e0e07&|)+0#e000e06&| +0#0000000&@66
+|e+0#af5f00255&|n|d@1|e|f| +0#0000000&@68
+@75
+@57|7|3|,|1| @9|B|o|t|
diff --git a/runtime/syntax/testdir/dumps/vim_ex_substitute_99.dump
b/runtime/syntax/testdir/dumps/vim_ex_substitute_99.dump
new file mode 100644
index 000000000..88cb7dc21
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_substitute_99.dump
@@ -0,0 +1,20 @@
+|s+0#af5f00255#ffffff0|^+0#e000e06&|/+0#0000000&|^+0#e000e06&|/+0#0000000&@1|^+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|_+0#e000e06&|/+0#0000000&|_+0#e000e06&|/+0#0000000&@1|_+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|`+0#e000e06&|/+0#0000000&|`+0#e000e06&|/+0#0000000&@1|`+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|{+0#e000e06&|/+0#0000000&|{+0#e000e06&|/+0#0000000&@1|{+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|"+0#0000e05&| |s|||/|||/@1||| |"| |c|o|m@1|e|n|t| |(|d|i|s|a|l@1|o|w|e|d|)|
+0#0000000&@42
+|s+0#af5f00255&|}+0#e000e06&|/+0#0000000&|}+0#e000e06&|/+0#0000000&@1|}+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+|s+0#af5f00255&|~+0#e000e06&|/+0#0000000&|~+0#e000e06&|/+0#0000000&@1|~+0#e000e06&|
+0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@57
+@75
+@75
+|"+0#0000e05&| |I|s@1|u|e| |#|1|3|8@1|3| +0#0000000&@60
+@75
+|s|t|r|[|s|]| @68
+|s|t|r|(+0#e000e06&|s+0#00e0e07&|)+0#e000e06&| +0#0000000&@68
+@75
+|d+0#af5f00255&|e|f| +0#0000000&|T|e|s|t|(+0#e000e06&|)| +0#0000000&@64
+@2|s|t|r|[|s|]| @66
+@2|s|t|r|(+0#e000e06&|s+0#00e0e07&|)+0#e000e06&| +0#0000000&@66
+|e+0#af5f00255&|n|d@1|e|f| +0#0000000&@68
+> @74
+@57|8|6|,|0|-|1| @7|B|o|t|
diff --git a/runtime/syntax/testdir/input/vim_ex_substitute.vim
b/runtime/syntax/testdir/input/vim_ex_substitute.vim
new file mode 100644
index 000000000..340d573ac
--- /dev/null
+++ b/runtime/syntax/testdir/input/vim_ex_substitute.vim
@@ -0,0 +1,86 @@
+substitute/foo/bar/&
+substitute/foo/bar/cegiInp#lr
+
+snomagic/foo/bar/&
+snomagic/foo/bar/cegiInp#lr
+
+smagic/foo/bar/&
+smagic/foo/bar/cegiInp#lr
+
+:substitute/foo/bar/&
+:substitute/foo/bar/cegiInp#lr
+
+:snomagic/foo/bar/&
+:snomagic/foo/bar/cegiInp#lr
+
+:smagic/foo/bar/&
+:smagic/foo/bar/cegiInp#lr
+
+call Foo() | substitute/foo/bar/&
+call Foo() | substitute/foo/bar/cegiInp#lr
+
+call Foo() | snomagic/foo/bar/&
+call Foo() | snomagic/foo/bar/cegiInp#lr
+
+call Foo() | smagic/foo/bar/&
+call Foo() | smagic/foo/bar/cegiInp#lr
+
+let foo = str->substitute(str, pat, sub, flags)
+
+function Foo()
+ substitute/foo/bar/
+ let bar = str->substitute(str, pat, sub, flags)
+endfunction
+
+def Foo()
+ substitute/foo/bar/
+ let bar = str->substitute(str, pat, sub, flags)
+enddef
+
+" various delimiters
+
+s!/!//! " comment
+" s"/"//" " comment (works but disallowed)
+s#/#//# " comment
+s$/$//$ " comment
+s%/%//% " comment
+s&/&//& " comment
+s'/'//' " comment
+" FIXME - matches vimUserFunc
+" s(/(//( " comment
+s)/)//) " comment
+s*/*//* " comment
+s+/+//+ " comment
+s,/,//, " comment
+s-/-//- " comment
+s././/. " comment
+s/X/XX/ " comment
+s:/://: " comment
+s;/;//; " comment
+s</<//< " comment
+s=/=//= " comment
+s>/>//> " comment
+s?/?//? " comment
+s@/@//@ " comment
+s[/[//[ " comment
+" s\/\//\ " comment (disallowed)
+s]/]//] " comment
+s^/^//^ " comment
+s_/_//_ " comment
+s`/`//` " comment
+s{/{//{ " comment
+" s|/|//| " comment (disallowed)
+s}/}//} " comment
+s~/~//~ " comment
+
+
+" Issue #13883
+
+str[s]
+str(s)
+
+def Test()
+ str[s]
+ str(s)
+enddef
+
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index 7dde1a340..c845651c9 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -3,7 +3,7 @@
" Maintainer: Hirohito Higashi <h.east.727 ATMARK gmail.com>
" Doug Kearns <[email protected]>
" URL: https://github.com/vim-jp/syntax-vim-ex
-" Last Change: Feb 23, 2024
+" Last Change: Feb 27, 2024
" Former Maintainer: Charles E. Campbell
" Base File URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_VIM
" Base File Version: 9.0-25
@@ -199,16 +199,16 @@ endif
" Numbers {{{2
" =======
-syn match vimNumber '\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '-\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '\<0[xX]\x\+' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '\%(^\|\A\)\zs#\x\{6}'
skipwhite nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '\<0[zZ][a-zA-Z0-9.]\+' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '0[0-7]\+' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '0[bB][01]\+' skipwhite
nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '-\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\<0[xX]\x\+' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\%(^\|\A\)\zs#\x\{6}'
skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\<0[zZ][a-zA-Z0-9.]\+' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '0[0-7]\+' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '0[bB][01]\+' skipwhite
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
" All vimCommands are contained by vimIsCommand. {{{2
-syn match vimCmdSep "[:|]\+" skipwhite
nextgroup=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimEcho,vimEchoHL,vimExecute,vimIsCommand,vimExtCmd,vimFilter,vimGlobal,vimHighlight,vimLet,vimMap,vimMark,vimNorm,vimSet,vimSyntax,vimUnlet,vimUnmap,vimUserCmd
+syn match vimCmdSep "[:|]\+" skipwhite
nextgroup=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimEcho,vimEchoHL,vimExecute,vimIsCommand,vimExtCmd,vimFilter,vimGlobal,vimHighlight,vimLet,vimMap,vimMark,vimNorm,vimSet,vimSubst1,vimSyntax,vimUnlet,vimUnmap,vimUserCmd
syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand
syn match vimVar contained "\<\h[a-zA-Z0-9#_]*\>"
syn match vimVar "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>"
@@ -236,7 +236,6 @@ syn match vimBehave "\<be\%[have]\>"
nextgroup=vimBehaveBang,vimBehaveModel,vi
syn match vimBehaveBang contained " \@1<=!"
nextgroup=vimBehaveModel skipwhite
syn keyword vimBehaveModel contained mswin xterm
-hi def link vimBehaveBang vimBang
" Filetypes {{{2
" =========
syn match vimFiletype "\<filet\%[ype]\(\s\+\I\i*\)*" skipwhite
contains=vimFTCmd,vimFTOption,vimFTError
@@ -312,12 +311,12 @@ syn region vimKeymap matchgroup=vimCommand
start="\<loadk\%[eymap]\>" end="\%$"
" Special Filenames, Modifiers, Extension Removal: {{{2
" ===============================================
-syn match vimSpecFile "<c\(word\|WORD\)>"
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "<\([acs]file\|amatch\|abuf\)>"
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "\s%[ :]"ms=s+1,me=e-1
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "\s%$"ms=s+1
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "\s%<"ms=s+1,me=e-1
nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "#\d\+\|[#%]<\>"
nextgroup=vimSpecFileMod,vimSubst
+syn match vimSpecFile "<c\(word\|WORD\)>"
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "<\([acs]file\|amatch\|abuf\)>"
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "\s%[ :]"ms=s+1,me=e-1
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "\s%$"ms=s+1
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "\s%<"ms=s+1,me=e-1
nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "#\d\+\|[#%]<\>"
nextgroup=vimSpecFileMod,vimSubst1
syn match vimSpecFileMod "\(:[phtre]\)\+" contained
" User-Specified Commands: {{{2
@@ -399,33 +398,34 @@ syn match vimStringInterpolationBrace "}}"
syn cluster vimSubstList
contains=vimPatSep,vimPatRegion,vimPatSepErr,vimSubstTwoBS,vimSubstRange,vimNotation
syn cluster vimSubstRepList
contains=vimSubstSubstr,vimSubstTwoBS,vimNotation
syn cluster vimSubstList add=vimCollection
-syn match vimSubst
"\(:\+\s*\|^\s*\||\s*\)\<\%(\<s\%[ubstitute]\>\|\<sm\%[agic]\>\|\<sno\%[magic]\>\)[:#[:alpha:]]\@!"
nextgroup=vimSubstPat
-"syn match vimSubst
"\%(^\|[^\]\)\<s\%[ubstitute]\>[:#[:alpha:]]\@!" nextgroup=vimSubstPat
contained
-syn match vimSubst
"\%(^\|[^\\"']\)\<s\%[ubstitute]\>[:#[:alpha:]\"']\@!" nextgroup=vimSubstPat
contained
-syn match vimSubst "/\zs\<s\%[ubstitute]\>\ze/"
nextgroup=vimSubstPat
-syn match vimSubst "\(:\+\s*\|^\s*\)s\ze#.\{-}#.\{-}#"
nextgroup=vimSubstPat
-syn match vimSubst1 contained "\<s\%[ubstitute]\>"
nextgroup=vimSubstPat
-syn match vimSubst2 contained "s\%[ubstitute]\>"
nextgroup=vimSubstPat
-syn region vimSubstPat contained matchgroup=vimSubstDelim
start="\z([^a-zA-Z( [\]&]\)"rs=s+1 skip="\\\|\\z1" end="\z1"re=e-1,me=e-1
contains=@vimSubstList nextgroup=vimSubstRep4 oneline
-syn region vimSubstRep4 contained matchgroup=vimSubstDelim
start="\z(.\)" skip="\\\|\\z1" end="\z1" matchgroup=vimNotation
end="<[cC][rR]>" contains=@vimSubstRepList nextgroup=vimSubstFlagErr
oneline
-syn region vimCollection contained transparent start="\\@<!\["
skip="\\[" end="\]" contains=vimCollClass
-syn match vimCollClassErr contained "\[:.\{-\}:\]"
-syn match vimCollClass contained transparent
"\%#=1\[:\(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\|retu\%[rn]\|tab\|escape\|backspace\):\]"
-syn match vimSubstSubstr contained "\z\=\d"
-syn match vimSubstTwoBS contained "\\"
-syn match vimSubstFlagErr contained "[^<
|]\+" contains=vimSubstFlags
-syn match vimSubstFlags contained "[&cegiIlnpr#]\+"
+syn match vimSubst
"^\s*\%(s\%[ubstitute]\|sm\%[agic]\|sno\%[magic]\)\>[\"#|]\@!"
nextgroup=vimSubstPat
+syn match vimSubst
"^\s*\%(s\%[ubstitute]\|sm\%[agic]\|sno\%[magic]\)_\@=" nextgroup=vimSubstPat
+syn match vimSubst
"^\s*\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)\ze#.\{-}#.\{-}#"
nextgroup=vimSubstPat
+syn match vimSubst1 contained
"\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)\>[\"#|]\@!"
nextgroup=vimSubstPat
+syn match vimSubst1 contained
"\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)_\@="
nextgroup=vimSubstPat
+syn match vimSubst1 contained
"\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)\ze#.\{-}#.\{-}#"
nextgroup=vimSubstPat
+" TODO: Vim9 illegal separators for abbreviated :s form are [-.:], :su\%[...]
required
+" : # is allowed but "not recommended" (see :h pattern-delimiter)
+syn region vimSubstPat contained matchgroup=vimSubstDelim
start="\z([!#$%&'()*+,-./:;<=>?@[\]^_`{}~]\)"rs=s+1 skip="\\\|\\z1"
end="\z1"re=e-1,me=e-1 contains=@vimSubstList nextgroup=vimSubstRep4
oneline
+syn region vimSubstRep4 contained matchgroup=vimSubstDelim
start="\z(.\)" skip="\\\|\\z1" end="\z1" matchgroup=vimNotation
end="<[cC][rR]>" contains=@vimSubstRepList
nextgroup=vimSubstFlagErr oneline
+syn region vimCollection contained transparent start="\\@<!\["
skip="\\[" end="\]" contains=vimCollClass
+syn match vimCollClassErr contained "\[:.\{-\}:\]"
+syn match vimCollClass contained transparent
"\%#=1\[:\(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\|retu\%[rn]\|tab\|escape\|backspace\):\]"
+syn match vimSubstSubstr contained "\z\=\d"
+syn match vimSubstTwoBS contained "\\"
+syn match vimSubstFlagErr contained "[^<
|]\+" contains=vimSubstFlags
+syn match vimSubstFlags contained "[&cegiIlnpr#]\+"
" 'String': {{{2
syn match vimString "[^(,]'[^']\{-}\zs'"
" Marks, Registers, Addresses, Filters: {{{2
-syn match vimMark "'[a-zA-Z0-9]\ze[-+,!]"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark "'[<>]\ze[-+,!]"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark ",\zs'[<>]\ze"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark "[!,:]\zs'[a-zA-Z0-9]"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark "\<norm\%[al]\s\zs'[a-zA-Z0-9]"
nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMarkNumber "[-+]\d\+" contained
contains=vimOper nextgroup=vimSubst2
+syn match vimMark "'[a-zA-Z0-9]\ze[-+,!]"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark "'[<>]\ze[-+,!]"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark ",\zs'[<>]\ze"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark "[!,:]\zs'[a-zA-Z0-9]"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark "\<norm\%[al]\s\zs'[a-zA-Z0-9]"
nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMarkNumber "[-+]\d\+" contained
contains=vimOper nextgroup=vimSubst1
syn match vimPlainMark contained "'[a-zA-Z0-9]"
syn match vimRange "[`'][a-zA-Z0-9],[`'][a-zA-Z0-9]"
contains=vimMark skipwhite nextgroup=vimFilter
@@ -761,8 +761,8 @@ syn match vimCommentTitleLeader '"\s\+'ms=s+1
contained
" ====================
syn match vimSearch '^\s*[/?].*' contains=vimSearchDelim
syn match vimSearchDelim '^\s*\zs[/?]\|[/?]$' contained
-syn region vimGlobal matchgroup=Statement start='\<g\%[lobal]!\=/'
skip='\.' end='/' skipwhite nextgroup=vimSubst
-syn region vimGlobal matchgroup=Statement start='\<v\%[global]!\=/'
skip='\.' end='/' skipwhite nextgroup=vimSubst
+syn region vimGlobal matchgroup=Statement start='\<g\%[lobal]!\=/'
skip='\.' end='/' skipwhite nextgroup=vimSubst1
+syn region vimGlobal matchgroup=Statement start='\<v\%[global]!\=/'
skip='\.' end='/' skipwhite nextgroup=vimSubst1
" Embedded Scripts: {{{2
" ================
@@ -982,7 +982,7 @@ if !exists("skip_vim_syntax_inits")
hi def link vimAutoCmdMod Special
hi def link vimAutoSet vimCommand
hi def link vimBang vimOper
- hi def link vimBehaveBang vimBang
+ hi def link vimBehaveBang vimBang
hi def link vimBehaveModel vimBehave
hi def link vimBehave vimCommand
hi def link vimBracket Delimiter
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/E1rehNP-003DUl-4Z%40256bit.org.