diff --git a/autoload/EasyMotion.vim b/autoload/EasyMotion.vim index d4dc4fa..7479fb9 100644 --- a/autoload/EasyMotion.vim +++ b/autoload/EasyMotion.vim @@ -1,7 +1,7 @@ " EasyMotion - Vim motions on speed! " " Author: haya14busa -" Last Change: 27 Jan 2014. +" Last Change: 29 Jan 2014. " Source: https://github.com/haya14busa/vim-easymotion " " Original Author: Kim Silkebækken @@ -575,7 +575,7 @@ function! s:findMotion(num_strokes, direction) "{{{ " Check that we have an input char if empty(input) - redraw | return '' + return '' endif let re = s:convertRegep(input) diff --git a/autoload/EasyMotion/command_line.vim b/autoload/EasyMotion/command_line.vim index b8883ba..f2b898d 100644 --- a/autoload/EasyMotion/command_line.vim +++ b/autoload/EasyMotion/command_line.vim @@ -2,7 +2,7 @@ " FILE: autoload/EasyMotion/command_line.vim " AUTHOR: haya14busa " Reference: https://github.com/osyo-manga/vim-over -" Last Change: 26 Jan 2014. +" Last Change: 01 Feb 2014. " License: MIT license {{{ " Permission is hereby granted, free of charge, to any person obtaining " a copy of this software and associated documentation files (the @@ -30,102 +30,101 @@ let s:save_cpo = &cpo set cpo&vim " }}} -" Autocmd: {{{ -augroup plugin-easymotion-dummy - autocmd! -augroup END +" CommandLine: +let s:cmdline = vital#of("easymotion").import("Over.Commandline") +let s:search = s:cmdline.make_plain("/") +let s:search.highlights.prompt = "Question" -let s:cache_command = {} -function! s:doautocmd_user(command) "{{{ - if !has_key(s:cache_command, a:command) - execute "autocmd plugin-easymotion-dummy" -\ . " User " . a:command." silent! execute ''" +" Add Module: {{{ +call s:search.connect(s:cmdline.module_delete()) +call s:search.connect(s:cmdline.module_cursor_move()) +call s:search.connect(s:cmdline.module_paste()) +call s:search.connect(s:cmdline.module_buffer_complete()) +call s:search.connect(s:cmdline.module_history("/")) +call s:search.connect(s:cmdline.module_no_insert_special_chars()) - if v:version > 703 || v:version == 703 && has("patch438") - " :helpgrep 7.4.438 - let s:cache_command[a:command] = "doautocmd User " . a:command - else - let s:cache_command[a:command] = "doautocmd User " . a:command - endif +let s:module = { +\ "name" : "EasyMotion", +\} +function! s:module.on_char_pre(cmdline) + if a:cmdline.is_input("(em-scroll-f)") + call s:scroll(0) + call a:cmdline.setchar('') + elseif a:cmdline.is_input("(em-scroll-b)") + call s:scroll(1) + call a:cmdline.setchar('') + elseif a:cmdline.is_input("(em-jumpback)") + keepjumps call setpos('.', s:save_orig_pos) + let s:orig_pos = s:save_orig_pos + let s:orig_line_start = getpos('w0') + let s:orig_line_end = getpos('w$') + let s:direction = s:save_direction + call a:cmdline.setchar('') + elseif a:cmdline.is_input("(em-openallfold)") + " TODO: better solution + normal! zR + call a:cmdline.setchar('') endif - - execute s:cache_command[a:command] -endfunction "}}} - -augroup easymotion-cmdline - autocmd! - autocmd User EasyMotionCmdLineEnter call s:init() - autocmd User EasyMotionCmdLineLeave call s:finish() -augroup END +endfunction +call s:search.connect(s:module) "}}} -" Activate: -function! s:init() "{{{ - " Cursor - let hl_cursor = EasyMotion#command_line#hl_cursor_off() - if !hlexists("EasyMotionCommandLineCursor") - execute "highlight EasyMotionCommandLineCursor " . hl_cursor . " term=underline gui=underline" - endif - " Save cursor visible - let s:old_t_ve = &t_ve - set t_ve= +" CommandLine Keymap: {{{ +let s:default_key_mapping = { +\ "\" : "(buffer-complete)", +\ "\" : "(em-scroll-f)", +\ "\" : "(em-scroll-b)", +\ "\" : "(em-jumpback)", +\ "\" : "(em-openallfold)", +\} +function! EasyMotion#command_line#keymaps() "{{{ + return extend(deepcopy(s:default_key_mapping), + \ g:EasyMotion_command_line_key_mappings) endfunction "}}} -function! s:finish() "{{{ - " Cursor - call EasyMotion#command_line#hl_cursor_on() - let &t_ve = s:old_t_ve +function! s:search.keymappings() "{{{ + return EasyMotion#command_line#keymaps() endfunction "}}} +"}}} -function! EasyMotion#command_line#hl_cursor_off() "{{{ - if exists("s:old_hi_cursor") - return s:old_hi_cursor - endif - let s:old_hi_cursor = 'cterm=reverse' - if hlexists('Cursor') - redir => cursor - silent highlight Cursor - redir END - let hl = substitute(matchstr(cursor, 'xxx \zs.*'), '[ \t\n]\+\|cleared', ' ', 'g') - if mode(1) == 'ce' - " TODO: this section exists only for vim-vspec test... - let hl = substitute(hl, '\sLast\sset\sfrom.*', '', '') - endif - if !empty(substitute(hl, '\s', '', 'g')) - let s:old_hi_cursor = hl - endif - highlight Cursor NONE - endif - return s:old_hi_cursor -endfunction "}}} -function! EasyMotion#command_line#hl_cursor_on() "{{{ - if exists('s:old_hi_cursor') - silent execute 'highlight Cursor ' . s:old_hi_cursor - unlet s:old_hi_cursor - endif -endfunction "}}} - -function! s:before_input(num_strokes) "{{{ - if a:num_strokes == -1 && g:EasyMotion_inc_highlight +" Event: {{{ +function! s:search.on_enter() "{{{ + if s:num_strokes == -1 call EasyMotion#highlight#delete_highlight() let shade_hl_re = '\_.*' call EasyMotion#highlight#add_highlight(shade_hl_re, g:EasyMotion_hl_group_shade) call EasyMotion#highlight#add_highlight('\%#', g:EasyMotion_hl_inc_cursor) endif endfunction "}}} -function! s:after_input() "{{{ - call EasyMotion#highlight#delete_highlight() +function! s:search.on_leave() "{{{ + call EasyMotion#highlight#delete_highlight(g:EasyMotion_hl_inc_search) endfunction "}}} +function! s:search.on_char() "{{{ + if s:num_strokes == -1 + let re = s:search.getline() + if g:EasyMotion_inc_highlight + let case_flag = EasyMotion#helper#should_use_smartcase(re) ? + \ '\c' : '\C' + let re .= case_flag + call s:inc_highlight(re) + endif + if g:EasyMotion_off_screen_search + call s:off_screen_search(re) + endif + elseif s:search.line.length() >= s:num_strokes + call s:search.exit() + endif +endfunction "}}} +function! s:search.on_cancel() "{{{ + call s:Cancell() + call s:search.setline('') +endfunction "}}} +"}}} " Main: function! EasyMotion#command_line#GetInput(num_strokes, prev, direction) "{{{ - call s:doautocmd_user("EasyMotionCmdLineEnter") - let previous_input = a:prev - let s:save_direction = a:direction == 1 ? 'b' : '' - let s:direction = s:save_direction + let s:num_strokes = a:num_strokes - " CommandLine: Input string and cursor position - let s:command_line = s:string_with_pos('') - let prompt = s:getPromptMessage(a:num_strokes) + let s:search.prompt = s:getPromptMessage(a:num_strokes) " Screen: cursor position, first and last line let s:orig_pos = getpos('.') @@ -133,305 +132,22 @@ function! EasyMotion#command_line#GetInput(num_strokes, prev, direction) "{{{ let s:orig_line_end = getpos('w$') let s:save_orig_pos = deepcopy(s:orig_pos) - call s:before_input(a:num_strokes) + " Direction: + let s:direction = a:direction == 1 ? 'b' : '' + let s:save_direction = deepcopy(s:direction) - let s:search_hist = [] - let s:search_cnt = 0 - - try - while s:command_line.length() < a:num_strokes || - \ a:num_strokes == -1 - if g:EasyMotion_show_prompt - call s:echo_cmdline(prompt, s:command_line) - endif - - let c = getchar() - let s:char = type(c) == type(0) ? nr2char(c) : c - - if EasyMotion#command_line#is_input("\") || - \ EasyMotion#command_line#is_input("\") - " Cancel if Escape key pressed - call s:Cancell() - call s:command_line.set('') - break - elseif EasyMotion#command_line#is_input("\") - if s:command_line.length() == 0 - call s:command_line.set(previous_input) - break - endif - break - elseif EasyMotion#command_line#is_input("\") - break - elseif EasyMotion#command_line#is_input("\") - " Delete one character - if s:command_line.length() == 0 - call s:Cancell() | break - endif - call s:command_line.remove_prev() - elseif EasyMotion#command_line#is_input("\") - " Delete one character - if s:command_line.length() == 0 - call s:Cancell() | break - endif - call s:command_line.remove_pos() - elseif EasyMotion#command_line#is_input("\") - " Delete all - if s:command_line.length() == 0 - call s:Cancell() | break - endif - call s:command_line.set(s:command_line.pos_word() . - \ s:command_line.forward()) "string - call s:command_line.set(0) " cursor - elseif EasyMotion#command_line#is_input("\") - " Delete word - let backward = matchstr(s:command_line.backward(), - \ '\v^\zs.\{-}\ze((\w*)|(.))$') - call s:command_line.set(backward . s:command_line.pos_word() . s:command_line.forward()) - call s:command_line.set(strchars(backward)) - elseif EasyMotion#command_line#is_input("\") || - \ EasyMotion#command_line#is_input("\") - " History - if s:search_cnt == 0 && empty(s:search_hist) - let cmdline = '^' . EasyMotion#command_line#getline() - let s:search_hist = filter(s:search_histories(), 'v:val =~ cmdline') - endif - if EasyMotion#command_line#is_input("\") - let s:search_cnt = max([s:search_cnt - 1, 0]) - endif - if EasyMotion#command_line#is_input("\") - let s:search_cnt = min([s:search_cnt + 1, len(s:search_hist)]) - endif - call EasyMotion#command_line#setline( - \ get(s:search_hist, s:search_cnt, - \ EasyMotion#command_line#getline())) - elseif EasyMotion#command_line#is_input("\") - call s:scroll(0) - elseif EasyMotion#command_line#is_input("\") - call s:scroll(1) - elseif EasyMotion#command_line#is_input("\") - keepjumps call setpos('.', s:save_orig_pos) - let s:orig_pos = s:save_orig_pos - let s:orig_line_start = getpos('w0') - let s:orig_line_end = getpos('w$') - let s:direction = s:save_direction - elseif EasyMotion#command_line#is_input("\") - " TODO: better solution - normal! zR - elseif EasyMotion#command_line#is_input("\") - call s:command_line.next() - elseif EasyMotion#command_line#is_input("\") - call s:command_line.prev() - elseif EasyMotion#command_line#is_input("\") - call s:command_line.set(0) - elseif EasyMotion#command_line#is_input("\") - call s:command_line.set(s:command_line.length()) - elseif char2nr(s:char) == 128 || char2nr(s:char) < 27 - " Do nothing for special key - continue - else - call s:command_line.input(s:char) - endif - - " Incremental routine {{{ - if a:num_strokes == -1 - let re = s:command_line.str() - let case_flag = EasyMotion#helper#should_use_smartcase(re) ? - \ '\c' : '\C' - let re .= case_flag - if g:EasyMotion_inc_highlight "{{{ - call s:inc_highlight(re) - endif "}}} - if g:EasyMotion_off_screen_search "{{{ - call s:off_screen_search(re) - endif "}}} - endif - "}}} - endwhile - finally - call s:after_input() - call s:doautocmd_user("EasyMotionCmdLineLeave") - endtry - return s:command_line.str() -endfunction "}}} -function! EasyMotion#command_line#char() "{{{ - return s:char -endfunction "}}} -function! EasyMotion#command_line#is_input(key) "{{{ - return EasyMotion#command_line#keymap(EasyMotion#command_line#char()) == a:key -endfunction "}}} -function! EasyMotion#command_line#keymap(key) "{{{ - return get(extend(deepcopy(s:default_key_mapping), g:EasyMotion_command_line_key_mappings), a:key, a:key) -endfunction "}}} -" Default_key_mapping: {{{ -let s:default_key_mapping = { -\ "\" : "\", -\ "\" : "\", -\ "\" : "\", -\ "\" : "\", -\ "\" : "\", -\ "\" : "\", -\ "\" : "\", -\ "\" : "\", -\} -"}}} - -" CommandLine: -function! s:echo_cmdline(prompt, pstr) "{{{ - " pstr -> cursor pos & string - redraw - echohl Question | echon a:prompt | echohl NONE - echon a:pstr.backward() - - echohl EasyMotionCommandLineCursor - if empty(a:pstr.pos_word()) - echon ' ' + let input = s:search.get() + if input == '' && ! s:search.exit_code() + return a:prev else - echon a:pstr.pos_word() + return input endif - echohl NONE - - echon a:pstr.forward() -endfunction "}}} -function! s:string_with_pos(...) "{{{ - " string with cursor position - " emulate cursor using list - - let default = get(a:, 1, '') " placeholder - let self = {} " OOP - - " NOTE: {{{ - " 'V!m!s{cursor}hment' - " self.list = ['V', '!', 'm', '!', 's', 'h', 'm', 'e', 'n', 't'] - " 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 - " self.col = 5 -> cursor - " self.length() = 10 - " self.backward() = 'V!m!s' - " self.pos_word() = 'h' - " self.forward() = 'ment' - " self.str() = 'V!m!s{cursor}hment' - "}}} - - " Set: {{{ - function! self.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! self.set_str(str) - " set string - let self.list = split(a:str, '\zs') - let self.col = EasyMotion#helper#strchars(a:str) - return self - endfunction - - function! self.set_pos(pos) - " set cursor position - let self.col = s:clamp(a:pos, 0, self.length()) - return self - endfunction - "}}} - - " Get Input: {{{ - function! self.str() - " to string - return join(self.list, '') - endfunction - - function! self.backward() - " get string backward from cursor pos - return self.col > 0 ? join(self.list[ : self.col-1], '') : '' - endfunction - - function! self.forward() - " get string forward from cursor pos - return join(self.list[self.col+1 : ], '') - endfunction - - function! self.pos_word() - " get cursor position character (word) - return get(self.list, self.col, '') - endfunction - "}}} - - " Input: {{{ - function! self.input(str) - call extend(self.list, split(a:str, '\zs'), self.col) - let self.col += len(split(a:str, '\zs')) - return self - endfunction - "}}} - - " Move Cursor: {{{ - function! self.next() - return self.set_pos(self.col + 1) - endfunction - - function! self.prev() - return self.set_pos(self.col - 1) - endfunction - "}}} - - " Remove: {{{ - function! self.remove(index) - " Remove character - if a:index < 0 || self.length() <= a:index - return self - endif - unlet self.list[a:index] - if a:index < self.col - call self.set(self.col - 1) - endif - return self - endfunction - - function! self.remove_pos() - return self.remove(self.col) - endfunction - - function! self.remove_prev() - return self.remove(self.col - 1) - endfunction - - function! self.remove_next() - return self.remove(self.col + 1) - endfunction - "}}} - - " Helper: {{{ - function! self.pos() - " describe cursor position as column number - return self.col - endfunction - - function! self.length() - return len(self.list) - endfunction - "}}} - - call self.set(default) - return self -endfunction "}}} -function! s:clamp(value, min, max) "{{{ - return min([max([a:value, a:min]), a:max]) -endfunction "}}} -function! EasyMotion#command_line#getline() "{{{ - return s:command_line.str() -endfunction "}}} -function! EasyMotion#command_line#setline(line) "{{{ - call s:command_line.set(a:line) endfunction "}}} " Helper: -function! s:InputPrompt(message, input) "{{{ - redraw - echohl Question | echon a:message | echohl None - echon a:input -endfunction "}}} function! s:Cancell() " {{{ - call s:after_input() + call EasyMotion#highlight#delete_highlight() keepjumps call setpos('.', s:save_orig_pos) - redraw echo 'EasyMotion: Cancelled' return '' endfunction " }}} @@ -455,6 +171,7 @@ endfunction "}}} function! s:off_screen_search(re) "{{{ " First: search within visible screen range call s:adjust_screen() + " Error occur when '\zs' without '!' silent! let pos = searchpos(a:re, s:direction . 'n', s:orig_line_end[1]) if pos != [0, 0] " Restore cursor posision @@ -497,18 +214,14 @@ function! s:scroll(direction) "{{{ let s:orig_line_end = getpos('w$') let s:direction = a:direction == 0 ? '' : 'b' endfunction "}}} -function! s:search_histories() "{{{ - return map(range(&history), 'histget("search", v:val * -1)') -endfunction "}}} function! s:inc_highlight(re) "{{{ - call EasyMotion#highlight#delete_highlight('EasyMotionIncSearch') - if s:command_line.length() > 0 + call EasyMotion#highlight#delete_highlight(g:EasyMotion_hl_inc_search) + if s:search.line.length() > 0 + " Error occur when '\zs' without '!' silent! call EasyMotion#highlight#add_highlight(a:re, g:EasyMotion_hl_inc_search) endif endfunction "}}} - - " Restore 'cpoptions' {{{ let &cpo = s:save_cpo unlet s:save_cpo diff --git a/autoload/vital/_easymotion/Over/Commandline.vim b/autoload/vital/_easymotion/Over/Commandline.vim index a66ccb6..d2ec86f 100644 --- a/autoload/vital/_easymotion/Over/Commandline.vim +++ b/autoload/vital/_easymotion/Over/Commandline.vim @@ -12,6 +12,9 @@ let s:modules = [ \ "History", \ "Incsearch", \ "BufferComplete", +\ "Cancel", +\ "Enter", +\ "NoInsert", \] let s:modules_snake = [ @@ -23,6 +26,9 @@ let s:modules_snake = [ \ "history", \ "incsearch", \ "buffer_complete", +\ "cancel", +\ "enter", +\ "no_insert", \] @@ -39,6 +45,32 @@ function! s:_vital_depends() endfunction +function! s:make_plain(prompt) + let result = deepcopy(s:base) + let result.prompt = a:prompt + call result.connect(s:module_cancel()) + call result.connect(s:module_enter()) + return result +endfunction + + +function! s:make_simple(prompt) + let result = s:make_plain(a:prompt) + call result.connect(s:module_scroll()) + call result.connect(s:module_delete()) + call result.connect(s:module_cursor_move()) + call result.connect(s:module_histadd()) + call result.connect(s:module_history()) + call result.connect(s:module_buffer_complete()) + call result.connect(s:module_no_insert_special_chars()) + return result +endfunction + + +function! s:make(prompt) + return s:make_simple(a:prompt) +endfunction + let s:base = { \ "prompt" : "> ", @@ -47,10 +79,12 @@ let s:base = { \ "char" : "", \ "input" : "", \ "wait_key" : "", +\ "exit" : 0, \ }, \ "highlights" : { -\ "Cursor" : "OverCommandLineDefaultCursor", -\ "CursorInsert" : "OverCommandLineDefaultCursorInsert" +\ "prompt" : "NONE", +\ "cursor" : "OverCommandLineDefaultCursor", +\ "cursor_insert" : "OverCommandLineDefaultCursorInsert" \ }, \ "modules" : {}, \ "keys" : { @@ -131,12 +165,18 @@ function! s:base.backward() endfunction -function! s:base.connect(module) - let self.modules[a:module.name] = a:module +function! s:base.connect(module, ...) + let name = get(a:, 1, a:module.name) + let self.modules[name] = a:module endfunction -for s:_ in ["enter", "leave", "char", "charpre", "executepre", "execute", "cancel"] +function! s:base.disconnect(name) + unlet self.modules[a:name] = a:module +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.modules), 'has_key(v:val, \"on_" . s:_ . "\") ? v:val.on_" . s:_ . "(self) : 0')", @@ -145,7 +185,6 @@ for s:_ in ["enter", "leave", "char", "charpre", "executepre", "execute", "cance \ ], "\n") execute "function! s:base.on_" . s:_ . "()" - endfunction endfor unlet s:_ @@ -157,94 +196,41 @@ function! s:base.keymappings() endfunction -function! s:make(prompt) - let result = deepcopy(s:base) - let result.prompt = a:prompt - return result -endfunction - - -function! s:make_simple(prompt) - let result = s:make(a:prompt) - call result.connect(s:module_scroll()) - call result.connect(s:module_delete()) - call result.connect(s:module_cursor_move()) - call result.connect(s:module_histadd()) - call result.connect(s:module_history()) - call result.connect(s:module_buffer_complete()) - return result -endfunction - - -function! s:_echo_cmdline(cmdline) - redraw - echon a:cmdline.prompt . a:cmdline.backward() - if empty(a:cmdline.line.pos_word()) - execute "echohl" a:cmdline.highlights.Cursor - echon ' ' - else - execute "echohl" a:cmdline.highlights.CursorInsert - echon a:cmdline.line.pos_word() - endif - echohl NONE - echon a:cmdline.forward() -endfunction - - function! s:base.execute() execute self.getline() endfunction function! s:base.exit(...) - let self.variables.exit = get(a:, 1, 0) + let self.variables.exit = 1 + let self.variables.exit_code = get(a:, 1, 0) endfunction -function! s:base.is_exit() - return has_key(self.variables, "exit") +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.start(...) - let result = call(self.get, a:000, self) - if result == "" - return + let exit_code = call(self._main, a:000, self) + if exit_code == 0 + call self._execute() endif - call self._execute() endfunction function! s:base.get(...) - try - call self._init() - let self.line = deepcopy(s:_string_with_pos(get(a:, 1, ""))) - call self._on_enter() - call self._inputkey() - - while !self.is_input(self.keys.quit) - if self.is_input(self.keys.enter) - return self.getline() - else - call self.insert(self.variables.input) - endif - call self._on_char() - - if self.is_exit() - call s:_redraw() - return "" - endif - - call self._inputkey() - endwhile - call self._on_cancel() - call s:_redraw() - catch - echohl ErrorMsg | echo v:throwpoint . " " . v:exception | echohl None - finally - call self._finish() - call self._on_leave() - endtry + let exit_code = call(self._main, a:000, self) + if exit_code == 0 + return self.getline() + endif return "" endfunction @@ -253,6 +239,8 @@ function! s:base._init() let self.variables.wait_key = "" let self.variables.char = "" let self.variables.input = "" + let self.variables.exit = 0 + let self.variables.exit_code = 1 let hl_cursor = s:_hl_cursor_off() if !hlexists("OverCommandLineDefaultCursor") execute "highlight OverCommandLineDefaultCursor " . hl_cursor @@ -266,30 +254,74 @@ endfunction function! s:base._execute() - call self._on_executepre() + call s:_redraw() + call self._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() finally call self._on_execute() endtry endfunction +function! s:base._main(...) + try + call self._init() + let self.line = deepcopy(s:_string_with_pos(get(a:, 1, ""))) + call self._on_enter() + + while !self._is_exit() + call s:_echo_cmdline(self) + + let self.variables.char = s:_getchar() + call self.setchar(self.variables.char) + + call self._on_char_pre() + call self.insert(self.variables.input) + call self._on_char() + endwhile + catch + echohl ErrorMsg | echo v:throwpoint . " " . v:exception | echohl None + finally + call self._finish() + call self._on_leave() + call s:_redraw() + endtry + return self.exit_code() +endfunction + + function! s:base._finish() cal s:_hl_cursor_on() let &t_ve = s:old_t_ve endfunction -function! s:base._inputkey() - call s:_echo_cmdline(self) - let self.variables.char = s:_getchar() - call self.setchar(self.variables.char) - call self._on_charpre() +function! s:_echo_cmdline(cmdline) + call s:_redraw() + execute "echohl" a:cmdline.highlights.prompt + echon a:cmdline.prompt + echohl NONE + echon a:cmdline.backward() + if empty(a:cmdline.line.pos_word()) + execute "echohl" a:cmdline.highlights.cursor + echon ' ' + else + execute "echohl" a:cmdline.highlights.cursor_insert + echon a:cmdline.line.pos_word() + endif + echohl NONE + echon a:cmdline.forward() +endfunction + + +function! s:base._is_exit() + return self.variables.exit endfunction @@ -303,8 +335,9 @@ for s:i in range(len(s:modules_snake)) endfor unlet s:i - - +function! s:module_no_insert_special_chars() + return s:NoInsert.make_special_chars() +endfunction function! s:_redraw() @@ -333,9 +366,15 @@ function! s:_hl_cursor_off() endif let s:old_hi_cursor = "cterm=reverse" if hlexists("Cursor") - redir => cursor - silent highlight Cursor - redir END + let save_verbose = &verbose + let &verbose = 0 + try + redir => cursor + silent highlight Cursor + redir END + finally + let &verbose = save_verbose + endtry let hl = substitute(matchstr(cursor, 'xxx \zs.*'), '[ \t\n]\+\|cleared', ' ', 'g') if !empty(substitute(hl, '\s', '', 'g')) let s:old_hi_cursor = hl diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/BufferComplete.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/BufferComplete.vim index e8f251b..249d660 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/BufferComplete.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/BufferComplete.vim @@ -97,8 +97,8 @@ function! s:_finish() endfunction -function! s:module.on_charpre(cmdline) - if a:cmdline.is_input("\") +function! s:module.on_char_pre(cmdline) + if a:cmdline.is_input("(buffer-complete)") if self.complete(a:cmdline) == -1 call s:_finish() call a:cmdline.setchar('') @@ -106,14 +106,14 @@ function! s:module.on_charpre(cmdline) endif call a:cmdline.setchar('') call a:cmdline.wait_keyinput_on("Completion") - elseif a:cmdline.is_input("\", "Completion") -\ || a:cmdline.is_input("\", "Completion") + elseif a:cmdline.is_input("(buffer-complete)", "Completion") +\ || a:cmdline.is_input("\", "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("\", "Completion") + elseif a:cmdline.is_input("\", "Completion") call a:cmdline.setchar('') let s:count -= 1 if s:count < 0 @@ -121,7 +121,7 @@ function! s:module.on_charpre(cmdline) endif else if a:cmdline.wait_keyinput_off("Completion") - call a:cmdline._on_charpre() + call a:cmdline._on_char_pre() endif call s:_finish() return diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/Cancel.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/Cancel.vim new file mode 100644 index 0000000..7961efc --- /dev/null +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/Cancel.vim @@ -0,0 +1,26 @@ +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("\") +\ || a:cmdline.is_input("\") +\ ||(a:cmdline.is_input("\") && a:cmdline.line.length() == 0) +\ ||(a:cmdline.is_input("\") && a:cmdline.line.length() == 0) + call a:cmdline.cancel() + call a:cmdline.setchar("") + endif +endfunction + + +function! s:make() + return deepcopy(s:module) +endfunction + + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/CursorMove.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/CursorMove.vim index da20f80..c3a02e8 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/CursorMove.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/CursorMove.vim @@ -6,20 +6,19 @@ set cpo&vim let s:module = { \ "name" : "CursorMove" \} -function! s:module.on_charpre(cmdline) - if a:cmdline.is_input("\") +function! s:module.on_char_pre(cmdline) + if a:cmdline.is_input("\") call a:cmdline.line.next() call a:cmdline.setchar('') - elseif a:cmdline.is_input("\") + elseif a:cmdline.is_input("\") call a:cmdline.line.prev() call a:cmdline.setchar('') - elseif a:cmdline.is_input("\") - call a:cmdline.line.remove_pos() - call a:cmdline.setchar('') - elseif a:cmdline.is_input("\") + elseif a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") call a:cmdline.setline(0) call a:cmdline.setchar('') elseif a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") call a:cmdline.setline(a:cmdline.line.length()) call a:cmdline.setchar('') endif diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/Delete.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/Delete.vim index 8a72014..b7b6053 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/Delete.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/Delete.vim @@ -6,13 +6,14 @@ set cpo&vim let s:module = { \ "name" : "Delete", \} -function! s:module.on_charpre(cmdline) +function! s:module.on_char_pre(cmdline) if a:cmdline.is_input("\") - if a:cmdline.line.length() == 0 - call a:cmdline.exit() - endif +\ || a:cmdline.is_input("\") call a:cmdline.line.remove_prev() call a:cmdline.setchar('') + elseif a:cmdline.is_input("\") + call a:cmdline.line.remove_pos() + call a:cmdline.setchar('') elseif a:cmdline.is_input("\") let backward = matchstr(a:cmdline.backward(), '^\zs.\{-}\ze\(\(\w*\)\|\(.\)\)$') call a:cmdline.setline(backward . a:cmdline.line.pos_word() . a:cmdline.forward()) diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/Enter.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/Enter.vim new file mode 100644 index 0000000..3a9423c --- /dev/null +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/Enter.vim @@ -0,0 +1,25 @@ +scriptencoding utf-8 +let s:save_cpo = &cpo +set cpo&vim + +let s:module = { +\ "name" : "Enter" +\} + +function! s:module.on_char_pre(cmdline) + if a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") + call a:cmdline.exit(0) + call a:cmdline.setchar("") + endif +endfunction + + +function! s:make() + return deepcopy(s:module) +endfunction + + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/History.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/History.vim index f349918..06700dc 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/History.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/History.vim @@ -17,8 +17,8 @@ function! s:module.enter(...) let s:count = 0 endfunction -function! s:module.on_charpre(cmdline) - if !a:cmdline.is_input("\") && !a:cmdline.is_input("\") +function! s:module.on_char_pre(cmdline) + if !a:cmdline.is_input("\") && !a:cmdline.is_input("\") let s:cmdhist = [] let s:count = 0 return @@ -29,10 +29,10 @@ function! s:module.on_charpre(cmdline) endif endif call a:cmdline.setchar("") - if a:cmdline.is_input("\") + if a:cmdline.is_input("\") let s:count = max([s:count - 1, 0]) endif - if a:cmdline.is_input("\") + if a:cmdline.is_input("\") let s:count = min([s:count + 1, len(s:cmdhist)]) endif call a:cmdline.setline(get(s:cmdhist, s:count, a:cmdline.getline())) diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/NoInsert.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/NoInsert.vim new file mode 100644 index 0000000..9196b76 --- /dev/null +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/NoInsert.vim @@ -0,0 +1,40 @@ +scriptencoding utf-8 +let s:save_cpo = &cpo +set cpo&vim + +let s:module = { +\ "name" : "NoInsert", +\ "chars" : [] +\} + + +function! s:module.is_insert(char) + return index(self.chars, a:char) >= 0 +endfunction + + +function! s:module.on_char_pre(cmdline) + if self.is_insert(a:cmdline.char()) + call a:cmdline.setchar("") + 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_insert(char) + return char2nr(a:char) == 128 || char2nr(a:char) < 27 + endfunction + return module +endfunction + + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/Paste.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/Paste.vim index 0c129ab..c0d4dd0 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/Paste.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/Paste.vim @@ -6,8 +6,9 @@ set cpo&vim let s:module = { \ "name" : "Paste" \} -function! s:module.on_charpre(cmdline) - if a:cmdline.is_input("\") + +function! s:module.on_char_pre(cmdline) + if a:cmdline.is_input("(paste)") call a:cmdline.insert(@*) call a:cmdline.setchar('') endif diff --git a/autoload/vital/_easymotion/Over/Commandline/Modules/Scroll.vim b/autoload/vital/_easymotion/Over/Commandline/Modules/Scroll.vim index 6e6b0fc..d875168 100644 --- a/autoload/vital/_easymotion/Over/Commandline/Modules/Scroll.vim +++ b/autoload/vital/_easymotion/Over/Commandline/Modules/Scroll.vim @@ -6,23 +6,23 @@ set cpo&vim let s:module = { \ "name" : "Scroll" \} -function! s:module.on_charpre(cmdline) - if a:cmdline.is_input("\(over-cmdline-scroll-y)") +function! s:module.on_char_pre(cmdline) + if a:cmdline.is_input("(scroll-y)") execute "normal! \" call a:cmdline.setchar('') - elseif a:cmdline.is_input("\(over-cmdline-scroll-u)") + elseif a:cmdline.is_input("(scroll-u)") execute "normal! \" call a:cmdline.setchar('') - elseif a:cmdline.is_input("\(over-cmdline-scroll-f)") + elseif a:cmdline.is_input("(scroll-f)") execute "normal! \" call a:cmdline.setchar('') - elseif a:cmdline.is_input("\(over-cmdline-scroll-e)") + elseif a:cmdline.is_input("(scroll-e)") execute "normal! \" call a:cmdline.setchar('') - elseif a:cmdline.is_input("\(over-cmdline-scroll-d)") + elseif a:cmdline.is_input("(scroll-d)") execute "normal! \" call a:cmdline.setchar('') - elseif a:cmdline.is_input("\(over-cmdline-scroll-b)") + elseif a:cmdline.is_input("(scroll-b)") execute "normal! \" call a:cmdline.setchar('') endif diff --git a/autoload/vital/easymotion.vital b/autoload/vital/easymotion.vital index 7a80ed3..5361449 100644 --- a/autoload/vital/easymotion.vital +++ b/autoload/vital/easymotion.vital @@ -1,4 +1,4 @@ easymotion -8c1ba73 +2b8ba7f Over.Commandline diff --git a/doc/easymotion.txt b/doc/easymotion.txt index e26cc95..5ebfd42 100644 --- a/doc/easymotion.txt +++ b/doc/easymotion.txt @@ -1,4 +1,4 @@ -*easymotion.txt* Version 2.0 Last change:26 Jan 2014. +*easymotion.txt* Version 2.0 Last change:02 Feb 2014. ______ __ ___ __ _ @@ -501,7 +501,67 @@ All Find motion (s,f,F,t,T,sl,fl,Fl,tl,Tl) support this feature! *(easymotion-sl2)* *(easymotion-fl2)* *(easymotion-Fl2)* *(easymotion-tl2)* *(easymotion-Tl2)* *(easymotion-bd-tl2)* -But |EasyMotion| is good at simple and fast motion with one or two character. +Find Motion Command Line~ + *easymotion-command-line* + EasyMotion has own command line for find motions, especially for 'n' key + motion(e.g. |(easymotoin-sn)|). This command line is inspired by + over.vim and actually uses the library of over.vim command line. + over.vim can be downloaded here: + + https://github.com/osyo-manga/vim-over + + Note: These settings are experimental. They could be changed in the near + future. + + Default Command Line Mappings~ + Most default mappings work same as default command line mapping of Vim. + See |cmdline.txt| + + Key Mappings | Details + ----------------------- |---------------------------------------------- + | Execute EasyMotion. + or | Cancel + | Cursor right + | Cursor left + or | cursor to beginning of command-line + or | cursor to end of command-line + or | Delete one character + | Delete the word before the cursor + | Delete all entered characters before the cursor + | Recall older (previous) search from history + | Recall more recent (next) search from history + ------------------------|--------------------------------------- + (paste) | Paste yanked text to the command line + | Default: + (buffer-complete) | Completion of buffer text Default: + *(em-scroll-f)* | Scroll window forward & jump to the next match + | Default: + *(em-scroll-b)* | Scroll window backward & jump to previous match + | Default: + *(em-jumpback)* | Jump back original cursor position like + | Default: + *(em-openallfold)* | Open all fold + | Default: + + Customize Command Line Mappings~ + *EMCommandLineNoremap* + + You can use |EMCommandLineNoremap| to customize find motion command line + key mappings by vimrc. This mapping is always no recursive mapping, so + you should map to not but (em-scroll-f). + + Example: +> + " EM is short for EasyMotion + EMCommandLineNoremap + EMCommandLineNoremap + EMCommandLineNoremap + EMCommandLineNoremap + EMCommandLineNoremap (buffer-complete) +< + Note(again): These settings, especially about keymappings are + __EXPERIMENTAL__. They could be changed in the near future. However, it + works well and so useful, so I release it. ------------------------------------------------------------------------------ 2.3 Special mappings *easymotion-special-mappings* diff --git a/plugin/EasyMotion.vim b/plugin/EasyMotion.vim index 98dc256..88dc03b 100644 --- a/plugin/EasyMotion.vim +++ b/plugin/EasyMotion.vim @@ -416,6 +416,21 @@ if g:EasyMotion_do_mapping == 1 || g:EasyMotion_do_special_mapping == 1 " }}} endif "}}} +" == CommandLine Mapping {{{ +function! s:key_mapping(lhs, rhs) + let g:EasyMotion_command_line_key_mappings[a:lhs] = a:rhs +endfunction + +function! s:as_keymapping(key) + execute 'let result = "' . substitute(a:key, '\(<.\{-}>\)', '\\\1', 'g') . '"' + return result +endfunction + +command! -nargs=* +\ EMCommandLineNoremap +\ call call("s:key_mapping", map([], "s:as_keymapping(v:val)")) +"}}} + " == Restore 'cpoptions' {{{ let &cpo = s:save_cpo unlet s:save_cpo