Merge branch 'update-vital'
Thanks 1500 GitHub stars ;)
This commit is contained in:
commit
ca1bb25ea7
@ -1,4 +1,4 @@
|
||||
function! vital#of(name)
|
||||
function! vital#of(name) abort
|
||||
let files = globpath(&runtimepath, 'autoload/vital/' . a:name . '.vital')
|
||||
let file = split(files, "\n")
|
||||
if empty(file)
|
||||
|
@ -5,7 +5,7 @@ let s:globpath_third_arg = v:version > 702 || v:version == 702 && has('patch51')
|
||||
|
||||
let s:loaded = {}
|
||||
|
||||
function! s:import(name, ...)
|
||||
function! s:import(name, ...) abort
|
||||
let target = {}
|
||||
let functions = []
|
||||
for a in a:000
|
||||
@ -29,7 +29,7 @@ function! s:import(name, ...)
|
||||
return target
|
||||
endfunction
|
||||
|
||||
function! s:load(...) dict
|
||||
function! s:load(...) dict abort
|
||||
for arg in a:000
|
||||
let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg]
|
||||
let target = split(join(as, ''), '\W\+')
|
||||
@ -55,21 +55,21 @@ function! s:load(...) dict
|
||||
return self
|
||||
endfunction
|
||||
|
||||
function! s:unload()
|
||||
function! s:unload() abort
|
||||
let s:loaded = {}
|
||||
endfunction
|
||||
|
||||
function! s:exists(name)
|
||||
function! s:exists(name) abort
|
||||
return s:_get_module_path(a:name) !=# ''
|
||||
endfunction
|
||||
|
||||
function! s:search(pattern)
|
||||
function! s:search(pattern) abort
|
||||
let paths = s:_vital_files(a:pattern)
|
||||
let modules = sort(map(paths, 's:_file2module(v:val)'))
|
||||
return s:_uniq(modules)
|
||||
endfunction
|
||||
|
||||
function! s:expand_modules(entry, all)
|
||||
function! s:expand_modules(entry, all) abort
|
||||
if type(a:entry) == type([])
|
||||
let candidates = s:_concat(map(copy(a:entry), 's:search(v:val)'))
|
||||
if empty(candidates)
|
||||
@ -93,7 +93,7 @@ function! s:expand_modules(entry, all)
|
||||
return modules
|
||||
endfunction
|
||||
|
||||
function! s:_import(name)
|
||||
function! s:_import(name) abort
|
||||
if type(a:name) == type(0)
|
||||
return s:_build_module(a:name)
|
||||
endif
|
||||
@ -116,7 +116,7 @@ function! s:_import(name)
|
||||
return s:_build_module(sid)
|
||||
endfunction
|
||||
|
||||
function! s:_get_module_path(name)
|
||||
function! s:_get_module_path(name) abort
|
||||
if s:_is_absolute_path(a:name) && filereadable(a:name)
|
||||
return a:name
|
||||
endif
|
||||
@ -133,7 +133,7 @@ function! s:_get_module_path(name)
|
||||
return path !=# '' ? path : ''
|
||||
endfunction
|
||||
|
||||
function! s:_get_sid_by_script(path)
|
||||
function! s:_get_sid_by_script(path) abort
|
||||
let path = s:_unify_path(a:path)
|
||||
for line in filter(split(s:_redir('scriptnames'), "\n"),
|
||||
\ 'stridx(v:val, s:self_version) > 0')
|
||||
@ -145,7 +145,7 @@ function! s:_get_sid_by_script(path)
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:_file2module(file)
|
||||
function! s:_file2module(file) abort
|
||||
let filename = fnamemodify(a:file, ':p:gs?[\\/]\+?/?')
|
||||
let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$')
|
||||
return join(split(tail, '[\\/]\+'), '.')
|
||||
@ -157,7 +157,7 @@ if filereadable(expand('<sfile>:r') . '.VIM')
|
||||
" Note: On windows, vim can't expand path names from 8.3 formats.
|
||||
" So if getting full path via <sfile> and $HOME was set as 8.3 format,
|
||||
" vital load duplicated scripts. Below's :~ avoid this issue.
|
||||
function! s:_unify_path(path)
|
||||
function! s:_unify_path(path) abort
|
||||
if has_key(s:_unify_path_cache, a:path)
|
||||
return s:_unify_path_cache[a:path]
|
||||
endif
|
||||
@ -167,24 +167,24 @@ if filereadable(expand('<sfile>:r') . '.VIM')
|
||||
return value
|
||||
endfunction
|
||||
else
|
||||
function! s:_unify_path(path)
|
||||
function! s:_unify_path(path) abort
|
||||
return resolve(fnamemodify(a:path, ':p:gs?[\\/]\+?/?'))
|
||||
endfunction
|
||||
endif
|
||||
|
||||
if s:globpath_third_arg
|
||||
function! s:_runtime_files(path)
|
||||
function! s:_runtime_files(path) abort
|
||||
return split(globpath(&runtimepath, a:path, 1), "\n")
|
||||
endfunction
|
||||
else
|
||||
function! s:_runtime_files(path)
|
||||
function! s:_runtime_files(path) abort
|
||||
return split(globpath(&runtimepath, a:path), "\n")
|
||||
endfunction
|
||||
endif
|
||||
|
||||
let s:_vital_files_cache_runtimepath = ''
|
||||
let s:_vital_files_cache = []
|
||||
function! s:_vital_files(pattern)
|
||||
function! s:_vital_files(pattern) abort
|
||||
if s:_vital_files_cache_runtimepath !=# &runtimepath
|
||||
let path = printf('autoload/vital/%s/**/*.vim', s:self_version)
|
||||
let s:_vital_files_cache = s:_runtime_files(path)
|
||||
@ -200,16 +200,16 @@ endfunction
|
||||
|
||||
" Copy from System.Filepath
|
||||
if has('win16') || has('win32') || has('win64')
|
||||
function! s:_is_absolute_path(path)
|
||||
function! s:_is_absolute_path(path) abort
|
||||
return a:path =~? '^[a-z]:[/\\]'
|
||||
endfunction
|
||||
else
|
||||
function! s:_is_absolute_path(path)
|
||||
function! s:_is_absolute_path(path) abort
|
||||
return a:path[0] ==# '/'
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:_build_module(sid)
|
||||
function! s:_build_module(sid) abort
|
||||
if has_key(s:loaded, a:sid)
|
||||
return copy(s:loaded[a:sid])
|
||||
endif
|
||||
@ -243,13 +243,13 @@ function! s:_build_module(sid)
|
||||
endfunction
|
||||
|
||||
if exists('+regexpengine')
|
||||
function! s:_get_functions(sid)
|
||||
function! s:_get_functions(sid) abort
|
||||
let funcs = s:_redir(printf("function /\\%%#=2^\<SNR>%d_", a:sid))
|
||||
let map_pat = '<SNR>' . a:sid . '_\zs\w\+'
|
||||
return map(split(funcs, "\n"), 'matchstr(v:val, map_pat)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_get_functions(sid)
|
||||
function! s:_get_functions(sid) abort
|
||||
let prefix = '<SNR>' . a:sid . '_'
|
||||
let funcs = s:_redir('function')
|
||||
let filter_pat = '^\s*function ' . prefix
|
||||
@ -261,11 +261,11 @@ else
|
||||
endif
|
||||
|
||||
if exists('*uniq')
|
||||
function! s:_uniq(list)
|
||||
function! s:_uniq(list) abort
|
||||
return uniq(a:list)
|
||||
endfunction
|
||||
else
|
||||
function! s:_uniq(list)
|
||||
function! s:_uniq(list) abort
|
||||
let i = len(a:list) - 1
|
||||
while 0 < i
|
||||
if a:list[i] ==# a:list[i - 1]
|
||||
@ -279,7 +279,7 @@ else
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:_concat(lists)
|
||||
function! s:_concat(lists) abort
|
||||
let result_list = []
|
||||
for list in a:lists
|
||||
let result_list += list
|
||||
@ -287,7 +287,7 @@ function! s:_concat(lists)
|
||||
return result_list
|
||||
endfunction
|
||||
|
||||
function! s:_redir(cmd)
|
||||
function! s:_redir(cmd) abort
|
||||
let [save_verbose, save_verbosefile] = [&verbose, &verbosefile]
|
||||
set verbose=0 verbosefile=
|
||||
redir => res
|
||||
@ -297,7 +297,7 @@ function! s:_redir(cmd)
|
||||
return res
|
||||
endfunction
|
||||
|
||||
function! vital#{s:self_version}#new()
|
||||
function! vital#{s:self_version}#new() abort
|
||||
return s:_import('')
|
||||
endfunction
|
||||
|
||||
|
@ -3,38 +3,38 @@
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:pop(list)
|
||||
function! s:pop(list) abort
|
||||
return remove(a:list, -1)
|
||||
endfunction
|
||||
|
||||
function! s:push(list, val)
|
||||
function! s:push(list, val) abort
|
||||
call add(a:list, a:val)
|
||||
return a:list
|
||||
endfunction
|
||||
|
||||
function! s:shift(list)
|
||||
function! s:shift(list) abort
|
||||
return remove(a:list, 0)
|
||||
endfunction
|
||||
|
||||
function! s:unshift(list, val)
|
||||
function! s:unshift(list, val) abort
|
||||
return insert(a:list, a:val)
|
||||
endfunction
|
||||
|
||||
function! s:cons(x, xs)
|
||||
function! s:cons(x, xs) abort
|
||||
return [a:x] + a:xs
|
||||
endfunction
|
||||
|
||||
function! s:conj(xs, x)
|
||||
function! s:conj(xs, x) abort
|
||||
return a:xs + [a:x]
|
||||
endfunction
|
||||
|
||||
" Removes duplicates from a list.
|
||||
function! s:uniq(list)
|
||||
function! s:uniq(list) abort
|
||||
return s:uniq_by(a:list, 'v:val')
|
||||
endfunction
|
||||
|
||||
" Removes duplicates from a list.
|
||||
function! s:uniq_by(list, f)
|
||||
function! s:uniq_by(list, f) abort
|
||||
let list = map(copy(a:list), printf('[v:val, %s]', a:f))
|
||||
let i = 0
|
||||
let seen = {}
|
||||
@ -50,7 +50,7 @@ function! s:uniq_by(list, f)
|
||||
return map(list, 'v:val[0]')
|
||||
endfunction
|
||||
|
||||
function! s:clear(list)
|
||||
function! s:clear(list) abort
|
||||
if !empty(a:list)
|
||||
unlet! a:list[0 : len(a:list) - 1]
|
||||
endif
|
||||
@ -59,7 +59,7 @@ endfunction
|
||||
|
||||
" Concatenates a list of lists.
|
||||
" XXX: Should we verify the input?
|
||||
function! s:concat(list)
|
||||
function! s:concat(list) abort
|
||||
let memo = []
|
||||
for Value in a:list
|
||||
let memo += Value
|
||||
@ -68,7 +68,7 @@ function! s:concat(list)
|
||||
endfunction
|
||||
|
||||
" Take each elements from lists to a new list.
|
||||
function! s:flatten(list, ...)
|
||||
function! s:flatten(list, ...) abort
|
||||
let limit = a:0 > 0 ? a:1 : -1
|
||||
let memo = []
|
||||
if limit == 0
|
||||
@ -87,7 +87,7 @@ endfunction
|
||||
|
||||
" Sorts a list with expression to compare each two values.
|
||||
" a:a and a:b can be used in {expr}.
|
||||
function! s:sort(list, expr)
|
||||
function! s:sort(list, expr) abort
|
||||
if type(a:expr) == type(function('function'))
|
||||
return sort(a:list, a:expr)
|
||||
endif
|
||||
@ -95,14 +95,14 @@ function! s:sort(list, expr)
|
||||
return sort(a:list, 's:_compare')
|
||||
endfunction
|
||||
|
||||
function! s:_compare(a, b)
|
||||
function! s:_compare(a, b) abort
|
||||
return eval(s:expr)
|
||||
endfunction
|
||||
|
||||
" Sorts a list using a set of keys generated by mapping the values in the list
|
||||
" through the given expr.
|
||||
" v:val is used in {expr}
|
||||
function! s:sort_by(list, expr)
|
||||
function! s:sort_by(list, expr) abort
|
||||
let pairs = map(a:list, printf('[v:val, %s]', a:expr))
|
||||
return map(s:sort(pairs,
|
||||
\ 'a:a[1] ==# a:b[1] ? 0 : a:a[1] ># a:b[1] ? 1 : -1'), 'v:val[0]')
|
||||
@ -111,7 +111,7 @@ endfunction
|
||||
" Returns a maximum value in {list} through given {expr}.
|
||||
" Returns 0 if {list} is empty.
|
||||
" v:val is used in {expr}
|
||||
function! s:max_by(list, expr)
|
||||
function! s:max_by(list, expr) abort
|
||||
if empty(a:list)
|
||||
return 0
|
||||
endif
|
||||
@ -123,13 +123,13 @@ endfunction
|
||||
" Returns 0 if {list} is empty.
|
||||
" v:val is used in {expr}
|
||||
" FIXME: -0x80000000 == 0x80000000
|
||||
function! s:min_by(list, expr)
|
||||
function! s:min_by(list, expr) abort
|
||||
return s:max_by(a:list, '-(' . a:expr . ')')
|
||||
endfunction
|
||||
|
||||
" Returns List of character sequence between [a:from, a:to]
|
||||
" e.g.: s:char_range('a', 'c') returns ['a', 'b', 'c']
|
||||
function! s:char_range(from, to)
|
||||
function! s:char_range(from, to) abort
|
||||
return map(
|
||||
\ range(char2nr(a:from), char2nr(a:to)),
|
||||
\ 'nr2char(v:val)'
|
||||
@ -138,21 +138,21 @@ endfunction
|
||||
|
||||
" Returns true if a:list has a:value.
|
||||
" Returns false otherwise.
|
||||
function! s:has(list, value)
|
||||
function! s:has(list, value) abort
|
||||
return index(a:list, a:value) isnot -1
|
||||
endfunction
|
||||
|
||||
" Returns true if a:list[a:index] exists.
|
||||
" Returns false otherwise.
|
||||
" NOTE: Returns false when a:index is negative number.
|
||||
function! s:has_index(list, index)
|
||||
function! s:has_index(list, index) abort
|
||||
" Return true when negative index?
|
||||
" let index = a:index >= 0 ? a:index : len(a:list) + a:index
|
||||
return 0 <= a:index && a:index < len(a:list)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Data.List.span
|
||||
function! s:span(f, xs)
|
||||
function! s:span(f, xs) abort
|
||||
let border = len(a:xs)
|
||||
for i in range(len(a:xs))
|
||||
if !eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g'))
|
||||
@ -164,41 +164,41 @@ function! s:span(f, xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Data.List.break
|
||||
function! s:break(f, xs)
|
||||
function! s:break(f, xs) abort
|
||||
return s:span(printf('!(%s)', a:f), a:xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Data.List.takeWhile
|
||||
function! s:take_while(f, xs)
|
||||
function! s:take_while(f, xs) abort
|
||||
return s:span(a:f, a:xs)[0]
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Data.List.partition
|
||||
function! s:partition(f, xs)
|
||||
function! s:partition(f, xs) abort
|
||||
return [filter(copy(a:xs), a:f), filter(copy(a:xs), '!(' . a:f . ')')]
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.all
|
||||
function! s:all(f, xs)
|
||||
function! s:all(f, xs) abort
|
||||
return !s:any(printf('!(%s)', a:f), a:xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.any
|
||||
function! s:any(f, xs)
|
||||
function! s:any(f, xs) abort
|
||||
return !empty(filter(map(copy(a:xs), a:f), 'v:val'))
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.and
|
||||
function! s:and(xs)
|
||||
function! s:and(xs) abort
|
||||
return s:all('v:val', a:xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.or
|
||||
function! s:or(xs)
|
||||
function! s:or(xs) abort
|
||||
return s:any('v:val', a:xs)
|
||||
endfunction
|
||||
|
||||
function! s:map_accum(expr, xs, init)
|
||||
function! s:map_accum(expr, xs, init) abort
|
||||
let memo = []
|
||||
let init = a:init
|
||||
for x in a:xs
|
||||
@ -211,7 +211,7 @@ function! s:map_accum(expr, xs, init)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.foldl
|
||||
function! s:foldl(f, init, xs)
|
||||
function! s:foldl(f, init, xs) abort
|
||||
let memo = a:init
|
||||
for x in a:xs
|
||||
let expr = substitute(a:f, 'v:val', string(x), 'g')
|
||||
@ -223,7 +223,7 @@ function! s:foldl(f, init, xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.foldl1
|
||||
function! s:foldl1(f, xs)
|
||||
function! s:foldl1(f, xs) abort
|
||||
if len(a:xs) == 0
|
||||
throw 'foldl1'
|
||||
endif
|
||||
@ -231,12 +231,12 @@ function! s:foldl1(f, xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.foldr
|
||||
function! s:foldr(f, init, xs)
|
||||
function! s:foldr(f, init, xs) abort
|
||||
return s:foldl(a:f, a:init, reverse(copy(a:xs)))
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.fold11
|
||||
function! s:foldr1(f, xs)
|
||||
function! s:foldr1(f, xs) abort
|
||||
if len(a:xs) == 0
|
||||
throw 'foldr1'
|
||||
endif
|
||||
@ -244,12 +244,12 @@ function! s:foldr1(f, xs)
|
||||
endfunction
|
||||
|
||||
" similar to python's zip()
|
||||
function! s:zip(...)
|
||||
function! s:zip(...) abort
|
||||
return map(range(min(map(copy(a:000), 'len(v:val)'))), "map(copy(a:000), 'v:val['.v:val.']')")
|
||||
endfunction
|
||||
|
||||
" similar to zip(), but goes until the longer one.
|
||||
function! s:zip_fill(xs, ys, filler)
|
||||
function! s:zip_fill(xs, ys, filler) abort
|
||||
if empty(a:xs) && empty(a:ys)
|
||||
return []
|
||||
elseif empty(a:ys)
|
||||
@ -262,14 +262,14 @@ function! s:zip_fill(xs, ys, filler)
|
||||
endfunction
|
||||
|
||||
" Inspired by Ruby's with_index method.
|
||||
function! s:with_index(list, ...)
|
||||
function! s:with_index(list, ...) abort
|
||||
let base = a:0 > 0 ? a:1 : 0
|
||||
return s:zip(a:list, range(base, len(a:list)+base-1))
|
||||
endfunction
|
||||
|
||||
" similar to Ruby's detect or Haskell's find.
|
||||
" TODO spec and doc
|
||||
function! s:find(list, default, f)
|
||||
function! s:find(list, default, f) abort
|
||||
for x in a:list
|
||||
if eval(substitute(a:f, 'v:val', string(x), 'g'))
|
||||
return x
|
||||
@ -278,14 +278,62 @@ function! s:find(list, default, f)
|
||||
return a:default
|
||||
endfunction
|
||||
|
||||
" Returns the index of the first element which satisfies the given expr.
|
||||
function! s:find_index(xs, f, ...) abort
|
||||
let len = len(a:xs)
|
||||
let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : 0
|
||||
let default = a:0 > 1 ? a:2 : -1
|
||||
if start >=# len || start < 0
|
||||
return default
|
||||
endif
|
||||
for i in range(start, len - 1)
|
||||
if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g'))
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
return default
|
||||
endfunction
|
||||
|
||||
" Returns the index of the last element which satisfies the given expr.
|
||||
function! s:find_last_index(xs, f, ...) abort
|
||||
let len = len(a:xs)
|
||||
let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : len - 1
|
||||
let default = a:0 > 1 ? a:2 : -1
|
||||
if start >=# len || start < 0
|
||||
return default
|
||||
endif
|
||||
for i in range(start, 0, -1)
|
||||
if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g'))
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
return default
|
||||
endfunction
|
||||
|
||||
" Similar to find_index but returns the list of indices satisfying the given expr.
|
||||
function! s:find_indices(xs, f, ...) abort
|
||||
let len = len(a:xs)
|
||||
let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : 0
|
||||
let result = []
|
||||
if start >=# len || start < 0
|
||||
return result
|
||||
endif
|
||||
for i in range(start, len - 1)
|
||||
if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g'))
|
||||
call add(result, i)
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
" Return non-zero if a:list1 and a:list2 have any common item(s).
|
||||
" Return zero otherwise.
|
||||
function! s:has_common_items(list1, list2)
|
||||
function! s:has_common_items(list1, list2) abort
|
||||
return !empty(filter(copy(a:list1), 'index(a:list2, v:val) isnot -1'))
|
||||
endfunction
|
||||
|
||||
" similar to Ruby's group_by.
|
||||
function! s:group_by(xs, f)
|
||||
function! s:group_by(xs, f) abort
|
||||
let result = {}
|
||||
let list = map(copy(a:xs), printf('[v:val, %s]', a:f))
|
||||
for x in list
|
||||
@ -301,6 +349,83 @@ function! s:group_by(xs, f)
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:_default_compare(a, b) abort
|
||||
return a:a <# a:b ? -1 : a:a ># a:b ? 1 : 0
|
||||
endfunction
|
||||
|
||||
function! s:binary_search(list, value, ...) abort
|
||||
let Predicate = a:0 >= 1 ? a:1 : 's:_default_compare'
|
||||
let dic = a:0 >= 2 ? a:2 : {}
|
||||
let start = 0
|
||||
let end = len(a:list) - 1
|
||||
|
||||
while 1
|
||||
if start > end
|
||||
return -1
|
||||
endif
|
||||
|
||||
let middle = (start + end) / 2
|
||||
|
||||
let compared = call(Predicate, [a:value, a:list[middle]], dic)
|
||||
|
||||
if compared < 0
|
||||
let end = middle - 1
|
||||
elseif compared > 0
|
||||
let start = middle + 1
|
||||
else
|
||||
return middle
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:product(lists) abort
|
||||
let result = [[]]
|
||||
for pool in a:lists
|
||||
let tmp = []
|
||||
for x in result
|
||||
let tmp += map(copy(pool), 'x + [v:val]')
|
||||
endfor
|
||||
let result = tmp
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:permutations(list, ...) abort
|
||||
if a:0 > 1
|
||||
throw 'vital: Data.List: too many arguments'
|
||||
endif
|
||||
let r = a:0 == 1 ? a:1 : len(a:list)
|
||||
if r > len(a:list)
|
||||
return []
|
||||
elseif r < 0
|
||||
throw 'vital: Data.List: {r} must be non-negative integer'
|
||||
endif
|
||||
let n = len(a:list)
|
||||
let result = []
|
||||
for indices in s:product(map(range(r), 'range(n)'))
|
||||
if len(s:uniq(indices)) == r
|
||||
call add(result, map(indices, 'a:list[v:val]'))
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:combinations(list, r) abort
|
||||
if a:r > len(a:list)
|
||||
return []
|
||||
elseif a:r < 0
|
||||
throw 'vital: Data:List: {r} must be non-negative integer'
|
||||
endif
|
||||
let n = len(a:list)
|
||||
let result = []
|
||||
for indices in s:permutations(range(n), a:r)
|
||||
if s:sort(copy(indices), 'a:a - a:b') == indices
|
||||
call add(result, map(indices, 'a:list[v:val]'))
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
|
@ -7,8 +7,8 @@ function! s:_vital_loaded(V)
|
||||
let s:V = a:V
|
||||
let s:String = s:V.import("Over.String")
|
||||
let s:Signals = s:V.import("Over.Signals")
|
||||
let s:Input = s:V.import("Over.Input")
|
||||
let s:Module = s:V.import("Over.Commandline.Modules")
|
||||
let s:List = s:V.import("Data.List")
|
||||
let s:base.variables.modules = s:Signals.make()
|
||||
function! s:base.variables.modules.get_slot(val)
|
||||
return a:val.slot.module
|
||||
@ -20,8 +20,8 @@ function! s:_vital_depends()
|
||||
return [
|
||||
\ "Over.String",
|
||||
\ "Over.Signals",
|
||||
\ "Over.Input",
|
||||
\ "Over.Commandline.Modules",
|
||||
\ "Data.List",
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
@ -168,6 +168,12 @@ function! s:base.backward()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.backward_word(...)
|
||||
let pat = get(a:, 1, '\k\+\s*\|.')
|
||||
return matchstr(self.backward(), '\%(' . pat . '\)$')
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.connect(module, ...)
|
||||
if type(a:module) == type("")
|
||||
return call(self.connect, [s:Module.make(a:module)] + a:000, self)
|
||||
@ -314,7 +320,7 @@ function! s:base.get(...)
|
||||
let Old_execute = self.execute
|
||||
let self.execute = self.__empty
|
||||
try
|
||||
let exit_code = self.start()
|
||||
let exit_code = call(self.start, a:000, self)
|
||||
if exit_code == 0
|
||||
return self.getline()
|
||||
endif
|
||||
@ -325,13 +331,36 @@ function! s:base.get(...)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base._init()
|
||||
function! s:base.input_key_stack()
|
||||
return self.variables.input_key_stack
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.input_key_stack_string()
|
||||
return join(self.variables.input_key_stack, "")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.set_input_key_stack(stack)
|
||||
let self.variables.input_key_stack = a:stack
|
||||
return self.variables.input_key_stack
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base._init_variables()
|
||||
let self.variables.tap_key = ""
|
||||
let self.variables.char = ""
|
||||
let self.variables.input = ""
|
||||
let self.variables.exit = 0
|
||||
let self.variables.exit_code = 1
|
||||
let self.variables.enable_keymapping = 1
|
||||
let self.variables.input_key_stack = []
|
||||
let self.line = deepcopy(s:String.make())
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base._init()
|
||||
call self._init_variables()
|
||||
call self.hl_cursor_off()
|
||||
if !hlexists(self.highlights.cursor)
|
||||
execute "highlight link " . self.highlights.cursor . " Cursor"
|
||||
@ -360,6 +389,17 @@ function! s:base._execute(command)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base._input_char(char)
|
||||
let char = a:char
|
||||
let self.variables.input_key = char
|
||||
let self.variables.char = char
|
||||
call self.setchar(self.variables.char)
|
||||
call self.callevent("on_char_pre")
|
||||
call self.insert(self.variables.input)
|
||||
call self.callevent("on_char")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base._input(input, ...)
|
||||
let self.variables.input_key = a:input
|
||||
if self.is_enable_keymapping()
|
||||
@ -367,39 +407,47 @@ function! s:base._input(input, ...)
|
||||
else
|
||||
let key = a:input
|
||||
endif
|
||||
if key == ""
|
||||
return
|
||||
endif
|
||||
|
||||
for char in s:_split_keys(key)
|
||||
let self.variables.input_key = char
|
||||
let self.variables.char = char
|
||||
call self.setchar(self.variables.char)
|
||||
call self.callevent("on_char_pre")
|
||||
call self.insert(self.variables.input)
|
||||
call self.callevent("on_char")
|
||||
endfor
|
||||
call self.set_input_key_stack(s:String.split_by_keys(key))
|
||||
while !(empty(self.input_key_stack()) || self._is_exit())
|
||||
call self._input_char(remove(self.input_key_stack(), 0))
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base._update()
|
||||
" call self.callevent("on_update")
|
||||
" if !getchar(1)
|
||||
" continue
|
||||
" endif
|
||||
"
|
||||
" call self._input(s:getchar(0))
|
||||
" call self.draw()
|
||||
|
||||
call self.callevent("on_update")
|
||||
call self._input(s:Input.getchar())
|
||||
if self._is_exit()
|
||||
return -1
|
||||
endif
|
||||
call self.draw()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base._main(...)
|
||||
try
|
||||
call self._init()
|
||||
let self.line = deepcopy(s:String.make(get(a:, 1, "")))
|
||||
call self.callevent("on_enter")
|
||||
|
||||
call self._input(get(a:, 1, ""))
|
||||
call self.draw()
|
||||
while !self._is_exit()
|
||||
try
|
||||
" call self.callevent("on_update")
|
||||
" if !getchar(1)
|
||||
" continue
|
||||
" endif
|
||||
"
|
||||
" call self._input(s:_getchar(0))
|
||||
" call self.draw()
|
||||
call self._input(s:_getchar())
|
||||
if self._is_exit()
|
||||
if self._update()
|
||||
break
|
||||
endif
|
||||
call self.draw()
|
||||
catch
|
||||
call self.callevent("on_exception")
|
||||
endtry
|
||||
@ -438,7 +486,7 @@ endfunction
|
||||
|
||||
|
||||
function! s:_unmap(mapping, key)
|
||||
let keys = s:_split_keys(a:key)
|
||||
let keys = s:String.split_by_keys(a:key)
|
||||
if len(keys) > 1
|
||||
return join(map(keys, 's:_unmap(a:mapping, v:val)'), '')
|
||||
endif
|
||||
@ -468,158 +516,5 @@ function! s:base._get_keymapping()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_getchar(...)
|
||||
while 1
|
||||
let char = call("getchar", a:000)
|
||||
" Workaround for the <expr> mappings
|
||||
if char !=# "\x80\xfd`"
|
||||
return type(char) == type(0) ? nr2char(char) : char
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
function! s:_split(str, pat)
|
||||
let pat = '\%#=2' . a:pat
|
||||
let list = split(a:str, pat . '\zs')
|
||||
return s:List.flatten(map(list, 'v:val == a:pat ? a:pat : v:val =~ pat . ''$'' ? split(v:val, pat) + [a:pat] : v:val'))
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_split_keystring(str, pats, ...)
|
||||
if a:str =~ '^<Over>(.\{-})$'
|
||||
\ || a:str =~ "^\<Plug>(.\\{-})$"
|
||||
return [a:str]
|
||||
endif
|
||||
let pats = a:pats
|
||||
let index = get(a:, 1, 0)
|
||||
if !exists("+regexpengine")
|
||||
\ || index > len(pats)
|
||||
\ || len(filter(copy(pats), 'a:str =~ ''\%#=2'' . v:val')) == 0
|
||||
if len(filter(copy(pats), 'a:str ==# v:val')) == 0
|
||||
return split(a:str, '\zs')
|
||||
else
|
||||
return [a:str]
|
||||
endif
|
||||
endif
|
||||
if len(filter(copy(pats), 'a:str == v:val')) == 1
|
||||
return [a:str]
|
||||
endif
|
||||
|
||||
let result = []
|
||||
let pat = pats[index]
|
||||
let list = s:_split(a:str, pat)
|
||||
let result += eval(join(map(list, "s:_split_keystring(v:val, pats, index+1)"), "+"))
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
|
||||
let s:special_keys = [
|
||||
\ "\<BS>",
|
||||
\ "\<Down>",
|
||||
\ "\<Up>",
|
||||
\ "\<Left>",
|
||||
\ "\<Right>",
|
||||
\ "\<Home>",
|
||||
\ "\<End>",
|
||||
\ "\<Insert>",
|
||||
\ "\<Delete>",
|
||||
\ "\<PageUp>",
|
||||
\ "\<PageDown>",
|
||||
\ "\<F1>",
|
||||
\ "\<F2>",
|
||||
\ "\<F3>",
|
||||
\ "\<F4>",
|
||||
\ "\<F5>",
|
||||
\ "\<F6>",
|
||||
\ "\<F7>",
|
||||
\ "\<F8>",
|
||||
\ "\<F9>",
|
||||
\ "\<F10>",
|
||||
\ "\<F11>",
|
||||
\ "\<F12>",
|
||||
\ "\<A-BS>",
|
||||
\ "\<A-Down>",
|
||||
\ "\<A-Up>",
|
||||
\ "\<A-Left>",
|
||||
\ "\<A-Right>",
|
||||
\ "\<A-Home>",
|
||||
\ "\<A-End>",
|
||||
\ "\<A-Insert>",
|
||||
\ "\<A-Delete>",
|
||||
\ "\<A-PageUp>",
|
||||
\ "\<A-PageDown>",
|
||||
\ "\<A-F1>",
|
||||
\ "\<A-F2>",
|
||||
\ "\<A-F3>",
|
||||
\ "\<A-F4>",
|
||||
\ "\<A-F5>",
|
||||
\ "\<A-F6>",
|
||||
\ "\<A-F7>",
|
||||
\ "\<A-F8>",
|
||||
\ "\<A-F9>",
|
||||
\ "\<A-F10>",
|
||||
\ "\<A-F11>",
|
||||
\ "\<A-F12>",
|
||||
\ "\<A-Tab>",
|
||||
\ "\<C-BS>",
|
||||
\ "\<C-Down>",
|
||||
\ "\<C-Up>",
|
||||
\ "\<C-Left>",
|
||||
\ "\<C-Right>",
|
||||
\ "\<C-Home>",
|
||||
\ "\<C-End>",
|
||||
\ "\<C-Insert>",
|
||||
\ "\<C-Delete>",
|
||||
\ "\<C-PageUp>",
|
||||
\ "\<C-PageDown>",
|
||||
\ "\<C-Tab>",
|
||||
\ "\<C-F1>",
|
||||
\ "\<C-F2>",
|
||||
\ "\<C-F3>",
|
||||
\ "\<C-F4>",
|
||||
\ "\<C-F5>",
|
||||
\ "\<C-F6>",
|
||||
\ "\<C-F7>",
|
||||
\ "\<C-F8>",
|
||||
\ "\<C-F9>",
|
||||
\ "\<C-F10>",
|
||||
\ "\<C-F11>",
|
||||
\ "\<C-F12>",
|
||||
\ "\<S-Down>",
|
||||
\ "\<S-Up>",
|
||||
\ "\<S-Left>",
|
||||
\ "\<S-Right>",
|
||||
\ "\<S-Home>",
|
||||
\ "\<S-Insert>",
|
||||
\ "\<S-PageUp>",
|
||||
\ "\<S-PageDown>",
|
||||
\ "\<S-F1>",
|
||||
\ "\<S-F2>",
|
||||
\ "\<S-F3>",
|
||||
\ "\<S-F4>",
|
||||
\ "\<S-F5>",
|
||||
\ "\<S-F6>",
|
||||
\ "\<S-F7>",
|
||||
\ "\<S-F8>",
|
||||
\ "\<S-F9>",
|
||||
\ "\<S-F10>",
|
||||
\ "\<S-F11>",
|
||||
\ "\<S-F12>",
|
||||
\ "\<S-Tab>",
|
||||
\]
|
||||
" Issues #45
|
||||
" \ "\<S-End>",
|
||||
" \ "\<S-Delete>",
|
||||
|
||||
function! s:_split_keys(str)
|
||||
return s:_split_keystring(a:str, s:special_keys)
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
@ -21,6 +21,15 @@ function! s:module.on_char_pre(cmdline)
|
||||
\ || a:cmdline.is_input("\<End>")
|
||||
call a:cmdline.setline(a:cmdline.line.length())
|
||||
call a:cmdline.setchar('')
|
||||
elseif a:cmdline.is_input("\<C-Left>")
|
||||
\ || a:cmdline.is_input("\<S-Left>")
|
||||
call a:cmdline.setline(strridx(a:cmdline.backward()[:-2], ' ') + 1)
|
||||
call a:cmdline.setchar('')
|
||||
elseif a:cmdline.is_input("\<C-Right>")
|
||||
\ || a:cmdline.is_input("\<S-Right>")
|
||||
let p = stridx(a:cmdline.forward()[1:], ' ')
|
||||
call a:cmdline.setline(p != -1 ? a:cmdline.line.pos() + p + 2 : a:cmdline.line.length())
|
||||
call a:cmdline.setchar('')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
@ -19,7 +19,8 @@ function! s:module.on_char_pre(cmdline)
|
||||
call a:cmdline.line.remove_pos()
|
||||
call a:cmdline.setchar('')
|
||||
elseif a:cmdline.is_input("\<C-w>")
|
||||
let backward = matchstr(a:cmdline.backward(), '^\zs.\{-}\ze\(\(\w*\)\|\(.\)\)$')
|
||||
let word = a:cmdline.backward_word()
|
||||
let backward = a:cmdline.backward()[ : -strlen(word)-1 ]
|
||||
call a:cmdline.setline(backward . a:cmdline.line.pos_word() . a:cmdline.forward())
|
||||
call a:cmdline.setline(strchars(backward))
|
||||
call a:cmdline.setchar('')
|
||||
|
@ -42,7 +42,7 @@ function! s:_redraw(cmdline)
|
||||
let left = a:cmdline.get_prompt() . a:cmdline.getline() . (empty(a:cmdline.line.pos_word()) ? " " : "")
|
||||
let width = len(left) + 1
|
||||
|
||||
if a:cmdline.get_suffix() != ""
|
||||
if a:cmdline.get_suffix() != ""
|
||||
let width += len(s:suffix(left, a:cmdline.get_suffix())) - 1
|
||||
endif
|
||||
|
||||
|
@ -8,31 +8,43 @@ let s:module = {
|
||||
\}
|
||||
|
||||
function! s:module.histories()
|
||||
return map(range(&history), 'histget(self.mode, v:val * -1)')
|
||||
return map(range(1, &history), 'histget(self.mode, v:val * -1)')
|
||||
endfunction
|
||||
|
||||
function! s:_should_match_cmdline(cmdline)
|
||||
return a:cmdline.is_input("\<Up>")
|
||||
\ || a:cmdline.is_input("\<Down>")
|
||||
endfunction
|
||||
|
||||
function! s:module.on_enter(...)
|
||||
function! s:_reset()
|
||||
let s:cmdhist = []
|
||||
let s:count = 0
|
||||
let s:is_match_mode = 0 " <Up>/<Down>: true, <C-n>/<C-p>: false
|
||||
endfunction
|
||||
|
||||
function! s:module.on_enter(...)
|
||||
call s:_reset()
|
||||
endfunction
|
||||
|
||||
function! s:module.on_char_pre(cmdline)
|
||||
if !a:cmdline.is_input("\<Up>") && !a:cmdline.is_input("\<Down>")
|
||||
let s:cmdhist = []
|
||||
let s:count = 0
|
||||
\ && !a:cmdline.is_input("\<C-p>") && !a:cmdline.is_input("\<C-n>")
|
||||
call s:_reset()
|
||||
return
|
||||
else
|
||||
if s:count == 0 && empty(s:cmdhist)
|
||||
\ || s:is_match_mode != s:_should_match_cmdline(a:cmdline)
|
||||
let cmdline = '^' . a:cmdline.getline()
|
||||
let s:cmdhist = filter(self.histories(), 'v:val =~ cmdline')
|
||||
let s:is_match_mode = s:_should_match_cmdline(a:cmdline)
|
||||
let s:cmdhist = [a:cmdline.getline()] + (s:is_match_mode ?
|
||||
\ filter(self.histories(), 'v:val =~ cmdline') : self.histories())
|
||||
endif
|
||||
endif
|
||||
call a:cmdline.setchar("")
|
||||
if a:cmdline.is_input("\<Down>")
|
||||
if a:cmdline.is_input("\<Down>") || a:cmdline.is_input("\<C-n>")
|
||||
let s:count = max([s:count - 1, 0])
|
||||
endif
|
||||
if a:cmdline.is_input("\<Up>")
|
||||
if a:cmdline.is_input("\<Up>") || a:cmdline.is_input("\<C-p>")
|
||||
let s:count = min([s:count + 1, len(s:cmdhist)])
|
||||
endif
|
||||
call a:cmdline.setline(get(s:cmdhist, s:count, a:cmdline.getline()))
|
||||
|
@ -3,6 +3,18 @@ let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:_vital_loaded(V)
|
||||
let s:V = a:V
|
||||
let s:String = s:V.import("Over.String")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return [
|
||||
\ "Over.String",
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:to_string(expr)
|
||||
return type(a:expr) == type("") ? a:expr : string(a:expr)
|
||||
@ -10,10 +22,24 @@ endfunction
|
||||
|
||||
|
||||
function! s:input(cmdline)
|
||||
let CR_index = index(a:cmdline.input_key_stack(), "\<CR>")
|
||||
if CR_index != -1
|
||||
let input = a:cmdline.input_key_stack_string()
|
||||
let input = input[ : CR_index-1]
|
||||
call a:cmdline.set_input_key_stack(a:cmdline.input_key_stack()[CR_index+1 : ])
|
||||
return eval(input)
|
||||
endif
|
||||
|
||||
let input_text = ""
|
||||
if !empty(a:cmdline.input_key_stack())
|
||||
let input_text = a:cmdline.input_key_stack_string()
|
||||
call a:cmdline.set_input_key_stack([])
|
||||
endif
|
||||
|
||||
call a:cmdline.hl_cursor_on()
|
||||
try
|
||||
redraw
|
||||
let input = input("=", "", "expression")
|
||||
let input = input("=", input_text, "expression")
|
||||
if !empty(input)
|
||||
let input = s:to_string(eval(input))
|
||||
endif
|
||||
@ -31,14 +57,29 @@ let s:module = {
|
||||
\}
|
||||
|
||||
|
||||
function! s:module.on_enter(...)
|
||||
|
||||
function! s:module.reset()
|
||||
let self.cword = expand("<cword>")
|
||||
let self.cWORD = expand("<cWORD>")
|
||||
let self.cfile = expand("<cfile>")
|
||||
endfunction
|
||||
|
||||
function! s:module.on_enter(...)
|
||||
call self.reset()
|
||||
" let self.prefix_key = ""
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:get_cmdline_cword(backward, cword)
|
||||
" let backward = matchstr(a:backward, '.\{-}\zs\k\+$')
|
||||
let backward = a:backward
|
||||
if &incsearch == 0 || a:cword == "" || a:backward == "" || s:String.index(a:cword, backward) != 0
|
||||
return a:cword
|
||||
endif
|
||||
return a:cword[len(backward) : ]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_char_pre(cmdline)
|
||||
if a:cmdline.is_input("\<C-r>")
|
||||
call a:cmdline.setchar('"')
|
||||
@ -57,7 +98,7 @@ function! s:module.on_char_pre(cmdline)
|
||||
elseif char == "="
|
||||
call a:cmdline.setchar(s:input(a:cmdline))
|
||||
elseif char == "\<C-w>"
|
||||
call a:cmdline.setchar(self.cword)
|
||||
call a:cmdline.setchar(s:get_cmdline_cword(a:cmdline.backward_word(), self.cword))
|
||||
elseif char == "\<C-a>"
|
||||
call a:cmdline.setchar(self.cWORD)
|
||||
elseif char == "\<C-f>"
|
||||
|
@ -2,6 +2,19 @@ scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:_vital_loaded(V)
|
||||
let s:Keymapping = a:V.import("Over.Keymapping")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return [
|
||||
\ "Over.Keymapping",
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
|
||||
let s:emacs = {
|
||||
\ "name" : "KeyMapping_emacs_like"
|
||||
\}
|
||||
@ -48,6 +61,16 @@ function! s:emacs.keymapping(cmdline)
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<A-b>" : {
|
||||
\ "key" : "\<S-Left>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<A-f>" : {
|
||||
\ "key" : "\<S-Right>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
@ -57,6 +80,39 @@ function! s:make_emacs()
|
||||
endfunction
|
||||
|
||||
|
||||
let s:vim_cmdline_mapping = {
|
||||
\ "name" : "KeyMapping_vim_cmdline_mapping",
|
||||
\ "_cmaps" : {}
|
||||
\}
|
||||
|
||||
function! s:_auto_cmap()
|
||||
let cmaps = {}
|
||||
let cmap_info = s:Keymapping.cmap_rhss(0, 1)
|
||||
" vital-over currently doesn't support <expr> nor <buffer> mappings
|
||||
for c in filter(cmap_info, "v:val['expr'] ==# 0 && v:val['buffer'] ==# 0")
|
||||
let cmaps[s:Keymapping.escape_key(c['lhs'])] = {
|
||||
\ 'noremap' : c['noremap'],
|
||||
\ 'key' : s:Keymapping.escape_key(c['rhs']),
|
||||
\ }
|
||||
endfor
|
||||
return cmaps
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:vim_cmdline_mapping.on_enter(cmdline)
|
||||
let self._cmaps = s:_auto_cmap()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:vim_cmdline_mapping.keymapping(cmdline)
|
||||
return self._cmaps
|
||||
endfunction
|
||||
|
||||
function! s:make_vim_cmdline_mapping()
|
||||
return deepcopy(s:vim_cmdline_mapping)
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
@ -41,6 +41,7 @@ function! s:module.redraw(cmdline)
|
||||
" https://github.com/osyo-manga/vital-over/issues/52
|
||||
" https://github.com/Lokaltog/vim-easymotion/issues/177#issuecomment-53663431
|
||||
if &cedit != "<C-c>"
|
||||
\ ||(v:version >= 704 && has("patch441"))
|
||||
normal! :
|
||||
else
|
||||
execute "normal! :\<Esc>"
|
||||
|
25
autoload/vital/_easymotion/Over/Input.vim
Normal file
25
autoload/vital/_easymotion/Over/Input.vim
Normal file
@ -0,0 +1,25 @@
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:getchar(...)
|
||||
let mode = get(a:, 1, 0)
|
||||
while 1
|
||||
" Workaround for https://github.com/osyo-manga/vital-over/issues/53
|
||||
try
|
||||
let char = call("getchar", a:000)
|
||||
catch /^Vim:Interrupt$/
|
||||
let char = 3 " <C-c>
|
||||
endtry
|
||||
" Workaround for the <expr> mappings
|
||||
if string(char) !=# "\x80\xfd`"
|
||||
return mode == 1 ? !!char
|
||||
\ : type(char) == type(0) ? nr2char(char) : char
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
55
autoload/vital/_easymotion/Over/Keymapping.vim
Normal file
55
autoload/vital/_easymotion/Over/Keymapping.vim
Normal file
@ -0,0 +1,55 @@
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:capture(cmd)
|
||||
let verbose_save = &verbose
|
||||
let &verbose = 0
|
||||
try
|
||||
redir => result
|
||||
execute "silent!" a:cmd
|
||||
redir END
|
||||
finally
|
||||
let &verbose = verbose_save
|
||||
endtry
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:escape_key(key)
|
||||
execute 'let result = "' . substitute(escape(a:key, '\"'), '\(<.\{-}>\)', '\\\1', 'g') . '"'
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:parse_mapping_lhs(map, mode)
|
||||
return matchstr(a:map, a:mode . '\s\+\zs\S\{-}\ze\s\+')
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:lhss(mode)
|
||||
let maps = s:capture(a:mode . "map")
|
||||
return filter(map(split(maps, "\n"), "s:parse_mapping_lhs(v:val, a:mode)"), 'v:val =~ ''\S\+''')
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:rhss(mode, ...)
|
||||
let abbr = get(a:, 1, 0)
|
||||
let dict = get(a:, 2, 0)
|
||||
return map(s:lhss(a:mode), "maparg(v:val, a:mode, abbr, dict)")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:cmap_lhss()
|
||||
return s:lhss("c")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:cmap_rhss(...)
|
||||
return call("s:rhss", ["c"] + a:000)
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -3,17 +3,30 @@ let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:_vital_loaded(V)
|
||||
let s:V = a:V
|
||||
let s:List = s:V.import("Data.List")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return [
|
||||
\ "Data.List",
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_clamp(x, max, min)
|
||||
return min([max([a:x, a:max]), a:min])
|
||||
endfunction
|
||||
|
||||
|
||||
let s:base = {}
|
||||
|
||||
|
||||
function! s:base.set(item)
|
||||
return type(a:item) == type("") ? self.set_str(a:item)
|
||||
\ : type(a:item) == type(0) ? self.set_pos(a:item)
|
||||
\ : self
|
||||
\ : type(a:item) == type(0) ? self.set_pos(a:item)
|
||||
\ : self
|
||||
endfunction
|
||||
|
||||
function! s:base.str()
|
||||
@ -97,5 +110,168 @@ function! s:make(...)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_split(str, pat)
|
||||
let pat = (exists("+regexpengine") ? '\%#=2' : '') . a:pat
|
||||
let list = split(a:str, pat . '\zs')
|
||||
return s:List.flatten(map(list, 'v:val == a:pat ? a:pat : v:val =~ pat . ''$'' ? split(v:val, pat) + [a:pat] : v:val'))
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_split_keystring(str, pats, ...)
|
||||
if a:str =~ '^<Over>(.\{-})$'
|
||||
\ || a:str =~ "^\<Plug>(.\\{-})$"
|
||||
return [a:str]
|
||||
endif
|
||||
let pats = a:pats
|
||||
let index = get(a:, 1, 0)
|
||||
if !exists("+regexpengine")
|
||||
\ || index > len(pats)
|
||||
\ || len(filter(copy(pats), 'a:str =~ ''\%#=2'' . v:val')) == 0
|
||||
if len(filter(copy(pats), 'a:str ==# v:val')) == 0
|
||||
return split(a:str, '\zs')
|
||||
else
|
||||
return [a:str]
|
||||
endif
|
||||
endif
|
||||
if len(filter(copy(pats), 'a:str == v:val')) == 1
|
||||
return [a:str]
|
||||
endif
|
||||
|
||||
let result = []
|
||||
let pat = pats[index]
|
||||
let list = s:_split(a:str, pat)
|
||||
let result += eval(join(map(list, "s:_split_keystring(v:val, pats, index+1)"), "+"))
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
let s:special_keys = [
|
||||
\ "\<BS>",
|
||||
\ "\<Down>",
|
||||
\ "\<Up>",
|
||||
\ "\<Left>",
|
||||
\ "\<Right>",
|
||||
\ "\<Home>",
|
||||
\ "\<End>",
|
||||
\ "\<Insert>",
|
||||
\ "\<Delete>",
|
||||
\ "\<PageUp>",
|
||||
\ "\<PageDown>",
|
||||
\ "\<F1>",
|
||||
\ "\<F2>",
|
||||
\ "\<F3>",
|
||||
\ "\<F4>",
|
||||
\ "\<F5>",
|
||||
\ "\<F6>",
|
||||
\ "\<F7>",
|
||||
\ "\<F8>",
|
||||
\ "\<F9>",
|
||||
\ "\<F10>",
|
||||
\ "\<F11>",
|
||||
\ "\<F12>",
|
||||
\ "\<A-BS>",
|
||||
\ "\<A-Down>",
|
||||
\ "\<A-Up>",
|
||||
\ "\<A-Left>",
|
||||
\ "\<A-Right>",
|
||||
\ "\<A-Home>",
|
||||
\ "\<A-End>",
|
||||
\ "\<A-Insert>",
|
||||
\ "\<A-Delete>",
|
||||
\ "\<A-PageUp>",
|
||||
\ "\<A-PageDown>",
|
||||
\ "\<A-F1>",
|
||||
\ "\<A-F2>",
|
||||
\ "\<A-F3>",
|
||||
\ "\<A-F4>",
|
||||
\ "\<A-F5>",
|
||||
\ "\<A-F6>",
|
||||
\ "\<A-F7>",
|
||||
\ "\<A-F8>",
|
||||
\ "\<A-F9>",
|
||||
\ "\<A-F10>",
|
||||
\ "\<A-F11>",
|
||||
\ "\<A-F12>",
|
||||
\ "\<A-Tab>",
|
||||
\ "\<C-BS>",
|
||||
\ "\<C-Down>",
|
||||
\ "\<C-Up>",
|
||||
\ "\<C-Left>",
|
||||
\ "\<C-Right>",
|
||||
\ "\<C-Home>",
|
||||
\ "\<C-End>",
|
||||
\ "\<C-Insert>",
|
||||
\ "\<C-Delete>",
|
||||
\ "\<C-PageUp>",
|
||||
\ "\<C-PageDown>",
|
||||
\ "\<C-Tab>",
|
||||
\ "\<C-F1>",
|
||||
\ "\<C-F2>",
|
||||
\ "\<C-F3>",
|
||||
\ "\<C-F4>",
|
||||
\ "\<C-F5>",
|
||||
\ "\<C-F6>",
|
||||
\ "\<C-F7>",
|
||||
\ "\<C-F8>",
|
||||
\ "\<C-F9>",
|
||||
\ "\<C-F10>",
|
||||
\ "\<C-F11>",
|
||||
\ "\<C-F12>",
|
||||
\ "\<S-Down>",
|
||||
\ "\<S-Up>",
|
||||
\ "\<S-Left>",
|
||||
\ "\<S-Right>",
|
||||
\ "\<S-Home>",
|
||||
\ "\<S-Insert>",
|
||||
\ "\<S-PageUp>",
|
||||
\ "\<S-PageDown>",
|
||||
\ "\<S-F1>",
|
||||
\ "\<S-F2>",
|
||||
\ "\<S-F3>",
|
||||
\ "\<S-F4>",
|
||||
\ "\<S-F5>",
|
||||
\ "\<S-F6>",
|
||||
\ "\<S-F7>",
|
||||
\ "\<S-F8>",
|
||||
\ "\<S-F9>",
|
||||
\ "\<S-F10>",
|
||||
\ "\<S-F11>",
|
||||
\ "\<S-F12>",
|
||||
\ "\<S-Tab>",
|
||||
\]
|
||||
" Issues #45
|
||||
" \ "\<S-End>",
|
||||
" \ "\<S-Delete>",
|
||||
|
||||
|
||||
" Workaround
|
||||
" https://github.com/osyo-manga/vital-over/pull/63
|
||||
" http://lingr.com/room/vim/archives/2014/10/29#message-20492403
|
||||
if exists("+regexpengine")
|
||||
function! s:_split_keystring(str, ...)
|
||||
return split(a:str, '\%#=2' . "\\m\\%(" . get(a:, 1, '') . "\x80\xfc.\\%(\x80..\\|.\\)\\zs\\|\x80..\\zs\\|.\\zs\\)")
|
||||
endfunction
|
||||
|
||||
function! s:split_by_keys(str)
|
||||
return s:_split_keystring(a:str, "\\%(\<Plug>\\|<Over>\\)(.\\{-})\\zs\\|")
|
||||
endfunction
|
||||
else
|
||||
function! s:split_by_keys(str)
|
||||
return s:_split_keystring(a:str, s:special_keys)
|
||||
endfunction
|
||||
endif
|
||||
|
||||
|
||||
function! s:index(haystack, needle, ...)
|
||||
let start = get(a:, 1, 0)
|
||||
let ignorecase = get(a:, 2, &ignorecase)
|
||||
if ignorecase
|
||||
return stridx(tolower(a:haystack), tolower(a:needle), start)
|
||||
else
|
||||
return stridx(a:haystack, a:needle, start)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
@ -1,5 +1,5 @@
|
||||
easymotion
|
||||
0116903
|
||||
651a023
|
||||
|
||||
Over.Commandline.Base
|
||||
Over.Commandline.Modules.Cancel
|
||||
|
Loading…
Reference in New Issue
Block a user