mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-04 02:20:04 +08:00
202 lines
4.6 KiB
VimL
202 lines
4.6 KiB
VimL
|
" ___vital___
|
||
|
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||
|
" Do not modify the code nor insert new lines before '" ___vital___'
|
||
|
function! s:_SID() abort
|
||
|
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||
|
endfunction
|
||
|
execute join(['function! vital#_openbrowser#Data#Optional#import() abort', printf("return map({'flat_map': '', 'has': '', 'flatten': '', 'some': '', 'apply': '', 'last': '', 'get_unsafe': '', 'new': '', 'is_optional': '', 'echo': '', 'exists': '', 'map': '', 'empty': '', 'get': '', 'first': '', 'unset': '', 'bind': '', 'none': '', 'get_or': '', 'set': '', 'optional': ''}, \"vital#_openbrowser#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||
|
delfunction s:_SID
|
||
|
" ___vital___
|
||
|
let s:save_cpo = &cpo
|
||
|
set cpo&vim
|
||
|
|
||
|
" NOTE: These are verbose to avoid key's unintentional confliction ;(
|
||
|
let s:SOME_KEY = 'vital_data_optional_some' | lockvar s:SOME_KEY
|
||
|
let s:NONE_KEY = 'vital_data_optional_none' | lockvar s:NONE_KEY
|
||
|
|
||
|
function! s:_require_optional(...) abort
|
||
|
for x in a:000
|
||
|
if !s:is_optional(x)
|
||
|
throw printf('vital: Data.Optional: Not an optional value `%s`', string(x))
|
||
|
endif
|
||
|
unlet x
|
||
|
endfor
|
||
|
endfunction
|
||
|
|
||
|
function! s:_require_optionals(xs) abort
|
||
|
call call(function('s:_require_optional'), a:xs)
|
||
|
endfunction
|
||
|
|
||
|
function! s:none() abort
|
||
|
let none = {}
|
||
|
let none[s:NONE_KEY] = {}
|
||
|
return none
|
||
|
endfunction
|
||
|
|
||
|
function! s:some(v) abort
|
||
|
let some = {}
|
||
|
let some[s:SOME_KEY] = a:v
|
||
|
return some
|
||
|
endfunction
|
||
|
|
||
|
function! s:new(v, ...) abort
|
||
|
return a:v == v:null || (a:0 > 0 && a:v == a:1)
|
||
|
\ ? s:none()
|
||
|
\ : s:some(a:v)
|
||
|
endfunction
|
||
|
|
||
|
function! s:is_optional(v) abort
|
||
|
return s:empty(a:v) || s:exists(a:v)
|
||
|
endfunction
|
||
|
|
||
|
function! s:empty(o) abort
|
||
|
return (type(a:o) is type({})) && has_key(a:o, s:NONE_KEY)
|
||
|
endfunction
|
||
|
|
||
|
function! s:exists(o) abort
|
||
|
return (type(a:o) is type({})) && has_key(a:o, s:SOME_KEY)
|
||
|
endfunction
|
||
|
|
||
|
function! s:set(o, v) abort
|
||
|
if s:empty(a:o)
|
||
|
unlet a:o[s:NONE_KEY]
|
||
|
endif
|
||
|
let a:o[s:SOME_KEY] = a:v
|
||
|
endfunction
|
||
|
|
||
|
function! s:unset(o) abort
|
||
|
if s:exists(a:o)
|
||
|
unlet a:o[s:SOME_KEY]
|
||
|
endif
|
||
|
let a:o[s:NONE_KEY] = {}
|
||
|
endfunction
|
||
|
|
||
|
function! s:get(o) abort
|
||
|
if s:empty(a:o)
|
||
|
throw 'vital: Data.Optional: An empty Data.Optional value'
|
||
|
endif
|
||
|
return a:o[s:SOME_KEY]
|
||
|
endfunction
|
||
|
|
||
|
function! s:get_unsafe(o) abort
|
||
|
return a:o[s:SOME_KEY]
|
||
|
endfunction
|
||
|
|
||
|
function! s:get_or(o, alt) abort
|
||
|
return get(a:o, s:SOME_KEY, a:alt())
|
||
|
endfunction
|
||
|
|
||
|
function! s:has(o, type) abort
|
||
|
return !s:empty(a:o) && (type(a:o[s:SOME_KEY]) is a:type)
|
||
|
endfunction
|
||
|
|
||
|
function! s:apply(f, ...) abort
|
||
|
call s:_require_optionals(a:000)
|
||
|
let args = []
|
||
|
|
||
|
for x in a:000
|
||
|
if s:empty(x)
|
||
|
return s:none()
|
||
|
endif
|
||
|
call add(args, s:get(x))
|
||
|
unlet x
|
||
|
endfor
|
||
|
|
||
|
return s:some(call(a:f, args))
|
||
|
endfunction
|
||
|
|
||
|
function! s:map(x, f) abort
|
||
|
if s:empty(a:x)
|
||
|
return s:none()
|
||
|
endif
|
||
|
let naked_result = call(a:f, [s:get(a:x)])
|
||
|
return s:some(naked_result)
|
||
|
endfunction
|
||
|
|
||
|
function! s:bind(f, ...) abort
|
||
|
call s:_require_optionals(a:000)
|
||
|
let args = []
|
||
|
|
||
|
for x in a:000
|
||
|
if s:empty(x)
|
||
|
return s:none()
|
||
|
endif
|
||
|
call add(args, s:get(x))
|
||
|
endfor
|
||
|
|
||
|
return call(a:f, args)
|
||
|
endfunction
|
||
|
|
||
|
let s:FLATTEN_DEFAULT_LIMIT = 1 | lockvar s:FLATTEN_DEFAULT_LIMIT
|
||
|
|
||
|
function! s:flatten(x, ...) abort
|
||
|
let limit = get(a:000, 0, s:FLATTEN_DEFAULT_LIMIT)
|
||
|
|
||
|
if limit is 0
|
||
|
return s:_flatten_fully(a:x)
|
||
|
endif
|
||
|
|
||
|
return s:_flatten_with_limit(a:x, limit)
|
||
|
endfunction
|
||
|
|
||
|
" Returns true for some({non optional}).
|
||
|
" Otherwise, returns false.
|
||
|
" (Returns false for none().)
|
||
|
function! s:_has_a_nest(x) abort
|
||
|
return s:exists(a:x) && !s:is_optional(s:get(a:x))
|
||
|
endfunction
|
||
|
|
||
|
function! s:_flatten_with_limit(x, limit) abort
|
||
|
if s:empty(a:x) || s:_has_a_nest(a:x) || (a:limit <= 0)
|
||
|
return a:x
|
||
|
endif
|
||
|
return s:_flatten_with_limit(s:get(a:x), a:limit - 1)
|
||
|
endfunction
|
||
|
|
||
|
function! s:_flatten_fully(x) abort
|
||
|
if s:empty(a:x) || s:_has_a_nest(a:x)
|
||
|
return a:x
|
||
|
endif
|
||
|
return s:_flatten_fully(s:get(a:x))
|
||
|
endfunction
|
||
|
|
||
|
function! s:flat_map(f, x) abort
|
||
|
return s:bind(a:f, a:x)
|
||
|
endfunction
|
||
|
|
||
|
function! s:optional(x, f, g) abort
|
||
|
return s:get_or(s:map(a:x, a:f), a:g)
|
||
|
endfunction
|
||
|
|
||
|
function! s:first(xs) abort
|
||
|
for x in a:xs
|
||
|
if s:exists(x)
|
||
|
return x
|
||
|
endif
|
||
|
endfor
|
||
|
return s:none()
|
||
|
endfunction
|
||
|
|
||
|
function! s:last(xs) abort
|
||
|
return s:first(reverse(copy(a:xs)))
|
||
|
endfunction
|
||
|
|
||
|
function! s:_echo(x) abort
|
||
|
if s:empty(a:x)
|
||
|
echo 'None'
|
||
|
return
|
||
|
endif
|
||
|
echo 'Some (' . s:get(a:x) . ')'
|
||
|
endfunction
|
||
|
|
||
|
function! s:echo(o, ...) abort
|
||
|
call s:_require_optional(a:o)
|
||
|
|
||
|
execute 'echohl' get(a:000, 0, 'None')
|
||
|
call s:map(a:o, function('s:_echo'))
|
||
|
echohl None
|
||
|
endfunction
|
||
|
|
||
|
let &cpo = s:save_cpo
|
||
|
unlet s:save_cpo
|