Update vital-over
This commit is contained in:
parent
19bdc5933c
commit
7acbd9996b
283
autoload/vital/_easymotion/Data/List.vim
Normal file
283
autoload/vital/_easymotion/Data/List.vim
Normal file
@ -0,0 +1,283 @@
|
||||
" Utilities for list.
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:pop(list)
|
||||
return remove(a:list, -1)
|
||||
endfunction
|
||||
|
||||
function! s:push(list, val)
|
||||
call add(a:list, a:val)
|
||||
return a:list
|
||||
endfunction
|
||||
|
||||
function! s:shift(list)
|
||||
return remove(a:list, 0)
|
||||
endfunction
|
||||
|
||||
function! s:unshift(list, val)
|
||||
return insert(a:list, a:val)
|
||||
endfunction
|
||||
|
||||
function! s:cons(x, xs)
|
||||
return [a:x] + a:xs
|
||||
endfunction
|
||||
|
||||
function! s:conj(xs, x)
|
||||
return a:xs + [a:x]
|
||||
endfunction
|
||||
|
||||
" Removes duplicates from a list.
|
||||
function! s:uniq(list, ...)
|
||||
if a:0
|
||||
echomsg "Vital.Data.List.uniq() with 2 arguments is deprecated! Please use uniq_by() instead, if you still want to use the 2nd argument."
|
||||
return s:uniq_by(a:list, a:1)
|
||||
else
|
||||
return s:uniq_by(a:list, 'v:val')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Removes duplicates from a list.
|
||||
function! s:uniq_by(list, f)
|
||||
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)
|
||||
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)
|
||||
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, ...)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
" 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)
|
||||
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)
|
||||
return s:span(printf('!(%s)', a:f), a:xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Data.List.takeWhile
|
||||
function! s:take_while(f, xs)
|
||||
return s:span(a:f, a:xs)[0]
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Data.List.partition
|
||||
function! s:partition(f, xs)
|
||||
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)
|
||||
return !s:any(printf('!(%s)', a:f), a:xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.any
|
||||
function! s:any(f, xs)
|
||||
return !empty(filter(map(copy(a:xs), a:f), 'v:val'))
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.and
|
||||
function! s:and(xs)
|
||||
return s:all('v:val', a:xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.or
|
||||
function! s:or(xs)
|
||||
return s:any('v:val', a:xs)
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.foldl
|
||||
function! s:foldl(f, init, xs)
|
||||
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)
|
||||
if len(a:xs) == 0
|
||||
throw '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)
|
||||
return s:foldl(a:f, a:init, reverse(copy(a:xs)))
|
||||
endfunction
|
||||
|
||||
" similar to Haskell's Prelude.fold11
|
||||
function! s:foldr1(f, xs)
|
||||
if len(a:xs) == 0
|
||||
throw 'foldr1'
|
||||
endif
|
||||
return s:foldr(a:f, a:xs[-1], a:xs[0:-2])
|
||||
endfunction
|
||||
|
||||
" similar to python's zip()
|
||||
function! s:zip(...)
|
||||
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)
|
||||
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, ...)
|
||||
let base = a:0 > 0 ? a:1 : 0
|
||||
return s:zip(a:list, range(base, len(a:list)+base-1))
|
||||
endfunction
|
||||
|
||||
" similar to Ruby's detect or Haskell's find.
|
||||
" TODO spec and doc
|
||||
function! s:find(list, default, f)
|
||||
for x in a:list
|
||||
if eval(substitute(a:f, 'v:val', string(x), 'g'))
|
||||
return x
|
||||
endif
|
||||
endfor
|
||||
return a:default
|
||||
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)
|
||||
return !empty(filter(copy(a:list1), 'index(a:list2, v:val) isnot -1'))
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et ts=2 sts=2 sw=2 tw=0:
|
@ -21,13 +21,20 @@ function! s:_vital_loaded(V)
|
||||
for module in s:modules
|
||||
let s:{module} = s:V.import('Over.Commandline.Modules.' . module)
|
||||
endfor
|
||||
let s:String = s:V.import("Over.String")
|
||||
let s:String = s:V.import("Over.String")
|
||||
let s:Signals = s:V.import("Over.Signals")
|
||||
let s:base.variables.modules = s:Signals.make()
|
||||
function! s:base.variables.modules.get_slot(val)
|
||||
return a:val.slot.module
|
||||
endfunction
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:_vital_depends()
|
||||
return ["Over.String"]
|
||||
\ + map(copy(s:modules), "'Over.Commandline.Modules.' . v:val")
|
||||
return [
|
||||
\ "Over.String",
|
||||
\ "Over.Signals",
|
||||
\ ] + map(copy(s:modules), "'Over.Commandline.Modules.' . v:val")
|
||||
endfunction
|
||||
|
||||
|
||||
@ -45,6 +52,7 @@ function! s:make_plain(prompt)
|
||||
let result.prompt = a:prompt
|
||||
call result.connect("Enter")
|
||||
call result.connect("Cancel")
|
||||
call result.connect(result, "_")
|
||||
return result
|
||||
endfunction
|
||||
|
||||
@ -75,7 +83,6 @@ let s:base = {
|
||||
\ "tap_key" : "",
|
||||
\ "exit" : 0,
|
||||
\ "keymapping" : {},
|
||||
\ "modules" : {},
|
||||
\ },
|
||||
\ "highlights" : {
|
||||
\ "prompt" : "NONE",
|
||||
@ -166,28 +173,30 @@ function! s:base.connect(module, ...)
|
||||
if type(a:module) == type("")
|
||||
return call(self.connect, [s:get_module(a:module).make()] + a:000, self)
|
||||
endif
|
||||
let name = get(a:, 1, a:module.name)
|
||||
let self.variables.modules[name] = a:module
|
||||
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)
|
||||
unlet self.variables.modules[a:name]
|
||||
return self.variables.modules.disconnect_by(
|
||||
\ "get(v:val.slot, 'name', '') == " . string(a:name)
|
||||
\ )
|
||||
" unlet self.variables.modules[a:name]
|
||||
endfunction
|
||||
|
||||
|
||||
for s:_ in ["enter", "leave", "char", "char_pre", "execute_pre", "execute_failed", "execute", "cancel"]
|
||||
execute join([
|
||||
\ "function! s:base._on_" . s:_ . "()",
|
||||
\ " call map(copy(self.variables.modules), 'has_key(v:val, \"on_" . s:_ . "\") ? v:val.on_" . s:_ . "(self) : 0')",
|
||||
\ " call self.on_" . s:_ . "()",
|
||||
\ "endfunction",
|
||||
\ ], "\n")
|
||||
|
||||
execute "function! s:base.on_" . s:_ . "()"
|
||||
endfunction
|
||||
endfor
|
||||
unlet s:_
|
||||
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)
|
||||
@ -310,16 +319,16 @@ endfunction
|
||||
|
||||
function! s:base._execute()
|
||||
call s:redraw()
|
||||
call self._on_execute_pre()
|
||||
call self.callevent("on_execute_pre")
|
||||
try
|
||||
call self.execute()
|
||||
catch
|
||||
echohl ErrorMsg
|
||||
echo matchstr(v:exception, 'Vim\((\w*)\)\?:\zs.*\ze')
|
||||
echohl None
|
||||
call self._on_execute_failed()
|
||||
call self.callevent("on_execute_failed")
|
||||
finally
|
||||
call self._on_execute()
|
||||
call self.callevent("on_execute")
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
@ -328,7 +337,7 @@ function! s:base._main(...)
|
||||
try
|
||||
call self._init()
|
||||
let self.line = deepcopy(s:String.make(get(a:, 1, "")))
|
||||
call self._on_enter()
|
||||
call self.callevent("on_enter")
|
||||
|
||||
while !self._is_exit()
|
||||
call s:_echo_cmdline(self)
|
||||
@ -339,18 +348,18 @@ function! s:base._main(...)
|
||||
|
||||
call self.setchar(self.variables.char)
|
||||
|
||||
call self._on_char_pre()
|
||||
call self.callevent("on_char_pre")
|
||||
call self.insert(self.variables.input)
|
||||
call self._on_char()
|
||||
call self.callevent("on_char")
|
||||
endwhile
|
||||
catch
|
||||
echohl ErrorMsg | echo v:throwpoint . " " . v:exception | echohl None
|
||||
return -1
|
||||
finally
|
||||
call self._finish()
|
||||
call self._on_leave()
|
||||
call s:redraw()
|
||||
call self.callevent("on_leave")
|
||||
endtry
|
||||
call s:redraw()
|
||||
return self.exit_code()
|
||||
endfunction
|
||||
|
||||
@ -410,9 +419,12 @@ endfunction
|
||||
|
||||
function! s:base._get_keymapping()
|
||||
let result = {}
|
||||
for module in values(self.variables.modules)
|
||||
" for module in values(self.variables.modules)
|
||||
for module in self.variables.modules.slots()
|
||||
if has_key(module, "keymapping")
|
||||
call extend(result, module.keymapping(self))
|
||||
if module isnot self
|
||||
call extend(result, module.keymapping(self))
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
return extend(extend(result, self.variables.keymapping), self.keymapping())
|
||||
|
104
autoload/vital/_easymotion/Over/Signals.vim
Normal file
104
autoload/vital/_easymotion/Over/Signals.vim
Normal file
@ -0,0 +1,104 @@
|
||||
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
|
Loading…
Reference in New Issue
Block a user