diff --git a/autoload/EasyMotion.vim b/autoload/EasyMotion.vim index 53ef1a7..4fffa70 100644 --- a/autoload/EasyMotion.vim +++ b/autoload/EasyMotion.vim @@ -16,6 +16,7 @@ function! EasyMotion#init() let s:previous = {} let s:dot_repeat = {} let s:migemo_dicts = {} + let s:EasyMotion_is_active = 0 call EasyMotion#reset() " Anywhere regular expression: {{{ let re = '\v' . @@ -340,10 +341,22 @@ function! EasyMotion#NextPrevious(visualmode, direction) " {{{ let re = s:previous.regexp let search_direction = (a:direction >= 1 ? 'b' : '') + if g:EasyMotion_move_highlight + call EasyMotion#highlight#attach_autocmd() + call EasyMotion#highlight#add_highlight(re,'EasyMotionMoveHL') + endif + + if ! empty(a:visualmode) + " FIXME: blink highlight + silent exec 'normal! gv' + endif for i in range(v:count1) call searchpos(re, search_direction) endfor call EasyMotion#reset() + " -- Activate EasyMotion ----------------- {{{ + let s:EasyMotion_is_active = 1 + call EasyMotion#attach_active_autocmd() "}}} endfunction " }}} " }}} " Helper Functions: {{{ @@ -460,7 +473,7 @@ function! s:findMotion(num_strokes) "{{{ " Check that we have an input char if empty(input) - redraw | echo '' | return '' + redraw | return '' endif let re = s:convertRegep(input) @@ -939,13 +952,19 @@ function! s:PromptUser(groups, allows_repeat, fixed_column) "{{{ " }}} " -- Highlight targets ------------------- {{{ if len(hl_coords) > 0 - let target_hl_id = matchadd(g:EasyMotion_hl_group_target, join(hl_coords, '\|'), 1) + call EasyMotion#highlight#add_highlight( + \ join(hl_coords, '\|'), + \ g:EasyMotion_hl_group_target) endif if len(hl2_second_coords) > 0 - let target_hl2_second_id = matchadd(g:EasyMotion_hl2_second_group_target, join(hl2_second_coords, '\|'), 1) + call EasyMotion#highlight#add_highlight( + \ join(hl2_second_coords, '\|'), + \ g:EasyMotion_hl2_second_group_target) endif if len(hl2_first_coords) > 0 - let target_hl2_first_id = matchadd(g:EasyMotion_hl2_first_group_target, join(hl2_first_coords, '\|'), 1) + call EasyMotion#highlight#add_highlight( + \ join(hl2_first_coords, '\|'), + \ g:EasyMotion_hl2_first_group_target) endif " }}} @@ -993,15 +1012,11 @@ function! s:PromptUser(groups, allows_repeat, fixed_column) "{{{ call s:SetLines(lines_items, 'orig') " Un-highlight targets {{{ - if exists('target_hl_id') - call matchdelete(target_hl_id) - endif - if exists('target_hl2_first_id') - call matchdelete(target_hl2_first_id) - endif - if exists('target_hl2_second_id') - call matchdelete(target_hl2_second_id) - endif + call EasyMotion#highlight#delete_highlight( + \ g:EasyMotion_hl_group_target, + \ g:EasyMotion_hl2_first_group_target, + \ g:EasyMotion_hl2_second_group_target, + \ ) " }}} " Restore undo tree {{{ @@ -1242,17 +1257,23 @@ function! s:EasyMotion(regexp, direction, visualmode, is_exclusive, ...) " {{{ let shade_hl_re = shade_hl_pos . '\_.*\%'. win_last_line .'l' elseif a:direction == 2 " Both directions" - let shade_hl_re = '\%'. win_first_line .'l\_.*\%'. win_last_line .'l' + let shade_hl_re = '.*' endif if !fixed_column - let shade_hl_id = matchadd(g:EasyMotion_hl_group_shade, shade_hl_re, 0) + call EasyMotion#highlight#add_highlight( + \ shade_hl_re, + \ g:EasyMotion_hl_group_shade) endif endif if hlcurrent != 0 - let shade_hl_line_id = matchadd(g:EasyMotion_hl_line_group_shade, '\%'. hlcurrent .'l.*', 1) + call EasyMotion#highlight#add_highlight( + \ '\%'. hlcurrent .'l.*', + \ g:EasyMotion_hl_line_group_shade) endif if !empty(hlchar) - let shade_hl_line_id = matchadd(g:EasyMotion_hl_line_group_shade, '\%'. hlchar[0] .'l\%' . hlchar[1] .'c' , 2) + call EasyMotion#highlight#add_highlight( + \ '\%'. hlchar[0] .'l\%' . hlchar[1] .'c', + \ g:EasyMotion_hl_line_group_shade) endif " }}} @@ -1376,15 +1397,35 @@ function! s:EasyMotion(regexp, direction, visualmode, is_exclusive, ...) " {{{ call EasyMotion#reset() " }}} " -- Remove shading ---------------------- {{{ - if g:EasyMotion_do_shade && exists('shade_hl_id') && (!fixed_column) - call matchdelete(shade_hl_id) - endif - if (hlcurrent || !empty(hlchar)) && exists('shade_hl_line_id') - call matchdelete(shade_hl_line_id) - endif + call EasyMotion#highlight#delete_highlight() " }}} + + " -- Landing Highlight ------------------- {{{ + if g:EasyMotion_landing_highlight + call EasyMotion#highlight#add_highlight(a:regexp, 'EasyMotionMoveHL') + call EasyMotion#highlight#attach_autocmd() + endif "}}} + " -- Activate EasyMotion ----------------- {{{ + let s:EasyMotion_is_active = 1 + call EasyMotion#attach_active_autocmd() "}}} endtry endfunction " }}} +function! EasyMotion#attach_active_autocmd() "{{{ + " Reference: https://github.com/justinmk/vim-sneak + augroup plugin-easymotion-active + autocmd! + autocmd InsertEnter,WinLeave,BufLeave + \ let s:EasyMotion_is_active = 0 + \ | autocmd! plugin-easymotion-active * + autocmd CursorMoved + \ autocmd plugin-easymotion-active CursorMoved + \ let s:EasyMotion_is_active = 0 + \ | autocmd! plugin-easymotion-active * + augroup END +endfunction "}}} +function! EasyMotion#is_active() "{{{ + return s:EasyMotion_is_active +endfunction "}}} "}}} " Call Init: {{{ call EasyMotion#init() diff --git a/autoload/EasyMotion/command_line.vim b/autoload/EasyMotion/command_line.vim index 791c089..0243dda 100644 --- a/autoload/EasyMotion/command_line.vim +++ b/autoload/EasyMotion/command_line.vim @@ -1,7 +1,8 @@ "============================================================================= " FILE: autoload/EasyMotion/command_line.vim " AUTHOR: haya14busa -" Last Change: 17 Jan 2014. +" Reference: https://github.com/osyo-manga/vim-over +" Last Change: 20 Jan 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 @@ -35,12 +36,13 @@ function! s:InputPrompt(message, input) "{{{ echon a:input endfunction "}}} function! s:Cancell() " {{{ + call EasyMotion#highlight#delete_highlight() redraw echo 'EasyMotion: Cancelled' return '' endfunction " }}} -function! s:getPromptMessage(num_strokes) +function! s:getPromptMessage(num_strokes) "{{{ if a:num_strokes == 1 let prompt = substitute( \ substitute(g:EasyMotion_prompt,'{n}', a:num_strokes, 'g'), @@ -55,13 +57,33 @@ function! s:getPromptMessage(num_strokes) \ '(s)', 's', 'g') endif return prompt -endfunction - +endfunction "}}} +function! s:before_input(num_strokes) "{{{ + if a:num_strokes == -1 && g:EasyMotion_inc_highlight + call EasyMotion#highlight#delete_highlight() + let shade_hl_re = '.*' + call EasyMotion#highlight#add_highlight(shade_hl_re, g:EasyMotion_hl_group_shade) + let cursor_hl_re = '\%'. line('.') .'l\%'. col('.') .'c' + call EasyMotion#highlight#add_highlight(cursor_hl_re, g:EasyMotion_hl_inc_cursor) + endif +endfunction "}}} +function! s:after_input(num_strokes) "{{{ + call EasyMotion#highlight#delete_highlight() +endfunction "}}} +function! s:should_use_smartcase(input) "{{{ + if g:EasyMotion_smartcase == 0 + return 0 + endif + " return 1 if input didn't match upporcase letter + return match(a:input, '\u') == -1 +endfunction "}}} function! EasyMotion#command_line#GetInput(num_strokes, ...) "{{{ let previous_input = a:0 == 1 ? a:1 : '' let input = '' let prompt = s:getPromptMessage(a:num_strokes) + call s:before_input(a:num_strokes) + while EasyMotion#helper#strchars(input) < a:num_strokes || \ a:num_strokes == -1 if g:EasyMotion_show_prompt @@ -71,21 +93,27 @@ function! EasyMotion#command_line#GetInput(num_strokes, ...) "{{{ let s:char = type(c) == type(0) ? nr2char(c) : c if EasyMotion#command_line#is_input("\") " Cancel if Escape key pressed - call s:Cancell() | return '' + call s:Cancell() | let input = '' | break elseif EasyMotion#command_line#is_input("\") " Cancel - call s:Cancell() | return '' + call s:Cancell() | let input = '' | break elseif EasyMotion#command_line#is_input("\") " Delete one character - if len(input) == 0 | call s:Cancell() | return '' | endif + if len(input) == 0 + call s:Cancell() | let input = '' | break + endif let input = substitute(input, '.$', '', '') elseif EasyMotion#command_line#is_input("\") " Delete one character - if len(input) == 0 | call s:Cancell() | return '' | endif + if len(input) == 0 + call s:Cancell() | let input = '' | break + endif let input = substitute(input, '.$', '', '') elseif EasyMotion#command_line#is_input("\") " Delete all - if len(input) == 0 | call s:Cancell() | return '' | endif + if len(input) == 0 + call s:Cancell() | let input = '' | break + endif let input = '' elseif EasyMotion#command_line#is_input("\") " Delete word @@ -96,23 +124,30 @@ function! EasyMotion#command_line#GetInput(num_strokes, ...) "{{{ let input = '' elseif EasyMotion#command_line#is_input("\") if len(input) == 0 - return previous_input + let input = previous_input | break endif - " Return input charcters - return input + break elseif EasyMotion#command_line#is_input("\") - " Return input charcters - return input + break elseif char2nr(s:char) == 128 || char2nr(s:char) < 27 " Do nothing for special key continue else let input .= s:char endif + if g:EasyMotion_inc_highlight + call EasyMotion#highlight#delete_highlight('EasyMotionIncSearch') + if a:num_strokes == -1 && len(input) > 0 + let re = input + let case_flag = s:should_use_smartcase(input) ? '\c' : '\C' + let re .= case_flag + call EasyMotion#highlight#add_highlight(re, g:EasyMotion_hl_inc_search) + endif + endif endwhile + call s:after_input(a:num_strokes) return input endfunction "}}} - function! EasyMotion#command_line#char() "{{{ return s:char endfunction "}}} @@ -134,7 +169,7 @@ let s:default_key_mapping = { \ "\" : "\", \} "}}} -" + " Restore 'cpoptions' {{{ let &cpo = s:save_cpo unlet s:save_cpo diff --git a/autoload/EasyMotion/highlight.vim b/autoload/EasyMotion/highlight.vim new file mode 100644 index 0000000..f2984b4 --- /dev/null +++ b/autoload/EasyMotion/highlight.vim @@ -0,0 +1,83 @@ +"============================================================================= +" FILE: highlight.vim +" AUTHOR: haya14busa +" Reference: https://github.com/t9md/vim-smalls +" Last Change: 21 Jan 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 +" "Software"), to deal in the Software without restriction, including +" without limitation the rights to use, copy, modify, merge, publish, +" distribute, sublicense, and/or sell copies of the Software, and to +" permit persons to whom the Software is furnished to do so, subject to +" the following conditions: +" +" The above copyright notice and this permission notice shall be included +" in all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +" IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +" CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +" SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +" }}} +"============================================================================= +scriptencoding utf-8 +" Saving 'cpoptions' {{{ +let s:save_cpo = &cpo +set cpo&vim +" }}} + +" Init: {{{ +let s:h = {} +let s:h.ids = {} +let s:priorities = { + \ 'EasyMotionTarget' : 1, + \ 'EasyMotionTarget2First' : 1, + \ 'EasyMotionTarget2Second' : 1, + \ 'EasyMotionShade' : 0, + \ 'EasyMotionShadeLine' : 0, + \ 'EasyMotionIncSearch' : 1, + \ 'EasyMotionIncCursor' : 2, + \ 'EasyMotionMoveHL' : 0, + \ } +for group in keys(s:priorities) + let s:h.ids[group] = [] +endfor +"}}} + +function! EasyMotion#highlight#delete_highlight(...) "{{{ + let groups = !empty(a:000) ? a:000 : keys(s:priorities) + for group in groups + for id in s:h.ids[group] + silent! call matchdelete(id) + endfor + let s:h.ids[group] = [] + endfor +endfunction "}}} +function! EasyMotion#highlight#add_highlight(re, group) "{{{ + call add(s:h.ids[a:group], matchadd(a:group, a:re, s:priorities[a:group])) +endfunction "}}} +function! EasyMotion#highlight#attach_autocmd() "{{{ + " Reference: https://github.com/justinmk/vim-sneak + augroup plugin-easymotion + autocmd! + autocmd InsertEnter,WinLeave,BufLeave + \ silent! call EasyMotion#highlight#delete_highlight() + \ | autocmd! plugin-easymotion * + autocmd CursorMoved + \ autocmd plugin-easymotion CursorMoved + \ silent! call EasyMotion#highlight#delete_highlight() + \ | autocmd! plugin-easymotion * + augroup END +endfunction "}}} +" Restore 'cpoptions' {{{ +let &cpo = s:save_cpo +unlet s:save_cpo +" }}} +" __END__ {{{ +" vim: expandtab softtabstop=4 shiftwidth=4 +" vim: foldmethod=marker +" }}} diff --git a/doc/easymotion.txt b/doc/easymotion.txt index be42d49..d0e9148 100644 --- a/doc/easymotion.txt +++ b/doc/easymotion.txt @@ -1,4 +1,4 @@ -*easymotion.txt* Version 2.0 Last change:17 Jan 2014. +*easymotion.txt* Version 2.0 Last change:21 Jan 2014. ______ __ ___ __ _ @@ -37,6 +37,7 @@ CONTENTS *easymotion-contents* 4.11.2 Select Phrase ........... |easymotion-select-phrase| 4.12 EasyMotion_enter_jump_first ... |EasyMotion_enter_jump_first| 4.13 EasyMotion_prompt ............. |EasyMotion_prompt| + 4.14 EasyMotion_highlight .......... |EasyMotion_highlight| 5. License ............................ |easymotion-license| 6. Known bugs ......................... |easymotion-known-bugs| 7. Contributing ....................... |easymotion-contributing| @@ -255,16 +256,18 @@ Repeat ~ Last Find Motion~ In Find motion (e.g. |(easymoion-s)| ), to type `` without input characters invoke last find motion. This - does not repeat motion type (e.g. othrer word motion, + does not repeat motion type (e.g. Other word motion, (easymotion-j) etc...) but only repeat input characters. (easymotion-next) *(easymotion-next)* (easymotion-prev) *(easymotion-prev)* - Jump to next/previous much. Only this motion can be move to offscrren + Jump to next/previous much. Only this motion can be move to off-screen match. This motion wrap around the end of the file if you set - |'wrapscan'| in your vimrc. + |'wrapscan'| in your vimrc. During this motion, matched text is + highlighted. If you don't want to highlight them, set + |g:EasyMotion_move_highlight| option to 0. Example: > @@ -446,6 +449,10 @@ vim-sneak, |EasyMotion| also provide this feature. With above keymapping, You can use to delete while typing. + Note: 'n' key motion provide incremental highlighting feature. If you + don't want to highlight incrementally, set + |g:EasyMotion_inc_highlight| option to 0. + All Find motion (s,f,F,t,T,sl,fl,Fl,tl,Tl) support this feature! (|l| means within line motion) @@ -875,6 +882,39 @@ Default: |(easymotion-s2)| -> 'Search for 2 characters: ' |(easymotion-sn)| -> 'Search for characters: ' +4.14 Customize highlight behavior *EasyMotion_highlight* + + *g:EasyMotion_inc_highlight* + + While 'n' key find motion(e.g. |(easymotion-sn)|), EasyMotion + incrementally highlight matched text. If you don't want to this feature, + set this option to 0 +> + let g:EasyMotion_inc_highlight = 0 +< + Default: 1 + + *g:EasyMotion_move_highlight* + + While moving motion(|(easymotion-next)|, |(easymotion-prev)|), + EasyMotion highlight matched text until cursor move, entering insert + mode, or leaving buffer. If you don't want this feature, set this option + to 0. +> + let g:EasyMotion_move_highlight = 0 +< + Default: 1 + + *g:EasyMotion_landing_highlight* + + If you want to highlight matched text temporarily (unhighlight timing + is same with |g:EasyMotion_move_highlight|) after EasyMotion + jump(landing), set this option to 0. +> + let g:EasyMotion_landing_highlight = 1 +< + Default: 0 + ============================================================================== 5. License *easymotion-license* diff --git a/plugin/EasyMotion.vim b/plugin/EasyMotion.vim index f3bf138..069cf17 100644 --- a/plugin/EasyMotion.vim +++ b/plugin/EasyMotion.vim @@ -36,6 +36,9 @@ let g:EasyMotion_use_migemo = get(g: , 'EasyMotion_use_migemo' , let g:EasyMotion_use_upper = get(g: , 'EasyMotion_use_upper' , 0) let g:EasyMotion_use_regexp = get(g: , 'EasyMotion_use_regexp' , 0) let g:EasyMotion_enter_jump_first = get(g: , 'EasyMotion_enter_jump_first' , 0) +let g:EasyMotion_inc_highlight = get(g: , 'EasyMotion_inc_highlight' , 1) +let g:EasyMotion_move_highlight = get(g: , 'EasyMotion_move_highlight' , 1) +let g:EasyMotion_landing_highlight = get(g: , 'EasyMotion_landing_highlight' , 0) let g:EasyMotion_show_prompt = get(g: , 'EasyMotion_show_prompt' , 1) let g:EasyMotion_prompt = \ get(g: , 'EasyMotion_prompt' , 'Search for {n} character(s): ') @@ -56,6 +59,13 @@ let g:EasyMotion_hl_group_shade = get(g:, let g:EasyMotion_hl_line_group_shade = get(g:, \ 'EasyMotion_hl_line_group_shade', 'EasyMotionShadeLine') +let g:EasyMotion_hl_inc_search = get(g:, + \ 'EasyMotion_hl_inc_search', 'EasyMotionIncSearch') +let g:EasyMotion_hl_inc_cursor = get(g:, + \ 'EasyMotion_hl_inc_cursor', 'EasyMotionIncCursor') +let g:EasyMotion_hl_move = get(g:, + \ 'EasyMotion_hl_move', 'EasyMotionMoveHL') + let s:target_hl_defaults = { \ 'gui' : ['NONE', '#ff0000' , 'bold'] \ , 'cterm256': ['NONE', '196' , 'bold'] @@ -86,12 +96,32 @@ let s:shade_hl_line_defaults = { \ , 'cterm' : ['red' , 'grey' , 'NONE'] \ } +let s:target_hl_inc = { + \ 'gui' : ['NONE', '#7fbf00' , 'bold'] + \ , 'cterm256': ['NONE', 'green' , 'bold'] + \ , 'cterm' : ['NONE', 'green' , 'bold'] + \ } +let s:target_hl_inc_cursor = { + \ 'gui' : ['#d13a84', 'NONE' , 'bold'] + \ , 'cterm256': ['magenta', 'NONE' , 'bold'] + \ , 'cterm' : ['magenta', 'NONE' , 'bold'] + \ } +let s:target_hl_move = { + \ 'gui' : ['#7fbf00', '#121813' , 'bold'] + \ , 'cterm256': ['green' , 'white' , 'bold'] + \ , 'cterm' : ['green' , 'white' , 'bold'] + \ } + call EasyMotion#init#InitHL(g:EasyMotion_hl_group_target, s:target_hl_defaults) call EasyMotion#init#InitHL(g:EasyMotion_hl2_first_group_target, s:target_hl2_first_defaults) call EasyMotion#init#InitHL(g:EasyMotion_hl2_second_group_target, s:target_hl2_second_defaults) call EasyMotion#init#InitHL(g:EasyMotion_hl_group_shade, s:shade_hl_defaults) call EasyMotion#init#InitHL(g:EasyMotion_hl_line_group_shade, s:shade_hl_line_defaults) +call EasyMotion#init#InitHL(g:EasyMotion_hl_inc_search, s:target_hl_inc) +call EasyMotion#init#InitHL(g:EasyMotion_hl_inc_cursor, s:target_hl_inc_cursor) +call EasyMotion#init#InitHL(g:EasyMotion_hl_move, s:target_hl_move) + " Reset highlighting after loading a new color scheme {{{ augroup EasyMotionInitHL autocmd! @@ -101,6 +131,10 @@ augroup EasyMotionInitHL autocmd ColorScheme * call EasyMotion#init#InitHL(g:EasyMotion_hl2_second_group_target, s:target_hl2_second_defaults) autocmd ColorScheme * call EasyMotion#init#InitHL(g:EasyMotion_hl_group_shade, s:shade_hl_defaults) autocmd ColorScheme * call EasyMotion#init#InitHL(g:EasyMotion_hl_line_group_shade, s:shade_hl_line_defaults) + + autocmd ColorScheme * call EasyMotion#init#InitHL(g:EasyMotion_hl_inc_search, s:target_hl_inc) + autocmd ColorScheme * call EasyMotion#init#InitHL(g:EasyMotion_hl_inc_cursor, s:target_hl_inc_cursor) + autocmd ColorScheme * call EasyMotion#init#InitHL(g:EasyMotion_hl_move, s:target_hl_move) augroup end " }}} " }}} @@ -319,6 +353,13 @@ nnoremap (easymotion-special-py) :call EasyMotion#Selec nnoremap (easymotion-special-pd) :call EasyMotion#SelectPhraseDelete() "}}} +map (easymotion-clever-s) + \ EasyMotion#is_active() ? '(easymotion-next)' : '(easymotion-s)' +map (easymotion-clever-s2) + \ EasyMotion#is_active() ? '(easymotion-next)' : '(easymotion-s2)' +map (easymotion-clever-sn) + \ EasyMotion#is_active() ? '(easymotion-next)' : '(easymotion-sn)' + " }}} " == Default key mapping {{{ diff --git a/t/easymotion_spec.vim b/t/easymotion_spec.vim index ade178f..07bf8e9 100644 --- a/t/easymotion_spec.vim +++ b/t/easymotion_spec.vim @@ -1,7 +1,7 @@ "============================================================================= " FILE: t/easymotion_spec.vim " AUTHOR: haya14busa -" Last Change: 17 Jan 2014. +" Last Change: 20 Jan 2014. " Test: https://github.com/kana/vim-vspec " Refer: https://github.com/rhysd/clever-f.vim " Description: EasyMotion test with vim-vspec @@ -425,6 +425,9 @@ describe 'Default settings' Expect g:EasyMotion_use_upper ==# 0 Expect g:EasyMotion_enter_jump_first ==# 0 Expect g:EasyMotion_show_prompt ==# 1 + Expect g:EasyMotion_inc_highlight ==# 1 + Expect g:EasyMotion_move_highlight ==# 1 + Expect g:EasyMotion_landing_highlight ==# 0 Expect g:EasyMotion_prompt ==# 'Search for {n} character(s): ' Expect g:EasyMotion_command_line_key_mappings ==# {} " }}}