Update vital

This commit is contained in:
haya14busa 2014-11-24 02:07:19 +09:00
parent 2dc0025881
commit 5922bb9462
15 changed files with 653 additions and 257 deletions

View File

@ -1,4 +1,4 @@
function! vital#of(name) function! vital#of(name) abort
let files = globpath(&runtimepath, 'autoload/vital/' . a:name . '.vital') let files = globpath(&runtimepath, 'autoload/vital/' . a:name . '.vital')
let file = split(files, "\n") let file = split(files, "\n")
if empty(file) if empty(file)

View File

@ -5,7 +5,7 @@ let s:globpath_third_arg = v:version > 702 || v:version == 702 && has('patch51')
let s:loaded = {} let s:loaded = {}
function! s:import(name, ...) function! s:import(name, ...) abort
let target = {} let target = {}
let functions = [] let functions = []
for a in a:000 for a in a:000
@ -29,7 +29,7 @@ function! s:import(name, ...)
return target return target
endfunction endfunction
function! s:load(...) dict function! s:load(...) dict abort
for arg in a:000 for arg in a:000
let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg] let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg]
let target = split(join(as, ''), '\W\+') let target = split(join(as, ''), '\W\+')
@ -55,21 +55,21 @@ function! s:load(...) dict
return self return self
endfunction endfunction
function! s:unload() function! s:unload() abort
let s:loaded = {} let s:loaded = {}
endfunction endfunction
function! s:exists(name) function! s:exists(name) abort
return s:_get_module_path(a:name) !=# '' return s:_get_module_path(a:name) !=# ''
endfunction endfunction
function! s:search(pattern) function! s:search(pattern) abort
let paths = s:_vital_files(a:pattern) let paths = s:_vital_files(a:pattern)
let modules = sort(map(paths, 's:_file2module(v:val)')) let modules = sort(map(paths, 's:_file2module(v:val)'))
return s:_uniq(modules) return s:_uniq(modules)
endfunction endfunction
function! s:expand_modules(entry, all) function! s:expand_modules(entry, all) abort
if type(a:entry) == type([]) if type(a:entry) == type([])
let candidates = s:_concat(map(copy(a:entry), 's:search(v:val)')) let candidates = s:_concat(map(copy(a:entry), 's:search(v:val)'))
if empty(candidates) if empty(candidates)
@ -93,7 +93,7 @@ function! s:expand_modules(entry, all)
return modules return modules
endfunction endfunction
function! s:_import(name) function! s:_import(name) abort
if type(a:name) == type(0) if type(a:name) == type(0)
return s:_build_module(a:name) return s:_build_module(a:name)
endif endif
@ -116,7 +116,7 @@ function! s:_import(name)
return s:_build_module(sid) return s:_build_module(sid)
endfunction endfunction
function! s:_get_module_path(name) function! s:_get_module_path(name) abort
if s:_is_absolute_path(a:name) && filereadable(a:name) if s:_is_absolute_path(a:name) && filereadable(a:name)
return a:name return a:name
endif endif
@ -133,7 +133,7 @@ function! s:_get_module_path(name)
return path !=# '' ? path : '' return path !=# '' ? path : ''
endfunction endfunction
function! s:_get_sid_by_script(path) function! s:_get_sid_by_script(path) abort
let path = s:_unify_path(a:path) let path = s:_unify_path(a:path)
for line in filter(split(s:_redir('scriptnames'), "\n"), for line in filter(split(s:_redir('scriptnames'), "\n"),
\ 'stridx(v:val, s:self_version) > 0') \ 'stridx(v:val, s:self_version) > 0')
@ -145,7 +145,7 @@ function! s:_get_sid_by_script(path)
return 0 return 0
endfunction endfunction
function! s:_file2module(file) function! s:_file2module(file) abort
let filename = fnamemodify(a:file, ':p:gs?[\\/]\+?/?') let filename = fnamemodify(a:file, ':p:gs?[\\/]\+?/?')
let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$') let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$')
return join(split(tail, '[\\/]\+'), '.') 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. " 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, " So if getting full path via <sfile> and $HOME was set as 8.3 format,
" vital load duplicated scripts. Below's :~ avoid this issue. " 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) if has_key(s:_unify_path_cache, a:path)
return s:_unify_path_cache[a:path] return s:_unify_path_cache[a:path]
endif endif
@ -167,24 +167,24 @@ if filereadable(expand('<sfile>:r') . '.VIM')
return value return value
endfunction endfunction
else else
function! s:_unify_path(path) function! s:_unify_path(path) abort
return resolve(fnamemodify(a:path, ':p:gs?[\\/]\+?/?')) return resolve(fnamemodify(a:path, ':p:gs?[\\/]\+?/?'))
endfunction endfunction
endif endif
if s:globpath_third_arg if s:globpath_third_arg
function! s:_runtime_files(path) function! s:_runtime_files(path) abort
return split(globpath(&runtimepath, a:path, 1), "\n") return split(globpath(&runtimepath, a:path, 1), "\n")
endfunction endfunction
else else
function! s:_runtime_files(path) function! s:_runtime_files(path) abort
return split(globpath(&runtimepath, a:path), "\n") return split(globpath(&runtimepath, a:path), "\n")
endfunction endfunction
endif endif
let s:_vital_files_cache_runtimepath = '' let s:_vital_files_cache_runtimepath = ''
let s:_vital_files_cache = [] let s:_vital_files_cache = []
function! s:_vital_files(pattern) function! s:_vital_files(pattern) abort
if s:_vital_files_cache_runtimepath !=# &runtimepath if s:_vital_files_cache_runtimepath !=# &runtimepath
let path = printf('autoload/vital/%s/**/*.vim', s:self_version) let path = printf('autoload/vital/%s/**/*.vim', s:self_version)
let s:_vital_files_cache = s:_runtime_files(path) let s:_vital_files_cache = s:_runtime_files(path)
@ -200,16 +200,16 @@ endfunction
" Copy from System.Filepath " Copy from System.Filepath
if has('win16') || has('win32') || has('win64') 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]:[/\\]' return a:path =~? '^[a-z]:[/\\]'
endfunction endfunction
else else
function! s:_is_absolute_path(path) function! s:_is_absolute_path(path) abort
return a:path[0] ==# '/' return a:path[0] ==# '/'
endfunction endfunction
endif endif
function! s:_build_module(sid) function! s:_build_module(sid) abort
if has_key(s:loaded, a:sid) if has_key(s:loaded, a:sid)
return copy(s:loaded[a:sid]) return copy(s:loaded[a:sid])
endif endif
@ -243,13 +243,13 @@ function! s:_build_module(sid)
endfunction endfunction
if exists('+regexpengine') 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 funcs = s:_redir(printf("function /\\%%#=2^\<SNR>%d_", a:sid))
let map_pat = '<SNR>' . a:sid . '_\zs\w\+' let map_pat = '<SNR>' . a:sid . '_\zs\w\+'
return map(split(funcs, "\n"), 'matchstr(v:val, map_pat)') return map(split(funcs, "\n"), 'matchstr(v:val, map_pat)')
endfunction endfunction
else else
function! s:_get_functions(sid) function! s:_get_functions(sid) abort
let prefix = '<SNR>' . a:sid . '_' let prefix = '<SNR>' . a:sid . '_'
let funcs = s:_redir('function') let funcs = s:_redir('function')
let filter_pat = '^\s*function ' . prefix let filter_pat = '^\s*function ' . prefix
@ -261,11 +261,11 @@ else
endif endif
if exists('*uniq') if exists('*uniq')
function! s:_uniq(list) function! s:_uniq(list) abort
return uniq(a:list) return uniq(a:list)
endfunction endfunction
else else
function! s:_uniq(list) function! s:_uniq(list) abort
let i = len(a:list) - 1 let i = len(a:list) - 1
while 0 < i while 0 < i
if a:list[i] ==# a:list[i - 1] if a:list[i] ==# a:list[i - 1]
@ -279,7 +279,7 @@ else
endfunction endfunction
endif endif
function! s:_concat(lists) function! s:_concat(lists) abort
let result_list = [] let result_list = []
for list in a:lists for list in a:lists
let result_list += list let result_list += list
@ -287,7 +287,7 @@ function! s:_concat(lists)
return result_list return result_list
endfunction endfunction
function! s:_redir(cmd) function! s:_redir(cmd) abort
let [save_verbose, save_verbosefile] = [&verbose, &verbosefile] let [save_verbose, save_verbosefile] = [&verbose, &verbosefile]
set verbose=0 verbosefile= set verbose=0 verbosefile=
redir => res redir => res
@ -297,7 +297,7 @@ function! s:_redir(cmd)
return res return res
endfunction endfunction
function! vital#{s:self_version}#new() function! vital#{s:self_version}#new() abort
return s:_import('') return s:_import('')
endfunction endfunction

View File

@ -3,38 +3,38 @@
let s:save_cpo = &cpo let s:save_cpo = &cpo
set cpo&vim set cpo&vim
function! s:pop(list) function! s:pop(list) abort
return remove(a:list, -1) return remove(a:list, -1)
endfunction endfunction
function! s:push(list, val) function! s:push(list, val) abort
call add(a:list, a:val) call add(a:list, a:val)
return a:list return a:list
endfunction endfunction
function! s:shift(list) function! s:shift(list) abort
return remove(a:list, 0) return remove(a:list, 0)
endfunction endfunction
function! s:unshift(list, val) function! s:unshift(list, val) abort
return insert(a:list, a:val) return insert(a:list, a:val)
endfunction endfunction
function! s:cons(x, xs) function! s:cons(x, xs) abort
return [a:x] + a:xs return [a:x] + a:xs
endfunction endfunction
function! s:conj(xs, x) function! s:conj(xs, x) abort
return a:xs + [a:x] return a:xs + [a:x]
endfunction endfunction
" Removes duplicates from a list. " Removes duplicates from a list.
function! s:uniq(list) function! s:uniq(list) abort
return s:uniq_by(a:list, 'v:val') return s:uniq_by(a:list, 'v:val')
endfunction endfunction
" Removes duplicates from a list. " 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 list = map(copy(a:list), printf('[v:val, %s]', a:f))
let i = 0 let i = 0
let seen = {} let seen = {}
@ -50,7 +50,7 @@ function! s:uniq_by(list, f)
return map(list, 'v:val[0]') return map(list, 'v:val[0]')
endfunction endfunction
function! s:clear(list) function! s:clear(list) abort
if !empty(a:list) if !empty(a:list)
unlet! a:list[0 : len(a:list) - 1] unlet! a:list[0 : len(a:list) - 1]
endif endif
@ -59,7 +59,7 @@ endfunction
" Concatenates a list of lists. " Concatenates a list of lists.
" XXX: Should we verify the input? " XXX: Should we verify the input?
function! s:concat(list) function! s:concat(list) abort
let memo = [] let memo = []
for Value in a:list for Value in a:list
let memo += Value let memo += Value
@ -68,7 +68,7 @@ function! s:concat(list)
endfunction endfunction
" Take each elements from lists to a new list. " 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 limit = a:0 > 0 ? a:1 : -1
let memo = [] let memo = []
if limit == 0 if limit == 0
@ -87,7 +87,7 @@ endfunction
" Sorts a list with expression to compare each two values. " Sorts a list with expression to compare each two values.
" a:a and a:b can be used in {expr}. " 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')) if type(a:expr) == type(function('function'))
return sort(a:list, a:expr) return sort(a:list, a:expr)
endif endif
@ -95,14 +95,14 @@ function! s:sort(list, expr)
return sort(a:list, 's:_compare') return sort(a:list, 's:_compare')
endfunction endfunction
function! s:_compare(a, b) function! s:_compare(a, b) abort
return eval(s:expr) return eval(s:expr)
endfunction endfunction
" Sorts a list using a set of keys generated by mapping the values in the list " Sorts a list using a set of keys generated by mapping the values in the list
" through the given expr. " through the given expr.
" v:val is used in {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)) let pairs = map(a:list, printf('[v:val, %s]', a:expr))
return map(s:sort(pairs, return map(s:sort(pairs,
\ 'a:a[1] ==# a:b[1] ? 0 : a:a[1] ># a:b[1] ? 1 : -1'), 'v:val[0]') \ '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 a maximum value in {list} through given {expr}.
" Returns 0 if {list} is empty. " Returns 0 if {list} is empty.
" v:val is used in {expr} " v:val is used in {expr}
function! s:max_by(list, expr) function! s:max_by(list, expr) abort
if empty(a:list) if empty(a:list)
return 0 return 0
endif endif
@ -123,13 +123,13 @@ endfunction
" Returns 0 if {list} is empty. " Returns 0 if {list} is empty.
" v:val is used in {expr} " v:val is used in {expr}
" FIXME: -0x80000000 == 0x80000000 " FIXME: -0x80000000 == 0x80000000
function! s:min_by(list, expr) function! s:min_by(list, expr) abort
return s:max_by(a:list, '-(' . a:expr . ')') return s:max_by(a:list, '-(' . a:expr . ')')
endfunction endfunction
" Returns List of character sequence between [a:from, a:to] " Returns List of character sequence between [a:from, a:to]
" e.g.: s:char_range('a', 'c') returns ['a', 'b', 'c'] " 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( return map(
\ range(char2nr(a:from), char2nr(a:to)), \ range(char2nr(a:from), char2nr(a:to)),
\ 'nr2char(v:val)' \ 'nr2char(v:val)'
@ -138,21 +138,21 @@ endfunction
" Returns true if a:list has a:value. " Returns true if a:list has a:value.
" Returns false otherwise. " Returns false otherwise.
function! s:has(list, value) function! s:has(list, value) abort
return index(a:list, a:value) isnot -1 return index(a:list, a:value) isnot -1
endfunction endfunction
" Returns true if a:list[a:index] exists. " Returns true if a:list[a:index] exists.
" Returns false otherwise. " Returns false otherwise.
" NOTE: Returns false when a:index is negative number. " 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? " Return true when negative index?
" let index = a:index >= 0 ? a:index : len(a:list) + a:index " let index = a:index >= 0 ? a:index : len(a:list) + a:index
return 0 <= a:index && a:index < len(a:list) return 0 <= a:index && a:index < len(a:list)
endfunction endfunction
" similar to Haskell's Data.List.span " similar to Haskell's Data.List.span
function! s:span(f, xs) function! s:span(f, xs) abort
let border = len(a:xs) let border = len(a:xs)
for i in range(len(a:xs)) for i in range(len(a:xs))
if !eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) if !eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g'))
@ -164,41 +164,41 @@ function! s:span(f, xs)
endfunction endfunction
" similar to Haskell's Data.List.break " 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) return s:span(printf('!(%s)', a:f), a:xs)
endfunction endfunction
" similar to Haskell's Data.List.takeWhile " 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] return s:span(a:f, a:xs)[0]
endfunction endfunction
" similar to Haskell's Data.List.partition " 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 . ')')] return [filter(copy(a:xs), a:f), filter(copy(a:xs), '!(' . a:f . ')')]
endfunction endfunction
" similar to Haskell's Prelude.all " 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) return !s:any(printf('!(%s)', a:f), a:xs)
endfunction endfunction
" similar to Haskell's Prelude.any " 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')) return !empty(filter(map(copy(a:xs), a:f), 'v:val'))
endfunction endfunction
" similar to Haskell's Prelude.and " similar to Haskell's Prelude.and
function! s:and(xs) function! s:and(xs) abort
return s:all('v:val', a:xs) return s:all('v:val', a:xs)
endfunction endfunction
" similar to Haskell's Prelude.or " similar to Haskell's Prelude.or
function! s:or(xs) function! s:or(xs) abort
return s:any('v:val', a:xs) return s:any('v:val', a:xs)
endfunction endfunction
function! s:map_accum(expr, xs, init) function! s:map_accum(expr, xs, init) abort
let memo = [] let memo = []
let init = a:init let init = a:init
for x in a:xs for x in a:xs
@ -211,7 +211,7 @@ function! s:map_accum(expr, xs, init)
endfunction endfunction
" similar to Haskell's Prelude.foldl " similar to Haskell's Prelude.foldl
function! s:foldl(f, init, xs) function! s:foldl(f, init, xs) abort
let memo = a:init let memo = a:init
for x in a:xs for x in a:xs
let expr = substitute(a:f, 'v:val', string(x), 'g') let expr = substitute(a:f, 'v:val', string(x), 'g')
@ -223,7 +223,7 @@ function! s:foldl(f, init, xs)
endfunction endfunction
" similar to Haskell's Prelude.foldl1 " similar to Haskell's Prelude.foldl1
function! s:foldl1(f, xs) function! s:foldl1(f, xs) abort
if len(a:xs) == 0 if len(a:xs) == 0
throw 'foldl1' throw 'foldl1'
endif endif
@ -231,12 +231,12 @@ function! s:foldl1(f, xs)
endfunction endfunction
" similar to Haskell's Prelude.foldr " 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))) return s:foldl(a:f, a:init, reverse(copy(a:xs)))
endfunction endfunction
" similar to Haskell's Prelude.fold11 " similar to Haskell's Prelude.fold11
function! s:foldr1(f, xs) function! s:foldr1(f, xs) abort
if len(a:xs) == 0 if len(a:xs) == 0
throw 'foldr1' throw 'foldr1'
endif endif
@ -244,12 +244,12 @@ function! s:foldr1(f, xs)
endfunction endfunction
" similar to python's zip() " 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.']')") return map(range(min(map(copy(a:000), 'len(v:val)'))), "map(copy(a:000), 'v:val['.v:val.']')")
endfunction endfunction
" similar to zip(), but goes until the longer one. " 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) if empty(a:xs) && empty(a:ys)
return [] return []
elseif empty(a:ys) elseif empty(a:ys)
@ -262,14 +262,14 @@ function! s:zip_fill(xs, ys, filler)
endfunction endfunction
" Inspired by Ruby's with_index method. " 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 let base = a:0 > 0 ? a:1 : 0
return s:zip(a:list, range(base, len(a:list)+base-1)) return s:zip(a:list, range(base, len(a:list)+base-1))
endfunction endfunction
" similar to Ruby's detect or Haskell's find. " similar to Ruby's detect or Haskell's find.
" TODO spec and doc " TODO spec and doc
function! s:find(list, default, f) function! s:find(list, default, f) abort
for x in a:list for x in a:list
if eval(substitute(a:f, 'v:val', string(x), 'g')) if eval(substitute(a:f, 'v:val', string(x), 'g'))
return x return x
@ -278,14 +278,62 @@ function! s:find(list, default, f)
return a:default return a:default
endfunction 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 non-zero if a:list1 and a:list2 have any common item(s).
" Return zero otherwise. " 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')) return !empty(filter(copy(a:list1), 'index(a:list2, v:val) isnot -1'))
endfunction endfunction
" similar to Ruby's group_by. " similar to Ruby's group_by.
function! s:group_by(xs, f) function! s:group_by(xs, f) abort
let result = {} let result = {}
let list = map(copy(a:xs), printf('[v:val, %s]', a:f)) let list = map(copy(a:xs), printf('[v:val, %s]', a:f))
for x in list for x in list
@ -301,6 +349,83 @@ function! s:group_by(xs, f)
return result return result
endfunction 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 let &cpo = s:save_cpo
unlet s:save_cpo unlet s:save_cpo

View File

@ -7,8 +7,8 @@ function! s:_vital_loaded(V)
let s:V = a:V let s:V = a:V
let s:String = s:V.import("Over.String") let s:String = s:V.import("Over.String")
let s:Signals = s:V.import("Over.Signals") 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:Module = s:V.import("Over.Commandline.Modules")
let s:List = s:V.import("Data.List")
let s:base.variables.modules = s:Signals.make() let s:base.variables.modules = s:Signals.make()
function! s:base.variables.modules.get_slot(val) function! s:base.variables.modules.get_slot(val)
return a:val.slot.module return a:val.slot.module
@ -20,8 +20,8 @@ function! s:_vital_depends()
return [ return [
\ "Over.String", \ "Over.String",
\ "Over.Signals", \ "Over.Signals",
\ "Over.Input",
\ "Over.Commandline.Modules", \ "Over.Commandline.Modules",
\ "Data.List",
\ ] \ ]
endfunction endfunction
@ -168,6 +168,12 @@ function! s:base.backward()
endfunction endfunction
function! s:base.backward_word(...)
let pat = get(a:, 1, '\k\+\s*\|.')
return matchstr(self.backward(), '\%(' . pat . '\)$')
endfunction
function! s:base.connect(module, ...) function! s:base.connect(module, ...)
if type(a:module) == type("") if type(a:module) == type("")
return call(self.connect, [s:Module.make(a:module)] + a:000, self) 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 Old_execute = self.execute
let self.execute = self.__empty let self.execute = self.__empty
try try
let exit_code = self.start() let exit_code = call(self.start, a:000, self)
if exit_code == 0 if exit_code == 0
return self.getline() return self.getline()
endif endif
@ -325,13 +331,36 @@ function! s:base.get(...)
endfunction 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.tap_key = ""
let self.variables.char = "" let self.variables.char = ""
let self.variables.input = "" let self.variables.input = ""
let self.variables.exit = 0 let self.variables.exit = 0
let self.variables.exit_code = 1 let self.variables.exit_code = 1
let self.variables.enable_keymapping = 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() call self.hl_cursor_off()
if !hlexists(self.highlights.cursor) if !hlexists(self.highlights.cursor)
execute "highlight link " . self.highlights.cursor . " Cursor" execute "highlight link " . self.highlights.cursor . " Cursor"
@ -360,6 +389,17 @@ function! s:base._execute(command)
endfunction 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, ...) function! s:base._input(input, ...)
let self.variables.input_key = a:input let self.variables.input_key = a:input
if self.is_enable_keymapping() if self.is_enable_keymapping()
@ -367,39 +407,47 @@ function! s:base._input(input, ...)
else else
let key = a:input let key = a:input
endif endif
if key == ""
return
endif
for char in s:_split_keys(key) call self.set_input_key_stack(s:String.split_by_keys(key))
let self.variables.input_key = char while !(empty(self.input_key_stack()) || self._is_exit())
let self.variables.char = char call self._input_char(remove(self.input_key_stack(), 0))
call self.setchar(self.variables.char) endwhile
call self.callevent("on_char_pre") endfunction
call self.insert(self.variables.input)
call self.callevent("on_char")
endfor 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 endfunction
function! s:base._main(...) function! s:base._main(...)
try try
call self._init() call self._init()
let self.line = deepcopy(s:String.make(get(a:, 1, "")))
call self.callevent("on_enter") call self.callevent("on_enter")
call self._input(get(a:, 1, ""))
call self.draw() call self.draw()
while !self._is_exit() while !self._is_exit()
try try
" call self.callevent("on_update") if self._update()
" if !getchar(1)
" continue
" endif
"
" call self._input(s:_getchar(0))
" call self.draw()
call self._input(s:_getchar())
if self._is_exit()
break break
endif endif
call self.draw()
catch catch
call self.callevent("on_exception") call self.callevent("on_exception")
endtry endtry
@ -438,7 +486,7 @@ endfunction
function! s:_unmap(mapping, key) 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 if len(keys) > 1
return join(map(keys, 's:_unmap(a:mapping, v:val)'), '') return join(map(keys, 's:_unmap(a:mapping, v:val)'), '')
endif endif
@ -468,158 +516,5 @@ function! s:base._get_keymapping()
endfunction 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 let &cpo = s:save_cpo
unlet s:save_cpo unlet s:save_cpo

View File

@ -21,6 +21,15 @@ function! s:module.on_char_pre(cmdline)
\ || a:cmdline.is_input("\<End>") \ || a:cmdline.is_input("\<End>")
call a:cmdline.setline(a:cmdline.line.length()) call a:cmdline.setline(a:cmdline.line.length())
call a:cmdline.setchar('') 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 endif
endfunction endfunction

View File

@ -19,7 +19,8 @@ function! s:module.on_char_pre(cmdline)
call a:cmdline.line.remove_pos() call a:cmdline.line.remove_pos()
call a:cmdline.setchar('') call a:cmdline.setchar('')
elseif a:cmdline.is_input("\<C-w>") 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(backward . a:cmdline.line.pos_word() . a:cmdline.forward())
call a:cmdline.setline(strchars(backward)) call a:cmdline.setline(strchars(backward))
call a:cmdline.setchar('') call a:cmdline.setchar('')

View File

@ -8,31 +8,43 @@ let s:module = {
\} \}
function! s:module.histories() 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 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:cmdhist = []
let s:count = 0 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 endfunction
function! s:module.on_char_pre(cmdline) function! s:module.on_char_pre(cmdline)
if !a:cmdline.is_input("\<Up>") && !a:cmdline.is_input("\<Down>") if !a:cmdline.is_input("\<Up>") && !a:cmdline.is_input("\<Down>")
let s:cmdhist = [] \ && !a:cmdline.is_input("\<C-p>") && !a:cmdline.is_input("\<C-n>")
let s:count = 0 call s:_reset()
return return
else else
if s:count == 0 && empty(s:cmdhist) if s:count == 0 && empty(s:cmdhist)
\ || s:is_match_mode != s:_should_match_cmdline(a:cmdline)
let cmdline = '^' . a:cmdline.getline() 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
endif endif
call a:cmdline.setchar("") 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]) let s:count = max([s:count - 1, 0])
endif 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)]) let s:count = min([s:count + 1, len(s:cmdhist)])
endif endif
call a:cmdline.setline(get(s:cmdhist, s:count, a:cmdline.getline())) call a:cmdline.setline(get(s:cmdhist, s:count, a:cmdline.getline()))

View File

@ -3,6 +3,18 @@ let s:save_cpo = &cpo
set cpo&vim 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) function! s:to_string(expr)
return type(a:expr) == type("") ? a:expr : string(a:expr) return type(a:expr) == type("") ? a:expr : string(a:expr)
@ -10,10 +22,24 @@ endfunction
function! s:input(cmdline) 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() call a:cmdline.hl_cursor_on()
try try
redraw redraw
let input = input("=", "", "expression") let input = input("=", input_text, "expression")
if !empty(input) if !empty(input)
let input = s:to_string(eval(input)) let input = s:to_string(eval(input))
endif 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.cWORD = expand("<cWORD>") let self.cWORD = expand("<cWORD>")
let self.cfile = expand("<cfile>") let self.cfile = expand("<cfile>")
endfunction
function! s:module.on_enter(...)
call self.reset()
" let self.prefix_key = "" " let self.prefix_key = ""
endfunction 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) function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("\<C-r>") if a:cmdline.is_input("\<C-r>")
call a:cmdline.setchar('"') call a:cmdline.setchar('"')
@ -57,7 +98,7 @@ function! s:module.on_char_pre(cmdline)
elseif char == "=" elseif char == "="
call a:cmdline.setchar(s:input(a:cmdline)) call a:cmdline.setchar(s:input(a:cmdline))
elseif char == "\<C-w>" 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>" elseif char == "\<C-a>"
call a:cmdline.setchar(self.cWORD) call a:cmdline.setchar(self.cWORD)
elseif char == "\<C-f>" elseif char == "\<C-f>"

View File

@ -2,6 +2,19 @@ scriptencoding utf-8
let s:save_cpo = &cpo let s:save_cpo = &cpo
set cpo&vim 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 = { let s:emacs = {
\ "name" : "KeyMapping_emacs_like" \ "name" : "KeyMapping_emacs_like"
\} \}
@ -48,6 +61,16 @@ function! s:emacs.keymapping(cmdline)
\ "noremap" : 1, \ "noremap" : 1,
\ "lock" : 1, \ "lock" : 1,
\ }, \ },
\ "\<A-b>" : {
\ "key" : "\<S-Left>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<A-f>" : {
\ "key" : "\<S-Right>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ } \ }
endfunction endfunction
@ -57,6 +80,39 @@ function! s:make_emacs()
endfunction 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 let &cpo = s:save_cpo
unlet s:save_cpo unlet s:save_cpo

View File

@ -41,6 +41,7 @@ function! s:module.redraw(cmdline)
" https://github.com/osyo-manga/vital-over/issues/52 " https://github.com/osyo-manga/vital-over/issues/52
" https://github.com/Lokaltog/vim-easymotion/issues/177#issuecomment-53663431 " https://github.com/Lokaltog/vim-easymotion/issues/177#issuecomment-53663431
if &cedit != "<C-c>" if &cedit != "<C-c>"
\ ||(v:version >= 704 && has("patch441"))
normal! : normal! :
else else
execute "normal! :\<Esc>" execute "normal! :\<Esc>"

View 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

View 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

View File

@ -3,6 +3,19 @@ let s:save_cpo = &cpo
set cpo&vim 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) function! s:_clamp(x, max, min)
return min([max([a:x, a:max]), a:min]) return min([max([a:x, a:max]), a:min])
endfunction endfunction
@ -97,5 +110,168 @@ function! s:make(...)
endfunction 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 let &cpo = s:save_cpo
unlet s:save_cpo unlet s:save_cpo

View File

@ -1,5 +1,5 @@
easymotion easymotion
0116903 651a023
Over.Commandline.Base Over.Commandline.Base
Over.Commandline.Modules.Cancel Over.Commandline.Modules.Cancel