summaryrefslogtreecommitdiffstats
path: root/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'syntax')
-rw-r--r--syntax/cnm.vim151
-rw-r--r--syntax/cnmfmt.vim87
-rw-r--r--syntax/cnp.vim113
3 files changed, 351 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:
diff --git a/syntax/cnmfmt.vim b/syntax/cnmfmt.vim
new file mode 100644
index 0000000..8787f08
--- /dev/null
+++ b/syntax/cnmfmt.vim
@@ -0,0 +1,87 @@
+" Vim syntax file
+" Language: CNMfmt (CNM 0.3)
+" Maintainer: <clsr@clsr.net>
+" Last Change: 2017-08-18
+" Version: 0.1.0
+" Bugs: expects LIFO tags
+
+if !exists('g:main_syntax')
+ if exists('b:current_syntax')
+ finish
+ endif
+ let g:main_syntax = 'cnmfmt'
+endif
+
+let s:fmts = {
+ \ 'B': {'tag': '\*', 'cterm': 'bold'},
+ \ 'I': {'tag': '/', 'cterm': 'italic'},
+ \ 'U': {'tag': '_', 'cterm': 'underline'},
+ \ 'M': {'tag': '`', 'cterm': 'inverse'},
+\ }
+
+let s:fmtkeepend = 1
+
+function! s:generateFmt(name)
+ let l:region = 'cnmfmt' . a:name
+ let l:cterm = 'cterm='
+ let l:containedin = []
+ let l:fmts = split(a:name, '\zs')
+ let l:tag = s:fmts[l:fmts[-1]]['tag']
+ let l:tag2 = l:tag . l:tag
+ let l:containedin = ''
+
+ for l:f in l:fmts
+ let l:cterm = l:cterm . s:fmts[l:f]['cterm'] . ','
+ endfor
+
+ if strlen(a:name) > 1
+ let l:containedin = ' containedin=cnmfmt' . a:name[:-2]
+ endif
+
+ " XXX: with keepend, URLs close too soon; without, tags don't close if not LIFO
+ exe 'syn region ' . l:region . ' start="' . l:tag2 . '" end="' . l:tag2 . '\|\n\t*\n" skip="\\\\\|\\' . l:tag . '" contained contains=@cnmfmts' . l:containedin . (s:fmtkeepend?' keepend':'')
+ exe 'hi def ' . l:region . ' ' . l:cterm[:-2]
+
+ for l:k in keys(s:fmts)
+ if index(l:fmts, l:k) < 0
+ call s:generateFmt(a:name . l:k)
+ endif
+ endfor
+endfunction
+
+for s:f in keys(s:fmts)
+ call s:generateFmt(s:f)
+endfor
+
+
+syn cluster cnmfmt contains=@cnmfmts,@cnmfmtStyles
+syn cluster cnmfmts contains=cnmfmtLink,cnmfmtEscape
+syn cluster cnmfmtStyles contains=cnmfmtB,cnmfmtI,cnmfmtU,cnmfmtM
+
+syn region cnmfmtLink matchgroup=cnmfmtLinkAt start="@@" end="@@\|\n\t*\n" skip="\\\\\|\\@" keepend contained contains=cnmfmtLinkUrl
+
+syn match cnmfmtLinkText ".*" contained contains=@cnmfmtStyles
+syn match cnmfmtLinkUrl "\(\\ \|\S\)\+" contained nextgroup=cnmfmtLinkText
+
+syn match cnmfmtEscape +\\[nt\\ */_`@]+
+syn match cnmfmtEscape +\\x\x\{2\}+
+syn match cnmfmtEscape +\\u\x\{4\}+
+syn match cnmfmtEscape +\\U\x\{8\}+
+
+
+syn match cnmfmtText "\%^\_.*\%$" contains=@cnmfmt,@Spell
+
+
+hi def link cnmfmtEscape Special
+hi def link cnmfmtLinkAt Special
+hi def link cnmfmtLinkUrl String
+hi def link cnmfmtLinkText Underlined
+
+
+let b:current_syntax = 'cnmfmt'
+if g:main_syntax ==# 'cnmfmt'
+ unlet g:main_syntax
+endif
+
+
+" vim: set noet:
diff --git a/syntax/cnp.vim b/syntax/cnp.vim
new file mode 100644
index 0000000..da9f4ba
--- /dev/null
+++ b/syntax/cnp.vim
@@ -0,0 +1,113 @@
+" Vim syntax file
+" Language: CNP 0.3rc1
+" Maintainer: <clsr@clsr.net>
+" Last Change: 2017-08-05
+" Version: 0.1.0-dev
+
+if !exists('g:main_syntax')
+ if exists('b:current_syntax')
+ finish
+ endif
+ let g:main_syntax = 'cnp'
+ syn sync minlines=50
+endif
+
+
+function! s:generateParamKey(kname, vname, key)
+ exe 'syn match cnpKey' . a:kname . ' "' . a:key . '=" contained contains=cnpParameterEquals nextgroup=cnpVal' . a:vname . ',cnpError'
+ exe 'syn cluster cnpDefinedParams add=cnpKey' . a:kname
+ exe 'hi def link cnpKey' . a:kname . ' cnpParameterKey'
+endfunction
+
+function! s:generateParamVal(vname, value)
+ exe 'syn match cnpVal' . a:vname . ' "' . a:value . '" contained contains=cnpEscape nextgroup=cnpError'
+ exe 'hi def link cnpVal' . a:vname . ' cnpParameterValue'
+endfunction
+
+
+syn match cnpError ".*"
+syn match cnpCR "\r$"
+
+if g:main_syntax ==# 'cnp'
+ syn match cnpVersion "^cnp/\(0\|[1-9][0-9]*\)\.\(0\|[1-9][0-9]*\)" contains=cnpSupported,cnpUnsupported nextgroup=cnpIntent
+else " allow embedding in e.g. markdown or cnm with indent
+ syn match cnpVersion "^\s*cnp/\(0\|[1-9][0-9]*\)\.\(0\|[1-9][0-9]*\)" contains=cnpSupported,cnpUnsupported nextgroup=cnpIntent
+endif
+
+syn match cnpUnsupported "cnp/\d\+\.\d\+" contained
+syn match cnpSupported "cnp/0\.3" contained
+"syn match cnpSupported "cnp/0\.4" contained
+
+syn match cnpIntent " \([^\n=\\ ]\|\\[n_0\\-]\)\+\n\?" contained contains=cnpError,cnpIntentMisc,cnpIntentResponse,cnpIntentRequest keepend nextgroup=cnpParameters,cnpBody
+
+syn match cnpIntentMisc " \([^/\n=\\ ]\|\\[n_0\\-]\)\+" contained contains=cnpEscape
+
+syn match cnpIntentResponse " ok\>" contained
+syn match cnpIntentResponse " not_modified\>" contained
+syn match cnpIntentResponse " redirect\>" contained
+syn match cnpIntentResponse " error\>" contained
+
+syn match cnpIntentRequest " \([^/\n=\\ ]\|\\[n_0\\-]\)*/" contained nextgroup=cnpIntentFilename contains=cnpIntentSlash,cnpEscape
+syn match cnpIntentFilename "\([^/\n=\\ ]\|\\[n_0\\-]\)\+" contained nextgroup=cnpIntentSlash contains=cnpEscape
+syn match cnpIntentSlash "/\+" contained nextgroup=cnpIntentFilename
+
+syn region cnpParameters start=" " end="\n\+" contains=cnpError,cnpParameter contained nextgroup=cnpBody
+syn match cnpParameter " \([^\n=\\ ]\|\\[n_0\\-]\)*=\([^\n=\\ ]\|\\[n_0\\-]\)*" contained contains=cnpParameterKey,@cnpDefinedParams keepend nextgroup=cnpParameter
+syn match cnpParameterKey "\([^\n=\\ ]\|\\[n_0\\-]\)*" contained nextgroup=cnpParameterEquals contains=cnpEscape
+syn match cnpParameterEquals "=" contained nextgroup=cnpParameterValue
+syn match cnpParameterValue "\([^\n=\\ ]\|\\[n_0\\-]\)*" contained contains=cnpEscape,cnpCR
+
+syn region cnpBody start="^" end="\%$" contained
+"syn match cnpBody "\_.*" contained
+
+syn match cnpEscape "\\[n_0\\-]" contained
+
+
+call s:generateParamKey('Length', 'Number', 'length')
+call s:generateParamVal('Number', '0\|[1-9][0-9]*')
+
+call s:generateParamKey('Type', 'MIME', 'type')
+call s:generateParamVal('MIME', '\(x-\)\?[a-z]\+/\([a-zA-Z0-9+._-]\+\|\*\)')
+
+call s:generateParamKey('Name', 'Filename', 'name')
+call s:generateParamVal('Filename', '\([^\n=\\/ ]\|\\[n_\\-]\)*')
+
+call s:generateParamKey('Time', 'RFC3339', 'time')
+call s:generateParamKey('Modified', 'RFC3339', 'modified')
+call s:generateParamKey('IfModified', 'RFC3339', 'if_modified')
+call s:generateParamVal('RFC3339', '\d\{4}-\d\{2}-\d\{2}T\d\{2}:\d\{2}:\d\{2}Z')
+
+call s:generateParamKey('Location', 'ReqIntent', 'location')
+call s:generateParamVal('ReqIntent', '\([^/\n=\\ ]\|\\[n_\\-]\)*\(/\([^/\n=\\ ]\|\\[n_\\-]\)*\)\+')
+
+call s:generateParamKey('Reason', 'Reason', 'reason')
+call s:generateParamVal('Reason', '\<\(syntax\|version\|invalid\|not_supported\|too_large\|not_found\|denied\|rejected\|server_error\)\>')
+
+call s:generateParamKey('Select', 'Selector', 'select')
+call s:generateParamVal('Selector', 'bytes:\(0\|[1-9][0-9]*\)\?-\(0\|[1-9][0-9]*\)\?')
+
+
+hi def link cnpError Error
+hi def link cnpUnsupported TODO
+hi def link cnpSupported Keyword
+hi def link cnpIntentRequest Identifier
+hi def link cnpIntentSlash String
+hi def link cnpIntentFilename String
+hi def link cnpIntentResponse Special
+hi def link cnpIntentMisc TODO
+hi def link cnpParameterKey Identifier
+hi def link cnpParameterEquals Special
+hi def link cnpParameterValue String
+hi def link cnpEscape Special
+hi def link cnpBody Comment
+
+hi def link cnpCR TODO
+
+
+let b:current_syntax = 'cnp'
+if g:main_syntax ==# 'cnp'
+ unlet g:main_syntax
+endif
+
+
+" vim: set noet: