Fixed vim and zsh
This commit is contained in:
@ -0,0 +1,116 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Data#Dict#import() abort
|
||||
return map({'pick': '', 'clear': '', 'max_by': '', 'foldl': '', 'swap': '', 'omit': '', 'min_by': '', 'foldr': '', 'make_index': '', 'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Data#Dict#import() abort', printf("return map({'pick': '', 'clear': '', 'max_by': '', 'foldl': '', 'swap': '', 'omit': '', 'min_by': '', 'foldr': '', 'make_index': '', 'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
" Utilities for dictionary.
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
" Makes a dict from keys and values
|
||||
function! s:make(keys, values, ...) abort
|
||||
let dict = {}
|
||||
let fill = a:0 ? a:1 : 0
|
||||
for i in range(len(a:keys))
|
||||
let key = type(a:keys[i]) == type('') ? a:keys[i] : string(a:keys[i])
|
||||
if key ==# ''
|
||||
throw "vital: Data.Dict: Can't use an empty string for key."
|
||||
endif
|
||||
let dict[key] = get(a:values, i, fill)
|
||||
endfor
|
||||
return dict
|
||||
endfunction
|
||||
|
||||
" Swaps keys and values
|
||||
function! s:swap(dict) abort
|
||||
return s:make(values(a:dict), keys(a:dict))
|
||||
endfunction
|
||||
|
||||
" Makes a index dict from a list
|
||||
function! s:make_index(list, ...) abort
|
||||
let value = a:0 ? a:1 : 1
|
||||
return s:make(a:list, [], value)
|
||||
endfunction
|
||||
|
||||
function! s:pick(dict, keys) abort
|
||||
let new_dict = {}
|
||||
for key in a:keys
|
||||
if has_key(a:dict, key)
|
||||
let new_dict[key] = a:dict[key]
|
||||
endif
|
||||
endfor
|
||||
return new_dict
|
||||
endfunction
|
||||
|
||||
function! s:omit(dict, keys) abort
|
||||
let new_dict = copy(a:dict)
|
||||
for key in a:keys
|
||||
if has_key(a:dict, key)
|
||||
call remove(new_dict, key)
|
||||
endif
|
||||
endfor
|
||||
return new_dict
|
||||
endfunction
|
||||
|
||||
function! s:clear(dict) abort
|
||||
for key in keys(a:dict)
|
||||
call remove(a:dict, key)
|
||||
endfor
|
||||
return a:dict
|
||||
endfunction
|
||||
|
||||
function! s:_max_by(dict, expr) abort
|
||||
let dict = s:swap(map(copy(a:dict), a:expr))
|
||||
let key = dict[max(keys(dict))]
|
||||
return [key, a:dict[key]]
|
||||
endfunction
|
||||
|
||||
function! s:max_by(dict, expr) abort
|
||||
if empty(a:dict)
|
||||
throw 'vital: Data.Dict: Empty dictionary'
|
||||
endif
|
||||
return s:_max_by(a:dict, a:expr)
|
||||
endfunction
|
||||
|
||||
function! s:min_by(dict, expr) abort
|
||||
if empty(a:dict)
|
||||
throw 'vital: Data.Dict: Empty dictionary'
|
||||
endif
|
||||
return s:_max_by(a:dict, '-(' . a:expr . ')')
|
||||
endfunction
|
||||
|
||||
function! s:_foldl(f, init, xs) abort
|
||||
let memo = a:init
|
||||
for [k, v] in a:xs
|
||||
let expr = substitute(a:f, 'v:key', string(k), 'g')
|
||||
let expr = substitute(expr, 'v:val', string(v), 'g')
|
||||
let expr = substitute(expr, 'v:memo', string(memo), 'g')
|
||||
unlet memo
|
||||
let memo = eval(expr)
|
||||
endfor
|
||||
return memo
|
||||
endfunction
|
||||
|
||||
function! s:foldl(f, init, dict) abort
|
||||
return s:_foldl(a:f, a:init, items(a:dict))
|
||||
endfunction
|
||||
|
||||
function! s:foldr(f, init, dict) abort
|
||||
return s:_foldl(a:f, a:init, reverse(items(a:dict)))
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et ts=2 sts=2 sw=2 tw=0:
|
@ -0,0 +1,457 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Data#List#import() abort
|
||||
return map({'combinations': '', 'and': '', 'sort_by': '', 'foldr1': '', 'sort': '', 'flatten': '', 'has_index': '', 'find_indices': '', 'any': '', 'unshift': '', 'span': '', 'pop': '', 'binary_search': '', 'uniq_by': '', 'or': '', 'all': '', 'zip': '', 'find_last_index': '', 'find': '', 'partition': '', 'map_accum': '', 'permutations': '', 'break': '', 'max_by': '', 'foldl': '', 'foldr': '', 'find_index': '', 'group_by': '', 'take_while': '', 'conj': '', 'push': '', 'char_range': '', 'cons': '', 'foldl1': '', 'intersect': '', 'concat': '', 'shift': '', 'clear': '', 'has_common_items': '', 'product': '', 'zip_fill': '', 'uniq': '', 'has': '', 'min_by': '', 'with_index': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Data#List#import() abort', printf("return map({'combinations': '', 'and': '', 'sort_by': '', 'foldr1': '', 'sort': '', 'flatten': '', 'has_index': '', 'find_indices': '', 'any': '', 'unshift': '', 'span': '', 'pop': '', 'binary_search': '', 'uniq_by': '', 'or': '', 'all': '', 'zip': '', 'find_last_index': '', 'find': '', 'partition': '', 'map_accum': '', 'permutations': '', 'break': '', 'max_by': '', 'foldl': '', 'foldr': '', 'find_index': '', 'group_by': '', 'take_while': '', 'conj': '', 'push': '', 'char_range': '', 'cons': '', 'foldl1': '', 'intersect': '', 'concat': '', 'shift': '', 'clear': '', 'has_common_items': '', 'product': '', 'zip_fill': '', 'uniq': '', 'has': '', 'min_by': '', 'with_index': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
" Utilities for list.
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:pop(list) abort
|
||||
return remove(a:list, -1)
|
||||
endfunction
|
||||
|
||||
function! s:push(list, val) abort
|
||||
call add(a:list, a:val)
|
||||
return a:list
|
||||
endfunction
|
||||
|
||||
function! s:shift(list) abort
|
||||
return remove(a:list, 0)
|
||||
endfunction
|
||||
|
||||
function! s:unshift(list, val) abort
|
||||
return insert(a:list, a:val)
|
||||
endfunction
|
||||
|
||||
function! s:cons(x, xs) abort
|
||||
return [a:x] + a:xs
|
||||
endfunction
|
||||
|
||||
function! s:conj(xs, x) abort
|
||||
return a:xs + [a:x]
|
||||
endfunction
|
||||
|
||||
" Removes duplicates from a 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) abort
|
||||
let list = map(copy(a:list), printf('[v:val, %s]', a:f))
|
||||
let i = 0
|
||||
let seen = {}
|
||||
while i < len(list)
|
||||
let key = string(list[i][1])
|
||||
if has_key(seen, key)
|
||||
call remove(list, i)
|
||||
else
|
||||
let seen[key] = 1
|
||||
let i += 1
|
||||
endif
|
||||
endwhile
|
||||
return map(list, 'v:val[0]')
|
||||
endfunction
|
||||
|
||||
function! s:clear(list) abort
|
||||
if !empty(a:list)
|
||||
unlet! a:list[0 : len(a:list) - 1]
|
||||
endif
|
||||
return a:list
|
||||
endfunction
|
||||
|
||||
" Concatenates a list of lists.
|
||||
" XXX: Should we verify the input?
|
||||
function! s:concat(list) abort
|
||||
let memo = []
|
||||
for Value in a:list
|
||||
let memo += Value
|
||||
endfor
|
||||
return memo
|
||||
endfunction
|
||||
|
||||
" Take each elements from lists to a new list.
|
||||
function! s:flatten(list, ...) abort
|
||||
let limit = a:0 > 0 ? a:1 : -1
|
||||
let memo = []
|
||||
if limit == 0
|
||||
return a:list
|
||||
endif
|
||||
let limit -= 1
|
||||
for Value in a:list
|
||||
let memo +=
|
||||
\ type(Value) == type([]) ?
|
||||
\ s:flatten(Value, limit) :
|
||||
\ [Value]
|
||||
unlet! Value
|
||||
endfor
|
||||
return memo
|
||||
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) abort
|
||||
if type(a:expr) == type(function('function'))
|
||||
return sort(a:list, a:expr)
|
||||
endif
|
||||
let s:expr = a:expr
|
||||
return sort(a:list, 's:_compare')
|
||||
endfunction
|
||||
|
||||
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) 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]')
|
||||
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) abort
|
||||
if empty(a:list)
|
||||
return 0
|
||||
endif
|
||||
let list = map(copy(a:list), a:expr)
|
||||
return a:list[index(list, max(list))]
|
||||
endfunction
|
||||
|
||||
" Returns a minimum value in {list} through given {expr}.
|
||||
" Returns 0 if {list} is empty.
|
||||
" v:val is used in {expr}
|
||||
" FIXME: -0x80000000 == 0x80000000
|
||||
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) abort
|
||||
return map(
|
||||
\ range(char2nr(a:from), char2nr(a:to)),
|
||||
\ 'nr2char(v:val)'
|
||||
\)
|
||||
endfunction
|
||||
|
||||
" Returns true if a:list has a:value.
|
||||
" Returns false otherwise.
|
||||
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) 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) 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'))
|
||||
let border = i
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
return border == 0 ? [[], copy(a:xs)] : [a:xs[: border - 1], a:xs[border :]]
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Data.List.break
|
||||
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) abort
|
||||
return s:span(a:f, a:xs)[0]
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Data.List.partition
|
||||
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) abort
|
||||
return !s:any(printf('!(%s)', a:f), a:xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.any
|
||||
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) abort
|
||||
return s:all('v:val', a:xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.or
|
||||
function! s:or(xs) abort
|
||||
return s:any('v:val', a:xs)
|
||||
endfunction
|
||||
|
||||
function! s:map_accum(expr, xs, init) abort
|
||||
let memo = []
|
||||
let init = a:init
|
||||
for x in a:xs
|
||||
let expr = substitute(a:expr, 'v:memo', init, 'g')
|
||||
let expr = substitute(expr, 'v:val', x, 'g')
|
||||
let [tmp, init] = eval(expr)
|
||||
call add(memo, tmp)
|
||||
endfor
|
||||
return memo
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.foldl
|
||||
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')
|
||||
let expr = substitute(expr, 'v:memo', string(memo), 'g')
|
||||
unlet memo
|
||||
let memo = eval(expr)
|
||||
endfor
|
||||
return memo
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.foldl1
|
||||
function! s:foldl1(f, xs) abort
|
||||
if len(a:xs) == 0
|
||||
throw 'vital: Data.List: foldl1'
|
||||
endif
|
||||
return s:foldl(a:f, a:xs[0], a:xs[1:])
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.foldr
|
||||
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) abort
|
||||
if len(a:xs) == 0
|
||||
throw 'vital: Data.List: foldr1'
|
||||
endif
|
||||
return s:foldr(a:f, a:xs[-1], a:xs[0:-2])
|
||||
endfunction
|
||||
|
||||
" similar to python'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) abort
|
||||
if empty(a:xs) && empty(a:ys)
|
||||
return []
|
||||
elseif empty(a:ys)
|
||||
return s:cons([a:xs[0], a:filler], s:zip_fill(a:xs[1 :], [], a:filler))
|
||||
elseif empty(a:xs)
|
||||
return s:cons([a:filler, a:ys[0]], s:zip_fill([], a:ys[1 :], a:filler))
|
||||
else
|
||||
return s:cons([a:xs[0], a:ys[0]], s:zip_fill(a:xs[1 :], a:ys[1: ], a:filler))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Inspired by Ruby's with_index method.
|
||||
function! s:with_index(list, ...) abort
|
||||
let base = a:0 > 0 ? a:1 : 0
|
||||
return map(copy(a:list), '[v:val, v:key + base]')
|
||||
endfunction
|
||||
|
||||
" similar to Ruby's detect or Haskell's find.
|
||||
function! s:find(list, default, f) abort
|
||||
for x in a:list
|
||||
if eval(substitute(a:f, 'v:val', string(x), 'g'))
|
||||
return x
|
||||
endif
|
||||
endfor
|
||||
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) abort
|
||||
return !empty(filter(copy(a:list1), 'index(a:list2, v:val) isnot -1'))
|
||||
endfunction
|
||||
|
||||
function! s:intersect(list1, list2) abort
|
||||
let items = []
|
||||
" for funcref
|
||||
for X in a:list1
|
||||
if index(a:list2, X) != -1 && index(items, X) == -1
|
||||
let items += [X]
|
||||
endif
|
||||
endfor
|
||||
return items
|
||||
endfunction
|
||||
|
||||
" similar to Ruby's group_by.
|
||||
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
|
||||
let Val = x[0]
|
||||
let key = type(x[1]) !=# type('') ? string(x[1]) : x[1]
|
||||
if has_key(result, key)
|
||||
call add(result[key], Val)
|
||||
else
|
||||
let result[key] = [Val]
|
||||
endif
|
||||
unlet Val
|
||||
endfor
|
||||
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
|
||||
|
||||
" vim:set et ts=2 sts=2 sw=2 tw=0:
|
@ -0,0 +1,284 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Data#Set#import() abort
|
||||
return map({'set': '', 'frozenset': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Data#Set#import() abort', printf("return map({'set': '', 'frozenset': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:TRUE = !0
|
||||
let s:FALSE = 0
|
||||
|
||||
function! s:set(...) abort
|
||||
return call(s:set._new, a:000, s:set)
|
||||
endfunction
|
||||
|
||||
function! s:frozenset(...) abort
|
||||
return call(s:frozenset._new, a:000, s:frozenset)
|
||||
endfunction
|
||||
|
||||
function! s:_hash_func(x) abort
|
||||
return a:x
|
||||
endfunction
|
||||
|
||||
let s:_base_set = {
|
||||
\ '_is_set' : s:TRUE,
|
||||
\ '_data' : {},
|
||||
\ '_hash_func' : function('s:_hash_func')
|
||||
\ }
|
||||
|
||||
function! s:_base_set._new(...) abort
|
||||
let obj = deepcopy(self)
|
||||
let xs = get(a:, 1, [])
|
||||
let obj._hash_func = get(a:, 2, obj._hash_func)
|
||||
call obj._set_data(xs)
|
||||
return obj
|
||||
endfunction
|
||||
|
||||
"" Return the union of two sets as a new set.
|
||||
" (I.e. all elements that are in either set.)
|
||||
function! s:_base_set.union(t) abort
|
||||
let r = deepcopy(self)
|
||||
call r._update(a:t)
|
||||
return r
|
||||
endfunction
|
||||
let s:_base_set.or = s:_base_set.union
|
||||
|
||||
"" Return the intersection of two sets as a new set.
|
||||
" (I.e. all elements that are in both sets.)
|
||||
function! s:_base_set.intersection(t) abort
|
||||
let t = self._to_set(a:t)
|
||||
let [little, big] = self.len() <= t.len() ? [self, t] : [t, self]
|
||||
return self._new(filter(copy(big.to_list()), 'little.in(v:val)'))
|
||||
endfunction
|
||||
let s:_base_set.and = s:_base_set.intersection
|
||||
|
||||
"" Return the symmetric difference of two sets as a new set.
|
||||
" (I.e. all elements that are in exactly one of the sets.)
|
||||
function! s:_base_set.symmetric_difference(t) abort
|
||||
let t = self._to_set(a:t)
|
||||
return self._new(filter(copy(self.to_list()), '!t.in(v:val)')
|
||||
\ + filter(copy(t.to_list()), '!self.in(v:val)'))
|
||||
endfunction
|
||||
let s:_base_set.xor = s:_base_set.symmetric_difference
|
||||
|
||||
"" Return the difference of two sets as a new Set.
|
||||
function! s:_base_set.difference(t) abort
|
||||
let t = self._to_set(a:t)
|
||||
return self._new(filter(copy(self.to_list()), '!t.in(v:val)'))
|
||||
endfunction
|
||||
let s:_base_set.sub = s:_base_set.difference
|
||||
|
||||
"" Report whether another set contains this set.
|
||||
function! s:_base_set.issubset(t) abort
|
||||
let t = self._to_set(a:t)
|
||||
return self.len() > t.len() ? s:FALSE
|
||||
\ : empty(filter(copy(self.to_list()), '!t.in(v:val)'))
|
||||
endfunction
|
||||
|
||||
"" Report whether this set contains another set.
|
||||
function! s:_base_set.issuperset(t) abort
|
||||
let t = self._to_set(a:t)
|
||||
return self.len() < t.len() ? s:FALSE
|
||||
\ : empty(filter(copy(t.to_list()), '!self.in(v:val)'))
|
||||
endfunction
|
||||
|
||||
" less than equal & greater than equal
|
||||
let s:_base_set.le = s:_base_set.issubset
|
||||
let s:_base_set.ge = s:_base_set.issuperset
|
||||
|
||||
" less than
|
||||
function! s:_base_set.lt(t) abort
|
||||
let t = self._to_set(a:t)
|
||||
return self.len() < t.len() && self.issubset(t)
|
||||
endfunction
|
||||
|
||||
" greater than
|
||||
function! s:_base_set.gt(t) abort
|
||||
let t = self._to_set(a:t)
|
||||
return self.len() > t.len() && self.issuperset(t)
|
||||
endfunction
|
||||
|
||||
function! s:_base_set.len() abort
|
||||
return len(self._data)
|
||||
endfunction
|
||||
|
||||
function! s:_base_set.to_list() abort
|
||||
return values(self._data)
|
||||
endfunction
|
||||
|
||||
function! s:_base_set._update(xs) abort
|
||||
for X in (s:_is_set(a:xs) ? a:xs.to_list() : a:xs)
|
||||
call self._add(X)
|
||||
unlet X
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:_base_set._add(x) abort
|
||||
let key = self._hash(a:x)
|
||||
if !has_key(self._data, key)
|
||||
let self._data[key] = a:x
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Report whether an element is a member of a set.
|
||||
function! s:_base_set.in(x) abort
|
||||
return has_key(self._data, self._hash(a:x))
|
||||
endfunction
|
||||
|
||||
function! s:_base_set._to_set(x) abort
|
||||
return s:_is_set(a:x) ? a:x : self._new(a:x)
|
||||
endfunction
|
||||
|
||||
function! s:_base_set._clear() abort
|
||||
let self._data = {}
|
||||
endfunction
|
||||
|
||||
function! s:_base_set._set_data(xs) abort
|
||||
call self._clear()
|
||||
call self._update(a:xs)
|
||||
endfunction
|
||||
|
||||
function! s:_base_set._hash(x) abort
|
||||
return string(self._hash_func(a:x))
|
||||
endfunction
|
||||
|
||||
" frozenset: Immutable set class.
|
||||
|
||||
let s:frozenset = deepcopy(s:_base_set)
|
||||
|
||||
" Set: Mutable set class.
|
||||
|
||||
let s:set = deepcopy(s:_base_set)
|
||||
|
||||
" Update a set with the union of itself and another.
|
||||
function! s:set.update(iterable) abort
|
||||
call self._update(a:iterable)
|
||||
endfunction
|
||||
|
||||
" Update a set with the union of itself and another.
|
||||
function! s:set.ior(t) abort
|
||||
call self.update(a:t)
|
||||
return self
|
||||
endfunction
|
||||
|
||||
" Update a set with the intersection of itself and another.
|
||||
function! s:set.intersection_update(t) abort
|
||||
let r = self.and(a:t).to_list()
|
||||
call self.clear()
|
||||
call self.update(r)
|
||||
endfunction
|
||||
|
||||
" Update a set with the intersection of itself and another.
|
||||
function! s:set.iand(t) abort
|
||||
call self.intersection_update(a:t)
|
||||
return self
|
||||
endfunction
|
||||
|
||||
" Update a set with the symmetric difference of itself and another.
|
||||
function! s:set.symmetric_difference_update(t) abort
|
||||
let t = self._to_set(a:t)
|
||||
if self is t
|
||||
call self.clear()
|
||||
return
|
||||
endif
|
||||
for X in t.to_list()
|
||||
if self.in(X)
|
||||
call self.remove(X)
|
||||
else
|
||||
call self._add(X)
|
||||
endif
|
||||
unlet X
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" Update a set with the symmetric difference of itself and another.
|
||||
function! s:set.ixor(t) abort
|
||||
call self.symmetric_difference_update(a:t)
|
||||
return self
|
||||
endfunction
|
||||
|
||||
" Remove all elements of another set from this set.
|
||||
function! s:set.difference_update(t) abort
|
||||
let t = self._to_set(a:t)
|
||||
if self is t
|
||||
call self.clear()
|
||||
return
|
||||
endif
|
||||
for X in filter(t.to_list(), 'self.in(v:val)')
|
||||
call self.remove(X)
|
||||
unlet X
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" Remove all elements of another set from this set.
|
||||
function! s:set.isub(t) abort
|
||||
call self.difference_update(a:t)
|
||||
return self
|
||||
endfunction
|
||||
|
||||
" Remove all elements from this set.
|
||||
function! s:set.clear() abort
|
||||
call self._clear()
|
||||
endfunction
|
||||
|
||||
"" Add an element to a set.
|
||||
" This has no effect if the element is already present.
|
||||
function! s:set.add(x) abort
|
||||
return self._add(a:x)
|
||||
endfunction
|
||||
|
||||
"" Remove an element from a set; it must be a member.
|
||||
" If the element is not a member, throw Exception.
|
||||
function! s:set.remove(e) abort
|
||||
try
|
||||
unlet self._data[self._hash(a:e)]
|
||||
catch /^Vim\%((\a\+)\)\?:E716/
|
||||
call s:_throw('the element is not a member')
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
"" Remove an element from a set if it is a member.
|
||||
" If the element is not a member, do nothing.
|
||||
function! s:set.discard(e) abort
|
||||
try
|
||||
call self.remove(a:e)
|
||||
catch /vital: Data.Set: the element is not a member/
|
||||
" Do nothing
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" Remove and return an arbitrary set element.
|
||||
function! s:set.pop() abort
|
||||
try
|
||||
let k = keys(self._data)[0]
|
||||
catch /^Vim\%((\a\+)\)\?:E684/
|
||||
call s:_throw('set is empty')
|
||||
endtry
|
||||
let v = self._data[k]
|
||||
unlet self._data[k]
|
||||
return v
|
||||
endfunction
|
||||
|
||||
" Helper:
|
||||
|
||||
function! s:_is_set(x) abort
|
||||
return type(a:x) is type({}) && get(a:x, '_is_set', s:FALSE)
|
||||
endfunction
|
||||
|
||||
function! s:_throw(message) abort
|
||||
throw 'vital: Data.Set: ' . a:message
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,126 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#HitAHint#Hint#import() abort
|
||||
return map({'create': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#HitAHint#Hint#import() abort', printf("return map({'create': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
" function() wrapper
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
let s:_function = function('function')
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
let s:_s = '<SNR>' . s:_SID() . '_'
|
||||
function! s:_function(fstr) abort
|
||||
return function(substitute(a:fstr, 's:', s:_s, 'g'))
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:_assert(...) abort
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:_vital_loaded(V) abort
|
||||
if a:V.exists('Vim.PowerAssert')
|
||||
let s:assert = a:V.import('Vim.PowerAssert').assert
|
||||
else
|
||||
let s:assert = s:_function('s:_assert')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" TERMS:
|
||||
" key: A character to generate hint. e.g. a,b,c,d,e,f,...
|
||||
" hint: A hint is a combination of keys. e.g. a,b,ab,abc,..
|
||||
|
||||
" s:create() assigns keys to each targets and generate hint dict.
|
||||
" Example:
|
||||
" let targets = [1, 2, 3, 4, 5, 6]
|
||||
" echo s:label(targets, ['a', 'b', 'c'])
|
||||
" " => {
|
||||
" 'a': 1,
|
||||
" 'b': {
|
||||
" 'a': 2,
|
||||
" 'b': 3
|
||||
" },
|
||||
" 'c': {
|
||||
" 'a': 4,
|
||||
" 'b': 5,
|
||||
" 'c': 6
|
||||
" }
|
||||
" }
|
||||
" Hint-to-target:
|
||||
" a -> 1
|
||||
" ba -> 2
|
||||
" bb -> 3
|
||||
" ca -> 4
|
||||
" cb -> 5
|
||||
" cc -> 6
|
||||
" @param {list<T>} targets
|
||||
" @param {list<string>} keys each key should be uniq
|
||||
" @return Tree{string: (T|Tree)}
|
||||
function! s:create(targets, keys) abort
|
||||
exe s:assert('len(a:keys) > 1')
|
||||
let groups = {}
|
||||
let keys_count = reverse(s:_keys_count(len(a:targets), len(a:keys)))
|
||||
|
||||
let target_idx = 0
|
||||
let key_idx = 0
|
||||
for key_count in keys_count
|
||||
if key_count > 1
|
||||
" We need to create a subgroup
|
||||
" Recurse one level deeper
|
||||
let sub_targets = a:targets[target_idx : target_idx + key_count - 1]
|
||||
let groups[a:keys[key_idx]] = s:create(sub_targets, a:keys)
|
||||
elseif key_count == 1
|
||||
" Assign single target key_idx
|
||||
let groups[a:keys[key_idx]] = a:targets[target_idx]
|
||||
else
|
||||
" No target
|
||||
continue
|
||||
endif
|
||||
let key_idx += 1
|
||||
let target_idx += key_count
|
||||
endfor
|
||||
return groups
|
||||
endfunction
|
||||
|
||||
" s:_keys_count() generates list which represents how many targets to be
|
||||
" assigned to the key.
|
||||
" If the count > 1, use tree recursively.
|
||||
" Example:
|
||||
" echo s:_keys_count(5, 3)
|
||||
" " => [3, 1, 1]
|
||||
" echo s:_keys_count(8, 3)
|
||||
" " => [3, 3, 2]
|
||||
" @param {number} target_len
|
||||
" @param {number} keys_len
|
||||
function! s:_keys_count(targets_len, keys_len) abort
|
||||
exe s:assert('a:keys_len > 1')
|
||||
let _keys_count = repeat([0], a:keys_len)
|
||||
let is_first_level = 1
|
||||
let targets_left_cnt = a:targets_len
|
||||
while targets_left_cnt > 0
|
||||
let cnt_to_add = is_first_level ? 1 : a:keys_len - 1
|
||||
for i in range(a:keys_len)
|
||||
let _keys_count[i] += cnt_to_add
|
||||
let targets_left_cnt -= cnt_to_add
|
||||
if targets_left_cnt <= 0
|
||||
let _keys_count[i] += targets_left_cnt
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
let is_first_level = 0
|
||||
endwhile
|
||||
exe s:assert('len(_keys_count) is# a:keys_len')
|
||||
return _keys_count
|
||||
endfunction
|
@ -0,0 +1,806 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#HitAHint#Motion#import() abort
|
||||
return map({'deepextend': '', 'gather_poses': '', 'tab2spacelen': '', 'move_f': '', 'setline': '', '_vital_depends': '', 'wincall': '', 'move': '', 'move_to_winpos': '', 'pos2hint_to_line2col2hint': '', 'gather_visible_matched_poses': '', 'move_to_win': '', 'throw': '', 'has_patch': '', 'win2pos2hint_to_w2l2c2h': '', 'move_f2': '', 'new_overwin': '', 'create_win2pos2hint': '', 'pos2poskey': '', 'winnr2poses_to_list': '', 'poskey2pos': '', 'is_in_fold': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#HitAHint#Motion#import() abort', printf("return map({'deepextend': '', 'gather_poses': '', 'tab2spacelen': '', 'move_f': '', 'setline': '', '_vital_depends': '', 'wincall': '', 'move': '', 'move_to_winpos': '', 'pos2hint_to_line2col2hint': '', 'gather_visible_matched_poses': '', 'move_to_win': '', 'throw': '', 'has_patch': '', 'win2pos2hint_to_w2l2c2h': '', 'move_f2': '', 'new_overwin': '', 'create_win2pos2hint': '', 'pos2poskey': '', 'winnr2poses_to_list': '', 'poskey2pos': '', 'is_in_fold': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
function! s:_vital_loaded(V) abort
|
||||
let s:Hint = a:V.import('HitAHint.Hint')
|
||||
let s:PHighlight = a:V.import('Palette.Highlight')
|
||||
let s:Buffer = a:V.import('Vim.Buffer')
|
||||
let s:Prelude = a:V.import('Prelude')
|
||||
let s:Set = a:V.import('Data.Set')
|
||||
let s:Input = a:V.import('Over.Input')
|
||||
endfunction
|
||||
|
||||
function! s:_vital_depends() abort
|
||||
return [
|
||||
\ 'HitAHint.Hint',
|
||||
\ 'Palette.Highlight',
|
||||
\ 'Vim.Buffer',
|
||||
\ 'Prelude',
|
||||
\ 'Data.Set',
|
||||
\ 'Over.Input',
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
let s:TRUE = !0
|
||||
let s:FALSE = 0
|
||||
let s:DIRECTION = {'forward': 0, 'backward': 1}
|
||||
|
||||
" Check Vim version
|
||||
function! s:has_patch(major, minor, patch) abort
|
||||
let l:version = (a:major * 100 + a:minor)
|
||||
return has('patch-' . a:major . '.' . a:minor . '.' . a:patch) ||
|
||||
\ (v:version > l:version) ||
|
||||
\ (v:version == l:version && 'patch' . a:patch)
|
||||
endfunction
|
||||
|
||||
" matchadd('Conceal', {pattern}, {priority}, -1, {'conceal': {char}}}) can
|
||||
" highlight pattern and conceal target correctly even if the target is keyword
|
||||
" characters.
|
||||
" - http://ftp.vim.org/vim/patches/7.4/7.4.792
|
||||
" - https://groups.google.com/forum/#!searchin/vim_dev/matchadd$20conceal/vim_dev/8bKa98GhHdk/VOzIBhd1m8YJ
|
||||
let s:can_preserve_syntax = s:has_patch(7, 4, 792)
|
||||
|
||||
" s:move() moves cursor over/accross window with Hit-A-Hint feature like
|
||||
" vim-easymotion
|
||||
" @param {dict} config
|
||||
function! s:move(pattern, ...) abort
|
||||
let o = s:new_overwin(get(a:, 1, {}))
|
||||
return o.pattern(a:pattern)
|
||||
endfunction
|
||||
|
||||
function! s:move_f(...) abort
|
||||
echo 'Target: '
|
||||
let c = s:Input.getchar()
|
||||
return s:move(c, get(a:, 1, {}))
|
||||
endfunction
|
||||
|
||||
function! s:move_f2() abort
|
||||
echo 'Target: '
|
||||
let c = s:Input.getchar()
|
||||
redraw
|
||||
echo 'Target: ' . c
|
||||
let c2 = s:Input.getchar()
|
||||
return s:move(s:Prelude.escape_pattern(c . c2), get(a:, 1, {}))
|
||||
endfunction
|
||||
|
||||
|
||||
let s:overwin = {
|
||||
\ 'config': {
|
||||
\ 'keys': 'asdghklqwertyuiopzxcvbnmfj;',
|
||||
\ 'use_upper': s:FALSE,
|
||||
\ 'auto_land': s:TRUE,
|
||||
\ 'highlight': {
|
||||
\ 'shade': 'HitAHintShade',
|
||||
\ 'target': 'HitAHintTarget',
|
||||
\ 'cursor': 'HitAHintCursor',
|
||||
\ },
|
||||
\ 'jump_first_target_keys': [],
|
||||
\ 'do_shade': s:TRUE,
|
||||
\ }
|
||||
\ }
|
||||
|
||||
function! s:_init_hl() abort
|
||||
highlight default HitAHintShade ctermfg=242 guifg=#777777
|
||||
highlight default HitAHintTarget ctermfg=81 guifg=#66D9EF
|
||||
" Cursor highlight doesn't exist for some environment with some
|
||||
" colorscheme ref:#275
|
||||
" e.g.
|
||||
" - :colorscheme default
|
||||
" - :colorscheme hybrid
|
||||
if hlexists('Cursor')
|
||||
highlight default link HitAHintCursor Cursor
|
||||
else
|
||||
highlight default HitAHintCursor term=reverse cterm=reverse gui=reverse
|
||||
endif
|
||||
endfunction
|
||||
|
||||
call s:_init_hl()
|
||||
|
||||
augroup vital-hit-a-hint-motion-default-highlight
|
||||
autocmd!
|
||||
autocmd ColorScheme * call s:_init_hl()
|
||||
augroup END
|
||||
|
||||
|
||||
function! s:new_overwin(...) abort
|
||||
let o = deepcopy(s:overwin)
|
||||
call s:deepextend(o.config, get(a:, 1, {}))
|
||||
return o
|
||||
endfunction
|
||||
|
||||
function! s:overwin.pattern(pattern) abort
|
||||
let winpos = self.select_winpos(self.gather_poses_overwin(a:pattern), self.config.keys)
|
||||
if winpos is# -1
|
||||
else
|
||||
call s:move_to_winpos(winpos)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" @param {{winnr: [lnum, cnum]}}
|
||||
function! s:move_to_winpos(winpos) abort
|
||||
let [winnr_str, pos] = a:winpos
|
||||
let winnr = str2nr(winnr_str)
|
||||
let is_win_moved = !(winnr is# winnr())
|
||||
if is_win_moved
|
||||
if exists('#WinLeave')
|
||||
silent doautocmd WinLeave
|
||||
endif
|
||||
call s:move_to_win(winnr)
|
||||
else
|
||||
normal! m`
|
||||
endif
|
||||
call cursor(pos)
|
||||
if is_win_moved && exists('#WinEnter')
|
||||
silent doautocmd WinEnter
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:overwin.select_winpos(winnr2poses, keys) abort
|
||||
let wposes = s:winnr2poses_to_list(a:winnr2poses)
|
||||
if self.config.auto_land && len(wposes) is# 1
|
||||
return wposes[0]
|
||||
endif
|
||||
call self.set_options()
|
||||
try
|
||||
return self.choose_prompt(s:Hint.create(wposes, a:keys))
|
||||
finally
|
||||
call self.restore_options()
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:overwin.set_options() abort
|
||||
" s:move_to_win() takes long time if 'foldmethod' == 'syntax' or 'expr'
|
||||
let self.save_foldmethod = {}
|
||||
for winnr in range(1, winnr('$'))
|
||||
let self.save_foldmethod[winnr] = getwinvar(winnr, '&foldmethod')
|
||||
call setwinvar(winnr, '&foldmethod', 'manual')
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:overwin.restore_options() abort
|
||||
for winnr in range(1, winnr('$'))
|
||||
call setwinvar(winnr, '&foldmethod', self.save_foldmethod[winnr])
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" s:wpos_to_hint() returns dict whose key is position with window and whose
|
||||
" value is the hints.
|
||||
" @param Tree{string: ((winnr, (number,number))|Tree)} hint_dict
|
||||
" @return {{winnr: {string: list<char>}}} poskey to hint for each window
|
||||
" e.g.
|
||||
" {
|
||||
" '1': {
|
||||
" '00168:00004': ['b', 'c', 'b'],
|
||||
" '00174:00001': ['b', 'c', 'a'],
|
||||
" '00188:00004': ['b', 'b'],
|
||||
" '00190:00001': ['b', 'a'],
|
||||
" '00191:00016': ['a', 'c'],
|
||||
" '00192:00004': ['a', 'b'],
|
||||
" '00195:00035': ['a', 'a']
|
||||
" },
|
||||
" '3': {
|
||||
" '00168:00004': ['c', 'c', 'c'],
|
||||
" '00174:00001': ['c', 'c', 'b'],
|
||||
" '00188:00004': ['c', 'c', 'a'],
|
||||
" '00190:00001': ['c', 'b'],
|
||||
" '00191:00016': ['c', 'a'],
|
||||
" '00192:00004': ['b', 'c', 'c']
|
||||
" }
|
||||
" }
|
||||
function! s:create_win2pos2hint(hint_dict) abort
|
||||
return s:_create_win2pos2hint({}, a:hint_dict)
|
||||
endfunction
|
||||
|
||||
function! s:_create_win2pos2hint(dict, hint_dict, ...) abort
|
||||
let prefix = get(a:, 1, [])
|
||||
for [hint, v] in items(a:hint_dict)
|
||||
if type(v) is# type({})
|
||||
call s:_create_win2pos2hint(a:dict, v, prefix + [hint])
|
||||
else
|
||||
let [winnr, pos] = v
|
||||
let a:dict[winnr] = get(a:dict, winnr, {})
|
||||
let a:dict[winnr][s:pos2poskey(pos)] = prefix + [hint]
|
||||
endif
|
||||
unlet v
|
||||
endfor
|
||||
return a:dict
|
||||
endfunction
|
||||
|
||||
" s:pos2poskey() convertes pos to poskey to use pos as dictionary keys and
|
||||
" sort pos correctly.
|
||||
" @param {(number,number)} pos
|
||||
" @return string
|
||||
" e.g. [1, 1] -> '00001:00001'
|
||||
function! s:pos2poskey(pos) abort
|
||||
return join(map(copy(a:pos), "printf('%05d', v:val)"), ':')
|
||||
endfunction
|
||||
|
||||
" s:poskey2pos() convertes poskey to pos.
|
||||
" @param {string} poskey e.g. '00001:00001'
|
||||
" @return {(number,number)}
|
||||
" e.g. '00001:00001' -> [1, 1]
|
||||
function! s:poskey2pos(poskey) abort
|
||||
return map(split(a:poskey, ':'), 'str2nr(v:val)')
|
||||
endfunction
|
||||
|
||||
function! s:overwin.choose_prompt(hint_dict) abort
|
||||
if empty(a:hint_dict)
|
||||
redraw
|
||||
echo 'No target'
|
||||
return -1
|
||||
endif
|
||||
let hinter = s:Hinter.new(a:hint_dict, self.config)
|
||||
try
|
||||
call hinter.before()
|
||||
call hinter.show_hint()
|
||||
redraw
|
||||
echo 'Target key: '
|
||||
let c = s:Input.getchar()
|
||||
if self.config.use_upper
|
||||
let c = toupper(c)
|
||||
endif
|
||||
catch
|
||||
echo v:throwpoint . ':' . v:exception
|
||||
return -1
|
||||
finally
|
||||
call hinter.after()
|
||||
endtry
|
||||
|
||||
" Jump to first target if target key is in config.jump_first_target_keys.
|
||||
if index(self.config.jump_first_target_keys, c) isnot# -1
|
||||
let c = split(self.config.keys, '\zs')[0]
|
||||
endif
|
||||
|
||||
if has_key(a:hint_dict, c)
|
||||
let target = a:hint_dict[c]
|
||||
return type(target) is# type({}) ? self.choose_prompt(target) : target
|
||||
else
|
||||
redraw
|
||||
echo 'Invalid target: ' . c
|
||||
return -1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Hinter show hints accross window.
|
||||
" save_lines: {{winnr: {lnum: string}}}
|
||||
" w2l2c2h: winnr to lnum to col num to hints. col2hints is tuple because we
|
||||
" need sorted col to hints pair.
|
||||
" save_syntax: {{winnr: &syntax}}
|
||||
" {{winnr: {lnum: list<(cnum, list<char>)>}}}
|
||||
let s:Hinter = {
|
||||
\ 'save_lines': {},
|
||||
\ 'w2l2c2h': {},
|
||||
\ 'winnrs': [],
|
||||
\ 'save_syntax': {},
|
||||
\ 'save_conceallevel': {},
|
||||
\ 'save_concealcursor': {},
|
||||
\ 'save_modified': {},
|
||||
\ 'save_modifiable': {},
|
||||
\ 'save_readonly': {},
|
||||
\ 'save_undo': {},
|
||||
\ 'highlight_ids': {},
|
||||
\ }
|
||||
|
||||
function! s:Hinter.new(hint_dict, config) abort
|
||||
let s = deepcopy(self)
|
||||
let s.config = a:config
|
||||
call s.init(a:hint_dict)
|
||||
return s
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.init(hint_dict) abort
|
||||
let win2pos2hint = s:create_win2pos2hint(a:hint_dict)
|
||||
let self.winnrs = sort(map(keys(win2pos2hint), 'str2nr(v:val)'))
|
||||
let self.win2pos2hint = win2pos2hint
|
||||
let self.w2l2c2h = s:win2pos2hint_to_w2l2c2h(win2pos2hint)
|
||||
let self.hl_target_ids = {}
|
||||
for winnr in self.winnrs
|
||||
let self.hl_target_ids[winnr] = []
|
||||
endfor
|
||||
call self._save_lines()
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.before() abort
|
||||
let self.highlight_id_cursor = matchadd(self.config.highlight.cursor, '\%#', 101)
|
||||
call self.save_options()
|
||||
call self.disable_conceal_in_other_win()
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.after() abort
|
||||
call matchdelete(self.highlight_id_cursor)
|
||||
call self.restore_env()
|
||||
call self.restore_conceal_in_other_win()
|
||||
endfunction
|
||||
|
||||
function! s:Hinter._save_lines() abort
|
||||
let nr = winnr()
|
||||
try
|
||||
for [winnr, pos2hint] in items(self.win2pos2hint)
|
||||
call s:move_to_win(winnr)
|
||||
let lnums = map(copy(keys(pos2hint)), 's:poskey2pos(v:val)[0]')
|
||||
let self.save_lines[winnr] = get(self.save_lines, winnr, {})
|
||||
for lnum in lnums
|
||||
let self.save_lines[winnr][lnum] = getline(lnum)
|
||||
endfor
|
||||
endfor
|
||||
finally
|
||||
call s:move_to_win(nr)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.restore_lines_for_win(winnr) abort
|
||||
let lnum2line = self.save_lines[a:winnr]
|
||||
for [lnum, line] in items(lnum2line)
|
||||
call s:setline(lnum, line)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.save_options() abort
|
||||
for winnr in self.winnrs
|
||||
let self.save_syntax[winnr] = getwinvar(winnr, '&syntax')
|
||||
let self.save_conceallevel[winnr] = getwinvar(winnr, '&conceallevel')
|
||||
let self.save_concealcursor[winnr] = getwinvar(winnr, '&concealcursor')
|
||||
let self.save_modified[winnr] = getwinvar(winnr, '&modified')
|
||||
let self.save_modifiable[winnr] = getwinvar(winnr, '&modifiable')
|
||||
let self.save_readonly[winnr] = getwinvar(winnr, '&readonly')
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.restore_options() abort
|
||||
for winnr in self.winnrs
|
||||
call setwinvar(winnr, '&conceallevel', self.save_conceallevel[winnr])
|
||||
call setwinvar(winnr, '&concealcursor', self.save_concealcursor[winnr])
|
||||
call setwinvar(winnr, '&modified', self.save_modified[winnr])
|
||||
call setwinvar(winnr, '&modifiable', self.save_modifiable[winnr])
|
||||
call setwinvar(winnr, '&readonly', self.save_readonly[winnr])
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.modify_env_for_win(winnr) abort
|
||||
let self.save_conceal = s:PHighlight.get('Conceal')
|
||||
let self.save_undo[a:winnr] = s:undo_lock.save()
|
||||
|
||||
setlocal modifiable
|
||||
setlocal noreadonly
|
||||
|
||||
if !s:can_preserve_syntax
|
||||
ownsyntax overwin
|
||||
endif
|
||||
|
||||
setlocal conceallevel=2
|
||||
setlocal concealcursor=ncv
|
||||
|
||||
let self.highlight_ids[a:winnr] = get(self.highlight_ids, a:winnr, [])
|
||||
if self.config.do_shade
|
||||
if !s:can_preserve_syntax
|
||||
syntax clear
|
||||
endif
|
||||
let self.highlight_ids[a:winnr] += [matchadd(self.config.highlight.shade, '\_.*', 100)]
|
||||
endif
|
||||
|
||||
" XXX: other plugins specific handling
|
||||
if getbufvar('%', 'indentLine_enabled', 0)
|
||||
silent! syntax clear IndentLine
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.restore_env() abort
|
||||
call s:PHighlight.set('Conceal', self.save_conceal)
|
||||
let nr = winnr()
|
||||
try
|
||||
for winnr in self.winnrs
|
||||
call s:move_to_win(winnr)
|
||||
call self.restore_lines_for_win(winnr)
|
||||
call self.remove_hints(winnr)
|
||||
|
||||
if !s:can_preserve_syntax && self.config.do_shade
|
||||
let &syntax = self.save_syntax[winnr]
|
||||
endif
|
||||
|
||||
call self.save_undo[winnr].restore()
|
||||
|
||||
for id in self.highlight_ids[winnr]
|
||||
call matchdelete(id)
|
||||
endfor
|
||||
|
||||
" XXX: other plugins specific handling
|
||||
if getbufvar('%', 'indentLine_enabled', 0) && exists(':IndentLinesEnable') is# 2
|
||||
call setbufvar('%', 'indentLine_enabled', 0)
|
||||
:IndentLinesEnable
|
||||
endif
|
||||
endfor
|
||||
catch
|
||||
call s:throw(v:throwpoint . ' ' . v:exception)
|
||||
finally
|
||||
call s:move_to_win(nr)
|
||||
endtry
|
||||
|
||||
call self.restore_options()
|
||||
endfunction
|
||||
|
||||
let s:undo_lock = {}
|
||||
|
||||
function! s:undo_lock.save() abort
|
||||
let undo = deepcopy(self)
|
||||
call undo._save()
|
||||
return undo
|
||||
endfunction
|
||||
|
||||
function! s:undo_lock._save() abort
|
||||
if undotree().seq_last == 0
|
||||
" if there are no undo history, disable undo feature by setting
|
||||
" 'undolevels' to -1 and restore it.
|
||||
let self.save_undolevels = &l:undolevels
|
||||
let &l:undolevels = -1
|
||||
elseif !s:Buffer.is_cmdwin()
|
||||
" command line window doesn't support :wundo.
|
||||
let self.undofile = tempname()
|
||||
execute 'wundo!' self.undofile
|
||||
else
|
||||
let self.is_cmdwin = s:TRUE
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:undo_lock.restore() abort
|
||||
if has_key(self, 'save_undolevels')
|
||||
let &l:undolevels = self.save_undolevels
|
||||
endif
|
||||
if has_key(self, 'undofile') && filereadable(self.undofile)
|
||||
silent execute 'rundo' self.undofile
|
||||
call delete(self.undofile)
|
||||
endif
|
||||
if has_key(self, 'is_cmdwin')
|
||||
" XXX: it breaks undo history. AFAIK, there are no way to save and restore
|
||||
" undo history in commandline window.
|
||||
call self.undobreak()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:undo_lock.undobreak() abort
|
||||
let old_undolevels = &l:undolevels
|
||||
setlocal undolevels=-1
|
||||
keepjumps call setline('.', getline('.'))
|
||||
let &l:undolevels = old_undolevels
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.disable_conceal_in_other_win() abort
|
||||
let allwinnrs = s:Set.set(range(1, winnr('$')))
|
||||
let other_winnrs = allwinnrs.sub(self.winnrs).to_list()
|
||||
for w in other_winnrs
|
||||
if 'help' !=# getwinvar(w, '&buftype')
|
||||
call setwinvar(w, 'overwin_save_conceallevel', getwinvar(w, '&conceallevel'))
|
||||
call setwinvar(w, '&conceallevel', 0)
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.restore_conceal_in_other_win() abort
|
||||
let allwinnrs = s:Set.set(range(1, winnr('$')))
|
||||
let other_winnrs = allwinnrs.sub(self.winnrs).to_list()
|
||||
for w in other_winnrs
|
||||
if 'help' !=# getwinvar(w, '&buftype')
|
||||
call setwinvar(w, '&conceallevel', getwinvar(w, 'overwin_save_conceallevel'))
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" ._pos2hint_to_line2col2hint() converts pos2hint to line2col2hint dict whose
|
||||
" key is line number and whose value is list of tuple of col number to hint.
|
||||
" line2col2hint is for show hint with replacing line by line.
|
||||
" col should be sorted.
|
||||
" @param {{string: list<char>}} pos2hint
|
||||
" @return {number: [(number, list<char>)]}
|
||||
function! s:Hinter._pos2hint_to_line2col2hint(pos2hint) abort
|
||||
let line2col2hint = {}
|
||||
let poskeys = sort(keys(a:pos2hint))
|
||||
for poskey in poskeys
|
||||
let [lnum, cnum] = s:poskey2pos(poskey)
|
||||
let line2col2hint[lnum] = get(line2col2hint, lnum, [])
|
||||
let line2col2hint[lnum] += [[cnum, a:pos2hint[poskey]]]
|
||||
endfor
|
||||
return line2col2hint
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.show_hint() abort
|
||||
let nr = winnr()
|
||||
try
|
||||
for winnr in self.winnrs
|
||||
call s:move_to_win(winnr)
|
||||
call self._show_hint_for_win(winnr)
|
||||
endfor
|
||||
finally
|
||||
call s:move_to_win(nr)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:Hinter._show_hint_for_win(winnr) abort
|
||||
call self.modify_env_for_win(a:winnr)
|
||||
|
||||
let hints = []
|
||||
for [lnum, col2hint] in items(self.w2l2c2h[a:winnr])
|
||||
let hints += self._show_hint_for_line(a:winnr, lnum, col2hint)
|
||||
endfor
|
||||
" Restore syntax and show hints after replacing all lines for performance.
|
||||
if !s:can_preserve_syntax && !self.config.do_shade
|
||||
let &l:syntax = self.save_syntax[a:winnr]
|
||||
endif
|
||||
execute 'highlight! link Conceal' self.config.highlight.target
|
||||
for [lnum, cnum, char] in hints
|
||||
call self.show_hint_pos(lnum, cnum, char, a:winnr)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:Hinter._show_hint_for_line(winnr, lnum, col2hint) abort
|
||||
let hints = [] " [lnum, cnum, char]
|
||||
let line = self.save_lines[a:winnr][a:lnum]
|
||||
let col_offset = 0
|
||||
let prev_cnum = -1
|
||||
let next_offset = 0
|
||||
for [cnum, hint] in a:col2hint
|
||||
let col_num = cnum + col_offset
|
||||
|
||||
let is_consecutive = cnum is# prev_cnum + 1
|
||||
if !is_consecutive
|
||||
let col_num += next_offset
|
||||
endif
|
||||
let save_next_offset = next_offset
|
||||
|
||||
let [line, offset, next_offset] = self._replace_line_for_hint(col_num, line, hint)
|
||||
|
||||
if is_consecutive
|
||||
let col_offset += save_next_offset
|
||||
endif
|
||||
let col_offset += offset
|
||||
|
||||
let hints = [[a:lnum, col_num, hint[0]]] + hints
|
||||
if len(hint) > 1
|
||||
let hints = [[a:lnum, col_num + 1, hint[1]]] + hints
|
||||
endif
|
||||
|
||||
let prev_cnum = cnum
|
||||
endfor
|
||||
call s:setline(a:lnum, line)
|
||||
return hints
|
||||
endfunction
|
||||
|
||||
" ._replace_line_for_hint() replaces line to show hints.
|
||||
" - It appends space if the line is empty
|
||||
" - It replaces <Tab> to space if the target character is <Tab>
|
||||
" - It replaces next target character if it's <Tab> and len(hint) > 1
|
||||
" Replacing line changes col number, so it returns offset of col number.
|
||||
" As for replaceing next target character, the timing to calculate offset
|
||||
" depends on the col number of next hint in the same line, so it returns
|
||||
" `next_offset` instead of returning offset all at once.
|
||||
" @return {(string, number, number)} (line, offset, next_offset)
|
||||
function! s:Hinter._replace_line_for_hint(col_num, line, hint) abort
|
||||
let line = a:line
|
||||
let col_num = a:col_num
|
||||
let do_replace_target = !(self.config.do_shade || s:can_preserve_syntax)
|
||||
let target = matchstr(line, '\%' . col_num .'c.')
|
||||
" Append one space for empty line or match at end of line
|
||||
if target is# ''
|
||||
let hintwidth = strdisplaywidth(join(a:hint[:1], ''))
|
||||
let char = do_replace_target ? ' ' : '.'
|
||||
let line .= repeat(char, hintwidth)
|
||||
return [line, hintwidth, 0]
|
||||
endif
|
||||
|
||||
let offset = 0
|
||||
if target is# "\t"
|
||||
let [line, offset] = self._replace_tab_target(col_num, line)
|
||||
elseif strdisplaywidth(target) > 1
|
||||
let line = self._replace_text_to_space(line, col_num, strdisplaywidth(target))
|
||||
let offset = strdisplaywidth(target) - len(target)
|
||||
else
|
||||
if do_replace_target
|
||||
" The priority of :syn-cchar is always under the priority of keywords.
|
||||
" So, Hit-A-Hint replaces targets character with '.'.
|
||||
let space = '.'
|
||||
let line = substitute(line, '\%' . col_num . 'c.', space, '')
|
||||
let offset = len(space) - len(target)
|
||||
endif
|
||||
endif
|
||||
|
||||
let next_offset = 0
|
||||
if len(a:hint) > 1 && target isnot# "\t"
|
||||
" pass [' '] as hint to stop recursion.
|
||||
let [line, next_offset, _] = self._replace_line_for_hint(col_num + offset + 1, line, [' '])
|
||||
endif
|
||||
return [line, offset, next_offset]
|
||||
endfunction
|
||||
|
||||
" @return {(line, offset)}
|
||||
function! s:Hinter._replace_tab_target(col_num, line) abort
|
||||
let space_len = s:tab2spacelen(a:line, a:col_num)
|
||||
let line = self._replace_text_to_space(a:line, a:col_num, space_len)
|
||||
return [line, space_len - 1]
|
||||
endfunction
|
||||
|
||||
function! s:Hinter._replace_text_to_space(line, col_num, len) abort
|
||||
let target = printf('\%%%dc.', a:col_num)
|
||||
let line = substitute(a:line, target, repeat(' ', a:len), '')
|
||||
return line
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.show_hint_pos(lnum, cnum, char, winnr) abort
|
||||
let p = '\%'. a:lnum . 'l\%'. a:cnum . 'c.'
|
||||
if s:can_preserve_syntax
|
||||
let self.hl_target_ids[a:winnr] += [matchadd('Conceal', p, 101, -1, {'conceal': a:char})]
|
||||
else
|
||||
exec "syntax match HitAHintTarget '". p . "' contains=NONE containedin=.* conceal cchar=". a:char
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Hinter.remove_hints(winnr) abort
|
||||
if s:can_preserve_syntax
|
||||
for id in self.hl_target_ids[a:winnr]
|
||||
call matchdelete(id)
|
||||
endfor
|
||||
else
|
||||
" Clear syntax defined by Hit-A-Hint motion before restoring syntax.
|
||||
syntax clear HitAHintTarget
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" @param {number} col_num col_num is 1 origin like col()
|
||||
function! s:tab2spacelen(line, col_num) abort
|
||||
let before_line = a:col_num > 2 ? a:line[: a:col_num - 2]
|
||||
\ : a:col_num is# 2 ? a:line[0]
|
||||
\ : ''
|
||||
let vcol_num = 1
|
||||
for c in split(before_line, '\zs')
|
||||
let vcol_num += c is# "\t" ? s:_virtual_tab2spacelen(vcol_num) : len(c)
|
||||
endfor
|
||||
return s:_virtual_tab2spacelen(vcol_num)
|
||||
endfunction
|
||||
|
||||
function! s:_virtual_tab2spacelen(col_num) abort
|
||||
return &tabstop - ((a:col_num - 1) % &tabstop)
|
||||
endfunction
|
||||
|
||||
function! s:win2pos2hint_to_w2l2c2h(win2pos2hint) abort
|
||||
let w2l2c2h = {}
|
||||
for [winnr, pos2hint] in items(a:win2pos2hint)
|
||||
let w2l2c2h[winnr] = s:pos2hint_to_line2col2hint(pos2hint)
|
||||
endfor
|
||||
return w2l2c2h
|
||||
endfunction
|
||||
|
||||
" s:pos2hint_to_line2col2hint() converts pos2hint to line2col2hint dict whose
|
||||
" key is line number and whose value is list of tuple of col number to hint.
|
||||
" line2col2hint is for show hint with replacing line by line.
|
||||
" col should be sorted.
|
||||
" @param {{string: list<char>}} pos2hint
|
||||
" @return {number: [(number, list<char>)]}
|
||||
function! s:pos2hint_to_line2col2hint(pos2hint) abort
|
||||
let line2col2hint = {}
|
||||
let poskeys = sort(keys(a:pos2hint))
|
||||
for poskey in poskeys
|
||||
let [lnum, cnum] = s:poskey2pos(poskey)
|
||||
let line2col2hint[lnum] = get(line2col2hint, lnum, [])
|
||||
let line2col2hint[lnum] += [[cnum, a:pos2hint[poskey]]]
|
||||
endfor
|
||||
return line2col2hint
|
||||
endfunction
|
||||
|
||||
" @param {number} winnr
|
||||
function! s:move_to_win(winnr) abort
|
||||
if a:winnr !=# winnr()
|
||||
execute 'noautocmd' a:winnr . 'wincmd w'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" @param {regex} pattern
|
||||
" @return {{winnr: list<list<(number,number))>}}
|
||||
function! s:overwin.gather_poses_overwin(pattern) abort
|
||||
return s:wincall(function('s:gather_poses'), [a:pattern])
|
||||
endfunction
|
||||
|
||||
" s:gather_poses() aggregates patterm matched positions in visible current
|
||||
" window for both direction excluding poses in fold.
|
||||
" @return {{list<list<(number,number))>}}
|
||||
function! s:gather_poses(pattern) abort
|
||||
let f = s:gather_visible_matched_poses(a:pattern, s:DIRECTION.forward, s:TRUE)
|
||||
let b = s:gather_visible_matched_poses(a:pattern, s:DIRECTION.backward, s:FALSE)
|
||||
return filter(f + b, '!s:is_in_fold(v:val[0])')
|
||||
endfunction
|
||||
|
||||
" s:gather_visible_matched_poses() aggregates pattern matched positions in visible current
|
||||
" window.
|
||||
" @param {regex} pattern
|
||||
" @param {enum<DIRECTION>} direction see s:DIRECTION
|
||||
" @param {bool} allow_cursor_pos_match
|
||||
" @return {list<list<(number,number)>>} positions
|
||||
function! s:gather_visible_matched_poses(pattern, direction, allow_cursor_pos_match) abort
|
||||
let stop_line = line(a:direction is# s:DIRECTION.forward ? 'w$' : 'w0')
|
||||
let search_flag = (a:direction is# s:DIRECTION.forward ? '' : 'b')
|
||||
let c_flag = a:allow_cursor_pos_match ? 'c' : ''
|
||||
let view = winsaveview()
|
||||
let poses = []
|
||||
keepjumps let pos = searchpos(a:pattern, c_flag . search_flag, stop_line)
|
||||
while pos != [0, 0]
|
||||
let poses += [pos]
|
||||
keepjumps let pos = searchpos(a:pattern, search_flag, stop_line)
|
||||
endwhile
|
||||
call winrestview(view)
|
||||
return poses
|
||||
endfunction
|
||||
|
||||
" @param {{winnr: list<list<(number,number))>}} winnr2poses
|
||||
" @param {number?} first_winnr the top winnr poses in returned list
|
||||
" @return {list<{list<(winnr, (number,number))}>}
|
||||
function! s:winnr2poses_to_list(winnr2poses, ...) abort
|
||||
let first_winnr = get(a:, 1, winnr())
|
||||
let first_winnr_poses = []
|
||||
let other_poses = []
|
||||
for [winnr_str, poses] in items(a:winnr2poses)
|
||||
let winnr = str2nr(winnr_str)
|
||||
if winnr is# first_winnr
|
||||
let first_winnr_poses = map(copy(poses), '[winnr, v:val]')
|
||||
else
|
||||
let other_poses += map(copy(poses), '[winnr, v:val]')
|
||||
endif
|
||||
endfor
|
||||
return first_winnr_poses + other_poses
|
||||
endfunction
|
||||
|
||||
" @param {number} lnum line number
|
||||
function! s:is_in_fold(lnum) abort
|
||||
return foldclosed(a:lnum) != -1
|
||||
endfunction
|
||||
|
||||
" @param {funcref} func
|
||||
" @param {arglist} list<S>
|
||||
" @param {dict?} dict for :h call()
|
||||
" @return {{winnr: <T>}}
|
||||
function! s:wincall(func, arglist, ...) abort
|
||||
let dict = get(a:, 1, {})
|
||||
let r = {}
|
||||
let start_winnr = winnr()
|
||||
let r[start_winnr] = call(a:func, a:arglist, dict)
|
||||
if s:Buffer.is_cmdwin()
|
||||
return r
|
||||
endif
|
||||
noautocmd wincmd w
|
||||
while winnr() isnot# start_winnr
|
||||
let r[winnr()] = call(a:func, a:arglist, dict)
|
||||
noautocmd wincmd w
|
||||
endwhile
|
||||
return r
|
||||
endfunction
|
||||
|
||||
" deepextend (nest: 1)
|
||||
function! s:deepextend(expr1, expr2) abort
|
||||
let expr2 = copy(a:expr2)
|
||||
for [k, V] in items(a:expr1)
|
||||
if (type(V) is type({}) || type(V) is type([])) && has_key(expr2, k)
|
||||
let a:expr1[k] = extend(a:expr1[k], expr2[k])
|
||||
unlet expr2[k]
|
||||
endif
|
||||
unlet V
|
||||
endfor
|
||||
return extend(a:expr1, expr2)
|
||||
endfunction
|
||||
|
||||
function! s:setline(lnum, text) abort
|
||||
if getline(a:lnum) isnot# a:text
|
||||
call setline(a:lnum, a:text)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:throw(message) abort
|
||||
throw 'vital: HitAHint.Motion: ' . a:message
|
||||
endfunction
|
||||
|
@ -0,0 +1,606 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Base#import() abort
|
||||
return map({'_vital_depends': '', 'make_plain': '', 'is_input_waiting': '', 'make': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Base#import() abort', printf("return map({'_vital_depends': '', 'make_plain': '', 'is_input_waiting': '', 'make': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
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")
|
||||
let s:Signals = s:V.import("Over.Signals")
|
||||
let s:Input = s:V.import("Over.Input")
|
||||
let s:Keymapping = s:V.import("Over.Keymapping")
|
||||
let s:Module = s:V.import("Over.Commandline.Modules")
|
||||
let s:base.variables.modules = s:Signals.make()
|
||||
function! s:base.variables.modules.get_slot(val)
|
||||
return a:val.slot.module
|
||||
endfunction
|
||||
|
||||
let s:Highlight = s:V.import("Palette.Highlight")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return [
|
||||
\ "Over.String",
|
||||
\ "Over.Signals",
|
||||
\ "Over.Input",
|
||||
\ "Over.Keymapping",
|
||||
\ "Over.Commandline.Modules",
|
||||
\ "Palette.Highlight",
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make(...)
|
||||
let result = deepcopy(s:base)
|
||||
call result.set_prompt(get(a:, 1, ":"))
|
||||
call result.connect(result, "_")
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make_plain()
|
||||
return deepcopy(s:base)
|
||||
endfunction
|
||||
|
||||
|
||||
let s:base = {
|
||||
\ "line" : {},
|
||||
\ "variables" : {
|
||||
\ "prompt" : "",
|
||||
\ "char" : "",
|
||||
\ "input" : "",
|
||||
\ "tap_key" : "",
|
||||
\ "exit" : 0,
|
||||
\ "keymapping" : {},
|
||||
\ "suffix" : "",
|
||||
\ "is_setted" : 0,
|
||||
\ },
|
||||
\ "highlights" : {
|
||||
\ "prompt" : "NONE",
|
||||
\ "cursor" : "VitalOverCommandLineCursor",
|
||||
\ "cursor_on" : "VitalOverCommandLineCursorOn",
|
||||
\ "cursor_insert" : "VitalOverCommandLineOnCursor",
|
||||
\ },
|
||||
\}
|
||||
|
||||
if exists("s:Signals")
|
||||
let s:base.variables.modules = s:Signals.make()
|
||||
function! s:base.variables.modules.get_slot(val)
|
||||
return a:val.slot.module
|
||||
endfunction
|
||||
endif
|
||||
|
||||
|
||||
function! s:base.getline()
|
||||
return self.line.str()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.setline(line)
|
||||
return self.line.set(a:line)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.char()
|
||||
return self.variables.char
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.setchar(char, ...)
|
||||
" 1 の場合は既に設定されていても上書きする
|
||||
" 0 の場合は既に設定されていれば上書きしない
|
||||
let overwrite = get(a:, 1, 1)
|
||||
if overwrite || self.variables.is_setted == 0
|
||||
let self.variables.input = a:char
|
||||
let self.variables.is_setted = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.getpos()
|
||||
return self.line.pos()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.setpos(pos)
|
||||
return self.line.set_pos(a:pos)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.tap_keyinput(key)
|
||||
let self.variables.tap_key = a:key
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.untap_keyinput(key)
|
||||
if self.variables.tap_key == a:key
|
||||
let self.variables.tap_key = ""
|
||||
return 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.get_tap_key()
|
||||
return self.variables.tap_key
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.is_input(key, ...)
|
||||
let prekey = get(a:, 1, "")
|
||||
return self.get_tap_key() ==# prekey
|
||||
\ && self.char() ==# a:key
|
||||
" \ && self.char() == (prekey . a:key)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.input_key()
|
||||
return self.variables.input_key
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.set_prompt(prompt)
|
||||
let self.variables.prompt = a:prompt
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.get_prompt()
|
||||
return self.variables.prompt
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.set_suffix(str)
|
||||
let self.variables.suffix = a:str
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.get_suffix()
|
||||
return self.variables.suffix
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.insert(word, ...)
|
||||
if a:0
|
||||
call self.line.set(a:1)
|
||||
endif
|
||||
call self.line.input(a:word)
|
||||
endfunction
|
||||
|
||||
function! s:base.forward()
|
||||
return self.line.forward()
|
||||
endfunction
|
||||
|
||||
function! s:base.backward()
|
||||
return self.line.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)
|
||||
endif
|
||||
if empty(a:module)
|
||||
return
|
||||
endif
|
||||
let name = a:0 > 0 ? a:1 : a:module.name
|
||||
let slot = self.variables.modules.find_first_by("get(v:val.slot, 'name', '') == " . string(name))
|
||||
if empty(slot)
|
||||
call self.variables.modules.connect({ "name" : name, "module" : a:module })
|
||||
else
|
||||
let slot.slot.module = a:module
|
||||
endif
|
||||
" let self.variables.modules[name] = a:module
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.disconnect(name)
|
||||
return self.variables.modules.disconnect_by(
|
||||
\ "get(v:val.slot, 'name', '') == " . string(a:name)
|
||||
\ )
|
||||
" unlet self.variables.modules[a:name]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.get_module(name)
|
||||
let slot = self.variables.modules.find_first_by("get(v:val.slot, 'name', '') == " . string(a:name))
|
||||
return empty(slot) ? {} : slot.slot.module
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.callevent(event)
|
||||
call self.variables.modules.sort_by("has_key(v:val.slot.module, 'priority') ? v:val.slot.module.priority('" . a:event . "') : 0")
|
||||
return self.variables.modules.call(a:event, [self])
|
||||
" call map(filter(copy(self.variables.modules), "has_key(v:val, a:event)"), "v:val." . a:event . "(self)")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.cmap(lhs, rhs)
|
||||
let self.variables.keymapping[a:lhs] = a:rhs
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.cnoremap(lhs, rhs)
|
||||
let key = s:Keymapping.as_key_config(a:rhs)
|
||||
let key.noremap = 1
|
||||
let self.variables.keymapping[a:lhs] = key
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.cunmap(lhs)
|
||||
unlet self.variables.keymapping[a:lhs]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.keymapping()
|
||||
return self.__keymapping__()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__keymapping__()
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.execute(...)
|
||||
let command = get(a:, 1, self.getline())
|
||||
call self.__execute(command)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.draw()
|
||||
call self.callevent("on_draw_pre")
|
||||
call self.callevent("on_draw")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.exit(...)
|
||||
let self.variables.exit = 1
|
||||
let self.variables.exit_code = get(a:, 1, 0)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.enable_keymapping()
|
||||
let self.variables.enable_keymapping = 1
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.disable_keymapping()
|
||||
let self.variables.enable_keymapping = 0
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.is_enable_keymapping()
|
||||
return self.variables.enable_keymapping
|
||||
endfunction
|
||||
|
||||
" function! s:base.cancel()
|
||||
" call self.exit(1)
|
||||
" call self.__on_cancel()
|
||||
" endfunction
|
||||
|
||||
|
||||
function! s:base.exit_code()
|
||||
return self.variables.exit_code
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.hl_cursor_on()
|
||||
if exists("self.variables.old_guicursor")
|
||||
set guicursor&
|
||||
let &guicursor = self.variables.old_guicursor
|
||||
unlet self.variables.old_guicursor
|
||||
endif
|
||||
|
||||
if exists("self.variables.old_t_ve")
|
||||
let &t_ve = self.variables.old_t_ve
|
||||
unlet self.variables.old_t_ve
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.hl_cursor_off()
|
||||
if exists("self.variables.old_t_ve")
|
||||
return
|
||||
endif
|
||||
|
||||
let self.variables.old_guicursor = &guicursor
|
||||
set guicursor=n:block-NONE
|
||||
let self.variables.old_t_ve = &t_ve
|
||||
set t_ve=
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.start(...)
|
||||
let exit_code = call(self.__main, a:000, self)
|
||||
return exit_code
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__empty(...)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.get(...)
|
||||
let Old_execute = self.execute
|
||||
let self.execute = self.__empty
|
||||
try
|
||||
let exit_code = call(self.start, a:000, self)
|
||||
if exit_code == 0
|
||||
return self.getline()
|
||||
endif
|
||||
finally
|
||||
let self.execute = Old_execute
|
||||
endtry
|
||||
return ""
|
||||
endfunction
|
||||
|
||||
|
||||
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.input_key_stack_pop()
|
||||
return remove(self.input_key_stack(), 0)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.getchar(...)
|
||||
if empty(self.input_key_stack())
|
||||
return call(s:Input.getchar, a:000, s:Input)
|
||||
endif
|
||||
return self.input_key_stack_pop()
|
||||
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:_is_valid_highlight(name)
|
||||
let highlight = s:Highlight.get(a:name)
|
||||
if empty(highlight)
|
||||
return 0
|
||||
endif
|
||||
|
||||
if has("gui_running")
|
||||
\ && (has_key(highlight, "guifg") || has_key(highlight, "guibg"))
|
||||
return 1
|
||||
elseif (has_key(highlight, "ctermfg") || has_key(highlight, "ctermbg"))
|
||||
return 1
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__init()
|
||||
call self.__init_variables()
|
||||
call self.hl_cursor_off()
|
||||
if !hlexists(self.highlights.cursor)
|
||||
if s:_is_valid_highlight("Cursor")
|
||||
execute "highlight link " . self.highlights.cursor . " Cursor"
|
||||
else
|
||||
" Workaround by CUI Vim Cursor Highlight
|
||||
" issues #92
|
||||
" https://github.com/osyo-manga/vital-over/issues/92
|
||||
execute "highlight " . self.highlights.cursor . " term=reverse cterm=reverse gui=reverse"
|
||||
endif
|
||||
endif
|
||||
if !hlexists(self.highlights.cursor_on)
|
||||
execute "highlight link " . self.highlights.cursor_on . " " . self.highlights.cursor
|
||||
endif
|
||||
if !hlexists(self.highlights.cursor_insert)
|
||||
execute "highlight " . self.highlights.cursor_insert . " cterm=underline term=underline gui=underline"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__execute(command)
|
||||
call self.callevent("on_execute_pre")
|
||||
try
|
||||
call self.__execute__(a:command)
|
||||
catch
|
||||
echohl ErrorMsg
|
||||
echom matchstr(v:exception, 'Vim\((\w*)\)\?:\zs.*\ze')
|
||||
echohl None
|
||||
call self.callevent("on_execute_failed")
|
||||
finally
|
||||
call self.callevent("on_execute")
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__execute__(cmd)
|
||||
execute a:cmd
|
||||
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)
|
||||
let self.variables.is_setted = 0
|
||||
call self.callevent("on_char_pre")
|
||||
call self.insert(self.variables.input)
|
||||
call self.callevent("on_char")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__input(input, ...)
|
||||
if a:input == ""
|
||||
return
|
||||
endif
|
||||
|
||||
let self.variables.input_key = a:input
|
||||
if a:0 == 0
|
||||
let keymapping = self.__get_keymapping()
|
||||
else
|
||||
let keymapping = a:1
|
||||
endif
|
||||
if self.is_enable_keymapping()
|
||||
let key = s:Keymapping.unmapping(keymapping, a:input)
|
||||
else
|
||||
let key = a:input
|
||||
endif
|
||||
if key == ""
|
||||
return
|
||||
endif
|
||||
|
||||
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(self.input_key_stack_pop())
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:is_input_waiting(keymapping, input)
|
||||
let num = len(filter(copy(a:keymapping), 'stridx(v:key, a:input) == 0'))
|
||||
return num > 1 || (num == 1 && !has_key(a:keymapping, a:input))
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__inputting()
|
||||
if !self.is_enable_keymapping()
|
||||
return self.__input(s:Input.getchar())
|
||||
endif
|
||||
|
||||
let input = s:Input.getchar()
|
||||
let old_line = self.getline()
|
||||
let old_pos = self.getpos()
|
||||
let keymapping = self.__get_keymapping()
|
||||
try
|
||||
let t = reltime()
|
||||
while s:is_input_waiting(keymapping, input)
|
||||
\ && str2nr(reltimestr(reltime(t))) * 1000 < &timeoutlen
|
||||
call self.setline(old_line)
|
||||
call self.insert(input)
|
||||
call self.setpos(old_pos)
|
||||
call self.draw()
|
||||
let input .= s:Input.getchar(0)
|
||||
endwhile
|
||||
finally
|
||||
call self.setline(old_line)
|
||||
call self.setpos(old_pos)
|
||||
endtry
|
||||
call self.__input(input, keymapping)
|
||||
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.__inputting()
|
||||
" 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()
|
||||
call self.callevent("on_enter")
|
||||
|
||||
call self.__input(get(a:, 1, ""))
|
||||
call self.draw()
|
||||
while !self.is_exit()
|
||||
try
|
||||
if self.__update()
|
||||
break
|
||||
endif
|
||||
catch
|
||||
call self.callevent("on_exception")
|
||||
endtry
|
||||
endwhile
|
||||
catch
|
||||
echohl ErrorMsg | echom v:throwpoint . " " . v:exception | echohl None
|
||||
let self.variables.exit_code = -1
|
||||
finally
|
||||
call self.__finish()
|
||||
call self.callevent("on_leave")
|
||||
endtry
|
||||
return self.exit_code()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__finish()
|
||||
call self.hl_cursor_on()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__is_exit()
|
||||
return self.is_exit()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.is_exit()
|
||||
return self.variables.exit
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.__get_keymapping()
|
||||
let result = {}
|
||||
" for module in values(self.variables.modules)
|
||||
for module in self.variables.modules.slots()
|
||||
if has_key(module, "keymapping")
|
||||
if module isnot self
|
||||
call extend(result, module.keymapping(self))
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
return extend(extend(result, self.variables.keymapping), self.keymapping())
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,42 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#import() abort
|
||||
return map({'get': '', 'make': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#import() abort', printf("return map({'get': '', 'make': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:_vital_loaded(V)
|
||||
let s:V = a:V
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:get(name)
|
||||
if exists("s:" . a:name)
|
||||
return s:{a:name}
|
||||
endif
|
||||
let s:{a:name} = s:V.import('Over.Commandline.Modules.' . a:name)
|
||||
return s:{a:name}
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make(name, ...)
|
||||
let module = s:get(a:name)
|
||||
return call(module.make, a:000, module)
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,179 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#BufferComplete#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#BufferComplete#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:_uniq(list)
|
||||
let dict = {}
|
||||
for _ in a:list
|
||||
let dict[_] = 0
|
||||
endfor
|
||||
return keys(dict)
|
||||
endfunction
|
||||
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "BufferComplete",
|
||||
\}
|
||||
|
||||
|
||||
function! s:_buffer_complete()
|
||||
return sort(s:_uniq(filter(split(join(getline(1, '$')), '\W'), '!empty(v:val)')), 1)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_parse_line(line)
|
||||
let keyword = matchstr(a:line, '\zs\w\+\ze$')
|
||||
let pos = strchars(a:line) - strchars(keyword)
|
||||
return [pos, keyword]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_as_statusline(list, count)
|
||||
if empty(a:list)
|
||||
return
|
||||
endif
|
||||
let hl_none = "%#StatusLine#"
|
||||
let hl_select = "%#StatusLineNC#"
|
||||
let tail = " > "
|
||||
let result = a:list[0]
|
||||
let pos = 0
|
||||
for i in range(1, len(a:list)-1)
|
||||
if strdisplaywidth(result . " " . a:list[i]) > &columns - len(tail)
|
||||
if a:count < i
|
||||
break
|
||||
else
|
||||
let pos = -i
|
||||
endif
|
||||
let result = a:list[i]
|
||||
else
|
||||
let result .= (" " . a:list[i])
|
||||
endif
|
||||
if a:count == i
|
||||
let pos = pos + i
|
||||
endif
|
||||
endfor
|
||||
return join(map(split(result, " "), 'v:key == pos ? hl_select . v:val . hl_none : v:val'))
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.get_complete_words()
|
||||
return s:_buffer_complete()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.complete(cmdline)
|
||||
call s:_finish()
|
||||
let s:old_statusline = &statusline
|
||||
|
||||
let backward = a:cmdline.backward()
|
||||
let [pos, keyword] = s:_parse_line(backward)
|
||||
|
||||
if !exists("s:complete")
|
||||
let s:complete = self.get_complete_words()
|
||||
endif
|
||||
let s:complete_list = filter(copy(s:complete), 'v:val =~ ''^''.keyword')
|
||||
if empty(s:complete_list)
|
||||
return -1
|
||||
endif
|
||||
|
||||
if pos == 0
|
||||
let backward = ""
|
||||
else
|
||||
let backward = join(split(backward, '\zs')[ : pos-1 ], "")
|
||||
endif
|
||||
let s:line = backward . a:cmdline.forward()
|
||||
let s:pos = pos
|
||||
call a:cmdline.setline(s:line)
|
||||
|
||||
let s:count = 0
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_finish()
|
||||
if exists("s:old_statusline")
|
||||
let &statusline = s:old_statusline
|
||||
unlet s:old_statusline
|
||||
redrawstatus
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_char_pre(cmdline)
|
||||
if a:cmdline.is_input("<Over>(buffer-complete)")
|
||||
\ || a:cmdline.is_input("<Over>(buffer-complete-prev)")
|
||||
if self.complete(a:cmdline) == -1
|
||||
call s:_finish()
|
||||
call a:cmdline.setchar('')
|
||||
return
|
||||
endif
|
||||
if a:cmdline.is_input("<Over>(buffer-complete-prev)")
|
||||
let s:count = len(s:complete_list) - 1
|
||||
endif
|
||||
call a:cmdline.setchar('')
|
||||
call a:cmdline.tap_keyinput("Completion")
|
||||
" elseif a:cmdline.is_input("\<Tab>", "Completion")
|
||||
elseif a:cmdline.is_input("<Over>(buffer-complete)", "Completion")
|
||||
\ || a:cmdline.is_input("\<Right>", "Completion")
|
||||
call a:cmdline.setchar('')
|
||||
let s:count += 1
|
||||
if s:count >= len(s:complete_list)
|
||||
let s:count = 0
|
||||
endif
|
||||
elseif a:cmdline.is_input("<Over>(buffer-complete-prev)", "Completion")
|
||||
\ || a:cmdline.is_input("\<Left>", "Completion")
|
||||
call a:cmdline.setchar('')
|
||||
let s:count -= 1
|
||||
if s:count < 0
|
||||
let s:count = len(s:complete_list) - 1
|
||||
endif
|
||||
else
|
||||
if a:cmdline.untap_keyinput("Completion")
|
||||
call a:cmdline.callevent("on_char_pre")
|
||||
endif
|
||||
call s:_finish()
|
||||
return
|
||||
endif
|
||||
call a:cmdline.setline(s:line)
|
||||
call a:cmdline.insert(s:complete_list[s:count], s:pos)
|
||||
if len(s:complete_list) > 1
|
||||
let &statusline = s:_as_statusline(s:complete_list, s:count)
|
||||
redrawstatus
|
||||
endif
|
||||
if len(s:complete_list) == 1
|
||||
call a:cmdline.untap_keyinput("Completion")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_draw_pre(...)
|
||||
" redrawstatus
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_leave(cmdline)
|
||||
call s:_finish()
|
||||
unlet! s:complete
|
||||
endfunction
|
||||
|
||||
function! s:make()
|
||||
return deepcopy(s:module)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,40 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#Cancel#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#Cancel#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "Cancel"
|
||||
\}
|
||||
|
||||
function! s:module.on_char_pre(cmdline)
|
||||
if a:cmdline.is_input("\<Esc>")
|
||||
\ || a:cmdline.is_input("\<C-c>")
|
||||
" call a:cmdline.cancel()
|
||||
call a:cmdline.exit(1)
|
||||
call a:cmdline.setchar("")
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make()
|
||||
return deepcopy(s:module)
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,58 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#CursorMove#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#CursorMove#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "CursorMove"
|
||||
\}
|
||||
function! s:module.on_char_pre(cmdline)
|
||||
if a:cmdline.is_input("\<Right>")
|
||||
call a:cmdline.line.next()
|
||||
call a:cmdline.setchar('')
|
||||
elseif a:cmdline.is_input("\<Left>")
|
||||
call a:cmdline.line.prev()
|
||||
call a:cmdline.setchar('')
|
||||
elseif a:cmdline.is_input("\<C-b>")
|
||||
\ || a:cmdline.is_input("\<Home>")
|
||||
call a:cmdline.setline(0)
|
||||
call a:cmdline.setchar('')
|
||||
elseif a:cmdline.is_input("\<C-e>")
|
||||
\ || 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
|
||||
|
||||
|
||||
function! s:make()
|
||||
return deepcopy(s:module)
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,56 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#Delete#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#Delete#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "Delete",
|
||||
\}
|
||||
function! s:module.on_char_pre(cmdline)
|
||||
if a:cmdline.is_input("\<C-h>")
|
||||
\ || a:cmdline.is_input("\<BS>")
|
||||
if a:cmdline.line.length() == 0
|
||||
return a:cmdline.exit(1)
|
||||
else
|
||||
call a:cmdline.line.remove_prev()
|
||||
call a:cmdline.setchar('')
|
||||
endif
|
||||
elseif a:cmdline.is_input("\<Del>")
|
||||
call a:cmdline.line.remove_pos()
|
||||
call a:cmdline.setchar('')
|
||||
elseif a:cmdline.is_input("\<C-w>")
|
||||
let word = a:cmdline.backward_word()
|
||||
let backward = a:cmdline.backward()[ : -strlen(word)-1 ]
|
||||
call a:cmdline.setline(backward . a:cmdline.line.pos_char() . a:cmdline.forward())
|
||||
call a:cmdline.setline(strchars(backward))
|
||||
call a:cmdline.setchar('')
|
||||
elseif a:cmdline.is_input("\<C-u>")
|
||||
call a:cmdline.setline(a:cmdline.line.pos_char() . a:cmdline.forward())
|
||||
call a:cmdline.setline(0)
|
||||
call a:cmdline.setchar('')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make()
|
||||
return deepcopy(s:module)
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,121 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#Doautocmd#import() abort
|
||||
return map({'_vital_depends': '', 'doautocmd_user': '', 'get_cmdline': '', 'make': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#Doautocmd#import() abort', printf("return map({'_vital_depends': '', 'doautocmd_user': '', 'get_cmdline': '', 'make': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:_vital_loaded(V)
|
||||
let s:V = a:V
|
||||
let s:E = s:V.import("Over.Exception")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return [
|
||||
\ "Over.Exception",
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
|
||||
let s:cache_command = {}
|
||||
function! s:doautocmd_user(prefix, command)
|
||||
let group = a:prefix . "-vital-over-commandline-doautocmd-dummy"
|
||||
if !has_key(s:cache_command, a:prefix)
|
||||
let s:cache_command[a:prefix] = {}
|
||||
endif
|
||||
|
||||
if !has_key(s:cache_command[a:prefix], a:command)
|
||||
execute "autocmd " . group
|
||||
\ . " User " . a:command." silent! execute ''"
|
||||
|
||||
if v:version > 703 || v:version == 703 && has("patch438")
|
||||
let s:cache_command[a:prefix][a:command] = "doautocmd <nomodeline> User " . a:command
|
||||
else
|
||||
let s:cache_command[a:prefix][a:command] = "doautocmd User " . a:command
|
||||
endif
|
||||
endif
|
||||
|
||||
execute s:cache_command[a:prefix][a:command]
|
||||
endfunction
|
||||
|
||||
|
||||
let s:hooks = [
|
||||
\ "enter",
|
||||
\ "leave",
|
||||
\ "char",
|
||||
\ "char_pre",
|
||||
\ "draw",
|
||||
\ "draw_pre",
|
||||
\ "execute_pre",
|
||||
\ "execute_failed",
|
||||
\ "execute",
|
||||
\ "exception",
|
||||
\]
|
||||
|
||||
let s:hooks_camel = [
|
||||
\ "Enter",
|
||||
\ "Leave",
|
||||
\ "Char",
|
||||
\ "CharPre",
|
||||
\ "Draw",
|
||||
\ "DrawPre",
|
||||
\ "ExecutePre",
|
||||
\ "ExecuteFailed",
|
||||
\ "Execute",
|
||||
\ "Exception",
|
||||
\]
|
||||
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "Doautocmd",
|
||||
\}
|
||||
|
||||
|
||||
for s:i in range(len(s:hooks))
|
||||
execute join([
|
||||
\ "function! s:module.on_" . s:hooks[s:i] . "(cmdline, ...)",
|
||||
\ " let s:cmdline = a:cmdline",
|
||||
\ " call s:doautocmd_user(self.prefix, self.prefix . " . string(s:hooks_camel[s:i]) . ")",
|
||||
\ "endfunction",
|
||||
\ ], "\n")
|
||||
endfor
|
||||
|
||||
|
||||
function! s:get_cmdline()
|
||||
if !exists("s:cmdline")
|
||||
execute s:E.throw_cmd("Undefined cmdline object.", "Over.Commandline.Modules.Doautocmd")
|
||||
endif
|
||||
return s:cmdline
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make(prefix)
|
||||
if has_key(s:cache_command, a:prefix)
|
||||
unlet! s:cache_command[a:prefix]
|
||||
endif
|
||||
execute "augroup " a:prefix . "-vital-over-commandline-doautocmd-dummy"
|
||||
autocmd!
|
||||
augroup END
|
||||
|
||||
let module = deepcopy(s:module)
|
||||
let module.prefix = a:prefix
|
||||
return module
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,155 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#DrawCommandline#import() abort
|
||||
return map({'suffix': '', 'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#DrawCommandline#import() abort', printf("return map({'suffix': '', 'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "DrawCommandline"
|
||||
\}
|
||||
|
||||
let s:cmdheight = {}
|
||||
|
||||
function! s:cmdheight.save()
|
||||
if has_key(self, "value")
|
||||
return
|
||||
endif
|
||||
let self.value = &cmdheight
|
||||
endfunction
|
||||
|
||||
function! s:cmdheight.restore()
|
||||
if has_key(self, "value")
|
||||
let &cmdheight = self.value
|
||||
unlet self.value
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:cmdheight.get()
|
||||
return self.value
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:suffix(left, suffix)
|
||||
let left_len = strdisplaywidth(a:left)
|
||||
let len = &columns - left_len % &columns
|
||||
let len = len + (&columns * (strdisplaywidth(a:suffix) > (len - 1))) - 1
|
||||
return repeat(" ", len - strdisplaywidth(a:suffix)) . a:suffix
|
||||
" return printf("%" . len . "S", a:suffix)
|
||||
endfunction
|
||||
|
||||
|
||||
let s:old_width = 0
|
||||
function! s:_redraw(cmdline)
|
||||
let left = a:cmdline.get_prompt() . a:cmdline.getline() . (empty(a:cmdline.line.pos_char()) ? " " : "")
|
||||
let width = len(left) + 1
|
||||
|
||||
if a:cmdline.get_suffix() != ""
|
||||
let width += len(s:suffix(left, a:cmdline.get_suffix())) - 1
|
||||
endif
|
||||
|
||||
if &columns >= width && &columns <= s:old_width && s:old_width >= width
|
||||
redraw
|
||||
normal! :
|
||||
elseif &columns <= width
|
||||
normal! :
|
||||
else
|
||||
redraw
|
||||
endif
|
||||
let s:old_width = width
|
||||
|
||||
call s:cmdheight.save()
|
||||
let height = max([(width - 1) / (&columns) + 1, s:cmdheight.get()])
|
||||
if height > &cmdheight || &cmdheight > height
|
||||
let &cmdheight = height
|
||||
redraw
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_as_echon(str)
|
||||
return "echon " . strtrans(string(a:str))
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_draw_pre(cmdline)
|
||||
if empty(a:cmdline.line.pos_char())
|
||||
let cursor = "echohl " . a:cmdline.highlights.cursor . " | echon ' '"
|
||||
else
|
||||
let cursor = "echohl " . a:cmdline.highlights.cursor_on . " | " . s:_as_echon(a:cmdline.line.pos_char())
|
||||
endif
|
||||
let suffix = ""
|
||||
if a:cmdline.get_suffix() != ""
|
||||
let suffix = s:_as_echon(s:suffix(a:cmdline.get_prompt() . a:cmdline.getline() . repeat(" ", empty(a:cmdline.line.pos_char())), a:cmdline.get_suffix()))
|
||||
endif
|
||||
let self.draw_command = join([
|
||||
\ "echohl " . a:cmdline.highlights.prompt,
|
||||
\ s:_as_echon(a:cmdline.get_prompt()),
|
||||
\ "echohl NONE",
|
||||
\ s:_as_echon(a:cmdline.backward()),
|
||||
\ cursor,
|
||||
\ "echohl NONE",
|
||||
\ s:_as_echon(a:cmdline.forward()),
|
||||
\ suffix,
|
||||
\ ], " | ")
|
||||
|
||||
call s:_redraw(a:cmdline)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_echon(expr)
|
||||
echon strtrans(a:expr)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_draw(cmdline)
|
||||
execute self.draw_command
|
||||
" execute "echohl" a:cmdline.highlights.prompt
|
||||
" call s:echon(a:cmdline.get_prompt())
|
||||
" echohl NONE
|
||||
" call s:echon(a:cmdline.backward())
|
||||
" if empty(a:cmdline.line.pos_char())
|
||||
" execute "echohl" a:cmdline.highlights.cursor
|
||||
" call s:echon(' ')
|
||||
" else
|
||||
" execute "echohl" a:cmdline.highlights.cursor_on
|
||||
" call s:echon(a:cmdline.line.pos_char())
|
||||
" endif
|
||||
" echohl NONE
|
||||
" call s:echon(a:cmdline.forward())
|
||||
" if a:cmdline.get_suffix() != ""
|
||||
" call s:echon(s:suffix(a:cmdline.get_prompt() . a:cmdline.getline() . repeat(" ", empty(a:cmdline.line.pos_char())), a:cmdline.get_suffix()))
|
||||
" endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_execute_pre(...)
|
||||
call s:cmdheight.restore()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_leave(...)
|
||||
call s:cmdheight.restore()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make()
|
||||
return deepcopy(s:module)
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,37 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#ExceptionExit#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#ExceptionExit#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "ExceptionExit",
|
||||
\}
|
||||
|
||||
|
||||
function! s:module.on_exception(cmdline)
|
||||
call a:cmdline.exit(-1)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make(...)
|
||||
let result = deepcopy(s:module)
|
||||
let result.exit_code = get(a:, 1, 0)
|
||||
return result
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,66 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#ExceptionMessage#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#ExceptionMessage#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
let s:vname = expand("<sfile>:h:h:h:h:t")
|
||||
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "ExceptionMessage",
|
||||
\}
|
||||
|
||||
|
||||
function! s:module.on_exception(cmdline)
|
||||
let self.exception = v:exception
|
||||
let self.throwpoint = v:throwpoint
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_draw_pre(cmdline)
|
||||
if has_key(self, "exception")
|
||||
call self.message(a:cmdline)
|
||||
unlet self.exception
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:module.message(...)
|
||||
echohl ErrorMsg
|
||||
execute self.command string(self.prefix . " : " . self.throwpoint . " " . self.exception)
|
||||
echohl None
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_leave(cmdline)
|
||||
if has_key(self, "exception")
|
||||
call self.message(a:cmdline)
|
||||
unlet self.exception
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make(...)
|
||||
let result = deepcopy(s:module)
|
||||
let result.prefix = get(a:, 1, "vital-over(".s:vname.") Exception")
|
||||
let result.command = get(a:, 2, "echom")
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,40 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#Exit#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#Exit#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "Exit",
|
||||
\ "exit_code" : 0
|
||||
\}
|
||||
|
||||
|
||||
function! s:module.on_char_pre(cmdline)
|
||||
if a:cmdline.is_input("<Over>(exit)")
|
||||
call a:cmdline.setchar("")
|
||||
call a:cmdline.exit(self.exit_code)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make()
|
||||
return deepcopy(s:module)
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,75 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#History#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#History#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "History",
|
||||
\ "mode" : "cmd",
|
||||
\}
|
||||
|
||||
function! s:module.histories()
|
||||
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:_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>")
|
||||
\ && !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: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>") || a:cmdline.is_input("\<C-n>")
|
||||
let s:count = max([s:count - 1, 0])
|
||||
endif
|
||||
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()))
|
||||
endfunction
|
||||
|
||||
function! s:make(...)
|
||||
let module = deepcopy(s:module)
|
||||
let module.mode = get(a:, 1, "cmd")
|
||||
return module
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,164 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#InsertRegister#import() abort
|
||||
return map({'_vital_depends': '', 'to_string': '', 'input': '', 'get_cmdline_cword': '', 'make': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#InsertRegister#import() abort', printf("return map({'_vital_depends': '', 'to_string': '', 'input': '', 'get_cmdline_cword': '', 'make': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
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)
|
||||
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("=", input_text, "expression")
|
||||
if !empty(input)
|
||||
let input = s:to_string(eval(input))
|
||||
endif
|
||||
catch
|
||||
return ""
|
||||
finally
|
||||
call a:cmdline.hl_cursor_off()
|
||||
endtry
|
||||
return input
|
||||
endfunction
|
||||
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "InsertRegister"
|
||||
\}
|
||||
|
||||
|
||||
|
||||
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('"')
|
||||
let self.prefix_key = a:cmdline.input_key()
|
||||
let self.old_line = a:cmdline.getline()
|
||||
let self.old_pos = a:cmdline.getpos()
|
||||
return
|
||||
elseif exists("self.prefix_key")
|
||||
\ && a:cmdline.get_tap_key() == self.prefix_key
|
||||
call a:cmdline.setline(self.old_line)
|
||||
call a:cmdline.setpos(self.old_pos)
|
||||
let char = a:cmdline.input_key()
|
||||
if char =~ '^[0-9a-zA-z.%#:/"\-*+]$'
|
||||
let register = tr(getreg(char), "\n", "\r")
|
||||
call a:cmdline.setchar(register)
|
||||
elseif char == "="
|
||||
call a:cmdline.setchar(s:input(a:cmdline))
|
||||
elseif char == "\<C-w>"
|
||||
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>"
|
||||
call a:cmdline.setchar(self.cfile)
|
||||
elseif char == "\<C-r>"
|
||||
call a:cmdline.setchar('"')
|
||||
else
|
||||
call a:cmdline.setchar("")
|
||||
endif
|
||||
" elseif a:cmdline.is_input('=', self.prefix_key)
|
||||
" call a:cmdline.setchar(s:input(a:cmdline))
|
||||
" elseif a:cmdline.is_input("\<C-w>", self.prefix_key)
|
||||
" call a:cmdline.setchar(self.cword)
|
||||
" elseif a:cmdline.is_input("\<C-a>", self.prefix_key)
|
||||
" call a:cmdline.setchar(self.cWORD)
|
||||
" elseif a:cmdline.is_input("\<C-f>", self.prefix_key)
|
||||
" call a:cmdline.setchar(self.cfile)
|
||||
" elseif a:cmdline.is_input("\<C-r>", self.prefix_key)
|
||||
" call a:cmdline.setchar('"')
|
||||
" else
|
||||
" call a:cmdline.setchar("")
|
||||
" endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_char(cmdline)
|
||||
if a:cmdline.is_input("\<C-r>")
|
||||
call a:cmdline.tap_keyinput(self.prefix_key)
|
||||
call a:cmdline.disable_keymapping()
|
||||
call a:cmdline.setpos(a:cmdline.getpos()-1)
|
||||
else
|
||||
if exists("self.prefix_key")
|
||||
call a:cmdline.untap_keyinput(self.prefix_key)
|
||||
call a:cmdline.enable_keymapping()
|
||||
unlet! self.prefix_key
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
function! s:make()
|
||||
return deepcopy(s:module)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,139 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#KeyMapping#import() abort
|
||||
return map({'_vital_depends': '', 'make_emacs': '', 'make_vim_cmdline_mapping': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#KeyMapping#import() abort', printf("return map({'_vital_depends': '', 'make_emacs': '', 'make_vim_cmdline_mapping': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:_vital_loaded(V)
|
||||
let s:Keymapping = a:V.import("Palette.Keymapping")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return [
|
||||
\ "Palette.Keymapping",
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
|
||||
let s:emacs = {
|
||||
\ "name" : "KeyMapping_emacs_like"
|
||||
\}
|
||||
|
||||
function! s:emacs.keymapping(cmdline)
|
||||
return {
|
||||
\ "\<C-f>" : {
|
||||
\ "key" : "\<Right>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<C-b>" : {
|
||||
\ "key" : "\<Left>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<C-n>" : {
|
||||
\ "key" : "\<Down>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<C-p>" : {
|
||||
\ "key" : "\<Up>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<C-a>" : {
|
||||
\ "key" : "\<Home>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<C-e>" : {
|
||||
\ "key" : "\<End>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<C-d>" : {
|
||||
\ "key" : "\<Del>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<A-d>" : {
|
||||
\ "key" : "\<C-w>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<A-b>" : {
|
||||
\ "key" : "\<S-Left>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ "\<A-f>" : {
|
||||
\ "key" : "\<S-Right>",
|
||||
\ "noremap" : 1,
|
||||
\ "lock" : 1,
|
||||
\ },
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make_emacs()
|
||||
return deepcopy(s:emacs)
|
||||
endfunction
|
||||
|
||||
|
||||
let s:vim_cmdline_mapping = {
|
||||
\ "name" : "KeyMapping_vim_cmdline_mapping",
|
||||
\ "_cmaps" : {}
|
||||
\}
|
||||
|
||||
function! s:_convert_sid(rhs, sid) abort
|
||||
return substitute(a:rhs, '<SID>', '<SNR>' . a:sid . '_', 'g')
|
||||
endfunction
|
||||
|
||||
function! s:_auto_cmap()
|
||||
let cmaps = {}
|
||||
let cmap_info = s:Keymapping.rhs_key_list("c", 0, 1)
|
||||
" vital-over currently doesn't support <buffer> mappings
|
||||
for c in filter(cmap_info, "v:val['buffer'] ==# 0")
|
||||
let cmaps[s:Keymapping.escape_special_key(c['lhs'])] = {
|
||||
\ 'noremap' : c['noremap'],
|
||||
\ 'key' : s:Keymapping.escape_special_key(s:_convert_sid(c['rhs'], c['sid'])),
|
||||
\ 'expr' : s:Keymapping.escape_special_key(c['expr']),
|
||||
\ }
|
||||
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
|
@ -0,0 +1,55 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#NoInsert#import() abort
|
||||
return map({'make_special_chars': '', 'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#NoInsert#import() abort', printf("return map({'make_special_chars': '', 'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "NoInsert",
|
||||
\ "chars" : []
|
||||
\}
|
||||
|
||||
|
||||
function! s:module.is_no_insert(char)
|
||||
return index(self.chars, a:char) >= 0
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:module.on_char_pre(cmdline)
|
||||
if self.is_no_insert(a:cmdline.char())
|
||||
call a:cmdline.setchar("", 0)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make(chars)
|
||||
let module = deepcopy(s:module)
|
||||
let module.chars = type(a:chars) == type([]) ? a:chars : [a:chars]
|
||||
return module
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make_special_chars()
|
||||
let module = s:make([])
|
||||
function! module.is_no_insert(char)
|
||||
return char2nr(a:char) == 128 || char2nr(a:char) < 27
|
||||
endfunction
|
||||
return module
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,40 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#Paste#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#Paste#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "Paste"
|
||||
\}
|
||||
|
||||
function! s:module.on_char_pre(cmdline)
|
||||
if a:cmdline.is_input("<Over>(paste)")
|
||||
let register = v:register == "" ? '"' : v:register
|
||||
call a:cmdline.insert(tr(getreg("*"), "\n", "\r"))
|
||||
call a:cmdline.setchar('')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make()
|
||||
return deepcopy(s:module)
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,72 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Commandline#Modules#Redraw#import() abort
|
||||
return map({'make': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Commandline#Modules#Redraw#import() abort', printf("return map({'make': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
let s:module = {
|
||||
\ "name" : "Redraw",
|
||||
\}
|
||||
|
||||
function! s:module.on_execute_pre(cmdline)
|
||||
call self.redraw(a:cmdline)
|
||||
endfunction
|
||||
|
||||
function! s:module.on_enter(...)
|
||||
let self.is_execute = 0
|
||||
endfunction
|
||||
|
||||
function! s:module.on_execute(...)
|
||||
let self.is_execute = 1
|
||||
endfunction
|
||||
|
||||
function! s:module.on_execute_failed(...)
|
||||
let self.is_execute = 0
|
||||
endfunction
|
||||
|
||||
function! s:module.on_leave(cmdline)
|
||||
if self.is_execute == 0 && a:cmdline.exit_code() != -1
|
||||
call self.redraw(a:cmdline)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
" function! s:module.on_draw_pre(cmdline)
|
||||
" call self.redraw(a:cmdline)
|
||||
" endfunction
|
||||
|
||||
|
||||
function! s:module.redraw(cmdline)
|
||||
redraw
|
||||
" Workaround for the :set cedit=<C-c>
|
||||
" 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 || v:version == 704 && has("patch441"))
|
||||
normal! :
|
||||
else
|
||||
execute "normal! :\<Esc>"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:make()
|
||||
return deepcopy(s:module)
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,46 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Exception#import() abort
|
||||
return map({'throw': '', 'throw_cmd': '', 'set_prefix': '', 'error': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Exception#import() abort', printf("return map({'throw': '', 'throw_cmd': '', 'set_prefix': '', 'error': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
let s:vname = expand("<sfile>:h:h:t")
|
||||
let s:prefix = printf("vital-over(%s) Exception", s:vname)
|
||||
|
||||
function! s:set_prefix(prefix)
|
||||
let s:prefix = a:prefix
|
||||
endfunction
|
||||
|
||||
function! s:throw_cmd(exp, where)
|
||||
return 'throw ' . string(s:prefix . " : " . a:exp . " in " . a:where)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:throw(exp, where)
|
||||
execute s:throw_cmd(a:exp, a:where)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:error(text, where)
|
||||
echohl ErrorMsg
|
||||
echom s:prefix . " : " . a:text . " in " . a:where
|
||||
echohl None
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,40 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Input#import() abort
|
||||
return map({'getchar': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Input#import() abort', printf("return map({'getchar': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
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
|
@ -0,0 +1,95 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Keymapping#import() abort
|
||||
return map({'_vital_depends': '', 'unmapping': '', 'as_key_config': '', 'match_key': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Keymapping#import() abort', printf("return map({'_vital_depends': '', 'unmapping': '', 'as_key_config': '', 'match_key': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
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:as_key_config(config)
|
||||
let base = {
|
||||
\ "noremap" : 0,
|
||||
\ "lock" : 0,
|
||||
\ "expr" : 0,
|
||||
\ }
|
||||
return type(a:config) == type({}) ? extend(base, a:config)
|
||||
\ : extend(base, {
|
||||
\ "key" : a:config,
|
||||
\ })
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:match_key(keymapping, key)
|
||||
let keys = sort(keys(a:keymapping))
|
||||
return get(filter(keys, 'stridx(a:key, v:val) == 0'), -1, '')
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_safe_eval(expr, ...)
|
||||
call extend(l:, get(a:, 1, {}))
|
||||
let result = get(a:, 2, "")
|
||||
try
|
||||
let result = eval(a:expr)
|
||||
catch
|
||||
echohl ErrorMsg | echom v:exception | echohl None
|
||||
endtry
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_get_key(conf)
|
||||
" call extend(l:, a:conf)
|
||||
let self = a:conf
|
||||
return get(a:conf, "expr", 0) ? s:_safe_eval(a:conf.key, l:) : a:conf.key
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:unmapping(keymapping, key, ...)
|
||||
let is_locking = get(a:, 1, 0)
|
||||
let key = s:match_key(a:keymapping, a:key)
|
||||
if key == ""
|
||||
return s:String.length(a:key) <= 1 ? a:key : s:unmapping(a:keymapping, a:key[0], is_locking) . s:unmapping(a:keymapping, a:key[1:], is_locking)
|
||||
endif
|
||||
|
||||
let map_conf = s:as_key_config(a:keymapping[key])
|
||||
|
||||
let next_input = s:unmapping(a:keymapping, a:key[len(key) : ], is_locking)
|
||||
if map_conf.lock == 0 && is_locking
|
||||
return key . next_input
|
||||
elseif map_conf.lock
|
||||
return s:unmapping(a:keymapping, s:_get_key(map_conf), is_locking) . next_input
|
||||
else
|
||||
return s:unmapping(a:keymapping, s:_get_key(map_conf), map_conf.noremap) . next_input
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,119 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#Signals#import() abort
|
||||
return map({'_vital_depends': '', 'call': '', 'make': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#Signals#import() abort', printf("return map({'_vital_depends': '', 'call': '', 'make': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:_vital_loaded(V)
|
||||
let s:V = a:V
|
||||
let s:L = s:V.import("Data.List")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return ["Data.List"]
|
||||
endfunction
|
||||
|
||||
|
||||
let s:base = {
|
||||
\ "variables" : {
|
||||
\ "slots" : [],
|
||||
\ "counter" : 0,
|
||||
\ }
|
||||
\}
|
||||
|
||||
|
||||
function! s:base.connect(slot)
|
||||
let self.variables.counter += 1
|
||||
let slot = { "id" : self.variables.counter, "slot" : a:slot }
|
||||
call add(self.variables.slots, slot)
|
||||
return slot
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.disconnect(slot)
|
||||
if empty(a:slot)
|
||||
return -1
|
||||
endif
|
||||
for i in range(len(self.variables.slots))
|
||||
if self.variables.slots[i].id == a:slot.id
|
||||
unlet self.variables.slots[i]
|
||||
return
|
||||
endif
|
||||
endfor
|
||||
return -1
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.disconnect_by(expr)
|
||||
return self.disconnect(self.find_first_by(a:expr))
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:call(list, func, ...)
|
||||
let args = get(a:, 1, [])
|
||||
let def = get(a:, 2, 0)
|
||||
return map(copy(a:list), "has_key(v:val, a:func) ? call(v:val.".a:func.", args, v:val) : def")
|
||||
endfunction
|
||||
|
||||
function! s:base.call(func, ...)
|
||||
return call("s:call", [self.slots(), a:func] + a:000)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.find_by(expr)
|
||||
return filter(copy(self.variables.slots), a:expr)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.find_first_by(expr)
|
||||
return get(self.find_by(a:expr), 0, {})
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.sort_by(expr)
|
||||
let self.variables.slots = s:L.sort_by(self.variables.slots, a:expr)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.get_slot(val)
|
||||
return a:val.slot
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:base.slots()
|
||||
return map(copy(self.variables.slots), "self.get_slot(v:val)")
|
||||
endfunction
|
||||
|
||||
|
||||
" function! s:base.dict()
|
||||
" let result = {}
|
||||
" for _ in self.variables.slots
|
||||
" let result[_.id] = _.value
|
||||
" endfor
|
||||
" return result
|
||||
" endfunction
|
||||
|
||||
|
||||
function! s:make()
|
||||
let result = deepcopy(s:base)
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,164 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Over#String#import() abort
|
||||
return map({'_vital_depends': '', 'length': '', 'index': '', 'split_by_keys': '', 'make': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Over#String#import() abort', printf("return map({'_vital_depends': '', 'length': '', 'index': '', 'split_by_keys': '', 'make': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
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
|
||||
endfunction
|
||||
|
||||
function! s:base.str()
|
||||
return join(self.list, "")
|
||||
endfunction
|
||||
|
||||
function! s:base.set_pos(pos)
|
||||
let self.col = s:_clamp(a:pos, 0, self.length())
|
||||
return self
|
||||
endfunction
|
||||
|
||||
function! s:base.backward()
|
||||
return self.col > 0 ? join(self.list[ : self.col-1], '') : ""
|
||||
endfunction
|
||||
|
||||
function! s:base.forward()
|
||||
return join(self.list[self.col+1 : ], '')
|
||||
endfunction
|
||||
|
||||
function! s:base.pos_char()
|
||||
return get(self.list, self.col, "")
|
||||
endfunction
|
||||
|
||||
function! s:base.set_str(str)
|
||||
let self.list = split(a:str, '\zs')
|
||||
let self.col = strchars(a:str)
|
||||
return self
|
||||
endfunction
|
||||
|
||||
function! s:base.pos()
|
||||
return self.col
|
||||
endfunction
|
||||
|
||||
function! s:base.input(str)
|
||||
call extend(self.list, split(a:str, '\zs'), self.col)
|
||||
let self.col += len(split(a:str, '\zs'))
|
||||
return self
|
||||
endfunction
|
||||
|
||||
function! s:base.length()
|
||||
return len(self.list)
|
||||
endfunction
|
||||
|
||||
function! s:base.next()
|
||||
return self.set_pos(self.col + 1)
|
||||
endfunction
|
||||
|
||||
function! s:base.prev()
|
||||
return self.set_pos(self.col - 1)
|
||||
endfunction
|
||||
|
||||
function! s:base.remove(index)
|
||||
if a:index < 0 || self.length() <= a:index
|
||||
return ""
|
||||
endif
|
||||
let result = self.list[a:index]
|
||||
unlet self.list[a:index]
|
||||
if a:index < self.col
|
||||
call self.set(self.col - 1)
|
||||
endif
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! s:base.remove_pos()
|
||||
return self.remove(self.col)
|
||||
endfunction
|
||||
|
||||
function! s:base.remove_prev()
|
||||
return self.remove(self.col - 1)
|
||||
endfunction
|
||||
|
||||
function! s:base.remove_next()
|
||||
return self.remove(self.col + 1)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:make(...)
|
||||
let default = get(a:, 1, "")
|
||||
let result = deepcopy(s:base)
|
||||
call result.set(default)
|
||||
return result
|
||||
endfunction
|
||||
|
||||
" NOTE: old regexpengine has a bug with string which contains binary
|
||||
" :echo "\x80" =~ "\\%#=1\x80" | " => 0
|
||||
" But it matches correctly with :h /collection
|
||||
" :echo "\x80" =~ "\\%#=1[\x80]" | " => 1
|
||||
" http://lingr.com/room/vim/archives/2015/02/13#message-21261450
|
||||
let s:_engine = exists("+regexpengine") ? '\%#=2' : ''
|
||||
" \<A-]> => Û\xfdQ
|
||||
" \<A-@> => À\xfeX
|
||||
let s:_regex = exists("+regexpengine")
|
||||
\ ? "\\%(Û\xfdQ\\|À\xfeX\\|\x80\xfc.\\%(\x80..\\|.\\)\\|\x80..\\|.\\)\\zs"
|
||||
\ : "\\%(Û[\xfd]Q\\|À[\xfe]X\\|[\x80][\xfc].\\%([\x80]..\\|.\\)\\|[\x80]..\\|.\\)\\zs"
|
||||
function! s:_split_keystring(str, ...)
|
||||
return split(a:str, s:_engine . '\m\%(' . get(a:, 1, '') . s:_regex . '\)')
|
||||
endfunction
|
||||
|
||||
function! s:split_by_keys(str)
|
||||
return s:_split_keystring(a:str, "\\%(\<Plug>\\|<Over>\\)(.\\{-})\\zs\\|")
|
||||
endfunction
|
||||
|
||||
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
|
||||
|
||||
|
||||
function! s:length(str)
|
||||
return len(s:split_by_keys(a:str))
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,74 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Palette#Capture#import() abort
|
||||
return map({'extend': '', 'command': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Palette#Capture#import() abort', printf("return map({'extend': '', 'command': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
let s:verbosefiles = []
|
||||
|
||||
function! s:_verbosefile_push(file)
|
||||
call add(s:verbosefiles, &verbosefile)
|
||||
let &verbosefile = a:file
|
||||
return a:file
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_verbosefile_pop()
|
||||
let filename = &verbosefile
|
||||
let &verbosefile = get(s:verbosefiles, -1)
|
||||
call remove(s:verbosefiles, -1)
|
||||
return filename
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_reset()
|
||||
let s:verbosefiles = []
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:extend(dict, src)
|
||||
for [key, value] in items(a:src)
|
||||
let a:dict[key] = value
|
||||
unlet value
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:command(cmd, ...)
|
||||
" Workaround : Vim 7.3.xxx in Travis and Ubuntu
|
||||
" https://github.com/osyo-manga/vital-palette/issues/5
|
||||
" call extend(l:, get(a:, 1, {}))
|
||||
if a:0 > 0
|
||||
call s:extend(l:, a:1)
|
||||
endif
|
||||
|
||||
call s:_verbosefile_push(tempname())
|
||||
try
|
||||
redir =>result
|
||||
silent execute a:cmd
|
||||
finally
|
||||
redir END
|
||||
endtry
|
||||
call s:_verbosefile_pop()
|
||||
" let result = substitute(result, "<SRN>", "\<SNR>", "g")
|
||||
" let result = substitute(result, "<SID>", "\<SID>", "g")
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,133 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Palette#Highlight#import() abort
|
||||
return map({'capture': '', '_vital_depends': '', 'parse': '', 'group_list': '', 'set': '', 'parse_to_name': '', 'links_to': '', 'get': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Palette#Highlight#import() abort', printf("return map({'capture': '', '_vital_depends': '', 'parse': '', 'group_list': '', 'set': '', 'parse_to_name': '', 'links_to': '', 'get': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
function! s:_vital_loaded(V)
|
||||
let s:V = a:V
|
||||
let s:Message = s:V.import("Vim.Message")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return [
|
||||
\ "Vim.Message",
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_execute(cmd)
|
||||
execute a:cmd
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:capture(name)
|
||||
if hlexists(a:name) == 0
|
||||
return ""
|
||||
endif
|
||||
return s:Message.capture("highlight " . a:name)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:links_to(highlight)
|
||||
return matchstr(a:highlight, '^\S\+\s\+xxx links to \zs.*\ze$')
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:parse_to_name(highlight)
|
||||
return matchstr(a:highlight, '^\zs\w\+\ze')
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:parse(highlight)
|
||||
let highlight = a:highlight
|
||||
|
||||
if highlight !~# '^\w\+\s\+xxx\s'
|
||||
return {}
|
||||
endif
|
||||
|
||||
let name = s:parse_to_name(a:highlight)
|
||||
let result = { "_name" : name }
|
||||
|
||||
if highlight =~# '^\w\+\s\+xxx cleared'
|
||||
let result.cleared = 1
|
||||
return result
|
||||
endif
|
||||
|
||||
let link = s:links_to(highlight)
|
||||
if link != ""
|
||||
let result.link = link
|
||||
return result
|
||||
endif
|
||||
|
||||
let attrs = [
|
||||
\ "term",
|
||||
\ "cterm",
|
||||
\ "ctermfg",
|
||||
\ "ctermbg",
|
||||
\ "gui",
|
||||
\ "font",
|
||||
\ "guifg",
|
||||
\ "guibg",
|
||||
\ "guisp",
|
||||
\ ]
|
||||
for attr in attrs
|
||||
let item = matchstr(highlight, '\s' . attr . '=\zs#\?\w\+\ze')
|
||||
if item != ""
|
||||
let result[attr] = item
|
||||
endif
|
||||
endfor
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:get(name, ...)
|
||||
if !hlexists(a:name)
|
||||
return {}
|
||||
endif
|
||||
let result = s:parse(substitute(s:capture(a:name), "\n", "", "g"))
|
||||
if has_key(result, "link") && get(a:, 1, 0)
|
||||
return s:get(result.link, get(a:, 1, 0))
|
||||
else
|
||||
return result
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:set(name, config)
|
||||
if type(a:config) == type("")
|
||||
return s:set(a:config, s:get(a:config))
|
||||
endif
|
||||
if has_key(a:config, "cleared")
|
||||
return s:_execute("highlight clear " . a:name)
|
||||
endif
|
||||
if has_key(a:config, "link")
|
||||
return s:_execute("highlight link " . a:name . " " . a:config.link)
|
||||
endif
|
||||
return s:_execute("highlight " . a:name . " " . join(map(items(filter(a:config, "v:key !=# '_name'")), "v:val[0] . '=' . v:val[1]"), " "))
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:group_list()
|
||||
let highlights = split(s:Message.capture("highlight"), "\n")
|
||||
return filter(map(highlights, "s:parse_to_name(v:val)"), "v:val != ''")
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,121 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Palette#Keymapping#import() abort
|
||||
return map({'capture': '', '_vital_depends': '', 'escape_special_key': '', 'rhs_key_list': '', 'parse_lhs_list': '', 'lhs_key_list': '', 'capture_list': '', 'parse_lhs': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Palette#Keymapping#import() abort', printf("return map({'capture': '', '_vital_depends': '', 'escape_special_key': '', 'rhs_key_list': '', 'parse_lhs_list': '', 'lhs_key_list': '', 'capture_list': '', 'parse_lhs': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
scriptencoding utf-8
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
let s:modep = "[nvoicsxl]"
|
||||
|
||||
|
||||
function! s:_vital_loaded(V)
|
||||
let s:V = a:V
|
||||
let s:Capture = s:V.import("Palette.Capture")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return [
|
||||
\ "Palette.Capture",
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_capture(mode)
|
||||
let cmd = "map"
|
||||
if a:mode ==# "!"
|
||||
let cmd = cmd . "!"
|
||||
elseif a:mode =~# "[nvoicsxl]"
|
||||
let cmd = a:mode . cmd
|
||||
endif
|
||||
return s:Capture.command(cmd)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:capture(...)
|
||||
let mode = get(a:, 1, "")
|
||||
let modes = split(mode, '\zs')
|
||||
return join(map(modes, "s:_capture(v:val)"), "\n")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_keymapping(str)
|
||||
return a:str =~ '^[!nvoicsxl]\s'
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:capture_list(...)
|
||||
let mode = get(a:, 1, "")
|
||||
return filter(split(s:capture(mode), "\n"), "s:_keymapping(v:val)")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:escape_special_key(key)
|
||||
" Workaround : <C-?> https://github.com/osyo-manga/vital-palette/issues/5
|
||||
if a:key ==# "<^?>"
|
||||
return "\<C-?>"
|
||||
endif
|
||||
execute 'let result = "' . substitute(escape(a:key, '\"'), '\(<.\{-}>\)', '\\\1', 'g') . '"'
|
||||
return result
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:parse_lhs(text, ...)
|
||||
let mode = get(a:, 1, '[!nvoicsxl]')
|
||||
" NOTE: :map! Surpport : https://github.com/osyo-manga/vital-palette/issues/4
|
||||
if get(a:, 1, "") =~# '[!ci]'
|
||||
let mode = '[!ci]'
|
||||
endif
|
||||
return matchstr(a:text, mode . '\{1,3\}\s*\zs\S\{-}\ze\s\+')
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:parse_lhs_list(...)
|
||||
let mode = get(a:, 1, "")
|
||||
return map(s:capture_list(mode), "s:parse_lhs(v:val, mode)")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:lhs_key_list(...)
|
||||
let mode = get(a:, 1, "")
|
||||
return map(s:parse_lhs_list(mode), "s:escape_special_key(v:val)")
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_maparg(name, mode, abbr, dict)
|
||||
" Workaround : <C-?> https://github.com/osyo-manga/vital-palette/issues/5
|
||||
if a:name ==# "<^?>"
|
||||
return maparg("\<C-?>", a:mode, a:abbr, a:dict)
|
||||
endif
|
||||
return maparg(a:name, a:mode, a:abbr, a:dict)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:rhs_key_list(...)
|
||||
let mode = get(a:, 1, "")
|
||||
let abbr = get(a:, 2, 0)
|
||||
let dict = get(a:, 3, 0)
|
||||
|
||||
let result = []
|
||||
for m in split(mode, '\zs')
|
||||
let result += map(s:parse_lhs_list(m), "s:_maparg(v:val, m, abbr, dict)")
|
||||
endfor
|
||||
return filter(result, "empty(v:val) == 0")
|
||||
endfunction
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
@ -0,0 +1,430 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Prelude#import() abort
|
||||
return map({'escape_pattern': '', 'is_funcref': '', 'path2directory': '', 'wcswidth': '', 'is_string': '', 'input_helper': '', 'is_number': '', 'is_cygwin': '', 'path2project_directory': '', 'strwidthpart_reverse': '', 'input_safe': '', 'is_list': '', 'truncate_skipping': '', 'glob': '', 'truncate': '', 'is_dict': '', 'set_default': '', 'is_numeric': '', 'getchar_safe': '', 'substitute_path_separator': '', 'is_mac': '', 'strwidthpart': '', 'getchar': '', 'is_unix': '', 'is_windows': '', 'globpath': '', 'escape_file_searching': '', 'is_float': '', 'smart_execute_command': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Prelude#import() abort', printf("return map({'escape_pattern': '', 'is_funcref': '', 'path2directory': '', 'wcswidth': '', 'is_string': '', 'input_helper': '', 'is_number': '', 'is_cygwin': '', 'path2project_directory': '', 'strwidthpart_reverse': '', 'input_safe': '', 'is_list': '', 'truncate_skipping': '', 'glob': '', 'truncate': '', 'is_dict': '', 'set_default': '', 'is_numeric': '', 'getchar_safe': '', 'substitute_path_separator': '', 'is_mac': '', 'strwidthpart': '', 'getchar': '', 'is_unix': '', 'is_windows': '', 'globpath': '', 'escape_file_searching': '', 'is_float': '', 'smart_execute_command': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
if v:version > 703 ||
|
||||
\ (v:version == 703 && has('patch465'))
|
||||
function! s:glob(expr) abort
|
||||
return glob(a:expr, 1, 1)
|
||||
endfunction
|
||||
else
|
||||
function! s:glob(expr) abort
|
||||
return split(glob(a:expr, 1), '\n')
|
||||
endfunction
|
||||
endif
|
||||
|
||||
if v:version > 704 ||
|
||||
\ (v:version == 704 && has('patch279'))
|
||||
function! s:globpath(path, expr) abort
|
||||
return globpath(a:path, a:expr, 1, 1)
|
||||
endfunction
|
||||
else
|
||||
function! s:globpath(path, expr) abort
|
||||
return split(globpath(a:path, a:expr, 1), '\n')
|
||||
endfunction
|
||||
endif
|
||||
|
||||
" Wrapper functions for type().
|
||||
" NOTE: __TYPE_FLOAT = -1 when -float.
|
||||
" this doesn't match to anything.
|
||||
if has('patch-7.4.2071')
|
||||
let [
|
||||
\ s:__TYPE_NUMBER,
|
||||
\ s:__TYPE_STRING,
|
||||
\ s:__TYPE_FUNCREF,
|
||||
\ s:__TYPE_LIST,
|
||||
\ s:__TYPE_DICT,
|
||||
\ s:__TYPE_FLOAT] = [
|
||||
\ v:t_number,
|
||||
\ v:t_string,
|
||||
\ v:t_func,
|
||||
\ v:t_list,
|
||||
\ v:t_dict,
|
||||
\ v:t_float]
|
||||
else
|
||||
let [
|
||||
\ s:__TYPE_NUMBER,
|
||||
\ s:__TYPE_STRING,
|
||||
\ s:__TYPE_FUNCREF,
|
||||
\ s:__TYPE_LIST,
|
||||
\ s:__TYPE_DICT,
|
||||
\ s:__TYPE_FLOAT] = [
|
||||
\ type(3),
|
||||
\ type(''),
|
||||
\ type(function('tr')),
|
||||
\ type([]),
|
||||
\ type({}),
|
||||
\ has('float') ? type(str2float('0')) : -1]
|
||||
endif
|
||||
|
||||
" Number or Float
|
||||
function! s:is_numeric(Value) abort
|
||||
let _ = type(a:Value)
|
||||
return _ ==# s:__TYPE_NUMBER
|
||||
\ || _ ==# s:__TYPE_FLOAT
|
||||
endfunction
|
||||
|
||||
" Number
|
||||
function! s:is_number(Value) abort
|
||||
return type(a:Value) ==# s:__TYPE_NUMBER
|
||||
endfunction
|
||||
|
||||
" String
|
||||
function! s:is_string(Value) abort
|
||||
return type(a:Value) ==# s:__TYPE_STRING
|
||||
endfunction
|
||||
|
||||
" Funcref
|
||||
function! s:is_funcref(Value) abort
|
||||
return type(a:Value) ==# s:__TYPE_FUNCREF
|
||||
endfunction
|
||||
|
||||
" List
|
||||
function! s:is_list(Value) abort
|
||||
return type(a:Value) ==# s:__TYPE_LIST
|
||||
endfunction
|
||||
|
||||
" Dictionary
|
||||
function! s:is_dict(Value) abort
|
||||
return type(a:Value) ==# s:__TYPE_DICT
|
||||
endfunction
|
||||
|
||||
" Float
|
||||
function! s:is_float(Value) abort
|
||||
return type(a:Value) ==# s:__TYPE_FLOAT
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:truncate_skipping(str, max, footer_width, separator) abort
|
||||
call s:_warn_deprecated('truncate_skipping', 'Data.String.truncate_skipping')
|
||||
|
||||
let width = s:wcswidth(a:str)
|
||||
if width <= a:max
|
||||
let ret = a:str
|
||||
else
|
||||
let header_width = a:max - s:wcswidth(a:separator) - a:footer_width
|
||||
let ret = s:strwidthpart(a:str, header_width) . a:separator
|
||||
\ . s:strwidthpart_reverse(a:str, a:footer_width)
|
||||
endif
|
||||
|
||||
return s:truncate(ret, a:max)
|
||||
endfunction
|
||||
|
||||
function! s:truncate(str, width) abort
|
||||
" Original function is from mattn.
|
||||
" http://github.com/mattn/googlereader-vim/tree/master
|
||||
|
||||
call s:_warn_deprecated('truncate', 'Data.String.truncate')
|
||||
|
||||
if a:str =~# '^[\x00-\x7f]*$'
|
||||
return len(a:str) < a:width ?
|
||||
\ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width)
|
||||
endif
|
||||
|
||||
let ret = a:str
|
||||
let width = s:wcswidth(a:str)
|
||||
if width > a:width
|
||||
let ret = s:strwidthpart(ret, a:width)
|
||||
let width = s:wcswidth(ret)
|
||||
endif
|
||||
|
||||
if width < a:width
|
||||
let ret .= repeat(' ', a:width - width)
|
||||
endif
|
||||
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:strwidthpart(str, width) abort
|
||||
call s:_warn_deprecated('strwidthpart', 'Data.String.strwidthpart')
|
||||
|
||||
if a:width <= 0
|
||||
return ''
|
||||
endif
|
||||
let ret = a:str
|
||||
let width = s:wcswidth(a:str)
|
||||
while width > a:width
|
||||
let char = matchstr(ret, '.$')
|
||||
let ret = ret[: -1 - len(char)]
|
||||
let width -= s:wcswidth(char)
|
||||
endwhile
|
||||
|
||||
return ret
|
||||
endfunction
|
||||
function! s:strwidthpart_reverse(str, width) abort
|
||||
call s:_warn_deprecated('strwidthpart_reverse', 'Data.String.strwidthpart_reverse')
|
||||
|
||||
if a:width <= 0
|
||||
return ''
|
||||
endif
|
||||
let ret = a:str
|
||||
let width = s:wcswidth(a:str)
|
||||
while width > a:width
|
||||
let char = matchstr(ret, '^.')
|
||||
let ret = ret[len(char) :]
|
||||
let width -= s:wcswidth(char)
|
||||
endwhile
|
||||
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
if v:version >= 703
|
||||
" Use builtin function.
|
||||
function! s:wcswidth(str) abort
|
||||
call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth')
|
||||
return strwidth(a:str)
|
||||
endfunction
|
||||
else
|
||||
function! s:wcswidth(str) abort
|
||||
call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth')
|
||||
|
||||
if a:str =~# '^[\x00-\x7f]*$'
|
||||
return strlen(a:str)
|
||||
end
|
||||
|
||||
let mx_first = '^\(.\)'
|
||||
let str = a:str
|
||||
let width = 0
|
||||
while 1
|
||||
let ucs = char2nr(substitute(str, mx_first, '\1', ''))
|
||||
if ucs == 0
|
||||
break
|
||||
endif
|
||||
let width += s:_wcwidth(ucs)
|
||||
let str = substitute(str, mx_first, '', '')
|
||||
endwhile
|
||||
return width
|
||||
endfunction
|
||||
|
||||
" UTF-8 only.
|
||||
function! s:_wcwidth(ucs) abort
|
||||
let ucs = a:ucs
|
||||
if (ucs >= 0x1100
|
||||
\ && (ucs <= 0x115f
|
||||
\ || ucs == 0x2329
|
||||
\ || ucs == 0x232a
|
||||
\ || (ucs >= 0x2e80 && ucs <= 0xa4cf
|
||||
\ && ucs != 0x303f)
|
||||
\ || (ucs >= 0xac00 && ucs <= 0xd7a3)
|
||||
\ || (ucs >= 0xf900 && ucs <= 0xfaff)
|
||||
\ || (ucs >= 0xfe30 && ucs <= 0xfe6f)
|
||||
\ || (ucs >= 0xff00 && ucs <= 0xff60)
|
||||
\ || (ucs >= 0xffe0 && ucs <= 0xffe6)
|
||||
\ || (ucs >= 0x20000 && ucs <= 0x2fffd)
|
||||
\ || (ucs >= 0x30000 && ucs <= 0x3fffd)
|
||||
\ ))
|
||||
return 2
|
||||
endif
|
||||
return 1
|
||||
endfunction
|
||||
endif
|
||||
|
||||
let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95')
|
||||
let s:is_cygwin = has('win32unix')
|
||||
let s:is_mac = !s:is_windows && !s:is_cygwin
|
||||
\ && (has('mac') || has('macunix') || has('gui_macvim') ||
|
||||
\ (!isdirectory('/proc') && executable('sw_vers')))
|
||||
let s:is_unix = has('unix')
|
||||
|
||||
function! s:is_windows() abort
|
||||
return s:is_windows
|
||||
endfunction
|
||||
|
||||
function! s:is_cygwin() abort
|
||||
return s:is_cygwin
|
||||
endfunction
|
||||
|
||||
function! s:is_mac() abort
|
||||
return s:is_mac
|
||||
endfunction
|
||||
|
||||
function! s:is_unix() abort
|
||||
return s:is_unix
|
||||
endfunction
|
||||
|
||||
function! s:_warn_deprecated(name, alternative) abort
|
||||
try
|
||||
echohl Error
|
||||
echomsg 'Prelude.' . a:name . ' is deprecated! Please use ' . a:alternative . ' instead.'
|
||||
finally
|
||||
echohl None
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:smart_execute_command(action, word) abort
|
||||
execute a:action . ' ' . (a:word ==# '' ? '' : '`=a:word`')
|
||||
endfunction
|
||||
|
||||
function! s:escape_file_searching(buffer_name) abort
|
||||
return escape(a:buffer_name, '*[]?{}, ')
|
||||
endfunction
|
||||
|
||||
function! s:escape_pattern(str) abort
|
||||
call s:_warn_deprecated(
|
||||
\ 'escape_pattern',
|
||||
\ 'Data.String.escape_pattern',
|
||||
\)
|
||||
return escape(a:str, '~"\.^$[]*')
|
||||
endfunction
|
||||
|
||||
function! s:getchar(...) abort
|
||||
let c = call('getchar', a:000)
|
||||
return type(c) == type(0) ? nr2char(c) : c
|
||||
endfunction
|
||||
|
||||
function! s:getchar_safe(...) abort
|
||||
let c = s:input_helper('getchar', a:000)
|
||||
return type(c) == type('') ? c : nr2char(c)
|
||||
endfunction
|
||||
|
||||
function! s:input_safe(...) abort
|
||||
return s:input_helper('input', a:000)
|
||||
endfunction
|
||||
|
||||
function! s:input_helper(funcname, args) abort
|
||||
let success = 0
|
||||
if inputsave() !=# success
|
||||
throw 'vital: Prelude: inputsave() failed'
|
||||
endif
|
||||
try
|
||||
return call(a:funcname, a:args)
|
||||
finally
|
||||
if inputrestore() !=# success
|
||||
throw 'vital: Prelude: inputrestore() failed'
|
||||
endif
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:set_default(var, val) abort
|
||||
if !exists(a:var) || type({a:var}) != type(a:val)
|
||||
let {a:var} = a:val
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:substitute_path_separator(path) abort
|
||||
return s:is_windows ? substitute(a:path, '\\', '/', 'g') : a:path
|
||||
endfunction
|
||||
|
||||
function! s:path2directory(path) abort
|
||||
return s:substitute_path_separator(isdirectory(a:path) ? a:path : fnamemodify(a:path, ':p:h'))
|
||||
endfunction
|
||||
|
||||
function! s:_path2project_directory_git(path) abort
|
||||
let parent = a:path
|
||||
|
||||
while 1
|
||||
let path = parent . '/.git'
|
||||
if isdirectory(path) || filereadable(path)
|
||||
return parent
|
||||
endif
|
||||
let next = fnamemodify(parent, ':h')
|
||||
if next == parent
|
||||
return ''
|
||||
endif
|
||||
let parent = next
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:_path2project_directory_svn(path) abort
|
||||
let search_directory = a:path
|
||||
let directory = ''
|
||||
|
||||
let find_directory = s:escape_file_searching(search_directory)
|
||||
let d = finddir('.svn', find_directory . ';')
|
||||
if d ==# ''
|
||||
return ''
|
||||
endif
|
||||
|
||||
let directory = fnamemodify(d, ':p:h:h')
|
||||
|
||||
" Search parent directories.
|
||||
let parent_directory = s:path2directory(
|
||||
\ fnamemodify(directory, ':h'))
|
||||
|
||||
if parent_directory !=# ''
|
||||
let d = finddir('.svn', parent_directory . ';')
|
||||
if d !=# ''
|
||||
let directory = s:_path2project_directory_svn(parent_directory)
|
||||
endif
|
||||
endif
|
||||
return directory
|
||||
endfunction
|
||||
|
||||
function! s:_path2project_directory_others(vcs, path) abort
|
||||
let vcs = a:vcs
|
||||
let search_directory = a:path
|
||||
|
||||
let find_directory = s:escape_file_searching(search_directory)
|
||||
let d = finddir(vcs, find_directory . ';')
|
||||
if d ==# ''
|
||||
return ''
|
||||
endif
|
||||
return fnamemodify(d, ':p:h:h')
|
||||
endfunction
|
||||
|
||||
function! s:path2project_directory(path, ...) abort
|
||||
let is_allow_empty = get(a:000, 0, 0)
|
||||
let search_directory = s:path2directory(a:path)
|
||||
let directory = ''
|
||||
|
||||
" Search VCS directory.
|
||||
for vcs in ['.git', '.bzr', '.hg', '.svn']
|
||||
if vcs ==# '.git'
|
||||
let directory = s:_path2project_directory_git(search_directory)
|
||||
elseif vcs ==# '.svn'
|
||||
let directory = s:_path2project_directory_svn(search_directory)
|
||||
else
|
||||
let directory = s:_path2project_directory_others(vcs, search_directory)
|
||||
endif
|
||||
if directory !=# ''
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
" Search project file.
|
||||
if directory ==# ''
|
||||
for d in ['build.xml', 'prj.el', '.project', 'pom.xml', 'package.json',
|
||||
\ 'Makefile', 'configure', 'Rakefile', 'NAnt.build',
|
||||
\ 'P4CONFIG', 'tags', 'gtags']
|
||||
let d = findfile(d, s:escape_file_searching(search_directory) . ';')
|
||||
if d !=# ''
|
||||
let directory = fnamemodify(d, ':p:h')
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
|
||||
if directory ==# ''
|
||||
" Search /src/ directory.
|
||||
let base = s:substitute_path_separator(search_directory)
|
||||
if base =~# '/src/'
|
||||
let directory = base[: strridx(base, '/src/') + 3]
|
||||
endif
|
||||
endif
|
||||
|
||||
if directory ==# '' && !is_allow_empty
|
||||
" Use original path.
|
||||
let directory = search_directory
|
||||
endif
|
||||
|
||||
return s:substitute_path_separator(directory)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et ts=2 sts=2 sw=2 tw=0:
|
@ -0,0 +1,187 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Vim#Buffer#import() abort
|
||||
return map({'parse_cmdarg': '', '_vital_depends': '', 'read_content': '', 'get_selected_text': '', 'is_cmdwin': '', 'edit_content': '', 'open': '', 'get_last_selected': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Vim#Buffer#import() abort', printf("return map({'parse_cmdarg': '', '_vital_depends': '', 'read_content': '', 'get_selected_text': '', 'is_cmdwin': '', 'edit_content': '', 'open': '', 'get_last_selected': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:_vital_loaded(V) abort
|
||||
let s:V = a:V
|
||||
let s:P = s:V.import('Prelude')
|
||||
let s:G = s:V.import('Vim.Guard')
|
||||
endfunction
|
||||
|
||||
function! s:_vital_depends() abort
|
||||
return ['Prelude', 'Vim.Guard']
|
||||
endfunction
|
||||
|
||||
if exists('*getcmdwintype')
|
||||
function! s:is_cmdwin() abort
|
||||
return getcmdwintype() !=# ''
|
||||
endfunction
|
||||
else
|
||||
function! s:is_cmdwin() abort
|
||||
return bufname('%') ==# '[Command Line]'
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! s:open(buffer, opener) abort
|
||||
let save_wildignore = &wildignore
|
||||
let &wildignore = ''
|
||||
try
|
||||
if s:P.is_funcref(a:opener)
|
||||
let loaded = !bufloaded(a:buffer)
|
||||
call a:opener(a:buffer)
|
||||
elseif a:buffer is 0 || a:buffer is# ''
|
||||
let loaded = 1
|
||||
silent execute a:opener
|
||||
enew
|
||||
else
|
||||
let loaded = !bufloaded(a:buffer)
|
||||
if s:P.is_string(a:buffer)
|
||||
execute a:opener '`=a:buffer`'
|
||||
elseif s:P.is_number(a:buffer)
|
||||
silent execute a:opener
|
||||
execute a:buffer 'buffer'
|
||||
else
|
||||
throw 'vital: Vim.Buffer: Unknown opener type.'
|
||||
endif
|
||||
endif
|
||||
finally
|
||||
let &wildignore = save_wildignore
|
||||
endtry
|
||||
return loaded
|
||||
endfunction
|
||||
|
||||
function! s:get_selected_text(...) abort
|
||||
echohl WarningMsg
|
||||
echom "[WARN] s:get_selected_text() is deprecated. Use 's:get_last_selected()'."
|
||||
echohl None
|
||||
return call('s:get_last_selected', a:000)
|
||||
endfunction
|
||||
|
||||
" Get the last selected text in visual mode
|
||||
" without using |gv| to avoid |textlock|.
|
||||
" NOTE:
|
||||
" * This function uses |gv| only when using |CTRL-V|
|
||||
" because |gv| is the only way to get selected text
|
||||
" when using <C-v>$ .
|
||||
" Please see #192 for the details.
|
||||
" * If you don't care about |textlock|,
|
||||
" you can use simple version of this function.
|
||||
" https://github.com/vim-jp/vital.vim/commit/39aae80f3839fdbeebd838ff14d87327a6b889a9
|
||||
function! s:get_last_selected() abort
|
||||
if visualmode() ==# "\<C-v>"
|
||||
let save = getreg('"', 1)
|
||||
let save_type = getregtype('"')
|
||||
try
|
||||
normal! gv""y
|
||||
return @"
|
||||
finally
|
||||
call setreg('"', save, save_type)
|
||||
endtry
|
||||
else
|
||||
let [begin, end] = [getpos("'<"), getpos("'>")]
|
||||
let lastchar = matchstr(getline(end[1])[end[2]-1 :], '.')
|
||||
if begin[1] ==# end[1]
|
||||
let lines = [getline(begin[1])[begin[2]-1 : end[2]-2]]
|
||||
else
|
||||
let lines = [getline(begin[1])[begin[2]-1 :]]
|
||||
\ + (end[1] - begin[1] <# 2 ? [] : getline(begin[1]+1, end[1]-1))
|
||||
\ + [getline(end[1])[: end[2]-2]]
|
||||
endif
|
||||
return join(lines, "\n") . lastchar . (visualmode() ==# 'V' ? "\n" : '')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:read_content(content, ...) abort
|
||||
let options = extend({
|
||||
\ 'tempfile': '',
|
||||
\ 'fileformat': '',
|
||||
\ 'encoding': '',
|
||||
\ 'binary': 0,
|
||||
\ 'nobinary': 0,
|
||||
\ 'bad': '',
|
||||
\ 'edit': 0,
|
||||
\ 'line': '',
|
||||
\}, get(a:000, 0, {}))
|
||||
let tempfile = empty(options.tempfile) ? tempname() : options.tempfile
|
||||
let optnames = [
|
||||
\ empty(options.fileformat) ? '' : '++ff=' . options.fileformat,
|
||||
\ empty(options.encoding) ? '' : '++enc=' . options.encoding,
|
||||
\ empty(options.binary) ? '' : '++bin',
|
||||
\ empty(options.nobinary) ? '' : '++nobin',
|
||||
\ empty(options.bad) ? '' : '++bad=' . options.bad,
|
||||
\ empty(options.edit) ? '' : '++edit',
|
||||
\]
|
||||
let optname = join(filter(optnames, '!empty(v:val)'))
|
||||
try
|
||||
call writefile(a:content, tempfile)
|
||||
execute printf('keepalt keepjumps %sread %s%s',
|
||||
\ options.line,
|
||||
\ empty(optname) ? '' : optname . ' ',
|
||||
\ fnameescape(tempfile),
|
||||
\)
|
||||
finally
|
||||
call delete(tempfile)
|
||||
execute 'bwipeout!' tempfile
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:edit_content(content, ...) abort
|
||||
let options = extend({
|
||||
\ 'edit': 1,
|
||||
\}, get(a:000, 0, {}))
|
||||
let guard = s:G.store(['&l:modifiable'])
|
||||
let saved_view = winsaveview()
|
||||
try
|
||||
let &l:modifiable=1
|
||||
silent keepjumps %delete _
|
||||
silent call s:read_content(a:content, options)
|
||||
silent keepjumps 1delete _
|
||||
finally
|
||||
keepjump call winrestview(saved_view)
|
||||
call guard.restore()
|
||||
endtry
|
||||
setlocal nomodified
|
||||
endfunction
|
||||
|
||||
function! s:parse_cmdarg(...) abort
|
||||
let cmdarg = get(a:000, 0, v:cmdarg)
|
||||
let options = {}
|
||||
if cmdarg =~# '++enc='
|
||||
let options.encoding = matchstr(cmdarg, '++enc=\zs[^ ]\+\ze')
|
||||
endif
|
||||
if cmdarg =~# '++ff='
|
||||
let options.fileformat = matchstr(cmdarg, '++ff=\zs[^ ]\+\ze')
|
||||
endif
|
||||
if cmdarg =~# '++bad='
|
||||
let options.bad = matchstr(cmdarg, '++bad=\zs[^ ]\+\ze')
|
||||
endif
|
||||
if cmdarg =~# '++bin'
|
||||
let options.binary = 1
|
||||
endif
|
||||
if cmdarg =~# '++nobin'
|
||||
let options.nobinary = 1
|
||||
endif
|
||||
if cmdarg =~# '++edit'
|
||||
let options.edit = 1
|
||||
endif
|
||||
return options
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et ts=2 sts=2 sw=2 tw=0:
|
@ -0,0 +1,240 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Vim#Guard#import() abort
|
||||
return map({'_vital_depends': '', '_vital_created': '', 'store': '', '_vital_loaded': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Vim#Guard#import() abort', printf("return map({'_vital_depends': '', '_vital_created': '', 'store': '', '_vital_loaded': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
" Use a Funcref as a special term _UNDEFINED
|
||||
function! s:_undefined() abort
|
||||
return 'undefined'
|
||||
endfunction
|
||||
let s:_UNDEFINED = function('s:_undefined')
|
||||
|
||||
function! s:_vital_loaded(V) abort
|
||||
let s:V = a:V
|
||||
let s:Prelude = s:V.import('Prelude')
|
||||
let s:List = s:V.import('Data.List')
|
||||
let s:Dict = s:V.import('Data.Dict')
|
||||
endfunction
|
||||
function! s:_vital_depends() abort
|
||||
return ['Prelude', 'Data.List', 'Data.Dict']
|
||||
endfunction
|
||||
function! s:_vital_created(module) abort
|
||||
" define constant variables
|
||||
if !exists('s:const')
|
||||
let s:const = {}
|
||||
let s:const.is_local_variable_supported =
|
||||
\ v:version > 703 || (v:version == 703 && has('patch560'))
|
||||
" NOTE:
|
||||
" The third argument is available from 7.4.242 but it had bug and that
|
||||
" bug was fixed from 7.4.513
|
||||
let s:const.is_third_argument_of_getreg_supported = has('patch-7.4.513')
|
||||
lockvar s:const
|
||||
endif
|
||||
call extend(a:module, s:const)
|
||||
endfunction
|
||||
function! s:_throw(msg) abort
|
||||
throw printf('vital: Vim.Guard: %s', a:msg)
|
||||
endfunction
|
||||
|
||||
let s:option = {}
|
||||
function! s:_new_option(name) abort
|
||||
if a:name !~# '^&'
|
||||
call s:_throw(printf(
|
||||
\'An option name "%s" requires to be started from "&"', a:name
|
||||
\))
|
||||
elseif !exists(a:name)
|
||||
call s:_throw(printf(
|
||||
\'An option name "%s" does not exist', a:name
|
||||
\))
|
||||
endif
|
||||
let option = copy(s:option)
|
||||
let option.name = a:name
|
||||
let option.value = eval(a:name)
|
||||
return option
|
||||
endfunction
|
||||
function! s:option.restore() abort
|
||||
execute printf('let %s = %s', self.name, string(self.value))
|
||||
endfunction
|
||||
|
||||
let s:register = {}
|
||||
function! s:_new_register(name) abort
|
||||
if len(a:name) != 2
|
||||
call s:_throw(printf(
|
||||
\'A register name "%s" requires to be "@" + a single character', a:name
|
||||
\))
|
||||
elseif a:name !~# '^@'
|
||||
call s:_throw(printf(
|
||||
\'A register name "%s" requires to be started from "@"', a:name
|
||||
\))
|
||||
elseif a:name =~# '^@[:.%]$'
|
||||
call s:_throw(printf(
|
||||
\'A register name "%s" is read only', a:name
|
||||
\))
|
||||
elseif a:name !~# '^@[@0-9a-zA-Z#=*+~_/-]$'
|
||||
call s:_throw(printf(
|
||||
\'A register name "%s" does not exist. See ":help let-register"', a:name
|
||||
\))
|
||||
endif
|
||||
let name = a:name ==# '@@' ? '' : a:name[1]
|
||||
let register = copy(s:register)
|
||||
let register.name = name
|
||||
if s:const.is_third_argument_of_getreg_supported
|
||||
let register.value = getreg(name, 1, 1)
|
||||
else
|
||||
let register.value = getreg(name, 1)
|
||||
endif
|
||||
let register.type = getregtype(name)
|
||||
return register
|
||||
endfunction
|
||||
function! s:register.restore() abort
|
||||
" https://github.com/vim/vim/commit/5a50c2255c447838d08d3b4895a3be3a41cd8eda
|
||||
if has('patch-7.4.243') || self.name !=# '='
|
||||
call setreg(self.name, self.value, self.type)
|
||||
else
|
||||
let @= = self.value
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let s:environment = {}
|
||||
function! s:_new_environment(name) abort
|
||||
if a:name !~# '^\$'
|
||||
call s:_throw(printf(
|
||||
\'An environment variable name "%s" requires to be started from "$"', a:name
|
||||
\))
|
||||
elseif !exists(a:name)
|
||||
call s:_throw(printf(
|
||||
\'An environment variable name "%s" does not exist. While Vim cannot unlet environment variable, it requires to exist', a:name
|
||||
\))
|
||||
endif
|
||||
let environment = copy(s:environment)
|
||||
let environment.name = a:name
|
||||
let environment.value = eval(a:name)
|
||||
return environment
|
||||
endfunction
|
||||
function! s:environment.restore() abort
|
||||
execute printf('let %s = %s', self.name, string(self.value))
|
||||
endfunction
|
||||
|
||||
let s:variable = {}
|
||||
function! s:_new_variable(name, ...) abort
|
||||
if a:0 == 0
|
||||
let m = matchlist(a:name, '^\([bwtg]:\)\(.*\)$')
|
||||
if empty(m)
|
||||
call s:_throw(printf(
|
||||
\ join([
|
||||
\ 'An variable name "%s" requires to start from b:, w:, t:, or g:',
|
||||
\ 'while no {namespace} is specified',
|
||||
\ ]),
|
||||
\ a:name,
|
||||
\))
|
||||
endif
|
||||
let [prefix, name] = m[1 : 2]
|
||||
let namespace = eval(prefix)
|
||||
else
|
||||
let name = a:name
|
||||
let namespace = a:1
|
||||
endif
|
||||
let variable = copy(s:variable)
|
||||
let variable.name = name
|
||||
let variable.value = get(namespace, name, s:_UNDEFINED)
|
||||
let variable.value =
|
||||
\ type(variable.value) == type({}) || type(variable.value) == type([])
|
||||
\ ? deepcopy(variable.value)
|
||||
\ : variable.value
|
||||
let variable._namespace = namespace
|
||||
return variable
|
||||
endfunction
|
||||
function! s:variable.restore() abort
|
||||
" unlet the variable to prevent variable type mis-match in case
|
||||
silent! unlet! self._namespace[self.name]
|
||||
if type(self.value) == type(s:_UNDEFINED) && self.value == s:_UNDEFINED
|
||||
" do nothing, leave the variable as undefined
|
||||
else
|
||||
let self._namespace[self.name] = self.value
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let s:instance = {}
|
||||
function! s:_new_instance(instance, ...) abort
|
||||
let shallow = get(a:000, 0, 0)
|
||||
if !s:Prelude.is_list(a:instance) && !s:Prelude.is_dict(a:instance)
|
||||
call s:_throw(printf(
|
||||
\'An instance "%s" requires to be List or Dictionary', string(a:instance)
|
||||
\))
|
||||
endif
|
||||
let instance = copy(s:instance)
|
||||
let instance.instance = a:instance
|
||||
let instance.values = shallow ? copy(a:instance) : deepcopy(a:instance)
|
||||
return instance
|
||||
endfunction
|
||||
function! s:instance.restore() abort
|
||||
if s:Prelude.is_list(self.instance)
|
||||
call s:List.clear(self.instance)
|
||||
else
|
||||
call s:Dict.clear(self.instance)
|
||||
endif
|
||||
call extend(self.instance, self.values)
|
||||
endfunction
|
||||
|
||||
let s:guard = {}
|
||||
function! s:store(targets) abort
|
||||
let resources = []
|
||||
for meta in a:targets
|
||||
if s:Prelude.is_list(meta)
|
||||
if len(meta) == 1
|
||||
call add(resources, s:_new_instance(meta[0]))
|
||||
elseif len(meta) == 2
|
||||
if s:Prelude.is_string(meta[0])
|
||||
call add(resources, call('s:_new_variable', meta))
|
||||
else
|
||||
call add(resources, call('s:_new_instance', meta))
|
||||
endif
|
||||
else
|
||||
call s:_throw('List assignment requires one or two elements')
|
||||
endif
|
||||
elseif type(meta) == type('')
|
||||
if meta =~# '^[bwtgls]:'
|
||||
" Note:
|
||||
" To improve an error message, handle l:XXX or s:XXX as well
|
||||
call add(resources, s:_new_variable(meta))
|
||||
elseif meta =~# '^&'
|
||||
call add(resources, s:_new_option(meta))
|
||||
elseif meta =~# '^@'
|
||||
call add(resources, s:_new_register(meta))
|
||||
elseif meta =~# '^\$'
|
||||
call add(resources, s:_new_environment(meta))
|
||||
else
|
||||
call s:_throw(printf(
|
||||
\ 'Unknown value "%s" was specified',
|
||||
\ meta
|
||||
\))
|
||||
endif
|
||||
endif
|
||||
unlet meta
|
||||
endfor
|
||||
let guard = copy(s:guard)
|
||||
let guard._resources = resources
|
||||
return guard
|
||||
endfunction
|
||||
function! s:guard.restore() abort
|
||||
for resource in self._resources
|
||||
call resource.restore()
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet! s:save_cpo
|
||||
" vim:set et ts=2 sts=2 sw=2 tw=0 fdm=marker:
|
@ -0,0 +1,80 @@
|
||||
" ___vital___
|
||||
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
||||
" Do not mofidify the code nor insert new lines before '" ___vital___'
|
||||
if v:version > 703 || v:version == 703 && has('patch1170')
|
||||
function! vital#_easymotion#Vim#Message#import() abort
|
||||
return map({'capture': '', 'echomsg': '', 'echo': '', 'warn': '', 'get_hit_enter_max_length': '', 'error': ''}, 'function("s:" . v:key)')
|
||||
endfunction
|
||||
else
|
||||
function! s:_SID() abort
|
||||
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
||||
endfunction
|
||||
execute join(['function! vital#_easymotion#Vim#Message#import() abort', printf("return map({'capture': '', 'echomsg': '', 'echo': '', 'warn': '', 'get_hit_enter_max_length': '', 'error': ''}, \"function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
||||
delfunction s:_SID
|
||||
endif
|
||||
" ___vital___
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
|
||||
|
||||
function! s:echo(hl, msg) abort
|
||||
execute 'echohl' a:hl
|
||||
try
|
||||
echo a:msg
|
||||
finally
|
||||
echohl None
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:echomsg(hl, msg) abort
|
||||
execute 'echohl' a:hl
|
||||
try
|
||||
for m in split(a:msg, "\n")
|
||||
echomsg m
|
||||
endfor
|
||||
finally
|
||||
echohl None
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:error(msg) abort
|
||||
call s:echomsg('ErrorMsg', a:msg)
|
||||
endfunction
|
||||
|
||||
function! s:warn(msg) abort
|
||||
call s:echomsg('WarningMsg', a:msg)
|
||||
endfunction
|
||||
|
||||
function! s:capture(command) abort
|
||||
try
|
||||
redir => out
|
||||
silent execute a:command
|
||||
finally
|
||||
redir END
|
||||
endtry
|
||||
return out
|
||||
endfunction
|
||||
|
||||
" * Get max length of |hit-enter|.
|
||||
" If a string length of a message is greater than the max length,
|
||||
" Vim waits for user input according to |hit-enter|.
|
||||
" XXX: Those fixed values may be different between different OSes?
|
||||
" Currently tested on only Windows.
|
||||
function! s:get_hit_enter_max_length() abort
|
||||
let maxlen = &columns * &cmdheight - 1
|
||||
if &ruler
|
||||
" TODO
|
||||
endif
|
||||
if &showcmd
|
||||
let maxlen -= 11
|
||||
endif
|
||||
return maxlen
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et ts=2 sts=2 sw=2 tw=0:
|
Reference in New Issue
Block a user