summaryrefslogtreecommitdiffstats
path: root/syntax/cnm.vim
diff options
context:
space:
mode:
Diffstat (limited to 'syntax/cnm.vim')
-rw-r--r--syntax/cnm.vim151
1 files changed, 151 insertions, 0 deletions
diff --git a/syntax/cnm.vim b/syntax/cnm.vim
new file mode 100644
index 0000000..5d3fabf
--- /dev/null
+++ b/syntax/cnm.vim
@@ -0,0 +1,151 @@
+" Vim syntax file
+" Language: CNM 0.3
+" Maintainer: <clsr@clsr.net>
+" 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: