fix(syntax): highlight code blocks with embedded language syntax
CI / cargo fmt --check (push) Successful in 1m10s
CI / cargo clippy (push) Successful in 19s
CI / cargo test (push) Successful in 28s
Release / build x86_64-unknown-linux-gnu (push) Successful in 1m1s
Release / build aarch64-unknown-linux-musl (push) Successful in 54s
Release / build aarch64-unknown-linux-gnu (push) Successful in 1m8s
Release / build x86_64-unknown-linux-musl (push) Successful in 1m13s
CI / editor keymaps (push) Successful in 1m32s
Release / gitea release (push) Successful in 23s
CI / cargo fmt --check (push) Successful in 1m10s
CI / cargo clippy (push) Successful in 19s
CI / cargo test (push) Successful in 28s
Release / build x86_64-unknown-linux-gnu (push) Successful in 1m1s
Release / build aarch64-unknown-linux-musl (push) Successful in 54s
Release / build aarch64-unknown-linux-gnu (push) Successful in 1m8s
Release / build x86_64-unknown-linux-musl (push) Successful in 1m13s
CI / editor keymaps (push) Successful in 1m32s
Release / gitea release (push) Successful in 23s
`{{{lang … }}}` fences were painted as one String group. Add automatic
nested-syntax highlighting (like vimwiki): scan the buffer for the languages
used, `:syntax include` each under a cluster, and define a contained region
per language so e.g. `{{{sh` blocks get shell highlighting and `{{{python`
gets Python. Bare `{{{` / `{{{class="…"` fences fall back to nuwikiPreformatted.
A small alias map maps labels like bash/shell → sh.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+72
-1
@@ -75,7 +75,7 @@ syntax match nuwikiHeading6 /^\s*======\s.\{-}\s======\s*$/
|
||||
syntax match nuwikiHorizontal /^-\{4,}\s*$/
|
||||
syntax match nuwikiCommentLine /^%%.*$/
|
||||
syntax region nuwikiCommentBlock start=/^%%+/ end=/+%%/ keepend
|
||||
syntax region nuwikiPreformatted start=/^{{{/ end=/^}}}/ keepend
|
||||
syntax region nuwikiPreformatted matchgroup=nuwikiPreDelim start=/^\s*{{{/ end=/^\s*}}}\s*$/ keepend
|
||||
syntax region nuwikiMathBlock start=/^{{\$/ end=/^}}\$/ keepend
|
||||
syntax match nuwikiPlaceholder /^%\(title\|nohtml\|template\|date\)\>.*$/
|
||||
|
||||
@@ -117,6 +117,7 @@ highlight default link nuwikiHorizontal Comment
|
||||
highlight default link nuwikiCommentLine Comment
|
||||
highlight default link nuwikiCommentBlock Comment
|
||||
highlight default link nuwikiPreformatted String
|
||||
highlight default link nuwikiPreDelim Comment
|
||||
highlight default link nuwikiMathBlock Number
|
||||
highlight default link nuwikiPlaceholder PreProc
|
||||
" Bold / Italic use explicit attributes so they work in plain Vim too (no
|
||||
@@ -134,4 +135,74 @@ highlight default link nuwikiWikilink Underlined
|
||||
highlight default link nuwikiTransclusion Identifier
|
||||
highlight default link nuwikiUrl Underlined
|
||||
|
||||
" ===== Nested syntax for code blocks =====
|
||||
"
|
||||
" Highlight `{{{lang … }}}` fences with the embedded language's syntax, like
|
||||
" vimwiki's automatic nested syntaxes. We scan the buffer for the languages
|
||||
" actually used, `:syntax include` each one under a cluster, then define a
|
||||
" contained region per language. Defined *after* nuwikiPreformatted so the
|
||||
" language regions win for tagged fences (Vim gives later items priority),
|
||||
" while bare `{{{` / `{{{class="…"` fences fall back to nuwikiPreformatted.
|
||||
|
||||
" Labels that don't match a Vim filetype name 1:1.
|
||||
let s:nuwiki_nested_aliases = {
|
||||
\ 'bash': 'sh', 'shell': 'sh', 'zsh': 'sh', 'console': 'sh',
|
||||
\ 'js': 'javascript', 'ts': 'typescript', 'py': 'python',
|
||||
\ 'rs': 'rust', 'yml': 'yaml', 'md': 'markdown', 'c++': 'cpp',
|
||||
\ }
|
||||
|
||||
" The language label of a fence line: the first whitespace-separated token
|
||||
" after `{{{` that isn't a `key=val` attribute (mirrors the Rust lexer).
|
||||
function! s:nuwiki_fence_label(line) abort
|
||||
let l:after = matchstr(a:line, '^\s*{{{\zs.*$')
|
||||
for l:tok in split(l:after, '\s\+')
|
||||
if l:tok !~# '='
|
||||
return l:tok
|
||||
endif
|
||||
endfor
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:nuwiki_setup_nested() abort
|
||||
let l:included = {}
|
||||
let l:defined = {}
|
||||
for l:lnum in range(1, line('$'))
|
||||
let l:line = getline(l:lnum)
|
||||
if l:line !~# '^\s*{{{'
|
||||
continue
|
||||
endif
|
||||
let l:label = s:nuwiki_fence_label(l:line)
|
||||
if l:label ==# '' || has_key(l:defined, l:label)
|
||||
continue
|
||||
endif
|
||||
let l:defined[l:label] = 1
|
||||
let l:ft = get(s:nuwiki_nested_aliases, tolower(l:label), tolower(l:label))
|
||||
let l:cluster = 'nuwikiNested_' . substitute(l:ft, '[^a-zA-Z0-9]', '_', 'g')
|
||||
if !has_key(l:included, l:cluster)
|
||||
if exists('b:current_syntax')
|
||||
unlet b:current_syntax
|
||||
endif
|
||||
try
|
||||
execute 'syntax include @' . l:cluster . ' syntax/' . l:ft . '.vim'
|
||||
catch
|
||||
" No syntax file for this language — leave it to nuwikiPreformatted.
|
||||
continue
|
||||
endtry
|
||||
if exists('b:current_syntax')
|
||||
unlet b:current_syntax
|
||||
endif
|
||||
let l:included[l:cluster] = 1
|
||||
endif
|
||||
let l:region = 'nuwikiNestedRegion_' . substitute(l:label, '[^a-zA-Z0-9]', '_', 'g')
|
||||
execute 'syntax region ' . l:region
|
||||
\ . ' matchgroup=nuwikiPreDelim'
|
||||
\ . ' start=/^\s*{{{\s*' . escape(l:label, '/\.*$^~[]') . '\>.*$/'
|
||||
\ . ' end=/^\s*}}}\s*$/'
|
||||
\ . ' contains=@' . l:cluster
|
||||
\ . ' keepend'
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
call s:nuwiki_setup_nested()
|
||||
|
||||
let b:current_syntax = 'vimwiki'
|
||||
|
||||
Reference in New Issue
Block a user