summaryrefslogtreecommitdiffstats
path: root/syntax/cnm.vim
blob: 5d3fabf3bb8bc7abc77cf7486edd86c807624abb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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: