" Vim syntax file " Language: CNM 0.3 " Maintainer: " Last Change: 2017-08-18 " Version: 0.1.0 " Filenames: *.cnm " Bugs: Nested syntaxes in raw blocks include block indentation if !exists('g:main_syntax') if exists('b:current_syntax') finish endif let g:main_syntax = 'cnm' " sync from the current top-level element syn sync match cnmSync grouphere NONE "^[^\t]" "syn sync fromstart endif function! s:generateRawSyntaxes() if !exists('g:cnm_raw_syntaxes') "let g:cnm_raw_syntaxes = { " \ 'text/json': 'json', " \ 'application/json': 'json', " \ 'json': 'json', let g:cnm_raw_syntaxes = { \ 'text/cnm': 'cnm', \ 'cnm': 'cnm', \ 'message/cnp': 'cnp', \ 'application/cnp': 'cnp', \ 'cnp': 'cnp', \ 'text/cnm-fmt': 'cnmfmt', \ 'cnm-fmt': 'cnmfmt', \ 'cnmfmt': 'cnmfmt', \ } endif if exists('g:cnm_raw_syntaxes_extra') for [l:k, l:v] in items(g:cnm_raw_syntaxes_extra) let g:cnm_raw_syntaxes[l:k] = l:v endfor endif " CNM and CNMfmt syntaxes are already defined below as clusters let l:syntaxes = {'Cnm': 1, 'Cnmfmt': 1} for [l:lang, l:syntax] in items(g:cnm_raw_syntaxes) let l:slang = substitute(l:syntax, '\(\w\+\)\W\?', '\u\1', 'g') "try if !has_key(l:syntaxes, l:slang) exe 'syn include @cnmLang' . l:slang . ' syntax/' . l:syntax . '.vim' unlet! b:current_syntax let l:syntaxes[l:slang] = 1 endif call s:generateBlock('raw ' . l:lang, 'cnmRaws', 'contained contains=@cnmLang' . l:slang) "catch "endtry endfor endfunction function! s:generateBlock(name, cluster, options) let l:region = 'cnm' . substitute(substitute(a:name, '\(\w\+\) \?', '\u\1', 'g'), '\W', '', 'g') let l:name = substitute(a:name, ' ', '\\s\\+', 'g') exe 'syn region ' . l:region . ' matchgroup=cnmBlock start="^\z(\t*\)\<' . l:name . '\(\s\|$\)\@=.*$" end="^\(\t*[^\t]\)\@=" skip="^\z1\t\+\([^\t]\)\@=" keepend ' . a:options exe 'syn cluster ' . a:cluster . ' add=' . l:region endfunction syn include @cnmFmt syntax/cnmfmt.vim " XXX: make `raw text/cnm` work syn cluster cnmLangCnm contains=@cnmToplevelBLocks,@cnmContentBlocks,cnmError " `raw text/cnm-fmt` syn cluster cnmLangCnmfmt contains=@cnmFmt " all blocks that contain other blocks syn cluster cnmToplevelBlocks contains=cnmUnknown syn cluster cnmContainerBlocks contains=cnmUnknown syn cluster cnmContentBlocks contains=cnmUnknown,@cnmContainerBlocks,@cnmTexts,@cnmRaws,cnmEmbed syn cluster cnmTableBlocks contains=cnmUnknown " misc. syn match cnmError ".*" syn match cnmEscape "\\[nt\\ ]" contained syn match cnmEscape "\\x\x\{2\}" contained syn match cnmEscape "\\u\x\{4\}" contained syn match cnmEscape "\\U\x\{8\}" contained " top-level blocks syn region cnmUnknown matchgroup=cnmError start="^\z(\t*\)[^\t].*$" end="^\(\t*[^\t]\)\@=" skip="^\z1\t\+\([^\t]\)\@=" keepend contains=cnmError call s:generateBlock('content', 'cnmToplevelBlocks', 'contains=@cnmContentBlocks') call s:generateBlock('site', 'cnmToplevelBlocks', 'contains=cnmSiteLines,cnmError') call s:generateBlock('title', 'cnmToplevelBlocks', 'contains=cnmEscape,@Spell') call s:generateBlock('links', 'cnmToplevelBlocks', 'contains=cnmLinkLines') " content/ call s:generateBlock('section', 'cnmContainerBlocks', 'contained contains=@cnmContentBlocks') call s:generateBlock('table', 'cnmContainerBlocks', 'contained contains=@cnmTableBlocks') call s:generateBlock('list', 'cnmContainerBlocks', 'contained contains=@cnmContentBlocks') " content/table/ call s:generateBlock('header', 'cnmTableBlocks', 'contained contains=@cnmContentBlocks') call s:generateBlock('row', 'cnmTableBlocks', 'contained contains=@cnmContentBlocks') " content/raw call s:generateBlock('raw', 'cnmRaws', 'contained') call s:generateRawSyntaxes() " content/text call s:generateBlock('text', 'cnmTexts', 'contained contains=cnmEscape,@Spell') call s:generateBlock('text plain', 'cnmTexts', 'contained contains=cnmEscape,@Spell') call s:generateBlock('text fmt', 'cnmTexts', 'contained contains=@cnmFmt,@Spell') " content/embed call s:generateBlock('embed', 'cnmEmbed', 'contained contains=cnmEscape,@Spell') " links/ syn match cnmLinkLines "^.*$" keepend contained contains=cnmLinkUrl,cnmLinkText syn match cnmLinkText "^\t\t.*" contained contains=cnmEscape syn match cnmLinkUrl "\S\+" contained " site/ syn match cnmSiteLines "^\t*[^\t ]\+\(\s.*\)\?$" keepend contained contains=cnmSitePath,cnmSiteText syn match cnmSitePath "\S\+" contained contains=cnmSiteSlash syn match cnmSiteText "\([^ \t]\)\@<=\s\+.*" contained contains=cnmEscape syn match cnmSiteSlash "/\S\@=" contained hi def link cnmBlock Keyword hi def link cnmError Error hi def link cnmLinkUrl Underlined hi def link cnmLinkText String hi def link cnmSitePath Underlined hi def link cnmSiteSlash Keyword hi def link cnmSiteText String "hi def link cnmText String hi def link cnmRaw String hi def link cnmEmbed String hi def link cnmTitle String hi def link cnmEscape Special syn match TODO "TODO" contained containedin=cnmText,@cnmFmt hi def link TODO TODO let b:current_syntax = 'cnm' if g:main_syntax ==# 'cnm' unlet g:main_syntax endif " vim: set noet: