runtime(vim): Improve Vim9 and legacy-script comment highlighting (#13104)

Commit: 
https://github.com/vim/vim/commit/04e5363b823827f144409df011376d00ea6df750
Author: dkearns <dougkea...@gmail.com>
Date:   Thu Apr 11 06:18:37 2024 +1000

    runtime(vim): Improve Vim9 and legacy-script comment highlighting 
(https://github.com/vim/vim/issues/13104)
    
    This is a first-pass attempt to limit matching of Vim9 and legacy-script
    comments to the appropriate syntactic contexts.
    
    Vim9-script comments are highlighted at top level in a Vim9-script file,
    in all :def functions, and in all :autocmd and :commmand command blocks.
    Legacy-script comments are highlighted at top level in a legacy script
    file, in all :func functions and in the Vim9-script preamble before the
    :vim9script marker command.
    
    Fixes #13047, #11307 and #9587.
    
    Signed-off-by: Doug Kearns <dougkea...@gmail.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index f8ea87ec1..ac127f0c1 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -222,6 +222,7 @@ runtime/ftplugin/typescript.vim             @dkearns
 runtime/ftplugin/typescriptreact.vim   @dkearns
 runtime/ftplugin/unison.vim            @chuwy
 runtime/ftplugin/vdf.vim               @ObserverOfTime
+runtime/ftplugin/vim.vim               @dkearns
 runtime/ftplugin/wast.vim              @rhysd
 runtime/ftplugin/wget.vim              @dkearns
 runtime/ftplugin/wget2.vim             @dkearns
diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim
index 575af7405..a8636f4c8 100644
--- a/runtime/ftplugin/vim.vim
+++ b/runtime/ftplugin/vim.vim
@@ -1,7 +1,7 @@
 " Vim filetype plugin
-" Language:    Vim
-" Maintainer:  The Vim Project <https://github.com/vim/vim>
-" Last Change: 2023 Aug 10
+" Language:            Vim
+" Maintainer:          Doug Kearns <dougkea...@gmail.com>
+" Last Change:         2024 Apr 08
 " Former Maintainer:   Bram Moolenaar <b...@vim.org>
 
 " Only do this when not done yet for this buffer
@@ -50,7 +50,7 @@ setlocal isk+=#
 setlocal keywordprg=:help
 
 " Comments starts with # in Vim9 script.  We have to guess which one to use.
-if "
" .. getline(1, 10)->join("
") =~# '
\s*vim9\%[script]\>'
+if "
" .. getline(1, 32)->join("
") =~# '
\s*vim9\%[script]\>'
   setlocal commentstring=#%s
 else
   setlocal commentstring=\"%s
diff --git a/runtime/syntax/generator/gen_syntax_vim.vim 
b/runtime/syntax/generator/gen_syntax_vim.vim
index da093ee6b..d320bdbda 100644
--- a/runtime/syntax/generator/gen_syntax_vim.vim
+++ b/runtime/syntax/generator/gen_syntax_vim.vim
@@ -3,7 +3,7 @@
 " Maintainer: Hirohito Higashi (h_east)
 " URL: https://github.com/vim-jp/syntax-vim-ex
 " Last Change: 2024 Apr 07
-" Version: 2.1.0
+" Version: 2.1.1
 
 let s:keepcpo= &cpo
 set cpo&vim
@@ -286,6 +286,7 @@ function! s:get_vim_command_type(cmd_name)
        \       'append', 'insert',
        \       'Next', 'Print', 'X',
        \       'new', 'popup',
+       \       'vim9script',
        \ ]
        " Required for original behavior
        " \     'global', 'vglobal'
diff --git a/runtime/syntax/generator/vim.vim.base 
b/runtime/syntax/generator/vim.vim.base
index 9ab923c4f..7c6a9a073 100644
--- a/runtime/syntax/generator/vim.vim.base
+++ b/runtime/syntax/generator/vim.vim.base
@@ -19,6 +19,8 @@ endif
 let s:keepcpo= &cpo
 set cpo&vim
 
+let s:vim9script = "
" .. getline(1, 32)->join("
") =~# '
\s*vim9\%[script]\>'
+
 " vimTodo: contains common special-notices for comments {{{2
 " Use the vimCommentGroup cluster to add your own.
 syn keyword vimTodo contained  COMBAK  FIXME   TODO    XXX
@@ -156,13 +158,13 @@ endif
 " Numbers {{{2
 " =======
 syn case ignore
-syn match      vimNumber       '\<\d\+\%(\.\d\+\%(e[+-]\=\d\+\)\=\)\=' 
skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0b[01]\+'                    skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0o\=\o\+'                    skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0x\x\+'                      skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0z\>'                        skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0z\%(\x\x\)\+\%(\.\%(\x\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       '\<\d\+\%(\.\d\+\%(e[+-]\=\d\+\)\=\)\=' 
skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0b[01]\+'                    skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0o\=\o\+'                    skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0x\x\+'                      skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0z\>'                        skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0z\%(\x\x\)\+\%(\.\%(\x\x\)\+\)*'    
skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\%(^\|\A\)\zs#\x\{6}'          skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
 syn case match
 
 " All vimCommands are contained by vimIsCommand. {{{2
@@ -208,7 +210,7 @@ syn keyword vimFTOption contained   detect indent off on 
plugin
 
 " Augroup : vimAugroupError removed because long augroups caused sync'ing 
problems. {{{2
 " ======= : Trade-off: Increasing synclines with slower editing vs augroup END 
error checking.
-syn cluster vimAugroupList     
contains=@vimCmdList,vimFilter,vimFunc,vimLineComment,vimSpecFile,vimOper,vimNumber,vimOperParen,vimComment,vim9Comment,vimString,vimSubst,vimRegister,vimCmplxRepeat,vimNotation,vimCtrlChar,vimFuncVar,vimContinue
+syn cluster vimAugroupList     
contains=@vimCmdList,vimFilter,vimFunc,vimLineComment,vimSpecFile,vimOper,vimNumber,vimOperParen,@vimComment,vimString,vimSubst,vimRegister,vimCmplxRepeat,vimNotation,vimCtrlChar,vimFuncVar,vimContinue
 syn match   vimAugroup "\<aug\%[roup]\>" contains=vimAugroupKey,vimAugroupBang 
skipwhite nextgroup=vimAugroupBang,vimAutoCmdGroup
 if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'a'
   syn region  vimAugroup  fold 
start="\<aug\%[roup]\>\ze\s\+\%([eE][nN][dD]\)\@!\S\+" matchgroup=vimAugroupKey 
end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" 
contains=vimAutoCmd,@vimAugroupList,vimAugroupkey skipwhite 
nextgroup=vimAugroupEnd
@@ -299,15 +301,21 @@ syn match vimUserType     contained       "\<\u\w*\>"
 
 syn cluster vimType contains=vimType,vimCompoundType,vimUserType
 
-" Keymaps: (Vim Project Addition) {{{2
+" Keymaps: {{{2
 " =======
 
-" TODO: handle Vim9 script comments when something like #13104 is merged
-syn match  vimKeymapStart      "^"     contained skipwhite 
nextgroup=vimKeymapLhs,vimKeymapLineComment
+syn match  vimKeymapStart      "^"     contained skipwhite 
nextgroup=vimKeymapLhs,@vimKeymapLineComment
 syn match  vimKeymapLhs        "\S\+"  contained skipwhite 
nextgroup=vimKeymapRhs contains=vimNotation
 syn match  vimKeymapRhs        "\S\+"  contained skipwhite 
nextgroup=vimKeymapTailComment contains=vimNotation
 syn match  vimKeymapTailComment        "\S.*"  contained
-syn match  vimKeymapLineComment        +".*+   contained 
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+
+" TODO: remove when :" comment is matched in parts as "ex-colon comment" --djk
+if s:vim9script
+  syn match  vim9KeymapLineComment     "#.*"   contained 
contains=@vimCommentGroup,vimCommentString,vim9CommentTitle
+else
+  syn match  vimKeymapLineComment      +".*+   contained 
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+endif
+syn cluster vimKeymapLineComment contains=vim9\=KeymapLineComment
 
 syn region vimKeymap matchgroup=vimCommand start="\<loadk\%[eymap]\>" 
end="\%$" contains=vimKeymapStart
 
@@ -323,9 +331,10 @@ syn match  vimSpecFileMod  "\(:[phtre]\)\+"        
contained
 
 " User-Specified Commands: {{{2
 " =======================
-syn cluster    vimUserCmdList  
contains=@vimCmdList,vimCmplxRepeat,vimComment,vim9Comment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange
+syn cluster    vimUserCmdList  
contains=@vimCmdList,vimCmplxRepeat,@vimComment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange
 syn keyword    vimUserCommand  contained       com[mand]
-syn match      vimUserCmd      "\<com\%[mand]!\=\>.*$" 
contains=vimUserAttrb,vimUserAttrbError,vimUserCommand,@vimUserCmdList,vimComFilter
+syn match      vimUserCmdName  contained       "\<\u\w*\>" 
nextgroup=vimUserCmdBlock skipwhite
+syn match      vimUserCmd      "\<com\%[mand]!\=\>.*$" 
contains=vimUserAttrb,vimUserAttrbError,vimUserCommand,@vimUserCmdList,vimComFilter,vimCmdBlock,vimUserCmdName
 syn match      vimUserAttrbError       contained       "- \+\ze\s"
 syn match      vimUserAttrb    contained       "-nargs=[01*?+]"        
contains=vimUserAttrbKey,vimOper
 syn match      vimUserAttrb    contained       "-complete="            
contains=vimUserAttrbKey,vimOper nextgroup=vimUserAttrbCmplt,vimUserCmdError
@@ -347,20 +356,41 @@ syn match vimUserAttrbCmpltFunc contained 
",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w*
 syn case match
 syn match      vimUserAttrbCmplt contained     "custom,\u\w*"
 
+syn region     vimUserCmdBlock contained       matchgroup=vimSep start="{" 
end="}" contains=@vimDefBodyList
+
 " Lower Priority Comments: after some vim commands... {{{2
 " =======================
-syn match      vimComment      excludenl +\s"[^\-:.%#=*].*$+lc=1       
contains=@vimCommentGroup,vimCommentString
-syn match      vimComment      +\<endif\s\+".*$+lc=5   
contains=@vimCommentGroup,vimCommentString
-syn match      vimComment      +\<else\s\+".*$+lc=4    
contains=@vimCommentGroup,vimCommentString
-syn region     vimCommentString        contained oneline start='\S\s\+"'ms=e   
end='"'
-" Vim9 comments - TODO: might be highlighted while they don't work
-syn match      vim9Comment     excludenl +\s#[^{].*$+lc=1      
contains=@vimCommentGroup,vimCommentString
-syn match      vim9Comment     +\<endif\s\+#[^{].*$+lc=5       
contains=@vimCommentGroup,vimCommentString
-syn match      vim9Comment     +\<else\s\+#[^{].*$+lc=4        
contains=@vimCommentGroup,vimCommentString
-" Vim9 comment inside expression
-syn match      vim9Comment     +\s\zs#[^{].*$+ms=s+1   
contains=@vimCommentGroup,vimCommentString
-syn match      vim9Comment     +^\s*#[^{].*$+  
contains=@vimCommentGroup,vimCommentString
-syn match      vim9Comment     +^\s*#$+        
contains=@vimCommentGroup,vimCommentString
+syn region     vimCommentString        contained oneline start='\S\s\+"'ms=e 
end='"'
+
+if s:vim9script
+  syn match    vimComment      excludenl +\s"[^\-:.%#=*].*$+lc=1       
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vimComment      +\<endif\s\+".*$+lc=5   
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vimComment      +\<else\s\+".*$+lc=4    
contains=@vimCommentGroup,vimCommentString contained
+  " Vim9 comments - TODO: might be highlighted while they don't work
+  syn match    vim9Comment     excludenl +\s#[^{].*$+lc=1      
contains=@vimCommentGroup,vimCommentString
+  syn match    vim9Comment     +\<endif\s\+#[^{].*$+lc=5       
contains=@vimCommentGroup,vimCommentString
+  syn match    vim9Comment     +\<else\s\+#[^{].*$+lc=4        
contains=@vimCommentGroup,vimCommentString
+  " Vim9 comment inside expression
+  " syn match  vim9Comment     +\s\zs#[^{].*$+ms=s+1   
contains=@vimCommentGroup,vimCommentString
+  " syn match  vim9Comment     +^\s*#[^{].*$+          
contains=@vimCommentGroup,vimCommentString
+  " syn match  vim9Comment     +^\s*#$+                
contains=@vimCommentGroup,vimCommentString
+
+  syn cluster vimComment contains=vim9Comment
+else
+  syn match    vimComment      excludenl +\s"[^\-:.%#=*].*$+lc=1       
contains=@vimCommentGroup,vimCommentString
+  syn match    vimComment      +\<endif\s\+".*$+lc=5   
contains=@vimCommentGroup,vimCommentString
+  syn match    vimComment      +\<else\s\+".*$+lc=4    
contains=@vimCommentGroup,vimCommentString
+  " Vim9 comments - TODO: might be highlighted while they don't work
+  syn match    vim9Comment     excludenl +\s#[^{].*$+lc=1      
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vim9Comment     +\<endif\s\+#[^{].*$+lc=5       
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vim9Comment     +\<else\s\+#[^{].*$+lc=4        
contains=@vimCommentGroup,vimCommentString contained
+  " Vim9 comment inside expression
+  syn match    vim9Comment     +\s\zs#[^{].*$+ms=s+1   
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vim9Comment     +^\s*#[^{].*$+          
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vim9Comment     +^\s*#$+                
contains=@vimCommentGroup,vimCommentString contained
+
+  syn cluster vimComment contains=vimComment
+endif
 
 " Environment Variables: {{{2
 " =====================
@@ -450,7 +480,7 @@ syn match   vimCmplxRepeat  
'[^a-zA-Z_/\()]q[0-9a-zA-Z"]\>'lc=1
 syn match      vimCmplxRepeat  '@[0-9a-z".=@:]\ze\($\|[^a-zA-Z]\>\)'
 
 " Set command and associated set-options (vimOptions) with comment {{{2
-syn region     vimSet          matchgroup=vimCommand 
start="\<\%(setl\%[ocal]\|setg\%[lobal]\|se\%[t]\)\>" skip="\%(\\\)*\.
\@!" end="$" end="|" matchgroup=vimNotation end="<[cC][rR]>" keepend 
contains=vimSetEqual,vimOption,vimErrSetting,vimComment,vim9Comment,vimSetString,vimSetMod
+syn region     vimSet          matchgroup=vimCommand 
start="\<\%(setl\%[ocal]\|setg\%[lobal]\|se\%[t]\)\>" skip="\%(\\\)*\.
\@!" end="$" end="|" matchgroup=vimNotation end="<[cC][rR]>" keepend 
contains=vimSetEqual,vimOption,vimErrSetting,@vimComment,vimSetString,vimSetMod
 syn region     vimSetEqual     contained       start="[=:]\|[-+^]=" 
skip="\\\|\\s" end="[|     ]"me=e-1 end="$"        
contains=vimCtrlChar,vimSetSep,vimNotation,vimEnvvar
 syn region     vimSetString    contained       start=+="+hs=s+1        
skip=+\\\|\"+  end=+"+          contains=vimCtrlChar
 syn match      vimSetSep       contained       "[,:]"
@@ -482,9 +512,10 @@ syn keyword        vimFor  for     skipwhite 
nextgroup=vimVar,vimVarList
 " =======
 syn match      vimAutoEventList        contained       "\(!\s\+\)\=\( \+,\)* 
\+"       contains=vimAutoEvent nextgroup=vimAutoCmdSpace
 syn match      vimAutoCmdSpace contained       "\s\+"  
nextgroup=vimAutoCmdSfxList
-syn match      vimAutoCmdSfxList       contained       "\S*"   skipwhite 
nextgroup=vimAutoCmdMod
+syn match      vimAutoCmdSfxList       contained       "\S*"   skipwhite 
nextgroup=vimAutoCmdMod,vimAutoCmdBlock
 syn keyword    vimAutoCmd      au[tocmd] do[autocmd] doautoa[ll]       
skipwhite nextgroup=vimAutoEventList
-syn match      vimAutoCmdMod   "\(++\)\=\(once\|nested\)"
+syn match      vimAutoCmdMod   "\(++\)\=\(once\|nested\)"      skipwhite 
nextgroup=vimAutoCmdBlock
+syn region     vimAutoCmdBlock contained       matchgroup=vimSep start="{" 
end="}" contains=@vimDefBodyList
 
 " Echo And Execute: -- prefer strings! {{{2
 " ================
@@ -624,7 +655,7 @@ if has("conceal")
  syn match     vimSynCcharValue        contained       "\S"
 endif
 
-syn match      vimSyntax       "\<sy\%[ntax]\>"        contains=vimCommand 
skipwhite nextgroup=vimSynType,vimComment,vim9Comment
+syn match      vimSyntax       "\<sy\%[ntax]\>"        contains=vimCommand 
skipwhite nextgroup=vimSynType,@vimComment
 syn cluster vimFuncBodyList add=vimSyntax
 
 " Syntax: case {{{2
@@ -713,7 +744,7 @@ syn match   vimIsCommand    "<Bar>\s* \+"   transparent 
contains=vimCommand,vimNotatio
 
 " Highlighting: {{{2
 " ============
-syn cluster    vimHighlightCluster             
contains=vimHiLink,vimHiClear,vimHiKeyList,vimComment,vim9Comment
+syn cluster    vimHighlightCluster             
contains=vimHiLink,vimHiClear,vimHiKeyList,@vimComment
 if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimhictermerror")
  syn match     vimHiCtermError contained       "\D\i*"
 endif
@@ -769,16 +800,21 @@ syn match vimCtrlChar     "[ -   - ]"
 
 " Beginners - Patterns that involve ^ {{{2
 " =========
-syn match      vimLineComment  +^[     :]*".*$+        
contains=@vimCommentGroup,vimCommentString,vimCommentTitle,vimComment
-syn match      vimLineComment  +^[     :]*"\("[^"]*"\|[^"]\)*$+        
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
-syn match      vim9LineComment +^[     :]\+#.*$+       
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+if s:vim9script
+  syn match    vimLineComment  +^[     :]*".*$+        
contains=@vimCommentGroup,vimCommentString,vimCommentTitle contained
+  syn match    vim9LineComment +^[     :]*#.*$+        
contains=@vimCommentGroup,vimCommentString,vim9CommentTitle
+else
+  syn match    vimLineComment  +^[     :]*".*$+        
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+  syn match    vim9LineComment +^[     :]*#.*$+        
contains=@vimCommentGroup,vimCommentString,vim9CommentTitle contained
+endif
 syn match      vimCommentTitle 
'"\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1    contained 
contains=vimCommentTitleLeader,vimTodo,@vimCommentGroup
-" Note: Look-behind to work around nextgroup skipnl consuming leading 
whitespace and preventing a match
+syn match      vim9CommentTitle        
'#\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1    contained 
contains=vim9CommentTitleLeader,vimTodo,@vimCommentGroup
 syn match      vimContinue             "^\s*\zs\"
 syn match         vimContinueComment   '^\s*\zs["#]\ .*' contained
 syn cluster    vimContinue contains=vimContinue,vimContinueComment
 syn region     vimString       start="^\s*\\z(['"]\)" skip='\\\|\\z1' 
end="\z1" oneline keepend contains=@vimStringGroup,vimContinue
 syn match      vimCommentTitleLeader   '"\s\+'ms=s+1   contained
+syn match      vim9CommentTitleLeader  '#\s\+'ms=s+1   contained
 
 " Searches And Globals: {{{2
 " ====================
@@ -787,6 +823,17 @@ syn match  vimSearchDelim  '^\s*\zs[/?]\|[/?]$'    
contained
 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
 
+" Vim9 Script Regions: {{{2
+" ==================
+
+if s:vim9script
+  syn cluster vimLegacyTop 
contains=TOP,vimPreVim9script,vim9Comment,vim9LineComment
+  syn region vimPreVim9script start="\%^" end="^\ze\s*vim9s\%[cript]\>" 
contains=@vimLegacyTop,vimComment,vimLineComment
+
+  syn keyword vim9ScriptArg noclear
+  syn keyword vimCommand vim9s[cript] nextgroup=vim9ScriptArg skipwhite
+endif
+
 " Embedded Scripts:  {{{2
 " ================
 "   perl,ruby     : Benoit Cerrina
@@ -994,6 +1041,7 @@ if !exists("skip_vim_syntax_inits")
   hi def link vimBufnrWarn     vimWarn
  endif
 
+ hi def link vim9ScriptArg     Special
  hi def link vimAbb    vimCommand
  hi def link vimAddress        vimMark
  hi def link vimAugroupBang    vimBang
@@ -1013,6 +1061,7 @@ if !exists("skip_vim_syntax_inits")
  hi def link vim9Comment       Comment
  hi def link vimCommentString  vimString
  hi def link vimCommentTitle   PreProc
+ hi def link vim9CommentTitle  PreProc
  hi def link vimCondHL vimCommand
  hi def link vimConst  vimCommand
  hi def link vimContinue       Special
@@ -1070,6 +1119,7 @@ if !exists("skip_vim_syntax_inits")
  hi def link vimHLGroup        vimGroup
  hi def link vimInsert vimString
  hi def link vimIskSep Delimiter
+ hi def link vim9KeymapLineComment     vimKeymapLineComment
  hi def link vimKeymapLineComment      vimComment
  hi def link vimKeymapTailComment      vimComment
  hi def link vimLet    vimCommand
@@ -1192,5 +1242,5 @@ delc VimFoldP
 delc VimFoldr
 delc VimFoldt
 let &cpo = s:keepcpo
-unlet s:keepcpo
+unlet s:keepcpo s:vim9script
 " vim:ts=18 fdm=marker ft=vim
diff --git a/runtime/syntax/testdir/dumps/vim9_keymap_00.dump 
b/runtime/syntax/testdir/dumps/vim9_keymap_00.dump
new file mode 100644
index 000000000..d1bc96cfd
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim9_keymap_00.dump
@@ -0,0 +1,20 @@
+>v+0#af5f00255#ffffff0|i|m|9|s|c|r|i|p|t| +0#0000000&@64
+@75
+|#+0#0000e05&| |V|i|m| |K|e|y|m|a|p| |f|i|l|e| |f|o|r| |s|y|n|t|a|x| 
|t|e|s|t|i|n|g| +0#0000000&@38
+@75
+|s+0#af5f00255&|c|r|i|p|t|e|n|c|o|d|i|n|g| 
+0#0000000&|u|t|f|-+0#af5f00255&|8+0#e000002&| +0#0000000&@54
+@75
+|l+0#af5f00255&|e|t| +0#0000000&|b+0#00e0e07&|:|k|e|y|m|a|p|_|n|a|m|e| 
+0#0000000&|=+0#af5f00255&| +0#0000000&|"+0#e000002&|s|y|n|t|a|x|-|t|e|s|t|"| 
+0#0000000&@41
+@75
+|l+0#af5f00255&|o|a|d|k|e|y|m|a|p| +0#0000000&@64
+@75
+|#+0#0000e05&| |L|i|n|e| |c|o|m@1|e|n|t| +0#0000000&@60
+@75
+@2|#+0#0000e05&| |A|n|o|t|h|e|r| |l|i|n|e| |c|o|m@1|e|n|t| +0#0000000&@50
+@75
+|a| |A| @3|B+0#0000e05&|a|s|i|c| |m|a|p@1|i|n|g| +0#0000000&@54
+|'|a| |√°| @2|M+0#0000e05&|o|r|e| |t|h|a|n| |o|n|e| |c|h|a|r| |i|n| 
|f|i|r|s|t| |c|o|l|u|m|n| +0#0000000&@33
+@75
+|#+0#0000e05&| |S|p|e|c|i|a|l| |n|o|t|a|t|i|o|n| +0#0000000&@56
+|<+0#e000e06&|c|h|a|r|-|6|2|>| +0#0000000&@5|B| @14|S+0#0000e05&|p|e|c|i|a|l| 
|n|o|t|a|t|i|o|n| |a|l@1|o|w|e|d| |i|n| |L|H|S| |-| |d|e|c|i|m|a|l| 
+0#0000000&@2
+@57|1|,|1| @10|T|o|p| 
diff --git a/runtime/syntax/testdir/dumps/vim9_keymap_01.dump 
b/runtime/syntax/testdir/dumps/vim9_keymap_01.dump
new file mode 100644
index 000000000..1d0823fe6
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim9_keymap_01.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@74
+|a| |A| @3|B+0#0000e05&|a|s|i|c| |m|a|p@1|i|n|g| +0#0000000&@54
+|'|a| |√°| @2|M+0#0000e05&|o|r|e| |t|h|a|n| |o|n|e| |c|h|a|r| |i|n| 
|f|i|r|s|t| |c|o|l|u|m|n| +0#0000000&@33
+@75
+|#+0#0000e05&| |S|p|e|c|i|a|l| |n|o|t|a|t|i|o|n| +0#0000000&@56
+><+0#e000e06&|c|h|a|r|-|6|2|>| +0#0000000&@5|B| @14|S+0#0000e05&|p|e|c|i|a|l| 
|n|o|t|a|t|i|o|n| |a|l@1|o|w|e|d| |i|n| |L|H|S| |-| |d|e|c|i|m|a|l| 
+0#0000000&@2
+|c| @13|<+0#e000e06&|c|h|a|r|-|0|1|0|3|>| 
+0#0000000&@4|S+0#0000e05&|p|e|c|i|a|l| |n|o|t|a|t|i|o|n| |a|l@1|o|w|e|d| |i|n| 
|R|H|S| |-| |o|c|t|a|l| +0#0000000&@4
+|<+0#e000e06&|c|h|a|r|-|0|x|0@1|6|4|>| 
+0#0000000&@1|<+0#e000e06&|c|h|a|r|-|0|x|0@1|4@1|>| 
+0#0000000&@2|S+0#0000e05&|p|e|c|i|a|l| |n|o|t|a|t|i|o|n| |a|l@1|o|w|e|d| |i|n| 
|L|H|S| |a|n|d| |R|H|S| |-| |h|e
+|x|a|d|e|c|i|m|a|l| +0#0000000&@65
+@75
+|#+0#0000e05&| |V|i|m|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| |c|h|a|r|a|c|t|e|r|s| 
+0#0000000&@43
+|\|#| |<+0#e000e06&|c|h|a|r|-|0|x|0@1|a|3|>| 
+0#0000000&@14|L+0#0000e05&|i|n|e| |s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| |a| 
|V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e
+|n|t| +0#0000000&@72
+|"| |“| @27|L+0#0000e05&|i|n|e| |s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| |a| 
|l|e|g|a|c|y|-|s|c|r|i|p|t| |c|o|m
+@1|e|n|t| +0#0000000&@70
+|:| |#| @27|L+0#0000e05&|i|n|e| |s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| |a| 
|V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e
+|n|t| +0#0000000&@72
+|~+0#4040ff13&| @73
+|~| @73
+| +0#0000000&@56|1|9|,|1| @9|B|o|t| 
diff --git a/runtime/syntax/testdir/dumps/vim9_keymap_99.dump 
b/runtime/syntax/testdir/dumps/vim9_keymap_99.dump
new file mode 100644
index 000000000..8afcbba81
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim9_keymap_99.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@74
+@2|#+0#0000e05&| |A|n|o|t|h|e|r| |l|i|n|e| |c|o|m@1|e|n|t| +0#0000000&@50
+@75
+|a| |A| @3|B+0#0000e05&|a|s|i|c| |m|a|p@1|i|n|g| +0#0000000&@54
+|'|a| |√°| @2|M+0#0000e05&|o|r|e| |t|h|a|n| |o|n|e| |c|h|a|r| |i|n| 
|f|i|r|s|t| |c|o|l|u|m|n| +0#0000000&@33
+@75
+|#+0#0000e05&| |S|p|e|c|i|a|l| |n|o|t|a|t|i|o|n| +0#0000000&@56
+|<+0#e000e06&|c|h|a|r|-|6|2|>| +0#0000000&@5|B| @14|S+0#0000e05&|p|e|c|i|a|l| 
|n|o|t|a|t|i|o|n| |a|l@1|o|w|e|d| |i|n| |L|H|S| |-| |d|e|c|i|m|a|l| 
+0#0000000&@2
+|c| @13|<+0#e000e06&|c|h|a|r|-|0|1|0|3|>| 
+0#0000000&@4|S+0#0000e05&|p|e|c|i|a|l| |n|o|t|a|t|i|o|n| |a|l@1|o|w|e|d| |i|n| 
|R|H|S| |-| |o|c|t|a|l| +0#0000000&@4
+|<+0#e000e06&|c|h|a|r|-|0|x|0@1|6|4|>| 
+0#0000000&@1|<+0#e000e06&|c|h|a|r|-|0|x|0@1|4@1|>| 
+0#0000000&@2|S+0#0000e05&|p|e|c|i|a|l| |n|o|t|a|t|i|o|n| |a|l@1|o|w|e|d| |i|n| 
|L|H|S| |a|n|d| |R|H|S| |-| |h|e
+|x|a|d|e|c|i|m|a|l| +0#0000000&@65
+@75
+|#+0#0000e05&| |V|i|m|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| |c|h|a|r|a|c|t|e|r|s| 
+0#0000000&@43
+|\|#| |<+0#e000e06&|c|h|a|r|-|0|x|0@1|a|3|>| 
+0#0000000&@14|L+0#0000e05&|i|n|e| |s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| |a| 
|V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e
+|n|t| +0#0000000&@72
+|"| |“| @27|L+0#0000e05&|i|n|e| |s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| |a| 
|l|e|g|a|c|y|-|s|c|r|i|p|t| |c|o|m
+@1|e|n|t| +0#0000000&@70
+>:| |#| @27|L+0#0000e05&|i|n|e| |s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| |a| 
|V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e
+|n|t| +0#0000000&@72
+@57|2|6|,|1| @9|B|o|t| 
diff --git a/runtime/syntax/testdir/dumps/vim9_legacy_header_00.dump 
b/runtime/syntax/testdir/dumps/vim9_legacy_header_00.dump
new file mode 100644
index 000000000..2f682d960
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim9_legacy_header_00.dump
@@ -0,0 +1,20 @@
+>"+0#0000e05#ffffff0| |c|o|m@1|e|n|t| +0#0000000&@65
+@75
+|i+0#af5f00255&|f| 
+0#0000000&|!+0#af5f00255&|h+0#00e0e07&|a|s|(+0#e000e06&|'+0#e000002&|v|i|m|9|s|c|r|i|p|t|'|)+0#e000e06&|
 +0#0000000&@53
+@2|#| |4+0#e000002&|2| +0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@58
+@2|s+0#af5f00255&|o|u|r|c|e| +0#0000000&|f|o@1|.+0#af5f00255&|v|i|m| 
+0#0000000&@58
+@2|f+0#af5f00255&|i|n|i|s|h| +0#0000000&@66
+|e+0#af5f00255&|n|d|i|f| +0#0000000&@69
+@75
+|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@65
+@75
+|v+0#af5f00255&|i|m|9|s|c|r|i|p|t| +0#0000000&|n+0#e000e06&|o|c|l|e|a|r| 
+0#0000000&@56
+@75
+|#+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@65
+@75
+| +0#0000e05&|#| |s|t|r|i|n|g| |o|n|l|y| |r|e|c|o|g|n|i|s|e|d| |w|i|t|h| 
|l|e|a|d|i|n|g| |c|h|a|r| +0#0000000&@31
+@1|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&@57
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|1|,|1| @10|A|l@1| 
diff --git a/runtime/syntax/testdir/dumps/vim9_legacy_header_99.dump 
b/runtime/syntax/testdir/dumps/vim9_legacy_header_99.dump
new file mode 100644
index 000000000..d400e3166
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim9_legacy_header_99.dump
@@ -0,0 +1,20 @@
+|"+0#0000e05#ffffff0| |c|o|m@1|e|n|t| +0#0000000&@65
+@75
+|i+0#af5f00255&|f| 
+0#0000000&|!+0#af5f00255&|h+0#00e0e07&|a|s|(+0#e000e06&|'+0#e000002&|v|i|m|9|s|c|r|i|p|t|'|)+0#e000e06&|
 +0#0000000&@53
+@2|#| |4+0#e000002&|2| +0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@58
+@2|s+0#af5f00255&|o|u|r|c|e| +0#0000000&|f|o@1|.+0#af5f00255&|v|i|m| 
+0#0000000&@58
+@2|f+0#af5f00255&|i|n|i|s|h| +0#0000000&@66
+|e+0#af5f00255&|n|d|i|f| +0#0000000&@69
+@75
+|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@65
+@75
+|v+0#af5f00255&|i|m|9|s|c|r|i|p|t| +0#0000000&|n+0#e000e06&|o|c|l|e|a|r| 
+0#0000000&@56
+@75
+|#+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@65
+@75
+| +0#0000e05&|#| |s|t|r|i|n|g| |o|n|l|y| |r|e|c|o|g|n|i|s|e|d| |w|i|t|h| 
|l|e|a|d|i|n|g| |c|h|a|r| +0#0000000&@31
+@1>"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&@57
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|1|6|,|2| @9|A|l@1| 
diff --git a/runtime/syntax/testdir/dumps/vim_00.dump 
b/runtime/syntax/testdir/dumps/vim_00.dump
new file mode 100644
index 000000000..852148f1f
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_00.dump
@@ -0,0 +1,20 @@
+>"+0#0000e05#ffffff0| +0#0000000&|I+0#e000e06&|s@1|u|e|:| 
+0#0000e05&|#|1|3|0|4|7| +0#0000000&@59
+@75
+|i+0#af5f00255&|f| 
+0#0000000&|!+0#af5f00255&|e+0#00e0e07&|x|i|s|t|s|(+0#e000e06&|"+0#e000002&|:|D|i|f@1|O|r|i|g|"|)+0#e000e06&|
 +0#0000000&@51
+@2|c+0#af5f00255&|o|m@1|a|n|d| +0#0000000&|D|i|f@1|O|r|i|g| 
|v+0#af5f00255&|e|r|t| +0#0000000&|n+0#af5f00255&|e|w| +0#0000000&||| 
|s+0#af5f00255&|e|t| +0#0000000&|b+0#e000e06&|t|=+0#0000000&|n|o|f|i|l|e| 
||+0#af5f00255&| +0#0000000&|r+0#af5f00255&| 
+0#0000000&|++0#af5f00255&@1|e|d|i|t| +0#0000000&|#| ||| 
|0+0#e000002&|d+0#0000000&|_| ||| |d+0#af5f00255&|i|f@1|t|h|i|s| +0#0000000&@1
+| +0#e000e06&@17|\| +0#0000000&||| |w+0#af5f00255&|i|n|c|m|d| 
+0#0000000&|p+0#af5f00255&| +0#0000000&||| |d+0#af5f00255&|i|f@1|t|h|i|s| 
+0#0000000&@33
+|e+0#af5f00255&|n|d|i|f| +0#0000000&@69
+@75
+@75
+|"+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1@1|3|0|7| 
|a|n|d| |#|1@1|5|6|0| +0#0000000&@48
+@75
+|"+0#0000e05&| |T|h|i|s| |i|s| |w|h|a|t| |w|e| |c|a|l@1| |"| |b|l|a|h| 
+0#0000000&@45
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|"+0#0000000&|i|n|p|u|t|/|v|i|m|.|v|i|m|"| |1@1|L|,| |2|0|9|B| @31|1|,|1| 
@10|A|l@1| 
diff --git a/runtime/syntax/testdir/dumps/vim_99.dump 
b/runtime/syntax/testdir/dumps/vim_99.dump
new file mode 100644
index 000000000..8e9320cc9
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_99.dump
@@ -0,0 +1,20 @@
+|"+0#0000e05#ffffff0| +0#0000000&|I+0#e000e06&|s@1|u|e|:| 
+0#0000e05&|#|1|3|0|4|7| +0#0000000&@59
+@75
+|i+0#af5f00255&|f| 
+0#0000000&|!+0#af5f00255&|e+0#00e0e07&|x|i|s|t|s|(+0#e000e06&|"+0#e000002&|:|D|i|f@1|O|r|i|g|"|)+0#e000e06&|
 +0#0000000&@51
+@2|c+0#af5f00255&|o|m@1|a|n|d| +0#0000000&|D|i|f@1|O|r|i|g| 
|v+0#af5f00255&|e|r|t| +0#0000000&|n+0#af5f00255&|e|w| +0#0000000&||| 
|s+0#af5f00255&|e|t| +0#0000000&|b+0#e000e06&|t|=+0#0000000&|n|o|f|i|l|e| 
||+0#af5f00255&| +0#0000000&|r+0#af5f00255&| 
+0#0000000&|++0#af5f00255&@1|e|d|i|t| +0#0000000&|#| ||| 
|0+0#e000002&|d+0#0000000&|_| ||| |d+0#af5f00255&|i|f@1|t|h|i|s| +0#0000000&@1
+| +0#e000e06&@17|\| +0#0000000&||| |w+0#af5f00255&|i|n|c|m|d| 
+0#0000000&|p+0#af5f00255&| +0#0000000&||| |d+0#af5f00255&|i|f@1|t|h|i|s| 
+0#0000000&@33
+|e+0#af5f00255&|n|d|i|f| +0#0000000&@69
+@75
+@75
+|"+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1@1|3|0|7| 
|a|n|d| |#|1@1|5|6|0| +0#0000000&@48
+@75
+>"+0#0000e05&| |T|h|i|s| |i|s| |w|h|a|t| |w|e| |c|a|l@1| |"| |b|l|a|h| 
+0#0000000&@45
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|"+0#0000000&|i|n|p|u|t|/|v|i|m|.|v|i|m|"| |1@1|L|,| |2|0|9|B| @31|1@1|,|1| 
@9|A|l@1| 
diff --git a/runtime/syntax/testdir/dumps/vim_ex_commands_31.dump 
b/runtime/syntax/testdir/dumps/vim_ex_commands_31.dump
index 07075f7d4..3711988d6 100644
--- a/runtime/syntax/testdir/dumps/vim_ex_commands_31.dump
+++ b/runtime/syntax/testdir/dumps/vim_ex_commands_31.dump
@@ -5,7 +5,7 @@
 |:|v+0#af5f00255&|e|r|b|o|s|e| +0#0000000&@66
 >:|v+0#af5f00255&|e|r|t|i|c|a|l| +0#0000000&@65
 |:|v+0#af5f00255&|i|m|9|c|m|d| +0#0000000&@66
-|:|v+0#af5f00255&|i|m|9|s|c|r|i|p|t| +0#0000000&@63
+|"+0#0000e05&| |:|v|i|m|9|s|c|r|i|p|t| +0#0000000&@61
 |:|v+0#af5f00255&|i|m|g|r|e|p| +0#0000000&@66
 |:|v+0#af5f00255&|i|m|g|r|e|p|a|d@1| +0#0000000&@63
 |:|v+0#af5f00255&|i|s|u|a|l| +0#0000000&@67
diff --git a/runtime/syntax/testdir/dumps/vim_ex_commands_64.dump 
b/runtime/syntax/testdir/dumps/vim_ex_commands_64.dump
index 5561d991d..bf3df8d62 100644
--- a/runtime/syntax/testdir/dumps/vim_ex_commands_64.dump
+++ b/runtime/syntax/testdir/dumps/vim_ex_commands_64.dump
@@ -5,7 +5,7 @@
 |c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&||| 
|v+0#af5f00255&|e|r|b|o|s|e| +0#0000000&@54
 >c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&||| 
 >|v+0#af5f00255&|e|r|t|i|c|a|l| +0#0000000&@53
 |c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&||| 
|v+0#af5f00255&|i|m|9|c|m|d| +0#0000000&@54
-|c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&||| 
|v+0#af5f00255&|i|m|9|s|c|r|i|p|t| +0#0000000&@51
+|"+0#0000e05&| |c|a|l@1| |F|o@1|(|)| ||| |v|i|m|9|s|c|r|i|p|t| +0#0000000&@49
 |c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&||| 
|v+0#af5f00255&|i|m|g|r|e|p| +0#0000000&@54
 |c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&||| 
|v+0#af5f00255&|i|m|g|r|e|p|a|d@1| +0#0000000&@51
 |c+0#af5f00255&|a|l@1| +0#0000000&|F|o@1|(+0#e000e06&|)| +0#0000000&||| 
|v+0#af5f00255&|i|s|u|a|l| +0#0000000&@55
diff --git a/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_00.dump 
b/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_00.dump
new file mode 100644
index 000000000..57b021621
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_00.dump
@@ -0,0 +1,20 @@
+>v+0#af5f00255#ffffff0|i|m|9|s|c|r|i|p|t| +0#0000000&@64
+@75
+|#+0#0000e05&| |V|i|m| |c|o|m@1|e|n|t|s| +0#0000000&@60
+@75
+|#+0#0000e05&| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@53
+@75
+| +0#0000e05&|#| |s|t|r|i|n|g| |o|n|l|y| |r|e|c|o|g|n|i|s|e|d| |w|i|t|h| 
|l|e|a|d|i|n|g| |c|h|a|r| +0#0000000&@31
+@1|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&@57
+@75
+|f+0#af5f00255&|u|n|c|t|i|o|n|!| +0#0000000&|F|o@1|(+0#e000e06&|)| 
+0#0000000&@59
+| +0#0000e05&@1|"| |L|e|g|a|c|y|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@49
+@2|#| |4+0#e000002&|2| +0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@58
+|e+0#af5f00255&|n|d|f|u|n|c|t|i|o|n| +0#0000000&@63
+@75
+|d+0#af5f00255&|e|f|!| +0#0000000&|B|a|r|(+0#e000e06&|)| +0#0000000&@64
+| +0#0000e05&@1|#| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@2|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&|#+0#0000e05&| 
|c|o|m@1|e|n|t| +0#0000000&@46
+|e+0#af5f00255&|n|d@1|e|f| +0#0000000&@68
+@75
+@57|1|,|1| @10|T|o|p| 
diff --git a/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_01.dump 
b/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_01.dump
new file mode 100644
index 000000000..1b0d7c935
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_01.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@74
+|d+0#af5f00255&|e|f|!| +0#0000000&|B|a|r|(+0#e000e06&|)| +0#0000000&@64
+| +0#0000e05&@1|#| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@2|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&|#+0#0000e05&| 
|c|o|m@1|e|n|t| +0#0000000&@46
+|e+0#af5f00255&|n|d@1|e|f| +0#0000000&@68
+> @74
+|c+0#af5f00255&|o|m@1|a|n|d| +0#0000000&|-+0#af5f00255&|c+0#e000e06&|o|u|n|t| 
+0#0000000&|F|o@1|C|o|m@1|a|n|d| |{+0#e000e06&| +0#0000000&@47
+| +0#0000e05&@1|#| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@2|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&|#+0#0000e05&| 
|c|o|m@1|e|n|t| +0#0000000&@46
+|}+0#e000e06&| +0#0000000&@73
+@75
+|a+0#af5f00255&|u|t|o|c|m|d| +0#0000000&|B+0#00e0003&|u|f|N|e|w|F|i|l|e| 
+0#0000000&|*| |{+0#e000e06&| +0#0000000&@52
+| +0#0000e05&@1|#| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@2|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&|#+0#0000e05&| 
|c|o|m@1|e|n|t| +0#0000000&@46
+|}+0#e000e06&| +0#0000000&@73
+@75
+@75
+|#+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1|3|0|4|7| 
+0#0000000&@59
+@75
+@57|1|9|,|0|-|1| @7|5|9|%| 
diff --git a/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_02.dump 
b/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_02.dump
new file mode 100644
index 000000000..7de6ffb97
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_02.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@74
+|i+0#af5f00255&|f| 
+0#0000000&|!+0#af5f00255&|e+0#00e0e07&|x|i|s|t|s|(+0#e000e06&|"+0#e000002&|:|D|i|f@1|O|r|i|g|"|)+0#e000e06&|
 +0#0000000&@51
+@2|c+0#af5f00255&|o|m@1|a|n|d| +0#0000000&|D|i|f@1|O|r|i|g| 
|v+0#af5f00255&|e|r|t| +0#0000000&|n+0#af5f00255&|e|w| +0#0000000&||| 
|s+0#af5f00255&|e|t| +0#0000000&|b+0#e000e06&|t|=+0#0000000&|n|o|f|i|l|e| 
||+0#af5f00255&| +0#0000000&|r+0#af5f00255&| 
+0#0000000&|++0#af5f00255&@1|e|d|i|t| +0#0000000&|%+0#af5f00255&@1| 
+0#0000000&||| |0+0#e000002&|d+0#0000000&|_| ||| |d+0#af5f00255&|i|f@1|t|h|i|s| 
+0#0000000&
+@18|\+0#e000e06&| +0#0000000&||| |w+0#af5f00255&|i|n|c|m|d| 
+0#0000000&|p+0#af5f00255&| +0#0000000&||| |d+0#af5f00255&|i|f@1|t|h|i|s| 
+0#0000000&@33
+|e+0#af5f00255&|n|d|i|f| +0#0000000&@69
+> @74
+@75
+|#+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1@1|3|0|7| 
|a|n|d| |#|1@1|5|6|0| +0#0000000&@48
+@75
+|#+0#0000e05&| |T|h|i|s| |i|s| |w|h|a|t| |w|e| |c|a|l@1| |"| |b|l|a|h| 
+0#0000000&@45
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|3|7|,|0|-|1| @7|B|o|t| 
diff --git a/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_99.dump 
b/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_99.dump
new file mode 100644
index 000000000..f8759da21
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_comment-vim9_99.dump
@@ -0,0 +1,20 @@
+|}+0#e000e06#ffffff0| +0#0000000&@73
+@75
+|a+0#af5f00255&|u|t|o|c|m|d| +0#0000000&|B+0#00e0003&|u|f|N|e|w|F|i|l|e| 
+0#0000000&|*| |{+0#e000e06&| +0#0000000&@52
+| +0#0000e05&@1|#| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@2|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&|#+0#0000e05&| 
|c|o|m@1|e|n|t| +0#0000000&@46
+|}+0#e000e06&| +0#0000000&@73
+@75
+@75
+|#+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1|3|0|4|7| 
+0#0000000&@59
+@75
+|i+0#af5f00255&|f| 
+0#0000000&|!+0#af5f00255&|e+0#00e0e07&|x|i|s|t|s|(+0#e000e06&|"+0#e000002&|:|D|i|f@1|O|r|i|g|"|)+0#e000e06&|
 +0#0000000&@51
+@2|c+0#af5f00255&|o|m@1|a|n|d| +0#0000000&|D|i|f@1|O|r|i|g| 
|v+0#af5f00255&|e|r|t| +0#0000000&|n+0#af5f00255&|e|w| +0#0000000&||| 
|s+0#af5f00255&|e|t| +0#0000000&|b+0#e000e06&|t|=+0#0000000&|n|o|f|i|l|e| 
||+0#af5f00255&| +0#0000000&|r+0#af5f00255&| 
+0#0000000&|++0#af5f00255&@1|e|d|i|t| +0#0000000&|%+0#af5f00255&@1| 
+0#0000000&||| |0+0#e000002&|d+0#0000000&|_| ||| |d+0#af5f00255&|i|f@1|t|h|i|s| 
+0#0000000&
+@18|\+0#e000e06&| +0#0000000&||| |w+0#af5f00255&|i|n|c|m|d| 
+0#0000000&|p+0#af5f00255&| +0#0000000&||| |d+0#af5f00255&|i|f@1|t|h|i|s| 
+0#0000000&@33
+|e+0#af5f00255&|n|d|i|f| +0#0000000&@69
+@75
+@75
+|#+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1@1|3|0|7| 
|a|n|d| |#|1@1|5|6|0| +0#0000000&@48
+@75
+>#+0#0000e05&| |T|h|i|s| |i|s| |w|h|a|t| |w|e| |c|a|l@1| |"| |b|l|a|h| 
+0#0000000&@45
+@57|4|1|,|1| @9|B|o|t| 
diff --git a/runtime/syntax/testdir/dumps/vim_ex_comment_00.dump 
b/runtime/syntax/testdir/dumps/vim_ex_comment_00.dump
new file mode 100644
index 000000000..a1c188092
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_comment_00.dump
@@ -0,0 +1,20 @@
+>"+0#0000e05#ffffff0| |V|i|m| |c|o|m@1|e|n|t|s| +0#0000000&@60
+@75
+|"+0#0000e05&| |L|e|g|a|c|y|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@75
+|#| |4+0#e000002&|2| +0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@60
+@75
+|f+0#af5f00255&|u|n|c|t|i|o|n|!| +0#0000000&|F|o@1|(+0#e000e06&|)| 
+0#0000000&@59
+| +0#0000e05&@1|"| |L|e|g|a|c|y|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@49
+@2|#| |4+0#e000002&|2| +0#0000000&|"+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@58
+|e+0#af5f00255&|n|d|f|u|n|c|t|i|o|n| +0#0000000&@63
+@75
+|d+0#af5f00255&|e|f|!| +0#0000000&|B|a|r|(+0#e000e06&|)| +0#0000000&@64
+| +0#0000e05&@1|#| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@2|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&|#+0#0000e05&| 
|c|o|m@1|e|n|t| +0#0000000&@46
+|e+0#af5f00255&|n|d@1|e|f| +0#0000000&@68
+@75
+|c+0#af5f00255&|o|m@1|a|n|d| 
+0#0000000&|-+0#af5f00255&|n+0#e000e06&|a|r|g|s|=+0#af5f00255&|1+0#00e0003&| 
+0#0000000&|F|o@1|C|o|m@1|a|n|d| |{+0#e000e06&| +0#0000000&@45
+| +0#0000e05&@1|#| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@2|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&|#+0#0000e05&| 
|c|o|m@1|e|n|t| +0#0000000&@46
+@57|1|,|1| @10|T|o|p| 
diff --git a/runtime/syntax/testdir/dumps/vim_ex_comment_01.dump 
b/runtime/syntax/testdir/dumps/vim_ex_comment_01.dump
new file mode 100644
index 000000000..513f64ca9
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_comment_01.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@1|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| 
+0#0000000&|#+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@46
+|e+0#af5f00255&|n|d@1|e|f| +0#0000000&@68
+@75
+|c+0#af5f00255&|o|m@1|a|n|d| 
+0#0000000&|-+0#af5f00255&|n+0#e000e06&|a|r|g|s|=+0#af5f00255&|1+0#00e0003&| 
+0#0000000&|F|o@1|C|o|m@1|a|n|d| |{+0#e000e06&| +0#0000000&@45
+| +0#0000e05&@1|#| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@2>"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&|#+0#0000e05&| 
|c|o|m@1|e|n|t| +0#0000000&@46
+|}+0#e000e06&| +0#0000000&@73
+@75
+|a+0#af5f00255&|u|t|o|c|m|d| +0#0000000&|B+0#00e0003&|u|f|N|e|w|F|i|l|e| 
+0#0000000&|*| |{+0#e000e06&| +0#0000000&@52
+| +0#0000e05&@1|#| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| +0#0000000&@51
+@2|"+0#e000002&|u|s|e|l|e|s@1| |s|t|r|i|n|g|"| +0#0000000&|#+0#0000e05&| 
|c|o|m@1|e|n|t| +0#0000000&@46
+|}+0#e000e06&| +0#0000000&@73
+@75
+@75
+|"+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1|3|0|4|7| 
+0#0000000&@59
+@75
+|i+0#af5f00255&|f| 
+0#0000000&|!+0#af5f00255&|e+0#00e0e07&|x|i|s|t|s|(+0#e000e06&|"+0#e000002&|:|D|i|f@1|O|r|i|g|"|)+0#e000e06&|
 +0#0000000&@51
+@2|c+0#af5f00255&|o|m@1|a|n|d| +0#0000000&|D|i|f@1|O|r|i|g| 
|v+0#af5f00255&|e|r|t| +0#0000000&|n+0#af5f00255&|e|w| +0#0000000&||| 
|s+0#af5f00255&|e|t| +0#0000000&|b+0#e000e06&|t|=+0#0000000&|n|o|f|i|l|e| 
||+0#af5f00255&| +0#0000000&|r+0#af5f00255&| 
+0#0000000&|++0#af5f00255&@1|e|d|i|t| +0#0000000&|#| ||| 
|0+0#e000002&|d+0#0000000&|_| ||| |d+0#af5f00255&|i|f@1|t|h|i|s| +0#0000000&@1
+@18|\+0#e000e06&| +0#0000000&||| |w+0#af5f00255&|i|n|c|m|d| 
+0#0000000&|p+0#af5f00255&| +0#0000000&||| |d+0#af5f00255&|i|f@1|t|h|i|s| 
+0#0000000&@33
+@57|1|9|,|3| @9|5|0|%| 
diff --git a/runtime/syntax/testdir/dumps/vim_ex_comment_02.dump 
b/runtime/syntax/testdir/dumps/vim_ex_comment_02.dump
new file mode 100644
index 000000000..e2b6092a8
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_comment_02.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@17|\+0#e000e06&| +0#0000000&||| |w+0#af5f00255&|i|n|c|m|d| 
+0#0000000&|p+0#af5f00255&| +0#0000000&||| |d+0#af5f00255&|i|f@1|t|h|i|s| 
+0#0000000&@33
+|e+0#af5f00255&|n|d|i|f| +0#0000000&@69
+@75
+@75
+|"+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1@1|3|0|7| 
|a|n|d| |#|1@1|5|6|0| +0#0000000&@48
+> @74
+|"+0#0000e05&| |T|h|i|s| |i|s| |w|h|a|t| |w|e| |c|a|l@1| |"| |b|l|a|h| 
+0#0000000&@45
+@75
+@75
+|"+0#0000e05&| |I|s@1|u|e| |#| |#|9|5|8|7| +0#0000000&@59
+@75
+|d+0#af5f00255&|e|f| +0#0000000&|C|o|m@1|e|n|t|T|i|t|l|e|(+0#e000e06&|)| 
+0#0000000&@56
+| +0#0000e05&@1|#| +0#0000000&|T+0#e000e06&|i|t|l|e|:| +0#0000e05&|.@2| 
+0#0000000&@60
+|e+0#af5f00255&|n|d@1|e|f| +0#0000000&@68
+|~+0#4040ff13&| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+| +0#0000000&@56|3|7|,|0|-|1| @7|B|o|t| 
diff --git a/runtime/syntax/testdir/dumps/vim_ex_comment_99.dump 
b/runtime/syntax/testdir/dumps/vim_ex_comment_99.dump
new file mode 100644
index 000000000..e9bcabeb9
--- /dev/null
+++ b/runtime/syntax/testdir/dumps/vim_ex_comment_99.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@74
+|"+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1|3|0|4|7| 
+0#0000000&@59
+@75
+|i+0#af5f00255&|f| 
+0#0000000&|!+0#af5f00255&|e+0#00e0e07&|x|i|s|t|s|(+0#e000e06&|"+0#e000002&|:|D|i|f@1|O|r|i|g|"|)+0#e000e06&|
 +0#0000000&@51
+@2|c+0#af5f00255&|o|m@1|a|n|d| +0#0000000&|D|i|f@1|O|r|i|g| 
|v+0#af5f00255&|e|r|t| +0#0000000&|n+0#af5f00255&|e|w| +0#0000000&||| 
|s+0#af5f00255&|e|t| +0#0000000&|b+0#e000e06&|t|=+0#0000000&|n|o|f|i|l|e| 
||+0#af5f00255&| +0#0000000&|r+0#af5f00255&| 
+0#0000000&|++0#af5f00255&@1|e|d|i|t| +0#0000000&|#| ||| 
|0+0#e000002&|d+0#0000000&|_| ||| |d+0#af5f00255&|i|f@1|t|h|i|s| +0#0000000&@1
+@18|\+0#e000e06&| +0#0000000&||| |w+0#af5f00255&|i|n|c|m|d| 
+0#0000000&|p+0#af5f00255&| +0#0000000&||| |d+0#af5f00255&|i|f@1|t|h|i|s| 
+0#0000000&@33
+|e+0#af5f00255&|n|d|i|f| +0#0000000&@69
+@75
+@75
+|"+0#0000e05&| +0#0000000&|I+0#e000e06&|s@1|u|e|:| +0#0000e05&|#|1@1|3|0|7| 
|a|n|d| |#|1@1|5|6|0| +0#0000000&@48
+@75
+|"+0#0000e05&| |T|h|i|s| |i|s| |w|h|a|t| |w|e| |c|a|l@1| |"| |b|l|a|h| 
+0#0000000&@45
+@75
+@75
+|"+0#0000e05&| |I|s@1|u|e| |#| |#|9|5|8|7| +0#0000000&@59
+@75
+|d+0#af5f00255&|e|f| +0#0000000&|C|o|m@1|e|n|t|T|i|t|l|e|(+0#e000e06&|)| 
+0#0000000&@56
+| +0#0000e05&@1|#| +0#0000000&|T+0#e000e06&|i|t|l|e|:| +0#0000e05&|.@2| 
+0#0000000&@60
+>e+0#af5f00255&|n|d@1|e|f| +0#0000000&@68
+@57|4|5|,|1| @9|B|o|t| 
diff --git a/runtime/syntax/testdir/dumps/vim_keymap_01.dump 
b/runtime/syntax/testdir/dumps/vim_keymap_01.dump
index 9a7a8333a..a07bfc405 100644
--- a/runtime/syntax/testdir/dumps/vim_keymap_01.dump
+++ b/runtime/syntax/testdir/dumps/vim_keymap_01.dump
@@ -17,4 +17,4 @@
 |"+0#0000e05&| |V|i|m|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| |c|h|a|r|a|c|t|e|r|s| 
@30| +0#0000000&@12
 |#| |<+0#e000e06&|c|h|a|r|-|0|x|0@1|a|3|>| +0#0000000&@15|L+0#0000e05&|i|n|e| 
|s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| |a| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e
 |n|t| +0#0000000&@72
-@57|1|9|,|1| @9|9|3|%| 
+@57|1|9|,|1| @9|8|7|%| 
diff --git a/runtime/syntax/testdir/dumps/vim_keymap_99.dump 
b/runtime/syntax/testdir/dumps/vim_keymap_99.dump
index ad6b5a58b..1b27d5781 100644
--- a/runtime/syntax/testdir/dumps/vim_keymap_99.dump
+++ b/runtime/syntax/testdir/dumps/vim_keymap_99.dump
@@ -1,6 +1,4 @@
-|a+0&#ffffff0| |A| @3|B+0#0000e05&|a|s|i|c| |m|a|p@1|i|n|g| @38| +0#0000000&@15
-|'|a| |√°| @2|M+0#0000e05&|o|r|e| |t|h|a|n| |o|n|e| |c|h|a|r| |i|n| 
|f|i|r|s|t| |c|o|l|u|m|n| @10| +0#0000000&@22
-@75
+| +0&#ffffff0@74
 |"+0#0000e05&| |S|p|e|c|i|a|l| |n|o|t|a|t|i|o|n| @56
 @60| +0#0000000&@14
 |<+0#e000e06&|c|h|a|r|-|6|2|>| +0#0000000&@5|B| @14|S+0#0000e05&|p|e|c|i|a|l| 
|n|o|t|a|t|i|o|n| |a|l@1|o|w|e|d| |i|n| |L|H|S| |-| |d|e|c|i|m|a|l| @2
@@ -15,6 +13,8 @@
 |"+0#0000e05&| |V|i|m|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| |c|h|a|r|a|c|t|e|r|s| 
@30| +0#0000000&@12
 |#| |<+0#e000e06&|c|h|a|r|-|0|x|0@1|a|3|>| +0#0000000&@15|L+0#0000e05&|i|n|e| 
|s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| |a| |V|i|m|9|-|s|c|r|i|p|t| |c|o|m@1|e
 |n|t| +0#0000000&@72
->\|"| |“| @18|L+0#0000e05&|i|n|e| |s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| 
|a| |l|e|g|a|c|y|-|s|c|r|i|p|t| |c|o|m@1|e|n|t| | +0#0000000&@2
-|~+0#4040ff13&| @73
-| +0#0000000&@56|2|6|,|1| @9|B|o|t| 
+|\|"| |“| @26|L+0#0000e05&|i|n|e| |s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| 
|a| |l|e|g|a|c|y|-|s|c|r|i|p|t| |c|o|m
+@1|e|n|t| | +0#0000000&@69
+>:| |"| @27|L+0#0000e05&|i|n|e| |s|h|o|u|l|d| |n|o|t| |m|a|t|c|h| |a|s| |a| 
|l|e|g|a|c|y|-|s|c|r|i|p|t| |c|o|m
+@1|e|n|t| +0#0000000&@70
+@57|2|7|,|1| @9|B|o|t| 
diff --git a/runtime/syntax/testdir/input/vim9_keymap.vim 
b/runtime/syntax/testdir/input/vim9_keymap.vim
new file mode 100644
index 000000000..a69b723a7
--- /dev/null
+++ b/runtime/syntax/testdir/input/vim9_keymap.vim
@@ -0,0 +1,26 @@
+vim9script
+
+# Vim Keymap file for syntax testing
+
+scriptencoding utf-8
+
+let b:keymap_name = "syntax-test"
+
+loadkeymap
+
+# Line comment
+
+  # Another line comment
+
+a A    Basic mapping
+'a √°   More than one char in first column
+
+# Special notation
+<char-62>      B               Special notation allowed in LHS - decimal
+c              <char-0103>     Special notation allowed in RHS - octal
+<char-0x0064>  <char-0x0044>   Special notation allowed in LHS and RHS - 
hexadecimal
+
+# Vim-script comment characters
+\# <char-0x00a3>               Line should not match as a Vim9-script comment
+" “                            Line should not match as a legacy-script 
comment
+: #                            Line should not match as a Vim9-script comment
diff --git a/runtime/syntax/testdir/input/vim9_legacy_header.vim 
b/runtime/syntax/testdir/input/vim9_legacy_header.vim
new file mode 100644
index 000000000..66aeb3961
--- /dev/null
+++ b/runtime/syntax/testdir/input/vim9_legacy_header.vim
@@ -0,0 +1,16 @@
+" comment
+
+if !has('vim9script')
+  # 42 " comment
+  source foo.vim
+  finish
+endif
+
+" comment
+
+vim9script noclear
+
+# comment
+
+ # string only recognised with leading char
+ "useless string"
diff --git a/runtime/syntax/testdir/input/vim_ex_commands.vim 
b/runtime/syntax/testdir/input/vim_ex_commands.vim
index 571fd7ba1..aaa351bd3 100644
--- a/runtime/syntax/testdir/input/vim_ex_commands.vim
+++ b/runtime/syntax/testdir/input/vim_ex_commands.vim
@@ -558,7 +558,7 @@
 :verbose
 :vertical
 :vim9cmd
-:vim9script
+" :vim9script
 :vimgrep
 :vimgrepadd
 :visual
@@ -1152,7 +1152,7 @@ call Foo() | version
 call Foo() | verbose
 call Foo() | vertical
 call Foo() | vim9cmd
-call Foo() | vim9script
+" call Foo() | vim9script
 call Foo() | vimgrep
 call Foo() | vimgrepadd
 call Foo() | visual
diff --git a/runtime/syntax/testdir/input/vim_ex_comment-vim9.vim 
b/runtime/syntax/testdir/input/vim_ex_comment-vim9.vim
new file mode 100644
index 000000000..786d11b43
--- /dev/null
+++ b/runtime/syntax/testdir/input/vim_ex_comment-vim9.vim
@@ -0,0 +1,41 @@
+vim9script
+
+# Vim comments
+
+# Vim9-script comment
+
+ # string only recognised with leading char
+ "useless string"
+
+function! Foo()
+  " Legacy-script comment
+  # 42 " comment
+endfunction
+
+def! Bar()
+  # Vim9-script comment
+  "useless string" # comment
+enddef
+
+command -count FooCommand {
+  # Vim9-script comment
+  "useless string" # comment
+}
+
+autocmd BufNewFile * {
+  # Vim9-script comment
+  "useless string" # comment
+}
+
+
+# Issue: #13047
+
+if !exists(":DiffOrig")
+  command DiffOrig vert new | set bt=nofile | r ++edit %% | 0d_ | diffthis
+                 \ | wincmd p | diffthis
+endif
+
+
+# Issue: #11307 and #11560
+
+# This is what we call " blah
diff --git a/runtime/syntax/testdir/input/vim_ex_comment.vim 
b/runtime/syntax/testdir/input/vim_ex_comment.vim
new file mode 100644
index 000000000..54e514eaa
--- /dev/null
+++ b/runtime/syntax/testdir/input/vim_ex_comment.vim
@@ -0,0 +1,45 @@
+" Vim comments
+
+" Legacy-script comment
+
+# 42 " comment
+
+function! Foo()
+  " Legacy-script comment
+  # 42 " comment
+endfunction
+
+def! Bar()
+  # Vim9-script comment
+  "useless string" # comment
+enddef
+
+command -nargs=1 FooCommand {
+  # Vim9-script comment
+  "useless string" # comment
+}
+
+autocmd BufNewFile * {
+  # Vim9-script comment
+  "useless string" # comment
+}
+
+
+" Issue: #13047
+
+if !exists(":DiffOrig")
+  command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ | diffthis
+                 \ | wincmd p | diffthis
+endif
+
+
+" Issue: #11307 and #11560
+
+" This is what we call " blah
+
+
+" Issue # #9587
+
+def CommentTitle()
+  # Title: ...
+enddef
diff --git a/runtime/syntax/testdir/input/vim_keymap.vim 
b/runtime/syntax/testdir/input/vim_keymap.vim
index 983c822c5..424d437a6 100644
--- a/runtime/syntax/testdir/input/vim_keymap.vim
+++ b/runtime/syntax/testdir/input/vim_keymap.vim
@@ -23,4 +23,5 @@ c              <char-0103>     Special notation allowed in 
RHS - octal
                                          
 " Vim-script comment characters                               
 # <char-0x00a3>                Line should not match as a Vim9-script comment
-\" “                   Line should not match as a legacy-script comment 
+\" “                           Line should not match as a legacy-script 
comment 
+: "                            Line should not match as a legacy-script comment
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index cfb94aecf..c016703b6 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 <dougkea...@gmail.com>
 " URL:    https://github.com/vim-jp/syntax-vim-ex
-" Last Change:    2024 Apr 09
+" Last Change:    2024 Apr 11
 " Former Maintainer: Charles E. Campbell
 
 " DO NOT CHANGE DIRECTLY.
@@ -19,6 +19,8 @@ endif
 let s:keepcpo= &cpo
 set cpo&vim
 
+let s:vim9script = "
" .. getline(1, 32)->join("
") =~# '
\s*vim9\%[script]\>'
+
 " vimTodo: contains common special-notices for comments {{{2
 " Use the vimCommentGroup cluster to add your own.
 syn keyword vimTodo contained  COMBAK  FIXME   TODO    XXX
@@ -31,7 +33,7 @@ syn keyword vimCommand contained comp[iler] con[tinue] 
conf[irm] cons[t] cope[n]
 syn keyword vimCommand contained helpg[rep] helpt[ags] ha[rdcopy] hi[ghlight] 
hid[e] his[tory] ho[rizontal] if ij[ump] il[ist] imp[ort] int[ro] inte[rface] 
is[earch] isp[lit] j[oin] ju[mps] k kee[pmarks] keepj[umps] keepp[atterns] 
keepa[lt] l[ist] lN[ext] lNf[ile] la[st] lab[ove] lan[guage] lad[dexpr] 
laddb[uffer] laddf[ile] laf[ter] lat[er] lb[uffer] lbe[fore] lbel[ow] lbo[ttom] 
lc[d] lch[dir] lcl[ose] lcs[cope] ld[o] le[ft] lefta[bove] let lex[pr] leg[acy] 
lf[ile] lfd[o] lfir[st] lg[etfile] lgetb[uffer] lgete[xpr] lgr[ep] lgrepa[dd] 
lh[elpgrep] lhi[story] ll lla[st] lli[st] lmak[e] lne[xt] lnew[er] lnf[ile] 
lo[adview] loadk[eymap] loc[kmarks] lockv[ar] lol[der] lop[en] lp[revious] 
lpf[ile] lr[ewind] lt[ag] lua luad[o] luaf[ile] lv[imgrep] lvimgrepa[dd] 
lw[indow]
 syn keyword vimCommand contained ls m[ove] ma[rk] mak[e] marks mat[ch] 
menut[ranslate] mes[sages] mk[exrc] mks[ession] mksp[ell] mkv[imrc] mkvie[w] 
mod[e] mz[scheme] mzf[ile] n[ext] nb[key] nbc[lose] nbs[tart] noa[utocmd] 
noh[lsearch] nos[wapfile] nu[mber] o[pen] ol[dfiles] on[ly] opt[ions] 
ow[nsyntax] p[rint] pa[ckadd] packl[oadall] pc[lose] pe[rl] perld[o] ped[it] 
po[p] pp[op] pre[serve] prev[ious] pro[mptfind] promptr[epl] prof[ile] 
profd[el] ps[earch] pt[ag] ptN[ext] ptf[irst] ptj[ump] ptl[ast] ptn[ext] 
ptp[revious] ptr[ewind] pts[elect] pu[t] pub[lic] pw[d] py[thon] pyd[o] 
pyf[ile] py3 py3d[o] python3 py3f[ile] pyx pyxd[o] pythonx pyxf[ile] q[uit] 
quita[ll] qa[ll] r[ead] rec[over] red[o] redi[r] redr[aw] redraws[tatus] 
redrawt[abline] reg[isters] res[ize]
 syn keyword vimCommand contained ret[ab] retu[rn] rew[ind] ri[ght] 
rightb[elow] ru[ntime] rub[y] rubyd[o] rubyf[ile] rund[o] rv[iminfo] sN[ext] 
sa[rgument] sal[l] san[dbox] sav[eas] sb[uffer] sbN[ext] sba[ll] sbf[irst] 
sbl[ast] sbm[odified] sbn[ext] sbp[revious] sbr[ewind] sc[riptnames] 
scripte[ncoding] scriptv[ersion] scs[cope] setf[iletype] sf[ind] sfir[st] 
sh[ell] si[malt] sig[n] sil[ent] sl[eep] sla[st] sn[ext] so[urce] sor[t] 
sp[lit] spe[llgood] spelld[ump] spelli[nfo] spellr[epall] spellra[re] 
spellu[ndo] spellw[rong] spr[evious] sr[ewind] st[op] sta[g] star[tinsert] 
startg[replace] startr[eplace] stat[ic] stopi[nsert] stj[ump] sts[elect] 
sun[hide] sus[pend] sv[iew] sw[apname] synti[me] sync[bind] smi[le] t tN[ext] 
ta[g] tags tab tabc[lose] tabd[o] tabe[dit]
-syn keyword vimCommand contained tabf[ind] tabfir[st] tabm[ove] tabl[ast] 
tabn[ext] tabnew tabo[nly] tabp[revious] tabN[ext] tabr[ewind] tabs tc[d] 
tch[dir] tcl tcld[o] tclf[ile] te[aroff] ter[minal] tf[irst] th[row] thi[s] 
tj[ump] tl[ast] tn[ext] to[pleft] tp[revious] tr[ewind] try ts[elect] ty[pe] 
u[ndo] undoj[oin] undol[ist] unh[ide] unl[et] unlo[ckvar] uns[ilent] up[date] 
v[global] ve[rsion] verb[ose] vert[ical] vi[sual] vie[w] vim[grep] vimgrepa[dd] 
vim9[cmd] vim9s[cript] viu[sage] vne[w] vs[plit] w[rite] wN[ext] wa[ll] wh[ile] 
wi[nsize] winc[md] wind[o] winp[os] wn[ext] wp[revious] wq wqa[ll] wu[ndo] 
wv[iminfo] x[it] xa[ll] xr[estore] y[ank] z dl dell delel deletl deletel dp dep 
delp delep deletp deletep a i
+syn keyword vimCommand contained tabf[ind] tabfir[st] tabm[ove] tabl[ast] 
tabn[ext] tabnew tabo[nly] tabp[revious] tabN[ext] tabr[ewind] tabs tc[d] 
tch[dir] tcl tcld[o] tclf[ile] te[aroff] ter[minal] tf[irst] th[row] thi[s] 
tj[ump] tl[ast] tn[ext] to[pleft] tp[revious] tr[ewind] try ts[elect] ty[pe] 
u[ndo] undoj[oin] undol[ist] unh[ide] unl[et] unlo[ckvar] uns[ilent] up[date] 
v[global] ve[rsion] verb[ose] vert[ical] vi[sual] vie[w] vim[grep] vimgrepa[dd] 
vim9[cmd] viu[sage] vne[w] vs[plit] w[rite] wN[ext] wa[ll] wh[ile] wi[nsize] 
winc[md] wind[o] winp[os] wn[ext] wp[revious] wq wqa[ll] wu[ndo] wv[iminfo] 
x[it] xa[ll] xr[estore] y[ank] z dl dell delel deletl deletel dp dep delp delep 
deletp deletep a i
 
 syn keyword vimCommand contained       2mat[ch] 3mat[ch]
 
@@ -193,13 +195,13 @@ endif
 " Numbers {{{2
 " =======
 syn case ignore
-syn match      vimNumber       '\<\d\+\%(\.\d\+\%(e[+-]\=\d\+\)\=\)\=' 
skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0b[01]\+'                    skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0o\=\o\+'                    skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0x\x\+'                      skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0z\>'                        skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
-syn match      vimNumber       '\<0z\%(\x\x\)\+\%(\.\%(\x\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       '\<\d\+\%(\.\d\+\%(e[+-]\=\d\+\)\=\)\=' 
skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0b[01]\+'                    skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0o\=\o\+'                    skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0x\x\+'                      skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0z\>'                        skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\<0z\%(\x\x\)\+\%(\.\%(\x\x\)\+\)*'    
skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
+syn match      vimNumber       '\%(^\|\A\)\zs#\x\{6}'          skipwhite 
nextgroup=vimGlobal,vimSubst1,vimCommand,@vimComment
 syn case match
 
 " All vimCommands are contained by vimIsCommand. {{{2
@@ -245,7 +247,7 @@ syn keyword vimFTOption contained   detect indent off on 
plugin
 
 " Augroup : vimAugroupError removed because long augroups caused sync'ing 
problems. {{{2
 " ======= : Trade-off: Increasing synclines with slower editing vs augroup END 
error checking.
-syn cluster vimAugroupList     
contains=@vimCmdList,vimFilter,vimFunc,vimLineComment,vimSpecFile,vimOper,vimNumber,vimOperParen,vimComment,vim9Comment,vimString,vimSubst,vimRegister,vimCmplxRepeat,vimNotation,vimCtrlChar,vimFuncVar,vimContinue
+syn cluster vimAugroupList     
contains=@vimCmdList,vimFilter,vimFunc,vimLineComment,vimSpecFile,vimOper,vimNumber,vimOperParen,@vimComment,vimString,vimSubst,vimRegister,vimCmplxRepeat,vimNotation,vimCtrlChar,vimFuncVar,vimContinue
 syn match   vimAugroup "\<aug\%[roup]\>" contains=vimAugroupKey,vimAugroupBang 
skipwhite nextgroup=vimAugroupBang,vimAutoCmdGroup
 if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'a'
   syn region  vimAugroup  fold 
start="\<aug\%[roup]\>\ze\s\+\%([eE][nN][dD]\)\@!\S\+" matchgroup=vimAugroupKey 
end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" 
contains=vimAutoCmd,@vimAugroupList,vimAugroupkey skipwhite 
nextgroup=vimAugroupEnd
@@ -336,15 +338,21 @@ syn match vimUserType     contained       "\<\u\w*\>"
 
 syn cluster vimType contains=vimType,vimCompoundType,vimUserType
 
-" Keymaps: (Vim Project Addition) {{{2
+" Keymaps: {{{2
 " =======
 
-" TODO: handle Vim9 script comments when something like #13104 is merged
-syn match  vimKeymapStart      "^"     contained skipwhite 
nextgroup=vimKeymapLhs,vimKeymapLineComment
+syn match  vimKeymapStart      "^"     contained skipwhite 
nextgroup=vimKeymapLhs,@vimKeymapLineComment
 syn match  vimKeymapLhs        "\S\+"  contained skipwhite 
nextgroup=vimKeymapRhs contains=vimNotation
 syn match  vimKeymapRhs        "\S\+"  contained skipwhite 
nextgroup=vimKeymapTailComment contains=vimNotation
 syn match  vimKeymapTailComment        "\S.*"  contained
-syn match  vimKeymapLineComment        +".*+   contained 
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+
+" TODO: remove when :" comment is matched in parts as "ex-colon comment" --djk
+if s:vim9script
+  syn match  vim9KeymapLineComment     "#.*"   contained 
contains=@vimCommentGroup,vimCommentString,vim9CommentTitle
+else
+  syn match  vimKeymapLineComment      +".*+   contained 
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+endif
+syn cluster vimKeymapLineComment contains=vim9\=KeymapLineComment
 
 syn region vimKeymap matchgroup=vimCommand start="\<loadk\%[eymap]\>" 
end="\%$" contains=vimKeymapStart
 
@@ -360,9 +368,10 @@ syn match  vimSpecFileMod  "\(:[phtre]\)\+"        
contained
 
 " User-Specified Commands: {{{2
 " =======================
-syn cluster    vimUserCmdList  
contains=@vimCmdList,vimCmplxRepeat,vimComment,vim9Comment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange
+syn cluster    vimUserCmdList  
contains=@vimCmdList,vimCmplxRepeat,@vimComment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange
 syn keyword    vimUserCommand  contained       com[mand]
-syn match      vimUserCmd      "\<com\%[mand]!\=\>.*$" 
contains=vimUserAttrb,vimUserAttrbError,vimUserCommand,@vimUserCmdList,vimComFilter
+syn match      vimUserCmdName  contained       "\<\u\w*\>" 
nextgroup=vimUserCmdBlock skipwhite
+syn match      vimUserCmd      "\<com\%[mand]!\=\>.*$" 
contains=vimUserAttrb,vimUserAttrbError,vimUserCommand,@vimUserCmdList,vimComFilter,vimCmdBlock,vimUserCmdName
 syn match      vimUserAttrbError       contained       "- \+\ze\s"
 syn match      vimUserAttrb    contained       "-nargs=[01*?+]"        
contains=vimUserAttrbKey,vimOper
 syn match      vimUserAttrb    contained       "-complete="            
contains=vimUserAttrbKey,vimOper nextgroup=vimUserAttrbCmplt,vimUserCmdError
@@ -385,20 +394,41 @@ syn match vimUserAttrbCmpltFunc contained 
",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w*
 syn case match
 syn match      vimUserAttrbCmplt contained     "custom,\u\w*"
 
+syn region     vimUserCmdBlock contained       matchgroup=vimSep start="{" 
end="}" contains=@vimDefBodyList
+
 " Lower Priority Comments: after some vim commands... {{{2
 " =======================
-syn match      vimComment      excludenl +\s"[^\-:.%#=*].*$+lc=1       
contains=@vimCommentGroup,vimCommentString
-syn match      vimComment      +\<endif\s\+".*$+lc=5   
contains=@vimCommentGroup,vimCommentString
-syn match      vimComment      +\<else\s\+".*$+lc=4    
contains=@vimCommentGroup,vimCommentString
-syn region     vimCommentString        contained oneline start='\S\s\+"'ms=e   
end='"'
-" Vim9 comments - TODO: might be highlighted while they don't work
-syn match      vim9Comment     excludenl +\s#[^{].*$+lc=1      
contains=@vimCommentGroup,vimCommentString
-syn match      vim9Comment     +\<endif\s\+#[^{].*$+lc=5       
contains=@vimCommentGroup,vimCommentString
-syn match      vim9Comment     +\<else\s\+#[^{].*$+lc=4        
contains=@vimCommentGroup,vimCommentString
-" Vim9 comment inside expression
-syn match      vim9Comment     +\s\zs#[^{].*$+ms=s+1   
contains=@vimCommentGroup,vimCommentString
-syn match      vim9Comment     +^\s*#[^{].*$+  
contains=@vimCommentGroup,vimCommentString
-syn match      vim9Comment     +^\s*#$+        
contains=@vimCommentGroup,vimCommentString
+syn region     vimCommentString        contained oneline start='\S\s\+"'ms=e 
end='"'
+
+if s:vim9script
+  syn match    vimComment      excludenl +\s"[^\-:.%#=*].*$+lc=1       
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vimComment      +\<endif\s\+".*$+lc=5   
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vimComment      +\<else\s\+".*$+lc=4    
contains=@vimCommentGroup,vimCommentString contained
+  " Vim9 comments - TODO: might be highlighted while they don't work
+  syn match    vim9Comment     excludenl +\s#[^{].*$+lc=1      
contains=@vimCommentGroup,vimCommentString
+  syn match    vim9Comment     +\<endif\s\+#[^{].*$+lc=5       
contains=@vimCommentGroup,vimCommentString
+  syn match    vim9Comment     +\<else\s\+#[^{].*$+lc=4        
contains=@vimCommentGroup,vimCommentString
+  " Vim9 comment inside expression
+  " syn match  vim9Comment     +\s\zs#[^{].*$+ms=s+1   
contains=@vimCommentGroup,vimCommentString
+  " syn match  vim9Comment     +^\s*#[^{].*$+          
contains=@vimCommentGroup,vimCommentString
+  " syn match  vim9Comment     +^\s*#$+                
contains=@vimCommentGroup,vimCommentString
+
+  syn cluster vimComment contains=vim9Comment
+else
+  syn match    vimComment      excludenl +\s"[^\-:.%#=*].*$+lc=1       
contains=@vimCommentGroup,vimCommentString
+  syn match    vimComment      +\<endif\s\+".*$+lc=5   
contains=@vimCommentGroup,vimCommentString
+  syn match    vimComment      +\<else\s\+".*$+lc=4    
contains=@vimCommentGroup,vimCommentString
+  " Vim9 comments - TODO: might be highlighted while they don't work
+  syn match    vim9Comment     excludenl +\s#[^{].*$+lc=1      
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vim9Comment     +\<endif\s\+#[^{].*$+lc=5       
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vim9Comment     +\<else\s\+#[^{].*$+lc=4        
contains=@vimCommentGroup,vimCommentString contained
+  " Vim9 comment inside expression
+  syn match    vim9Comment     +\s\zs#[^{].*$+ms=s+1   
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vim9Comment     +^\s*#[^{].*$+          
contains=@vimCommentGroup,vimCommentString contained
+  syn match    vim9Comment     +^\s*#$+                
contains=@vimCommentGroup,vimCommentString contained
+
+  syn cluster vimComment contains=vimComment
+endif
 
 " Environment Variables: {{{2
 " =====================
@@ -488,7 +518,7 @@ syn match   vimCmplxRepeat  
'[^a-zA-Z_/\()]q[0-9a-zA-Z"]\>'lc=1
 syn match      vimCmplxRepeat  '@[0-9a-z".=@:]\ze\($\|[^a-zA-Z]\>\)'
 
 " Set command and associated set-options (vimOptions) with comment {{{2
-syn region     vimSet          matchgroup=vimCommand 
start="\<\%(setl\%[ocal]\|setg\%[lobal]\|se\%[t]\)\>" skip="\%(\\\)*\.
\@!" end="$" end="|" matchgroup=vimNotation end="<[cC][rR]>" keepend 
contains=vimSetEqual,vimOption,vimErrSetting,vimComment,vim9Comment,vimSetString,vimSetMod
+syn region     vimSet          matchgroup=vimCommand 
start="\<\%(setl\%[ocal]\|setg\%[lobal]\|se\%[t]\)\>" skip="\%(\\\)*\.
\@!" end="$" end="|" matchgroup=vimNotation end="<[cC][rR]>" keepend 
contains=vimSetEqual,vimOption,vimErrSetting,@vimComment,vimSetString,vimSetMod
 syn region     vimSetEqual     contained       start="[=:]\|[-+^]=" 
skip="\\\|\\s" end="[|     ]"me=e-1 end="$"        
contains=vimCtrlChar,vimSetSep,vimNotation,vimEnvvar
 syn region     vimSetString    contained       start=+="+hs=s+1        
skip=+\\\|\"+  end=+"+          contains=vimCtrlChar
 syn match      vimSetSep       contained       "[,:]"
@@ -522,9 +552,10 @@ syn keyword vimAbb abc[lear] cabc[lear] iabc[lear] 
skipwhite nextgroup=vimMapMod
 " =======
 syn match      vimAutoEventList        contained       "\(!\s\+\)\=\( \+,\)* 
\+"       contains=vimAutoEvent nextgroup=vimAutoCmdSpace
 syn match      vimAutoCmdSpace contained       "\s\+"  
nextgroup=vimAutoCmdSfxList
-syn match      vimAutoCmdSfxList       contained       "\S*"   skipwhite 
nextgroup=vimAutoCmdMod
+syn match      vimAutoCmdSfxList       contained       "\S*"   skipwhite 
nextgroup=vimAutoCmdMod,vimAutoCmdBlock
 syn keyword    vimAutoCmd      au[tocmd] do[autocmd] doautoa[ll]       
skipwhite nextgroup=vimAutoEventList
-syn match      vimAutoCmdMod   "\(++\)\=\(once\|nested\)"
+syn match      vimAutoCmdMod   "\(++\)\=\(once\|nested\)"      skipwhite 
nextgroup=vimAutoCmdBlock
+syn region     vimAutoCmdBlock contained       matchgroup=vimSep start="{" 
end="}" contains=@vimDefBodyList
 
 " Echo And Execute: -- prefer strings! {{{2
 " ================
@@ -668,7 +699,7 @@ if has("conceal")
  syn match     vimSynCcharValue        contained       "\S"
 endif
 
-syn match      vimSyntax       "\<sy\%[ntax]\>"        contains=vimCommand 
skipwhite nextgroup=vimSynType,vimComment,vim9Comment
+syn match      vimSyntax       "\<sy\%[ntax]\>"        contains=vimCommand 
skipwhite nextgroup=vimSynType,@vimComment
 syn cluster vimFuncBodyList add=vimSyntax
 
 " Syntax: case {{{2
@@ -757,7 +788,7 @@ syn match   vimIsCommand    "<Bar>\s* \+"   transparent 
contains=vimCommand,vimNotatio
 
 " Highlighting: {{{2
 " ============
-syn cluster    vimHighlightCluster             
contains=vimHiLink,vimHiClear,vimHiKeyList,vimComment,vim9Comment
+syn cluster    vimHighlightCluster             
contains=vimHiLink,vimHiClear,vimHiKeyList,@vimComment
 if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimhictermerror")
  syn match     vimHiCtermError contained       "\D\i*"
 endif
@@ -813,16 +844,21 @@ syn match vimCtrlChar     "[ -   - ]"
 
 " Beginners - Patterns that involve ^ {{{2
 " =========
-syn match      vimLineComment  +^[     :]*".*$+        
contains=@vimCommentGroup,vimCommentString,vimCommentTitle,vimComment
-syn match      vimLineComment  +^[     :]*"\("[^"]*"\|[^"]\)*$+        
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
-syn match      vim9LineComment +^[     :]\+#.*$+       
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+if s:vim9script
+  syn match    vimLineComment  +^[     :]*".*$+        
contains=@vimCommentGroup,vimCommentString,vimCommentTitle contained
+  syn match    vim9LineComment +^[     :]*#.*$+        
contains=@vimCommentGroup,vimCommentString,vim9CommentTitle
+else
+  syn match    vimLineComment  +^[     :]*".*$+        
contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+  syn match    vim9LineComment +^[     :]*#.*$+        
contains=@vimCommentGroup,vimCommentString,vim9CommentTitle contained
+endif
 syn match      vimCommentTitle 
'"\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1    contained 
contains=vimCommentTitleLeader,vimTodo,@vimCommentGroup
-" Note: Look-behind to work around nextgroup skipnl consuming leading 
whitespace and preventing a match
+syn match      vim9CommentTitle        
'#\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1    contained 
contains=vim9CommentTitleLeader,vimTodo,@vimCommentGroup
 syn match      vimContinue             "^\s*\zs\"
 syn match         vimContinueComment   '^\s*\zs["#]\ .*' contained
 syn cluster    vimContinue contains=vimContinue,vimContinueComment
 syn region     vimString       start="^\s*\\z(['"]\)" skip='\\\|\\z1' 
end="\z1" oneline keepend contains=@vimStringGroup,vimContinue
 syn match      vimCommentTitleLeader   '"\s\+'ms=s+1   contained
+syn match      vim9CommentTitleLeader  '#\s\+'ms=s+1   contained
 
 " Searches And Globals: {{{2
 " ====================
@@ -831,6 +867,17 @@ syn match  vimSearchDelim  '^\s*\zs[/?]\|[/?]$'    
contained
 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
 
+" Vim9 Script Regions: {{{2
+" ==================
+
+if s:vim9script
+  syn cluster vimLegacyTop 
contains=TOP,vimPreVim9script,vim9Comment,vim9LineComment
+  syn region vimPreVim9script start="\%^" end="^\ze\s*vim9s\%[cript]\>" 
contains=@vimLegacyTop,vimComment,vimLineComment
+
+  syn keyword vim9ScriptArg noclear
+  syn keyword vimCommand vim9s[cript] nextgroup=vim9ScriptArg skipwhite
+endif
+
 " Embedded Scripts:  {{{2
 " ================
 "   perl,ruby     : Benoit Cerrina
@@ -1038,6 +1085,7 @@ if !exists("skip_vim_syntax_inits")
   hi def link vimBufnrWarn     vimWarn
  endif
 
+ hi def link vim9ScriptArg     Special
  hi def link vimAbb    vimCommand
  hi def link vimAddress        vimMark
  hi def link vimAugroupBang    vimBang
@@ -1057,6 +1105,7 @@ if !exists("skip_vim_syntax_inits")
  hi def link vim9Comment       Comment
  hi def link vimCommentString  vimString
  hi def link vimCommentTitle   PreProc
+ hi def link vim9CommentTitle  PreProc
  hi def link vimCondHL vimCommand
  hi def link vimConst  vimCommand
  hi def link vimContinue       Special
@@ -1114,6 +1163,7 @@ if !exists("skip_vim_syntax_inits")
  hi def link vimHLGroup        vimGroup
  hi def link vimInsert vimString
  hi def link vimIskSep Delimiter
+ hi def link vim9KeymapLineComment     vimKeymapLineComment
  hi def link vimKeymapLineComment      vimComment
  hi def link vimKeymapTailComment      vimComment
  hi def link vimLet    vimCommand
@@ -1236,5 +1286,5 @@ delc VimFoldP
 delc VimFoldr
 delc VimFoldt
 let &cpo = s:keepcpo
-unlet s:keepcpo
+unlet s:keepcpo s:vim9script
 " vim:ts=18 fdm=marker ft=vim

-- 
-- 
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 vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1ruea5-002mnu-2i%40256bit.org.

Raspunde prin e-mail lui