From 03573c9921432e9c5abb8275e8e86140c3c426df Mon Sep 17 00:00:00 2001 From: haya14busa Date: Sat, 7 Jun 2014 01:35:19 +0900 Subject: [PATCH 1/2] [WIP] couldn't input 4??? --- autoload/vital/_easymotion.vim | 101 ++++++++- autoload/vital/_easymotion/Data/List.vim | 21 +- .../_easymotion/Over/Commandline/Base.vim | 205 ++++++++++++++++-- .../Over/Commandline/Modules/Doautocmd.vim | 8 +- .../Commandline/Modules/DrawCommandline.vim | 2 +- .../Over/Commandline/Modules/History.vim | 2 +- .../Commandline/Modules/InsertRegister.vim | 8 +- .../Over/Commandline/Modules/Paste.vim | 3 +- autoload/vital/easymotion.vital | 2 +- 9 files changed, 313 insertions(+), 39 deletions(-) diff --git a/autoload/vital/_easymotion.vim b/autoload/vital/_easymotion.vim index 6a0aac3..dd02388 100644 --- a/autoload/vital/_easymotion.vim +++ b/autoload/vital/_easymotion.vim @@ -59,6 +59,43 @@ function! s:unload() let s:loaded = {} endfunction +function! s:exists(name) + return s:_get_module_path(a:name) !=# '' +endfunction + +function! s:search(pattern) + let target = substitute(a:pattern, '\.', '/', 'g') + let tailpath = printf('autoload/vital/%s/%s.vim', s:self_version, target) + + let paths = s:_runtime_files(tailpath) + let modules = sort(map(paths, 's:_file2module(v:val)')) + return s:_uniq(modules) +endfunction + +function! s:expand_modules(entry, all) + if type(a:entry) == type([]) + let candidates = s:_concat(map(copy(a:entry), 's:search(v:val)')) + if empty(candidates) + throw printf('vital: Any of module %s is not found', string(a:entry)) + endif + if eval(join(map(copy(candidates), 'has_key(a:all, v:val)'), '+')) + let modules = [] + else + let modules = [candidates[0]] + endif + else + let modules = s:search(a:entry) + if empty(modules) + throw printf('vital: Module %s is not found', a:entry) + endif + endif + call filter(modules, '!has_key(a:all, v:val)') + for module in modules + let a:all[module] = 1 + endfor + return modules +endfunction + function! s:_import(name) if type(a:name) == type(0) return s:_build_module(a:name) @@ -89,19 +126,16 @@ function! s:_get_module_path(name) if a:name ==# '' let tailpath = printf('autoload/vital/%s.vim', s:self_version) elseif a:name =~# '\v^\u\w*%(\.\u\w*)*$' - let target = '/' . substitute(a:name, '\W\+', '/', 'g') - let tailpath = printf('autoload/vital/%s%s.vim', s:self_version, target) + let target = substitute(a:name, '\W\+', '/', 'g') + let tailpath = printf('autoload/vital/%s/%s.vim', s:self_version, target) else throw 'vital: Invalid module name: ' . a:name endif - if s:globpath_third_arg - let paths = split(globpath(&runtimepath, tailpath, 1), "\n") - else - let paths = split(globpath(&runtimepath, tailpath), "\n") - endif + let paths = s:_runtime_files(tailpath) call filter(paths, 'filereadable(v:val)') - return s:_unify_path(get(paths, 0, '')) + let path = get(paths, 0, '') + return path !=# '' ? s:_unify_path(path) : '' endfunction function! s:_scripts() @@ -116,13 +150,19 @@ function! s:_scripts() return scripts endfunction +function! s:_file2module(file) + let filename = fnamemodify(a:file, ':p:gs?[\\/]\+?/?') + let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$') + return join(split(tail, '[\\/]\+'), '.') +endfunction + if filereadable(expand(':r') . '.VIM') function! s:_unify_path(path) " Note: On windows, vim can't expand path names from 8.3 formats. " So if getting full path via and $HOME was set as 8.3 format, " vital load duplicated scripts. Below's :~ avoid this issue. return tolower(fnamemodify(resolve(fnamemodify( - \ a:path, ':p:gs?[\\/]\+?/?')), ':~')) + \ a:path, ':p')), ':~:gs?[\\/]\+?/?')) endfunction else function! s:_unify_path(path) @@ -130,6 +170,16 @@ else endfunction endif +if s:globpath_third_arg + function! s:_runtime_files(path) + return split(globpath(&runtimepath, a:path, 1), "\n") + endfunction +else + function! s:_runtime_files(path) + return split(globpath(&runtimepath, a:path), "\n") + endfunction +endif + " Copy from System.Filepath if has('win16') || has('win32') || has('win64') function! s:_is_absolute_path(path) @@ -155,7 +205,11 @@ function! s:_build_module(sid) if has_key(module, '_vital_loaded') let V = vital#{s:self_version}#new() if has_key(module, '_vital_depends') - call call(V.load, module._vital_depends(), V) + let all = {} + let modules = + \ s:_concat(map(module._vital_depends(), + \ 's:expand_modules(v:val, all)')) + call call(V.load, modules, V) endif try call module._vital_loaded(V) @@ -188,6 +242,33 @@ else endfunction endif +if exists('*uniq') + function! s:_uniq(list) + return uniq(a:list) + endfunction +else + function! s:_uniq(list) + let i = len(a:list) - 1 + while 0 < i + if a:list[i] ==# a:list[i - 1] + call remove(a:list, i) + let i -= 2 + else + let i -= 1 + endif + endwhile + return a:list + endfunction +endif + +function! s:_concat(lists) + let result_list = [] + for list in a:lists + let result_list += list + endfor + return result_list +endfunction + function! s:_redir(cmd) let [save_verbose, save_verbosefile] = [&verbose, &verbosefile] set verbose=0 verbosefile= diff --git a/autoload/vital/_easymotion/Data/List.vim b/autoload/vital/_easymotion/Data/List.vim index 4a1fbca..29e373e 100644 --- a/autoload/vital/_easymotion/Data/List.vim +++ b/autoload/vital/_easymotion/Data/List.vim @@ -29,13 +29,8 @@ function! s:conj(xs, 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 +function! s:uniq(list) + return s:uniq_by(a:list, 'v:val') endfunction " Removes duplicates from a list. @@ -203,6 +198,18 @@ function! s:or(xs) return s:any('v:val', a:xs) endfunction +function! s:map_accum(expr, xs, init) + 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) let memo = a:init diff --git a/autoload/vital/_easymotion/Over/Commandline/Base.vim b/autoload/vital/_easymotion/Over/Commandline/Base.vim index 396f32f..067c6d2 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Base.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Base.vim @@ -8,6 +8,7 @@ function! s:_vital_loaded(V) let s:String = s:V.import("Over.String") let s:Signals = s:V.import("Over.Signals") let s:Module = s:V.import("Over.Commandline.Modules") + let s:List = s:V.import("Data.List") let s:base.variables.modules = s:Signals.make() function! s:base.variables.modules.get_slot(val) return a:val.slot.module @@ -20,6 +21,7 @@ function! s:_vital_depends() \ "Over.String", \ "Over.Signals", \ "Over.Commandline.Modules", +\ "Data.List", \ ] endfunction @@ -247,6 +249,20 @@ function! s:base.exit(...) 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() @@ -315,6 +331,7 @@ function! s:base._init() let self.variables.input = "" let self.variables.exit = 0 let self.variables.exit_code = 1 + let self.variables.enable_keymapping = 1 call self.hl_cursor_off() if !hlexists(self.highlights.cursor) execute "highlight link " . self.highlights.cursor . " Cursor" @@ -343,25 +360,43 @@ function! s:base._execute(command) endfunction +function! s:base._input(input, ...) + let self.variables.input_key = a:input + if self.is_enable_keymapping() + let key = s:_unmap(self._get_keymapping(), a:input) + else + let key = a:input + endif + + for char in s:_split_keys(key) + let self.variables.input_key = char + let self.variables.char = char + call self.setchar(self.variables.char) + call self.callevent("on_char_pre") + call self.insert(self.variables.input) + call self.callevent("on_char") + endfor +endfunction + + function! s:base._main(...) try call self._init() let self.line = deepcopy(s:String.make(get(a:, 1, ""))) call self.callevent("on_enter") + call self.draw() while !self._is_exit() try - call self.draw() - - let self.variables.input_key = s:_getchar() - let self.variables.char = s:_unmap(self._get_keymapping(), self.variables.input_key) -" let self.variables.char = s:_unmap(self._get_keymapping(), self.get_tap_key() . self.variables.input_key) - - call self.setchar(self.variables.char) - - call self.callevent("on_char_pre") - call self.insert(self.variables.input) - call self.callevent("on_char") +" call self.callevent("on_update") +" if !getchar(1) +" continue +" endif +" +" call self._input(s:_getchar(0)) +" call self.draw() + call self._input(s:_getchar()) + call self.draw() catch call self.callevent("on_exception") endtry @@ -400,6 +435,10 @@ endfunction function! s:_unmap(mapping, key) + let keys = s:_split_keys(a:key) + if len(keys) > 1 + return join(map(keys, 's:_unmap(a:mapping, v:val)'), '') + endif if !has_key(a:mapping, a:key) return a:key endif @@ -426,11 +465,151 @@ function! s:base._get_keymapping() endfunction -function! s:_getchar() - let char = getchar() +function! s:_getchar(...) + let char = call("getchar", a:000) return type(char) == type(0) ? nr2char(char) : char endfunction + +function! s:_split(str, pat) + let pat = '\%#=2' . a:pat + let list = split(a:str, pat . '\zs') + return s:List.flatten(map(list, 'v:val == a:pat ? a:pat : v:val =~ pat . ''$'' ? split(v:val, pat) + [a:pat] : v:val')) +endfunction + + +function! s:_split_keystring(str, pats, ...) + if a:str =~ '^(.\{-})$' +\ || a:str =~ "^\(.\\{-})$" + return [a:str] + endif + let pats = a:pats + let index = get(a:, 1, 0) + if !exists("+regexpengine") +\ || index > len(pats) +\ || len(filter(copy(pats), 'a:str =~ ''\%#=2'' . v:val')) == 0 + if len(filter(copy(pats), 'a:str ==# v:val')) == 0 + return split(a:str, '\zs') + else + return [a:str] + endif + endif + if len(filter(copy(pats), 'a:str == v:val')) == 1 + return [a:str] + endif + + let result = [] + let pat = pats[index] + let list = s:_split(a:str, pat) + let result += eval(join(map(list, "s:_split_keystring(v:val, pats, index+1)"), "+")) + return result +endfunction + + + + +let s:special_keys = [ +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\ "\", +\] + +function! s:_split_keys(str) + return s:_split_keystring(a:str, s:special_keys) +endfunction + + let &cpo = s:save_cpo unlet s:save_cpo diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/Doautocmd.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/Doautocmd.vim index 8858147..03298da 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/Doautocmd.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/Doautocmd.vim @@ -29,10 +29,12 @@ let s:hooks = [ \ "leave", \ "char", \ "char_pre", +\ "draw", +\ "draw_pre", \ "execute_pre", \ "execute_failed", \ "execute", -\ "cancel" +\ "exception", \] let s:hooks_camel = [ @@ -40,10 +42,12 @@ let s:hooks_camel = [ \ "Leave", \ "Char", \ "CharPre", +\ "Draw", +\ "DrawPre", \ "ExecutePre", \ "ExecuteFailed", \ "Execute", -\ "Cancel" +\ "Exception", \] diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/DrawCommandline.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/DrawCommandline.vim index 4482ac3..7953657 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/DrawCommandline.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/DrawCommandline.vim @@ -66,7 +66,7 @@ endfunction function! s:_as_echon(str) - return "echon " . string(a:str) + return "echon " . strtrans(string(a:str)) endfunction diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/History.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/History.vim index 06700dc..4e6db3c 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/History.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/History.vim @@ -12,7 +12,7 @@ function! s:module.histories() endfunction -function! s:module.enter(...) +function! s:module.on_enter(...) let s:cmdhist = [] let s:count = 0 endfunction diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/InsertRegister.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/InsertRegister.vim index 37342a2..93c8404 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/InsertRegister.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/InsertRegister.vim @@ -51,9 +51,9 @@ function! s:module.on_char_pre(cmdline) 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.%#:/"\-*]$' - execute "let regist = @" . char - call a:cmdline.setchar(regist) + 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 == "\" @@ -87,10 +87,12 @@ endfunction function! s:module.on_char(cmdline) if a:cmdline.is_input("\") 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 diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/Paste.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/Paste.vim index c0d4dd0..6b1a99b 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/Paste.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/Paste.vim @@ -9,7 +9,8 @@ let s:module = { function! s:module.on_char_pre(cmdline) if a:cmdline.is_input("(paste)") - call a:cmdline.insert(@*) + let register = v:register == "" ? '"' : v:register + call a:cmdline.insert(tr(getreg("*"), "\n", "\r")) call a:cmdline.setchar('') endif endfunction diff --git a/autoload/vital/easymotion.vital b/autoload/vital/easymotion.vital index e2f4490..66e2156 100644 --- a/autoload/vital/easymotion.vital +++ b/autoload/vital/easymotion.vital @@ -1,5 +1,5 @@ easymotion -39d8e9c +fb554d1 Over.Commandline.Base Over.Commandline.Modules.Cancel From d910e4f1a25991145f55fe1cea1387b68038770a Mon Sep 17 00:00:00 2001 From: haya14busa Date: Sat, 7 Jun 2014 02:23:42 +0900 Subject: [PATCH 2/2] Fix cannot input 4 & 7 by workaround --- autoload/vital/_easymotion/Over/Commandline/Base.vim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/autoload/vital/_easymotion/Over/Commandline/Base.vim b/autoload/vital/_easymotion/Over/Commandline/Base.vim index 067c6d2..03d4a80 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Base.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Base.vim @@ -586,9 +586,7 @@ let s:special_keys = [ \ "\", \ "\", \ "\", -\ "\", \ "\", -\ "\", \ "\", \ "\", \ "\", @@ -606,10 +604,12 @@ let s:special_keys = [ \ "\", \] +" \ "\", -> conflict with 4 +" \ "\", -> conflict with 7 + function! s:_split_keys(str) return s:_split_keystring(a:str, s:special_keys) endfunction - let &cpo = s:save_cpo unlet s:save_cpo