From d4584903f3a7123a389332afa2620f2b997b7f1b Mon Sep 17 00:00:00 2001 From: Muntasir Mahmud Date: Sun, 9 Mar 2025 15:13:52 +0600 Subject: [PATCH] vim-patch:9.1.1188: runtime(tera): tera support can be improved (#32799) Problem: runtime(tera): tera support can be improved Solution: update tera filetype plugin, include a tera syntax script update the filetype test, update makemenu and synmenu vim scripts (MuntasirSZN) closes: vim/vim#16830 vim/vim@14da0fb --- runtime/ftplugin/tera.vim | 23 ++++++- runtime/makemenu.vim | 3 +- runtime/synmenu.vim | 41 ++++++------- runtime/syntax/tera.vim | 96 ++++++++++++++++++++++++++++++ test/old/testdir/test_filetype.vim | 2 +- 5 files changed, 140 insertions(+), 25 deletions(-) create mode 100644 runtime/syntax/tera.vim diff --git a/runtime/ftplugin/tera.vim b/runtime/ftplugin/tera.vim index 47636f29fa..65bae70048 100644 --- a/runtime/ftplugin/tera.vim +++ b/runtime/ftplugin/tera.vim @@ -1,13 +1,30 @@ " Vim filetype plugin file " Language: Tera " Maintainer: Muntasir Mahmud -" Last Change: 2025 Mar 06 +" Last Change: 2025 Mar 08 if exists("b:did_ftplugin") finish endif let b:did_ftplugin = 1 -setlocal commentstring={#\ %s\ #} +setlocal autoindent -let b:undo_ftplugin = "setlocal commentstring<" +setlocal commentstring={#\ %s\ #} +setlocal comments=s:{#,e:#} + +if exists("loaded_matchit") + let b:match_ignorecase = 0 + let b:match_words = '{#:##\|#},{% *if:{% *else\>:{% *elif\>:{% *endif %},{% *for\>:{% *endfor %},{% *macro\>:{% *endmacro %},{% *block\>:{% *endblock %},{% *filter\>:{% *endfilter %},{% *set\>:{% *endset %},{% *raw\>:{% *endraw %},{% *with\>:{% *endwith %}' +endif + +setlocal includeexpr=substitute(v:fname,'\\([^.]*\\)$','\\1','g') +setlocal suffixesadd=.tera + +setlocal expandtab +setlocal shiftwidth=2 +setlocal softtabstop=2 + +let b:undo_ftplugin = "setlocal autoindent< commentstring< comments< " .. + \ "includeexpr< suffixesadd< expandtab< shiftwidth< softtabstop<" +let b:undo_ftplugin .= "|unlet! b:match_ignorecase b:match_words" diff --git a/runtime/makemenu.vim b/runtime/makemenu.vim index 01f214cfa0..3d27bfc551 100644 --- a/runtime/makemenu.vim +++ b/runtime/makemenu.vim @@ -1,6 +1,6 @@ " Script to define the syntax menu in synmenu.vim " Maintainer: The Vim Project -" Last Change: 2023 Aug 10 +" Last Change: 2025 Mar 09 " Former Maintainer: Bram Moolenaar " This is used by "make menu" in the src directory. @@ -602,6 +602,7 @@ SynMenu T.Tcl/Tk:tcl SynMenu T.TealInfo:tli SynMenu T.Telix\ Salt:tsalt SynMenu T.Termcap/Printcap:ptcap +SynMenu T.Tera:tera SynMenu T.Terminfo:terminfo SynMenu T.Tera\ Term:teraterm SynMenu T.TeX.TeX/LaTeX:tex diff --git a/runtime/synmenu.vim b/runtime/synmenu.vim index edc6eabd1d..6a3bb8eaf4 100644 --- a/runtime/synmenu.vim +++ b/runtime/synmenu.vim @@ -582,26 +582,27 @@ an 50.150.190 &Syntax.T.TealInfo :cal SetSyn("tli") an 50.150.200 &Syntax.T.Telix\ Salt :cal SetSyn("tsalt") an 50.150.210 &Syntax.T.Termcap/Printcap :cal SetSyn("ptcap") an 50.150.220 &Syntax.T.Terminfo :cal SetSyn("terminfo") -an 50.150.230 &Syntax.T.Tera\ Term :cal SetSyn("teraterm") -an 50.150.240 &Syntax.T.TeX.TeX/LaTeX :cal SetSyn("tex") -an 50.150.250 &Syntax.T.TeX.plain\ TeX :cal SetSyn("plaintex") -an 50.150.260 &Syntax.T.TeX.Initex :cal SetSyn("initex") -an 50.150.270 &Syntax.T.TeX.ConTeXt :cal SetSyn("context") -an 50.150.280 &Syntax.T.TeX.TeX\ configuration :cal SetSyn("texmf") -an 50.150.290 &Syntax.T.TeX.Texinfo :cal SetSyn("texinfo") -an 50.150.300 &Syntax.T.TF\ mud\ client :cal SetSyn("tf") -an 50.150.310 &Syntax.T.Tidy\ configuration :cal SetSyn("tidy") -an 50.150.320 &Syntax.T.Tilde :cal SetSyn("tilde") -an 50.150.330 &Syntax.T.Tmux\ configuration :cal SetSyn("tmux") -an 50.150.340 &Syntax.T.TPP :cal SetSyn("tpp") -an 50.150.350 &Syntax.T.Trasys\ input :cal SetSyn("trasys") -an 50.150.360 &Syntax.T.Treetop :cal SetSyn("treetop") -an 50.150.370 &Syntax.T.Trustees :cal SetSyn("trustees") -an 50.150.380 &Syntax.T.TSS.Command\ Line :cal SetSyn("tsscl") -an 50.150.390 &Syntax.T.TSS.Geometry :cal SetSyn("tssgm") -an 50.150.400 &Syntax.T.TSS.Optics :cal SetSyn("tssop") -an 50.150.410 &Syntax.T.Typescript :cal SetSyn("typescript") -an 50.150.420 &Syntax.T.TypescriptReact :cal SetSyn("typescriptreact") +an 50.150.230 &Syntax.T.Tera :cal SetSyn("tera") +an 50.150.240 &Syntax.T.Tera\ Term :cal SetSyn("teraterm") +an 50.150.250 &Syntax.T.TeX.TeX/LaTeX :cal SetSyn("tex") +an 50.150.260 &Syntax.T.TeX.plain\ TeX :cal SetSyn("plaintex") +an 50.150.270 &Syntax.T.TeX.Initex :cal SetSyn("initex") +an 50.150.280 &Syntax.T.TeX.ConTeXt :cal SetSyn("context") +an 50.150.290 &Syntax.T.TeX.TeX\ configuration :cal SetSyn("texmf") +an 50.150.300 &Syntax.T.TeX.Texinfo :cal SetSyn("texinfo") +an 50.150.310 &Syntax.T.TF\ mud\ client :cal SetSyn("tf") +an 50.150.320 &Syntax.T.Tidy\ configuration :cal SetSyn("tidy") +an 50.150.330 &Syntax.T.Tilde :cal SetSyn("tilde") +an 50.150.340 &Syntax.T.Tmux\ configuration :cal SetSyn("tmux") +an 50.150.350 &Syntax.T.TPP :cal SetSyn("tpp") +an 50.150.360 &Syntax.T.Trasys\ input :cal SetSyn("trasys") +an 50.150.370 &Syntax.T.Treetop :cal SetSyn("treetop") +an 50.150.380 &Syntax.T.Trustees :cal SetSyn("trustees") +an 50.150.390 &Syntax.T.TSS.Command\ Line :cal SetSyn("tsscl") +an 50.150.400 &Syntax.T.TSS.Geometry :cal SetSyn("tssgm") +an 50.150.410 &Syntax.T.TSS.Optics :cal SetSyn("tssop") +an 50.150.420 &Syntax.T.Typescript :cal SetSyn("typescript") +an 50.150.430 &Syntax.T.TypescriptReact :cal SetSyn("typescriptreact") an 50.160.100 &Syntax.UV.Udev\ config :cal SetSyn("udevconf") an 50.160.110 &Syntax.UV.Udev\ permissions :cal SetSyn("udevperm") an 50.160.120 &Syntax.UV.Udev\ rules :cal SetSyn("udevrules") diff --git a/runtime/syntax/tera.vim b/runtime/syntax/tera.vim new file mode 100644 index 0000000000..922b9c9752 --- /dev/null +++ b/runtime/syntax/tera.vim @@ -0,0 +1,96 @@ +" Vim syntax file +" Language: Tera +" Maintainer: Muntasir Mahmud +" Last Change: 2025 Mar 09 + +if exists("b:current_syntax") + finish +endif + +" Detect the underlying language based on filename pattern +" For files like file.html.tera, we want to load html syntax +let s:filename = expand("%:t") +let s:dotpos = strridx(s:filename, '.', strridx(s:filename, '.tera') - 1) +let s:underlying_filetype = "" + +if s:dotpos != -1 + let s:underlying_ext = s:filename[s:dotpos+1:strridx(s:filename, '.tera')-1] + if s:underlying_ext != "" && s:underlying_ext != "tera" + let s:underlying_filetype = s:underlying_ext + endif +endif + +" Load the underlying language syntax if detected +if s:underlying_filetype != "" + execute "runtime! syntax/" . s:underlying_filetype . ".vim" + unlet! b:current_syntax +else + " Default to HTML if no specific language detected + runtime! syntax/html.vim + unlet! b:current_syntax +endif + +" Tera comment blocks: {# comment #} +syn region teraCommentBlock start="{#" end="#}" contains=@Spell containedin=cssDefinition,cssStyle,htmlHead,htmlTitle + +" Tera statements: {% if condition %} +syn region teraStatement start="{%" end="%}" contains=teraKeyword,teraString,teraNumber,teraFunction,teraBoolean,teraFilter,teraOperator containedin=cssDefinition,cssStyle,htmlHead,htmlTitle + +" Tera expressions: {{ variable }} +syn region teraExpression start="{{" end="}}" contains=teraString,teraNumber,teraFunction,teraBoolean,teraFilter,teraOperator,teraIdentifier containedin=cssDefinition,cssStyle,htmlHead,htmlTitle + +" Special handling for raw blocks - content inside shouldn't be processed +syn region teraRawBlock start="{% raw %}" end="{% endraw %}" contains=TOP,teraCommentBlock,teraStatement,teraExpression + +" Control structure keywords +syn keyword teraKeyword contained if else elif endif for endfor in macro endmacro +syn keyword teraKeyword contained block endblock extends include import set endset +syn keyword teraKeyword contained break continue filter endfilter raw endraw with endwith + +" Identifiers - define before operators for correct priority +syn match teraIdentifier contained "\<\w\+\>" + +" Operators used in expressions and statements +syn match teraOperator contained "==\|!=\|>=\|<=\|>\|<\|+\|-\|*\|/" +syn match teraOperator contained "{\@" +syn match teraNumber contained "\<\d\+\.\d\+\>" + +" Boolean values +syn keyword teraBoolean contained true false + +" Highlighting links +hi def link teraCommentBlock Comment +hi def link teraKeyword Statement +hi def link teraOperator Operator +hi def link teraFunction Function +hi def link teraIdentifier Identifier +hi def link teraString String +hi def link teraNumber Number +hi def link teraBoolean Boolean +hi def link teraFilter PreProc + +" Special highlighting for blocks and expressions +hi def link teraStatement PreProc +hi def link teraExpression PreProc + +" Clean up script-local variables +unlet s:filename +unlet s:dotpos +if exists("s:underlying_ext") + unlet s:underlying_ext +endif +unlet s:underlying_filetype + +let b:current_syntax = "tera" diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim index 590a460f3c..296062f92c 100644 --- a/test/old/testdir/test_filetype.vim +++ b/test/old/testdir/test_filetype.vim @@ -801,7 +801,7 @@ func s:GetFilenameChecks() abort \ 'teal': ['file.tl'], \ 'templ': ['file.templ'], \ 'template': ['file.tmpl'], - \ 'tera': ['file.tera'], + \ 'tera': ['file.tera', 'file.toml.tera', 'file.html.tera', 'file.css.tera'], \ 'teraterm': ['file.ttl'], \ 'terminfo': ['file.ti'], \ 'terraform-vars': ['file.tfvars'],