diff --git a/autoload/vimtex/options.vim b/autoload/vimtex/options.vim index 0366d64ffc..dbb32270a3 100644 --- a/autoload/vimtex/options.vim +++ b/autoload/vimtex/options.vim @@ -349,6 +349,7 @@ function! vimtex#options#init() abort " {{{1 call s:init_option('vimtex_syntax_conceal_disable', 0) call s:init_option('vimtex_syntax_custom_cmds', []) call s:init_option('vimtex_syntax_custom_cmds_with_concealed_delims', []) + call s:init_option('vimtex_syntax_custom_envs', []) call s:init_option('vimtex_syntax_nested', { \ 'aliases' : { \ 'C' : 'c', diff --git a/autoload/vimtex/syntax/core.vim b/autoload/vimtex/syntax/core.vim index 31619a4bd7..4611b5cca9 100644 --- a/autoload/vimtex/syntax/core.vim +++ b/autoload/vimtex/syntax/core.vim @@ -461,7 +461,10 @@ function! vimtex#syntax#core#init_rules() abort " {{{1 " {{{2 Zone: Verbatim " Verbatim environment - call vimtex#syntax#core#new_region_env('texVerbZone', '[vV]erbatim') + call vimtex#syntax#core#new_env({ + \ 'name': '[vV]erbatim', + \ 'region': 'texVerbZone', + \}) " Verbatim inline syntax match texCmdVerb "\\verb\>\*\?" nextgroup=texVerbZoneInline @@ -530,10 +533,26 @@ function! vimtex#syntax#core#init_rules() abort " {{{1 \}) " Math regions: environments - call vimtex#syntax#core#new_region_math('displaymath') - call vimtex#syntax#core#new_region_math('eqnarray') - call vimtex#syntax#core#new_region_math('equation') - call vimtex#syntax#core#new_region_math('math') + call vimtex#syntax#core#new_env({ + \ 'name': 'displaymath', + \ 'starred': v:true, + \ 'math': v:true + \}) + call vimtex#syntax#core#new_env({ + \ 'name': 'eqnarray', + \ 'starred': v:true, + \ 'math': v:true + \}) + call vimtex#syntax#core#new_env({ + \ 'name': 'equation', + \ 'starred': v:true, + \ 'math': v:true + \}) + call vimtex#syntax#core#new_env({ + \ 'name': 'math', + \ 'starred': v:true, + \ 'math': v:true + \}) " Math regions: Inline Math Zones let l:conceal = g:vimtex_syntax_conceal.math_bounds ? 'concealends' : '' @@ -704,6 +723,10 @@ function! vimtex#syntax#core#init_custom() abort " {{{1 for l:item in g:vimtex_syntax_custom_cmds_with_concealed_delims call vimtex#syntax#core#new_cmd_with_concealed_delims(l:item) endfor + + for l:item in g:vimtex_syntax_custom_envs + call vimtex#syntax#core#new_env(l:item) + endfor endfunction " }}}1 @@ -1150,52 +1173,87 @@ function! vimtex#syntax#core#new_cmd_with_concealed_delims(cfg) abort " {{{1 endfunction " }}}1 - -function! vimtex#syntax#core#new_region_env(grp, envname, ...) abort " {{{1 +function! vimtex#syntax#core#new_env(cfg) abort " {{{1 let l:cfg = extend({ - \ 'contains': '', + \ 'name': '', + \ 'region': '', + \ 'math': v:false, + \ 'math_nextgroup': '', + \ 'starred': v:false, + \ 'transparent': v:false, \ 'opts': '', - \ 'transparent': 0, - \}, a:0 > 0 ? a:1 : {}) + \ 'contains': '', + \ 'nested': '', + \ '__predicate': '', + \}, a:cfg) - let l:contains = 'contains=texCmdEnv' - if !empty(l:cfg.contains) - let l:contains .= ',' . l:cfg.contains + if type(l:cfg.nested) == v:t_dict && !empty(l:cfg.nested) + for [l:lang, l:predicate] in items(l:cfg.nested) + let l:nested_cfg = deepcopy(l:cfg) + let l:nested_cfg.nested = l:lang + let l:nested_cfg.__predicate = l:predicate + call vimtex#syntax#core#new_env(l:nested_cfg) + endfor + return endif - let l:options = 'keepend' - if l:cfg.transparent - let l:options .= ' transparent' - endif - if !empty(l:cfg.opts) - let l:options .= ' ' . l:cfg.opts - endif + let l:env_name = l:cfg.name . (l:cfg.starred ? '\*\?' : '') - execute 'syntax region' a:grp - \ 'start="\\begin{' . a:envname .'}"' - \ 'end="\\end{' . a:envname .'}"' - \ l:contains - \ l:options -endfunction + if l:cfg.math + let l:cfg.region = 'texMathZoneEnv' + let l:options = 'keepend' + let l:contains = 'contains=texMathEnvBgnEnd,@texClusterMath' -" }}}1 -function! vimtex#syntax#core#new_region_math(mathzone, ...) abort " {{{1 - let l:cfg = extend({ - \ 'starred': 1, - \ 'next': '', - \}, a:0 > 0 ? a:1 : {}) + let l:next = '' + if !empty(l:cfg.math_nextgroup) + let l:next = 'nextgroup=' . l:cfg.math_nextgroup . ' skipwhite skipnl' + endif + + execute 'syntax match texMathEnvBgnEnd' + \ '"\\\%(begin\|end\){' . l:env_name . '}"' + \ 'contained contains=texCmdMathEnv' + \ l:next + execute 'syntax match texMathError "\\end{' . l:env_name . '}"' + else + if empty(l:cfg.region) + let l:cfg.region = printf( + \ 'tex%sZone', + \ toupper(l:cfg.name[0]) . l:cfg.name[1:]) + endif - let l:envname = a:mathzone . (l:cfg.starred ? '\*\?' : '') + let l:options = 'keepend' + if l:cfg.transparent + let l:options .= ' transparent' + endif + if !empty(l:cfg.opts) + let l:options .= ' ' . l:cfg.opts + endif - execute 'syntax match texMathEnvBgnEnd "\\\%(begin\|end\)\>{' . l:envname . '}"' - \ 'contained contains=texCmdMathEnv' - \ (empty(l:cfg.next) ? '' : 'nextgroup=' . l:cfg.next . ' skipwhite skipnl') - execute 'syntax match texMathError "\\end{' . l:envname . '}"' - execute 'syntax region texMathZoneEnv' - \ 'start="\\begin{\z(' . l:envname . '\)}"' + let l:contains = 'contains=texCmdEnv' + if !empty(l:cfg.contains) + let l:contains .= ',' . l:cfg.contains + endif + + if !empty(l:cfg.nested) + let l:nested = vimtex#syntax#nested#include(l:cfg.nested) + if !empty(l:nested) + let l:contains .= ',' . l:nested + else + execute 'highlight def link' l:cfg.region 'texZone' + endif + endif + endif + + let l:start = '\\begin{\z(' . l:env_name .'\)}' + if !empty(l:cfg.__predicate) + let l:start .= '\s*\[\_[^\]]\{-}' . l:cfg.__predicate . '\_[^\]]\{-}\]' + endif + + execute 'syntax region' l:cfg.region + \ 'start="' . l:start . '"' \ 'end="\\end{\z1}"' - \ 'contains=texMathEnvBgnEnd,@texClusterMath' - \ 'keepend' + \ l:contains + \ l:options endfunction " }}}1 diff --git a/autoload/vimtex/syntax/nested.vim b/autoload/vimtex/syntax/nested.vim index 5ae254db0f..9f4379fbab 100644 --- a/autoload/vimtex/syntax/nested.vim +++ b/autoload/vimtex/syntax/nested.vim @@ -11,7 +11,7 @@ function! vimtex#syntax#nested#include(name) abort " {{{1 let s:included[l:inc_name] = s:include(l:inc_name, a:name) endif - return s:included[l:inc_name] ? l:inc_name : '' + return s:included[l:inc_name] ? '@' . l:inc_name : '' endfunction " }}}1 diff --git a/autoload/vimtex/syntax/p/amsmath.vim b/autoload/vimtex/syntax/p/amsmath.vim index 7f18a8c3fc..8e23ae7f16 100644 --- a/autoload/vimtex/syntax/p/amsmath.vim +++ b/autoload/vimtex/syntax/p/amsmath.vim @@ -7,14 +7,27 @@ scriptencoding utf-8 function! vimtex#syntax#p#amsmath#load(cfg) abort " {{{1 - call vimtex#syntax#core#new_region_math('align') - call vimtex#syntax#core#new_region_math('alignat') - call vimtex#syntax#core#new_region_math('flalign') - call vimtex#syntax#core#new_region_math('gather') - call vimtex#syntax#core#new_region_math('mathpar') - call vimtex#syntax#core#new_region_math('multline') - call vimtex#syntax#core#new_region_math('xalignat') - call vimtex#syntax#core#new_region_math('xxalignat', {'starred': 0}) + for l:env in [ + \ 'align', + \ 'alignat', + \ 'flalign', + \ 'gather', + \ 'mathpar', + \ 'multline', + \ 'xalignat', + \] + call vimtex#syntax#core#new_env(#{ + \ name: l:env, + \ starred: v:true, + \ math: v:true + \}) + endfor + + " This does not accept starred variant + call vimtex#syntax#core#new_env({ + \ 'name': 'xxalignat', + \ 'math': v:true + \}) syntax match texMathCmdEnv contained contains=texCmdMathEnv nextgroup=texMathArrayArg skipwhite skipnl "\\begin{subarray}" syntax match texMathCmdEnv contained contains=texCmdMathEnv nextgroup=texMathArrayArg skipwhite skipnl "\\begin{x\?alignat\*\?}" diff --git a/autoload/vimtex/syntax/p/asymptote.vim b/autoload/vimtex/syntax/p/asymptote.vim index aa41f17557..70ad323a7e 100644 --- a/autoload/vimtex/syntax/p/asymptote.vim +++ b/autoload/vimtex/syntax/p/asymptote.vim @@ -5,16 +5,11 @@ " function! vimtex#syntax#p#asymptote#load(cfg) abort " {{{1 - let l:opts = empty(vimtex#syntax#nested#include('asy')) - \ ? {} - \ : {'contains': '@vimtex_nested_asy'} - - call vimtex#syntax#core#new_region_env('texAsymptoteZone', 'asy', l:opts) - call vimtex#syntax#core#new_region_env('texAsymptoteZone', 'asydef', l:opts) - - if empty(l:opts) - highlight def link texAsymptoteZone texZone - endif + call vimtex#syntax#core#new_env({ + \ 'name': 'asy\(def\)?', + \ 'region': 'texAsymptoteZone', + \ 'nested': 'asy', + \}) endfunction " }}}1 diff --git a/autoload/vimtex/syntax/p/breqn.vim b/autoload/vimtex/syntax/p/breqn.vim index e11e41f6d5..5e8d69ec83 100644 --- a/autoload/vimtex/syntax/p/breqn.vim +++ b/autoload/vimtex/syntax/p/breqn.vim @@ -4,13 +4,14 @@ " Email: karl.yngve@gmail.com " -scriptencoding utf-8 - function! vimtex#syntax#p#breqn#load(cfg) abort " {{{1 - call vimtex#syntax#core#new_region_math('dmath') - call vimtex#syntax#core#new_region_math('dseries') - call vimtex#syntax#core#new_region_math('dgroup') - call vimtex#syntax#core#new_region_math('darray') + for l:env in ['dmath', 'dseries', 'dgroup', 'darray'] + call vimtex#syntax#core#new_env(#{ + \ name: l:env, + \ starred: v:true, + \ math: v:true + \}) + endfor endfunction " }}}1 diff --git a/autoload/vimtex/syntax/p/cases.vim b/autoload/vimtex/syntax/p/cases.vim index 484bea743a..538ebd6a1a 100644 --- a/autoload/vimtex/syntax/p/cases.vim +++ b/autoload/vimtex/syntax/p/cases.vim @@ -4,10 +4,11 @@ " Email: karl.yngve@gmail.com " -scriptencoding utf-8 - function! vimtex#syntax#p#cases#load(cfg) abort " {{{1 - call vimtex#syntax#core#new_region_math('\(sub\)\?numcases', {'starred': 0}) + call vimtex#syntax#core#new_env({ + \ 'name': '\(sub\)\?numcases', + \ 'math': v:true, + \}) endfunction " }}}1 diff --git a/autoload/vimtex/syntax/p/circuitikz.vim b/autoload/vimtex/syntax/p/circuitikz.vim index dc28ba71e1..9cb8bb66d8 100644 --- a/autoload/vimtex/syntax/p/circuitikz.vim +++ b/autoload/vimtex/syntax/p/circuitikz.vim @@ -10,9 +10,11 @@ function! vimtex#syntax#p#circuitikz#load(cfg) abort " {{{1 syntax match texTikzEnvBgn "\\begin{circuitikz}" \ nextgroup=texTikzOpt skipwhite skipnl \ contains=texCmdEnv - call vimtex#syntax#core#new_region_env('texTikzZone', 'circuitikz', { + call vimtex#syntax#core#new_env({ + \ 'name': 'circuitikz', + \ 'region': 'texTikzZone', \ 'contains': '@texClusterTikz', - \ 'transparent': 1, + \ 'transparent': v:true, \}) endfunction diff --git a/autoload/vimtex/syntax/p/dot2texi.vim b/autoload/vimtex/syntax/p/dot2texi.vim index 628acf8832..8616b33205 100644 --- a/autoload/vimtex/syntax/p/dot2texi.vim +++ b/autoload/vimtex/syntax/p/dot2texi.vim @@ -5,9 +5,11 @@ " function! vimtex#syntax#p#dot2texi#load(cfg) abort " {{{1 - call vimtex#syntax#nested#include('dot') - call vimtex#syntax#core#new_region_env('texDotZone', 'dot2tex', - \ {'contains': '@vimtex_nested_dot'}) + call vimtex#syntax#core#new_env({ + \ 'name': 'dot2tex', + \ 'region': 'texDotZone', + \ 'nested': 'dot' + \}) endfunction " }}}1 diff --git a/autoload/vimtex/syntax/p/empheq.vim b/autoload/vimtex/syntax/p/empheq.vim index c47f8e7296..47c6fa937c 100644 --- a/autoload/vimtex/syntax/p/empheq.vim +++ b/autoload/vimtex/syntax/p/empheq.vim @@ -5,8 +5,11 @@ " function! vimtex#syntax#p#empheq#load(cfg) abort " {{{1 - call vimtex#syntax#core#new_region_math('empheq', { - \ 'next': 'texEmpheqArg', + call vimtex#syntax#core#new_env({ + \ 'name': 'empheq', + \ 'starred': v:true, + \ 'math': v:true, + \ 'mtah_nextgroup': 'texEmpheqArg', \}) call vimtex#syntax#core#new_arg('texEmpheqArg') diff --git a/autoload/vimtex/syntax/p/gnuplottex.vim b/autoload/vimtex/syntax/p/gnuplottex.vim index d4cf787eac..8cecd689e3 100644 --- a/autoload/vimtex/syntax/p/gnuplottex.vim +++ b/autoload/vimtex/syntax/p/gnuplottex.vim @@ -5,9 +5,11 @@ " function! vimtex#syntax#p#gnuplottex#load(cfg) abort " {{{1 - call vimtex#syntax#nested#include('gnuplot') - call vimtex#syntax#core#new_region_env('texGnuplotZone', 'gnuplot', - \ {'contains': '@vimtex_nested_gnuplot'}) + call vimtex#syntax#core#new_env({ + \ 'name': 'gnuplot', + \ 'region': 'texGnuplotZone', + \ 'nested': 'gnuplot' + \}) endfunction " }}}1 diff --git a/autoload/vimtex/syntax/p/ieeetrantools.vim b/autoload/vimtex/syntax/p/ieeetrantools.vim index 6fc11247ed..175a059dfb 100644 --- a/autoload/vimtex/syntax/p/ieeetrantools.vim +++ b/autoload/vimtex/syntax/p/ieeetrantools.vim @@ -9,8 +9,11 @@ function! vimtex#syntax#p#ieeetrantools#load(cfg) abort " {{{1 call vimtex#syntax#core#new_opt('texMathEnvIEEEOpt', \ {'next': 'texMathEnvIEEEArg'}) for l:env in ['IEEEeqnarray', 'IEEEeqnarrayboxm'] - call vimtex#syntax#core#new_region_math(l:env, { - \ 'next': 'texMathEnvIEEEOpt,texMathEnvIEEEArg', + call vimtex#syntax#core#new_env({ + \ 'name': l:env, + \ 'starred': v:true, + \ 'math': v:true, + \ 'math_nextgroup': 'texMathEnvIEEEOpt,texMathEnvIEEEArg', \}) endfor diff --git a/autoload/vimtex/syntax/p/listings.vim b/autoload/vimtex/syntax/p/listings.vim index e9b2dcb05c..0f1531c8c3 100644 --- a/autoload/vimtex/syntax/p/listings.vim +++ b/autoload/vimtex/syntax/p/listings.vim @@ -24,7 +24,9 @@ function! vimtex#syntax#p#listings#load(cfg) abort " {{{1 syntax match texLstEnvBgn "\\begin{lstlisting}" \ nextgroup=texLstOpt skipwhite skipnl contains=texCmdEnv call vimtex#syntax#core#new_opt('texLstOpt') - call vimtex#syntax#core#new_region_env('texLstZone', 'lstlisting', { + call vimtex#syntax#core#new_env({ + \ 'name': 'lstlisting', + \ 'region': 'texLstZone', \ 'contains': 'texLstEnvBgn', \}) @@ -46,14 +48,15 @@ function! vimtex#syntax#p#listings#load(cfg) abort " {{{1 let l:name = toupper(l:nested[0]) . l:nested[1:] let l:grp = 'texLstZone' . l:name let l:grp_inline = 'texLstZoneInline' . l:name - let l:cluster = '@' . l:cluster execute 'syntax match texLstsetArg' \ '"\c{\_[^}]*language=' . l:nested . '\%(\s*,\|}\)"' \ 'nextgroup=' . l:grp 'skipwhite skipnl' \ 'contains=texLstsetArg' - call vimtex#syntax#core#new_region_env(l:grp, 'lstlisting', { + call vimtex#syntax#core#new_env({ + \ 'name': 'lstlisting', + \ 'region': l:grp, \ 'contains': 'texLstEnvBgn,' . l:cluster, \ 'opts': 'contained', \}) diff --git a/autoload/vimtex/syntax/p/luacode.vim b/autoload/vimtex/syntax/p/luacode.vim index 628de4b0e5..203fd1ebe2 100644 --- a/autoload/vimtex/syntax/p/luacode.vim +++ b/autoload/vimtex/syntax/p/luacode.vim @@ -5,10 +5,12 @@ " function! vimtex#syntax#p#luacode#load(cfg) abort " {{{1 - call vimtex#syntax#nested#include('lua') - - call vimtex#syntax#core#new_region_env('texLuaZone', 'luacode\*\?', - \ {'contains': '@vimtex_nested_lua,texCmd'}) + call vimtex#syntax#core#new_env({ + \ 'name': 'luacode\*\?', + \ 'region': 'texLuaZone', + \ 'contains': 'texCmd', + \ 'nested': 'lua', + \}) syntax match texCmdLua "\\\%(directlua\|luadirect\)\>" \ nextgroup=texLuaArg skipwhite skipnl diff --git a/autoload/vimtex/syntax/p/markdown.vim b/autoload/vimtex/syntax/p/markdown.vim index 925435b532..c4f5691c3b 100644 --- a/autoload/vimtex/syntax/p/markdown.vim +++ b/autoload/vimtex/syntax/p/markdown.vim @@ -5,11 +5,15 @@ " function! vimtex#syntax#p#markdown#load(cfg) abort " {{{1 - call vimtex#syntax#nested#include('markdown') - call vimtex#syntax#core#new_region_env('texMarkdownZone', 'markdown', - \ {'contains': 'texCmd,@vimtex_nested_markdown'}) + call vimtex#syntax#core#new_env({ + \ 'name': 'markdown', + \ 'region': 'texMarkdownZone', + \ 'contains': 'texCmd', + \ 'nested': 'markdown', + \}) - syntax match texCmdInput "\\markdownInput\>" nextgroup=texFileArg skipwhite skipnl + syntax match texCmdInput "\\markdownInput\>" + \ nextgroup=texFileArg skipwhite skipnl endfunction " }}}1 diff --git a/autoload/vimtex/syntax/p/mhequ.vim b/autoload/vimtex/syntax/p/mhequ.vim index 19adf072d9..fc049d2ce5 100644 --- a/autoload/vimtex/syntax/p/mhequ.vim +++ b/autoload/vimtex/syntax/p/mhequ.vim @@ -5,8 +5,11 @@ " function! vimtex#syntax#p#mhequ#load(cfg) abort " {{{1 - call vimtex#syntax#core#new_region_math('equ') - call vimtex#syntax#core#new_region_math('equs') + call vimtex#syntax#core#new_env({ + \ 'name': 'equs\?', + \ 'starred': v:true, + \ 'math': v:true + \}) endfunction " }}}1 diff --git a/autoload/vimtex/syntax/p/minted.vim b/autoload/vimtex/syntax/p/minted.vim index ca5d60c5cd..87a99901dd 100644 --- a/autoload/vimtex/syntax/p/minted.vim +++ b/autoload/vimtex/syntax/p/minted.vim @@ -30,7 +30,9 @@ function! vimtex#syntax#p#minted#load(cfg) abort " {{{1 call vimtex#syntax#core#new_arg('texMintedEnvArgOpt', {'contains': ''}) " Match generic minted environment regions - call vimtex#syntax#core#new_region_env('texMintedZone', 'minted', { + call vimtex#syntax#core#new_env({ + \ 'name': 'minted', + \ 'region': 'texMintedZone', \ 'contains': 'texCmdEnv,texMintedEnvBgn', \}) @@ -56,8 +58,8 @@ function! vimtex#syntax#p#minted#load(cfg) abort " {{{1 let l:contains_inline = '' if !empty(l:cluster) - let l:contains .= ',@' . l:cluster - let l:contains_inline = '@' . l:cluster + let l:contains .= ',' . l:cluster + let l:contains_inline = l:cluster else execute 'highlight def link' l:grp_env 'texMintedZone' execute 'highlight def link' l:grp_inline 'texMintedZoneInline' diff --git a/autoload/vimtex/syntax/p/moreverb.vim b/autoload/vimtex/syntax/p/moreverb.vim index 620c77f15b..65b0a9bd39 100644 --- a/autoload/vimtex/syntax/p/moreverb.vim +++ b/autoload/vimtex/syntax/p/moreverb.vim @@ -5,9 +5,12 @@ " function! vimtex#syntax#p#moreverb#load(cfg) abort " {{{1 - call vimtex#syntax#core#new_region_env('texVerbZone', 'verbatimtab') - call vimtex#syntax#core#new_region_env('texVerbZone', 'verbatimwrite') - call vimtex#syntax#core#new_region_env('texVerbZone', 'boxedverbatim') + for l:env in ['verbatimtab', 'verbatimwrite', 'boxedverbatim'] + call vimtex#syntax#core#new_env({ + \ 'name': l:env, + \ 'region': 'texVerbZone' + \}) + endfor endfunction " }}}1 diff --git a/autoload/vimtex/syntax/p/optidef.vim b/autoload/vimtex/syntax/p/optidef.vim index b24d4c42e2..8be6f7ef25 100644 --- a/autoload/vimtex/syntax/p/optidef.vim +++ b/autoload/vimtex/syntax/p/optidef.vim @@ -5,10 +5,15 @@ " function! vimtex#syntax#p#optidef#load(cfg) abort " {{{1 - call vimtex#syntax#core#new_region_math('\(arg\)\?mini') - call vimtex#syntax#core#new_region_math('\(arg\)\?mini[e!]', {'starred': 0}) - call vimtex#syntax#core#new_region_math('\(arg\)\?maxi') - call vimtex#syntax#core#new_region_math('\(arg\)\?maxi\!', {'starred': 0}) + call vimtex#syntax#core#new_env({ + \ 'name': '\(arg\)\?\(mini\|maxi\)', + \ 'starred': v:true, + \ 'math': v:true, + \}) + call vimtex#syntax#core#new_env({ + \ 'name': '\(arg\)\?\(mini[e!]\|maxi\!\)', + \ 'math': v:true, + \}) endfunction -" }}}1 \ No newline at end of file +" }}}1 diff --git a/autoload/vimtex/syntax/p/pgfplots.vim b/autoload/vimtex/syntax/p/pgfplots.vim index b7ceabccc1..4859b3350a 100644 --- a/autoload/vimtex/syntax/p/pgfplots.vim +++ b/autoload/vimtex/syntax/p/pgfplots.vim @@ -14,9 +14,11 @@ function! vimtex#syntax#p#pgfplots#load(cfg) abort " {{{1 syntax match texTikzEnvBgn contains=texCmdEnv nextgroup=texTikzOpt skipwhite skipnl "\\begin{\%(log\)*axis}" syntax match texTikzEnvBgn contains=texCmdEnv nextgroup=texTikzOpt skipwhite skipnl "\\begin{groupplot}" for l:env in ['axis', 'logaxis', 'loglogaxis', 'groupplot'] - call vimtex#syntax#core#new_region_env('texTikzZone', l:env, { + call vimtex#syntax#core#new_env({ + \ 'name': l:env, + \ 'region': 'texTikzZone', \ 'contains': '@texClusterTikz', - \ 'transparent': 1, + \ 'transparent': v:true, \}) endfor diff --git a/autoload/vimtex/syntax/p/pyluatex.vim b/autoload/vimtex/syntax/p/pyluatex.vim index eb1f45a5fb..20a9272914 100644 --- a/autoload/vimtex/syntax/p/pyluatex.vim +++ b/autoload/vimtex/syntax/p/pyluatex.vim @@ -5,12 +5,11 @@ " function! vimtex#syntax#p#pyluatex#load(cfg) abort " {{{1 - call vimtex#syntax#nested#include('python') - - for l:env in ['python', 'pythonq', 'pythonrepl'] - call vimtex#syntax#core#new_region_env( - \ 'texPyluatexZone', l:env, {'contains': '@vimtex_nested_python'}) - endfor + call vimtex#syntax#core#new_env({ + \ 'name': 'python\(q\|repl\)\?', + \ 'region': 'texPyluatexZone', + \ 'nested': 'python', + \}) highlight def link texCmdPyluatex texCmd endfunction diff --git a/autoload/vimtex/syntax/p/pythontex.vim b/autoload/vimtex/syntax/p/pythontex.vim index 17ba22d23f..497c4ab52d 100644 --- a/autoload/vimtex/syntax/p/pythontex.vim +++ b/autoload/vimtex/syntax/p/pythontex.vim @@ -8,15 +8,19 @@ function! vimtex#syntax#p#pythontex#load(cfg) abort " {{{1 call vimtex#syntax#nested#include('python') syntax match texCmdPythontex /\\py[bsc]\?/ nextgroup=texPythontexArg skipwhite skipnl - call vimtex#syntax#core#new_arg('texPythontexArg', {'contains': '@vimtex_nested_python', 'opts': 'contained keepend'}) + call vimtex#syntax#core#new_arg('texPythontexArg', { + \ 'contains': '@vimtex_nested_python', + \ 'opts': 'contained keepend' + \}) syntax region texPythontexArg matchgroup=texDelim \ start='\z([#@]\)' end='\z1' \ contained contains=@vimtex_nested_python keepend - call vimtex#syntax#core#new_region_env('texPythontexZone', 'pyblock', - \ {'contains': '@vimtex_nested_python'}) - call vimtex#syntax#core#new_region_env('texPythontexZone', 'pycode', - \ {'contains': '@vimtex_nested_python'}) + call vimtex#syntax#core#new_env({ + \ 'name': 'py\%(block\|code\)', + \ 'region': 'texPythontexZone', + \ 'contains': '@vimtex_nested_python' + \}) highlight def link texCmdPythontex texCmd endfunction diff --git a/autoload/vimtex/syntax/p/sagetex.vim b/autoload/vimtex/syntax/p/sagetex.vim index 700ba317f0..a413f3d659 100644 --- a/autoload/vimtex/syntax/p/sagetex.vim +++ b/autoload/vimtex/syntax/p/sagetex.vim @@ -12,12 +12,17 @@ function! vimtex#syntax#p#sagetex#load(cfg) abort " {{{1 syntax match texCmdSagetex /\\sageplot\>/ \ nextgroup=texSagetexOpt,texSagetexArg skipwhite skipnl - call vimtex#syntax#core#new_arg('texSagetexArg', - \ {'contains': '@vimtex_nested_python', 'opts': 'contained keepend'}) + call vimtex#syntax#core#new_arg('texSagetexArg', { + \ 'contains': '@vimtex_nested_python', + \ 'opts': 'contained keepend' + \}) call vimtex#syntax#core#new_opt('texSagetexOpt', {'next': 'texSagetexArg'}) - call vimtex#syntax#core#new_region_env('texSagetexZone', 'sagesilent', - \ {'contains': '@vimtex_nested_python'}) + call vimtex#syntax#core#new_env({ + \ 'name': 'sagesilent', + \ 'region': 'texSagetexZone', + \ 'contains': '@vimtex_nested_python' + \}) highlight def link texCmdSagetex texCmd endfunction diff --git a/autoload/vimtex/syntax/p/tcolorbox.vim b/autoload/vimtex/syntax/p/tcolorbox.vim index 539c33b5e7..7f63317439 100644 --- a/autoload/vimtex/syntax/p/tcolorbox.vim +++ b/autoload/vimtex/syntax/p/tcolorbox.vim @@ -15,8 +15,10 @@ function! vimtex#syntax#p#tcolorbox#load(cfg) abort " {{{1 " Add listing support for detected environments for l:env in b:vimtex.syntax.tcolorbox.listing_envs - call vimtex#syntax#core#new_region_env('texTCBZone', l:env, { - \'contains': 'texCmdEnv,texCmdTCBEnv', + call vimtex#syntax#core#new_env({ + \ 'name': l:env, + \ 'region': 'texTCBZone', + \ 'contains': 'texCmdEnv,texCmdTCBEnv', \}) endfor diff --git a/autoload/vimtex/syntax/p/tikz.vim b/autoload/vimtex/syntax/p/tikz.vim index 09ad5651d8..3510be65c4 100644 --- a/autoload/vimtex/syntax/p/tikz.vim +++ b/autoload/vimtex/syntax/p/tikz.vim @@ -16,9 +16,11 @@ function! vimtex#syntax#p#tikz#load(cfg) abort " {{{1 syntax match texTikzEnvBgn "\\begin{tikzpicture}" \ nextgroup=texTikzOpt skipwhite skipnl \ contains=texCmdEnv - call vimtex#syntax#core#new_region_env('texTikzZone', 'tikzpicture', { + call vimtex#syntax#core#new_env({ + \ 'name': 'tikzpicture', + \ 'region': 'texTikzZone', \ 'contains': '@texClusterTikz', - \ 'transparent': 1 + \ 'transparent': v:true \}) call vimtex#syntax#core#new_opt('texTikzOpt', \ {'contains': '@texClusterTikzset'}) diff --git a/autoload/vimtex/syntax/p/witharrows.vim b/autoload/vimtex/syntax/p/witharrows.vim index 6e9f82c33c..2aceff7857 100644 --- a/autoload/vimtex/syntax/p/witharrows.vim +++ b/autoload/vimtex/syntax/p/witharrows.vim @@ -5,7 +5,11 @@ " function! vimtex#syntax#p#witharrows#load(cfg) abort " {{{1 - call vimtex#syntax#core#new_region_math('DispWithArrows') + call vimtex#syntax#core#new_env({ + \ 'name': 'DispWithArrows', + \ 'starred': v:true, + \ 'math': v:true + \}) syntax match texMathCmdText "\\Arrow\>" \ contained skipwhite nextgroup=texMathTextArg diff --git a/doc/vimtex.txt b/doc/vimtex.txt index 17e31dbbc2..386877336e 100644 --- a/doc/vimtex.txt +++ b/doc/vimtex.txt @@ -2726,6 +2726,98 @@ OPTIONS *vimtex-options* < Default value: [] +*g:vimtex_syntax_custom_envs* + A list of environments for which to apply custom styling. This allows to + define custom math environments or to specify custom environments for which + to load nested syntaxes. The latter is relevant e.g. if you use the + `\lstnewenvironment` from the `listings` package. + + Each environment is expected to look like this: >latex + + \begin{env_name}[optional argument] + … + \end{env_name} +< + It is important to be aware that these customizations will be applied on top + of the existing syntax rules. They may therefore override both the core + syntax rules and extensions from syntax packages. + + Each element in the list must be a dictionary with the following keys: + + name ~ + Default: Undefined (REQUIRED) + The name of the environment to highlight (`env_name`). The string is + used as a regular expression. + + region ~ + Default: Undefined (REQUIRED, unless `math` is |v:true|) + The syntax group used to match the defined region. + + math ~ + Default: |v:false| + If true, then the environment is a math region. + + starred ~ + Default: |v:false| + Whether the corresponding starred environment should also be matched. + + transparent ~ + Default: |v:false| + If the matched syntax region should be transparent: |syn-transparent|. + + opts ~ + Default: Undefined + A string with additional options that will be passed to the `syntax + region` command (see |syn-region|). + + contains ~ + Default: Undefined + A comma-separated string of syntax groups that should be contained in + within the matched region (see |syn-contains|). + + nested ~ + Default: Undefined + This can be either a string or a dictionary: + + |String|: specify nested syntax to load inside the environment + |Dictionary|: specify "predicated" nested syntaxes (more flexible) + + The dictionary uses the target syntax as the key and the "predicate" as + the value. This predicate is a string that must be contained within the + optional argument. See below for an example. + + Notice that one should also be aware of |g:vimtex_syntax_nested|. + + The following example creates three rules. The first creates the environment + `MyMathEnv` that opens a new math environment. The second creates + a `python_code` environment that applies nested Python syntax rules in the + environment region. The third rule creates a `code` environment that will + open nested syntax regions if the optional group contains the specified + predicate strings. >vim + + let g:vimtex_syntax_custom_envs = [ + \ { + \ 'name': 'MyMathEnv', + \ 'math': v:true + \ }, + \ { + \ 'name': 'python_code', + \ 'region': 'texPythonCodeZone', + \ 'nested': 'python', + \ }, + \ { + \ 'name': 'code', + \ 'region': 'texCodeZone', + \ 'nested': { + \ 'python': 'language=python', + \ 'c': 'language=C', + \ 'rust': 'language=rust', + \ }, + \ }, + \] +< + Default value: [] + *g:vimtex_syntax_nested* A dictionary for configuring nested syntaxes. The following keys are available for configuration: diff --git a/test/test-syntax/test-custom-envs.tex b/test/test-syntax/test-custom-envs.tex new file mode 100644 index 0000000000..3a92538e7c --- /dev/null +++ b/test/test-syntax/test-custom-envs.tex @@ -0,0 +1,35 @@ +\documentclass{minimal} + +\usepackage{listings} +\lstnewenvironment{code}[1][]{\lstset{#1}}{} +\lstnewenvironment{python_code}{\lstset{language=python}}{} + +\begin{document} + +\begin{MyMathEnv} + f(x) = 1 +\end{MyMathEnv} + +\begin{python_code} +def test(argument: str) -> str: + """ + Test function. + """ + return argument +\end{python_code} + +\begin{code}[language=rust] +fn main() { + println!("Hello World!"); +} +\end{code} + +\begin{code}[language=C] +#include +main() { + int i = 0; + printf("Hello World"); +} +\end{code} + +\end{document} diff --git a/test/test-syntax/test-custom-envs.vim b/test/test-syntax/test-custom-envs.vim new file mode 100644 index 0000000000..e3e630fb3e --- /dev/null +++ b/test/test-syntax/test-custom-envs.vim @@ -0,0 +1,28 @@ +source common.vim + +let g:vimtex_syntax_custom_envs = [ + \ { + \ 'name': 'MyMathEnv', + \ 'math': v:true + \ }, + \ { + \ 'name': 'python_code', + \ 'region': 'texPythonCodeZone', + \ 'nested': 'python', + \ }, + \ { + \ 'name': 'code', + \ 'region': 'texCodeZone', + \ 'nested': { + \ 'python': 'language=python', + \ 'c': 'language=C', + \ 'rust': 'language=rust', + \ }, + \ }, + \] + +Edit test-custom-envs.tex + +if empty($INMAKE) | finish | endif + +call vimtex#test#finished()