spacevim/autoload/SpaceVim/api/data/toml.vim
JIe 2bb7059579
Some checks failed
Detach Plugins / check (FlyGrep.vim) (push) Has been cancelled
Detach Plugins / check (GitHub.vim) (push) Has been cancelled
Detach Plugins / check (JavaUnit.vim) (push) Has been cancelled
Detach Plugins / check (SourceCounter.vim) (push) Has been cancelled
Detach Plugins / check (cpicker.nvim) (push) Has been cancelled
Detach Plugins / check (dein-ui.vim) (push) Has been cancelled
Detach Plugins / check (git.vim) (push) Has been cancelled
Detach Plugins / check (iedit.vim) (push) Has been cancelled
Detach Plugins / check (scrollbar.vim) (push) Has been cancelled
Detach Plugins / check (vim-chat) (push) Has been cancelled
Detach Plugins / check (vim-cheat) (push) Has been cancelled
Detach Plugins / check (vim-todo) (push) Has been cancelled
Detach Plugins / check (xmake.vim) (push) Has been cancelled
test / Linux (nvim, nightly) (push) Has been cancelled
test / Linux (nvim, v0.3.8) (push) Has been cancelled
test / Linux (nvim, v0.4.0) (push) Has been cancelled
test / Linux (nvim, v0.4.2) (push) Has been cancelled
test / Linux (nvim, v0.4.3) (push) Has been cancelled
test / Linux (nvim, v0.4.4) (push) Has been cancelled
test / Linux (nvim, v0.5.0) (push) Has been cancelled
test / Linux (nvim, v0.5.1) (push) Has been cancelled
test / Linux (nvim, v0.6.0) (push) Has been cancelled
test / Linux (nvim, v0.6.1) (push) Has been cancelled
test / Linux (nvim, v0.7.0) (push) Has been cancelled
test / Linux (nvim, v0.7.2) (push) Has been cancelled
test / Linux (nvim, v0.8.0) (push) Has been cancelled
test / Linux (nvim, v0.8.1) (push) Has been cancelled
test / Linux (nvim, v0.8.2) (push) Has been cancelled
test / Linux (nvim, v0.8.3) (push) Has been cancelled
test / Linux (nvim, v0.9.0) (push) Has been cancelled
test / Linux (nvim, v0.9.1) (push) Has been cancelled
test / Linux (true, vim, v7.4.052) (push) Has been cancelled
test / Linux (true, vim, v7.4.1689) (push) Has been cancelled
test / Linux (true, vim, v7.4.629) (push) Has been cancelled
test / Linux (true, vim, v8.0.0027) (push) Has been cancelled
test / Linux (true, vim, v8.0.0183) (push) Has been cancelled
test / Linux (vim, nightly) (push) Has been cancelled
test / Linux (vim, v8.0.0184) (push) Has been cancelled
test / Linux (vim, v8.0.1453) (push) Has been cancelled
test / Linux (vim, v8.1.2269) (push) Has been cancelled
test / Linux (vim, v8.2.2434) (push) Has been cancelled
test / Linux (vim, v8.2.3995) (push) Has been cancelled
test / Windows (nvim, nightly) (push) Has been cancelled
test / Windows (nvim, v0.3.8) (push) Has been cancelled
test / Windows (nvim, v0.4.2) (push) Has been cancelled
test / Windows (nvim, v0.4.3) (push) Has been cancelled
test / Windows (nvim, v0.4.4) (push) Has been cancelled
test / Windows (nvim, v0.5.0) (push) Has been cancelled
test / Windows (nvim, v0.5.1) (push) Has been cancelled
test / Windows (nvim, v0.6.0) (push) Has been cancelled
test / Windows (nvim, v0.6.1) (push) Has been cancelled
test / Windows (nvim, v0.7.0) (push) Has been cancelled
test / Windows (nvim, v0.7.2) (push) Has been cancelled
test / Windows (nvim, v0.8.0) (push) Has been cancelled
test / Windows (nvim, v0.8.1) (push) Has been cancelled
test / Windows (nvim, v0.8.2) (push) Has been cancelled
test / Windows (nvim, v0.8.3) (push) Has been cancelled
test / Windows (nvim, v0.9.0) (push) Has been cancelled
test / Windows (nvim, v0.9.1) (push) Has been cancelled
test / Windows (vim, nightly) (push) Has been cancelled
test / Windows (vim, v7.4.1185) (push) Has been cancelled
test / Windows (vim, v7.4.1689) (push) Has been cancelled
test / Windows (vim, v8.0.0027) (push) Has been cancelled
test / Windows (vim, v8.0.1453) (push) Has been cancelled
test / Windows (vim, v8.1.2269) (push) Has been cancelled
test / Windows (vim, v8.2.2434) (push) Has been cancelled
test / Windows (vim, v8.2.3995) (push) Has been cancelled
docker / docker (push) Has been cancelled
mirror / check (coding) (push) Has been cancelled
mirror / check (gitee) (push) Has been cancelled
mirror / check (gitlab) (push) Has been cancelled
init
2024-08-21 14:17:26 +08:00

389 lines
9.7 KiB
VimL

"=============================================================================
" toml.vim --- toml api for SpaceVim
" Copyright (c) 2016-2023 Wang Shidong & Contributors
" Author: Wang Shidong < wsdjeg@outlook.com >
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
let s:self = {}
"
" public api
"
function! s:self.parse(text) abort
let input = {
\ 'text': a:text,
\ 'p': 0,
\ 'length': strlen(a:text),
\}
return s:_parse(input)
endfunction
function! s:self.parse_file(filename) abort
if !filereadable(a:filename)
throw printf("toml API: No such file `%s'.", a:filename)
endif
let text = join(readfile(a:filename), "\n")
" fileencoding is always UTF-8
return self.parse(iconv(text, 'utf-8', &encoding))
endfunction
"
" private api
"
let s:skip_pattern = '\C^\%(\%(\s\|\r\?\n\)\+\|#[^\r\n]*\)'
let s:bare_key_pattern = '\%([A-Za-z0-9_-]\+\)'
function! s:_skip(input) abort
while s:_match(a:input, '\%(\s\|\r\?\n\|#\)')
let a:input.p = matchend(a:input.text, s:skip_pattern, a:input.p)
endwhile
endfunction
" XXX: old engine is faster than NFA engine (in this context).
if exists('+regexpengine')
let s:regex_prefix = '\%#=1\C^'
else
let s:regex_prefix = '\C^'
endif
function! s:_consume(input, pattern) abort
call s:_skip(a:input)
let end = matchend(a:input.text, s:regex_prefix . a:pattern, a:input.p)
if end == -1
call s:_error(a:input)
elseif end == a:input.p
return ''
endif
let matched = strpart(a:input.text, a:input.p, end - a:input.p)
let a:input.p = end
return matched
endfunction
function! s:_match(input, pattern) abort
return match(a:input.text, s:regex_prefix . a:pattern, a:input.p) != -1
endfunction
function! s:_eof(input) abort
return a:input.p >= a:input.length
endfunction
function! s:_error(input) abort
let s = matchstr(a:input.text, s:regex_prefix . '.\{-}\ze\%(\r\?\n\|$\)', a:input.p)
let s = substitute(s, '\r', '\\r', 'g')
throw printf("toml API: Illegal TOML format at `%s'.", s)
endfunction
function! s:_parse(input) abort
let data = {}
call s:_skip(a:input)
while !s:_eof(a:input)
if s:_match(a:input, '[^ [:tab:]#.[\]]')
let keys = s:_keys(a:input, '=')
call s:_equals(a:input)
let value = s:_value(a:input)
call s:_put_dict(data, keys, value)
elseif s:_match(a:input, '\[\[')
let [keys, value] = s:_array_of_tables(a:input)
call s:_put_array(data, keys, value)
elseif s:_match(a:input, '\[')
let [keys, value] = s:_table(a:input)
call s:_put_dict(data, keys, value)
else
call s:_error(a:input)
endif
call s:_skip(a:input)
unlet keys value
endwhile
return data
endfunction
function! s:_keys(input, end) abort
let keys = []
while !s:_eof(a:input) && !s:_match(a:input, a:end)
call s:_skip(a:input)
if s:_match(a:input, '"')
let key = s:_basic_string(a:input)
elseif s:_match(a:input, "'")
let key = s:_literal(a:input)
else
let key = s:_consume(a:input, s:bare_key_pattern)
endif
let keys += [key]
call s:_consume(a:input, '\.\?')
endwhile
if empty(keys)
return s:_error(a:input)
endif
return keys
endfunction
function! s:_equals(input) abort
return s:_consume(a:input, '=')
endfunction
function! s:_value(input) abort
call s:_skip(a:input)
if s:_match(a:input, '"\{3}')
return s:_multiline_basic_string(a:input)
elseif s:_match(a:input, '"')
return s:_basic_string(a:input)
elseif s:_match(a:input, "'\\{3}")
return s:_multiline_literal(a:input)
elseif s:_match(a:input, "'")
return s:_literal(a:input)
elseif s:_match(a:input, '\[')
return s:_array(a:input)
elseif s:_match(a:input, '{')
return s:_inline_table(a:input)
elseif s:_match(a:input, '\%(true\|false\)')
return s:_boolean(a:input)
elseif s:_match(a:input, '\d\{4}-')
return s:_datetime(a:input)
elseif s:_match(a:input, '\d\{2}:')
return s:_local_time(a:input)
elseif s:_match(a:input, '[+-]\?\d\+\%(_\d\+\)*\%(\.\d\+\%(_\d\+\)*\|\%(\.\d\+\%(_\d\+\)*\)\?[eE]\)')
return s:_float(a:input)
elseif s:_match(a:input, '[+-]\?\%(inf\|nan\)')
return s:_special_float(a:input)
else
return s:_integer(a:input)
endif
endfunction
"
" String
"
function! s:_basic_string(input) abort
let s = s:_consume(a:input, '"\%(\\"\|[^"]\)*"')
let s = s[1 : -2]
return s:_unescape(s)
endfunction
function! s:_multiline_basic_string(input) abort
let s = s:_consume(a:input, '"\{3}\%(\\.\|\_.\)\{-}"\{,2}"\{3}')
let s = s[3 : -4]
let s = substitute(s, '^\r\?\n', '', '')
let s = substitute(s, '\\\%(\s\|\r\?\n\)*', '', 'g')
return s:_unescape(s)
endfunction
function! s:_literal(input) abort
let s = s:_consume(a:input, "'[^']*'")
return s[1 : -2]
endfunction
function! s:_multiline_literal(input) abort
let s = s:_consume(a:input, "'\\{3}.\\{-}'\\{,2}'\\{3}")
let s = s[3 : -4]
let s = substitute(s, '^\r\?\n', '', '')
return s
endfunction
"
" Integer
"
function! s:_integer(input) abort
if s:_match(a:input, '0b')
let s = s:_consume(a:input, '0b[01]\+\%(_[01]\+\)*')
let base = 2
elseif s:_match(a:input, '0o')
let s = s:_consume(a:input, '0o[0-7]\+\%(_[0-7]\+\)*')
let s = s[2 :]
let base = 8
elseif s:_match(a:input, '0x')
let s = s:_consume(a:input, '0x[A-Fa-f0-9]\+\%(_[A-Fa-f0-9]\+\)*')
let base = 16
else
let s = s:_consume(a:input, '[+-]\?\d\+\%(_\d\+\)*')
let base = 10
endif
let s = substitute(s, '_', '', 'g')
return str2nr(s, base)
endfunction
"
" Float
"
function! s:_float(input) abort
let s = s:_consume(a:input, '[+-]\?[0-9._]\+\%([eE][+-]\?\d\+\%(_\d\+\)*\)\?')
let s = substitute(s, '_', '', 'g')
return str2float(s)
endfunction
function! s:_special_float(input) abort
let s = s:_consume(a:input, '[+-]\?\%(inf\|nan\)')
return str2float(s)
endfunction
"
" Boolean
"
function! s:_boolean(input) abort
let s = s:_consume(a:input, '\%(true\|false\)')
return s ==# 'true'
endfunction
"
" Offset Date-Time
" Local Date-Time
" Local Date
"
function! s:_datetime(input) abort
return s:_consume(a:input, '\d\{4}-\d\{2}-\d\{2}\%([T ]\d\{2}:\d\{2}:\d\{2}\%(\.\d\+\)\?\%(Z\|[+-]\d\{2}:\d\{2}\)\?\)\?')
endfunction
"
" Local Time
"
function! s:_local_time(input) abort
return s:_consume(a:input, '\d\{2}:\d\{2}:\d\{2}\%(\.\d\+\)\?')
endfunction
"
" Array
"
function! s:_array(input) abort
let ary = []
call s:_consume(a:input, '\[')
call s:_skip(a:input)
while !s:_eof(a:input) && !s:_match(a:input, '\]')
let ary += [s:_value(a:input)]
call s:_consume(a:input, ',\?')
call s:_skip(a:input)
endwhile
call s:_consume(a:input, '\]')
return ary
endfunction
"
" Table
"
function! s:_table(input) abort
let tbl = {}
call s:_consume(a:input, '\[')
let name = s:_keys(a:input, '\]')
call s:_consume(a:input, '\]')
call s:_skip(a:input)
" while !s:_eof(a:input) && !s:_match(a:input, '\[\{1,2}[a-zA-Z0-9.]\+\]\{1,2}')
while !s:_eof(a:input) && !s:_match(a:input, '\[')
let keys = s:_keys(a:input, '=')
call s:_equals(a:input)
let value = s:_value(a:input)
call s:_put_dict(tbl, keys, value)
call s:_skip(a:input)
unlet keys value
endwhile
return [name, tbl]
endfunction
"
" Inline Table
"
function! s:_inline_table(input) abort
let tbl = {}
call s:_consume(a:input, '{')
while !s:_eof(a:input) && !s:_match(a:input, '}')
let keys = s:_keys(a:input, '=')
call s:_equals(a:input)
let value = s:_value(a:input)
call s:_put_dict(tbl, keys, value)
call s:_consume(a:input, ',\?')
call s:_skip(a:input)
endwhile
call s:_consume(a:input, '}')
return tbl
endfunction
"
" Array of Tables
"
function! s:_array_of_tables(input) abort
let tbl = {}
call s:_consume(a:input, '\[\[')
let name = s:_keys(a:input, '\]\]')
call s:_consume(a:input, '\]\]')
call s:_skip(a:input)
" while !s:_eof(a:input) && !s:_match(a:input, '\[\{1,2}[a-zA-Z0-9.]\+\]\{1,2}')
while !s:_eof(a:input) && !s:_match(a:input, '\[')
let keys = s:_keys(a:input, '=')
call s:_equals(a:input)
let value = s:_value(a:input)
call s:_put_dict(tbl, keys, value)
call s:_skip(a:input)
endwhile
return [name, [tbl]]
endfunction
function! s:_unescape(text) abort
let text = a:text
let text = substitute(text, '\\"', '"', 'g')
let text = substitute(text, '\\b', "\b", 'g')
let text = substitute(text, '\\t', "\t", 'g')
let text = substitute(text, '\\n', "\n", 'g')
let text = substitute(text, '\\f', "\f", 'g')
let text = substitute(text, '\\r', "\r", 'g')
let text = substitute(text, '\\\\', '\', 'g')
let text = substitute(text, '\C\\u\(\x\{4}\)', '\=s:_nr2char("0x" . submatch(1))', 'g')
let text = substitute(text, '\C\\U\(\x\{8}\)', '\=s:_nr2char("0x" . submatch(1))', 'g')
return text
endfunction
function! s:_nr2char(nr) abort
return iconv(nr2char(a:nr), &encoding, 'utf-8')
endfunction
function! s:_put_dict(dict, keys, value) abort
let ref = a:dict
for key in a:keys[: -2]
if has_key(ref, key) && type(ref[key]) == 4
let ref = ref[key]
elseif has_key(ref, key) && type(ref[key]) == 3
let ref = ref[key][-1]
else
let ref[key] = {}
let ref = ref[key]
endif
endfor
if has_key(ref, a:keys[-1]) && type(a:value) == 4
call extend(ref[a:keys[-1]], a:value)
else
let ref[a:keys[-1]] = a:value
endif
endfunction
function! s:_put_array(dict, keys, value) abort
let ref = a:dict
for key in a:keys[: -2]
let ref[key] = get(ref, key, {})
if type(ref[key]) == 3
let ref = ref[key][-1]
else
let ref = ref[key]
endif
endfor
let ref[a:keys[-1]] = get(ref, a:keys[-1], []) + a:value
endfunction
function! SpaceVim#api#data#toml#get() abort
return deepcopy(s:self)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0: