Files
nuwiki/syntax/vimwiki.vim
T

218 lines
9.8 KiB
VimL
Raw Normal View History

" syntax/vimwiki.vim — default highlight groups for nuwiki.
"
" Two responsibilities:
" 1. Default `@vimwiki*` highlight groups for the LSP semantic tokens.
" Loaded eagerly so the very first hover/highlight
" cycle after server startup already has colours.
" 2. A small regex-based fallback so static highlighting works on
" buffers where the LSP isn't running yet.
"
" The `@group.modifier` group names are Neovim's Tree-sitter convention
" — plain Vim rejects `@` and `.` with W18, so the LSP-token defaults
" are gated behind `has('nvim')`. The static fallback below works
" everywhere.
if exists('b:current_syntax')
finish
endif
" ===== Semantic-token defaults (Neovim only — uses TS-style @group names) =====
if has('nvim')
" Headings — level modifiers map to progressively softer accents.
highlight default link @vimwikiHeading Title
highlight default link @vimwikiHeading.level1 Title
highlight default link @vimwikiHeading.level2 Function
highlight default link @vimwikiHeading.level3 Identifier
highlight default link @vimwikiHeading.level4 Type
highlight default link @vimwikiHeading.level5 Constant
highlight default link @vimwikiHeading.level6 PreProc
highlight default link @vimwikiHeading.centered Title
" Inline text styling.
" Use @markup.* (nvim 0.9+ treesitter standard groups, defined by all
" colorschemes) instead of markdownBold/Italic which only exist when the
" markdown treesitter parser is loaded — never the case in a vimwiki buffer.
highlight default link @vimwikiBold @markup.strong
highlight default link @vimwikiItalic @markup.italic
highlight default link @vimwikiBoldItalic @markup.strong
highlight default link @vimwikiStrikethrough @markup.strikethrough
highlight default link @vimwikiSuperscript Special
highlight default link @vimwikiSubscript Special
" Code + math.
highlight default link @vimwikiCode @markup.raw.inline
highlight default link @vimwikiCodeBlock @markup.raw.block
highlight default link @vimwikiMath Number
highlight default link @vimwikiMathBlock Number
" Links + transclusions.
highlight default link @vimwikiWikilink @markup.link
highlight default link @vimwikiExternalLink @markup.link.url
highlight default link @vimwikiUrl @markup.link.url
highlight default link @vimwikiTransclusion Identifier
" Misc.
highlight default link @vimwikiKeyword Todo
highlight default link @vimwikiComment Comment
highlight default link @vimwikiDefinitionTerm Statement
" NOTE: no default for @vimwikiColor. Colour spans are coloured client-side
" in their *actual* colour by nuwiki#colors#refresh() (conceal + per-colour
" highlight); linking the LSP token to a fixed group here would override that
" real colour on the concealed text in Neovim.
endif
" ===== Static fallback (no LSP required) =====
syntax case match
" One match per heading level so colorschemes can style each differently.
" Each pattern requires whitespace immediately after the equals run, which
" makes the levels mutually exclusive (`==` won't match `===`).
syntax match nuwikiHeading1 /^\s*=\s.\{-}\s=\s*$/
syntax match nuwikiHeading2 /^\s*==\s.\{-}\s==\s*$/
syntax match nuwikiHeading3 /^\s*===\s.\{-}\s===\s*$/
syntax match nuwikiHeading4 /^\s*====\s.\{-}\s====\s*$/
syntax match nuwikiHeading5 /^\s*=====\s.\{-}\s=====\s*$/
syntax match nuwikiHeading6 /^\s*======\s.\{-}\s======\s*$/
syntax match nuwikiHorizontal /^-\{4,}\s*$/
syntax match nuwikiCommentLine /^%%.*$/
syntax region nuwikiCommentBlock 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\)\>.*$/
syntax match nuwikiBold /\*[^*]\+\*/ contains=nuwikiBoldDelim
syntax match nuwikiBoldDelim /\*/ contained conceal
syntax match nuwikiItalic /\<_[^_]\+_\>/ contains=nuwikiItalicDelim
syntax match nuwikiItalicDelim /_/ contained conceal
syntax match nuwikiCode /`[^`]\+`/ contains=nuwikiCodeDelim
syntax match nuwikiCodeDelim /`/ contained conceal
syntax match nuwikiMathInline /\$[^$]\+\$/
" Two keyword groups so the editor can colour them like the HTML export:
" attention/pending (red) vs resolved/in-progress (green).
2026-05-28 22:05:23 -03:00
syntax match nuwikiKeywordAttn /\<\(TODO\|FIXME\|XXX\|STOPPED\)\>/
syntax match nuwikiKeywordDone /\<\(DONE\|FIXED\|STARTED\)\>/
" Wikilink conceal: hide [[ / ]], and for [[target|desc]] hide target|.
syntax region nuwikiWikilink start=/\[\[/ end=/\]\]/ keepend contains=nuwikiWikilinkBracket,nuwikiWikilinkTarget
syntax match nuwikiWikilinkBracket /\[\[/ contained conceal
syntax match nuwikiWikilinkBracket /\]\]/ contained conceal
syntax match nuwikiWikilinkTarget /[^|\]]*|/ contained conceal
syntax region nuwikiTransclusion start=/{{[^{]/ end=/}}/ keepend
syntax match nuwikiUrl /\<\(https\?\|ftp\|mailto\|file\):\/\?\/\?\S\+/
" Heading levels map to progressively softer accents — matches the Neovim
" semantic-token mapping above so static fallback and LSP-driven highlights
" agree. Colorschemes that don't differentiate Title vs Function vs etc.
" will still show all six as the same colour, but most do.
highlight default link nuwikiHeading1 Title
highlight default link nuwikiHeading2 Function
highlight default link nuwikiHeading3 Identifier
highlight default link nuwikiHeading4 Type
highlight default link nuwikiHeading5 Constant
highlight default link nuwikiHeading6 PreProc
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
" dependency on the 'Bold' / 'Italic' groups which are Neovim-only).
highlight default nuwikiBold gui=bold cterm=bold term=bold
highlight default nuwikiItalic gui=italic cterm=italic term=italic
highlight default link nuwikiCode String
highlight default link nuwikiMathInline Number
" Explicit colours (not a `Todo` link) so the red/green split is visible in any
" colorscheme. Matches the HTML export: TODO/FIXME/XXX red, DONE/FIXED/STARTED
" green.
highlight default nuwikiKeywordAttn gui=bold cterm=bold term=bold guifg=#F44747 ctermfg=203
highlight default nuwikiKeywordDone gui=bold cterm=bold term=bold guifg=#2EA043 ctermfg=35
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()
" Conceal `:VimwikiColorize` spans (`<span style="color:…">…</span>`) down to
" their coloured text. Reset the per-buffer cache first so a syntax reload
" (e.g. on :colorscheme) re-establishes the regions cleared by `:syntax clear`.
let b:nuwiki_color_seen = {}
call nuwiki#colors#refresh()
let b:current_syntax = 'vimwiki'