From 2b5fb6212351b0b8de1be3ad382cd6611fc49134 Mon Sep 17 00:00:00 2001 From: haya14busa Date: Mon, 20 Jan 2014 01:28:48 +0900 Subject: [PATCH] Implement & Improve highlight Implement: - increment highlight - moving highlight - cursor highlight Improve: - method - bi-directional shade regexp --- autoload/EasyMotion.vim | 62 +++++++++++++-------- autoload/EasyMotion/command_line.vim | 67 ++++++++++++++++------ autoload/EasyMotion/highlight.vim | 83 ++++++++++++++++++++++++++++ plugin/EasyMotion.vim | 30 ++++++++++ t/easymotion_spec.vim | 5 +- 5 files changed, 207 insertions(+), 40 deletions(-) create mode 100644 autoload/EasyMotion/highlight.vim diff --git a/autoload/EasyMotion.vim b/autoload/EasyMotion.vim index f915f37..88c008f 100644 --- a/autoload/EasyMotion.vim +++ b/autoload/EasyMotion.vim @@ -340,6 +340,13 @@ function! EasyMotion#NextPrevious(visualmode, direction) " {{{ let re = s:previous.regexp let search_direction = (a:direction >= 1 ? 'b' : '') + call EasyMotion#highlight#attach_autocmd() + call EasyMotion#highlight#add_highlight(re,'EasyMotionMoveHL') + + if ! empty(a:visualmode) + " FIXME: blink highlight + silent exec 'normal! gv' + endif for i in range(v:count1) call searchpos(re, search_direction) endfor @@ -460,7 +467,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 +946,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 +1006,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 +1251,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 " }}} @@ -1371,13 +1386,14 @@ 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 "}}} endtry endfunction " }}} "}}} 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..677e8a3 --- /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: 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 +" "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' : 1, + \ '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/plugin/EasyMotion.vim b/plugin/EasyMotion.vim index df09b51..7dc63b7 100644 --- a/plugin/EasyMotion.vim +++ b/plugin/EasyMotion.vim @@ -33,6 +33,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): ') @@ -53,6 +56,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'] @@ -83,12 +93,32 @@ let s:shade_hl_line_defaults = { \ , 'cterm' : ['red' , 'grey' , 'NONE'] \ } +let s:target_hl_inc = { + \ 'gui' : ['NONE', '#00ff00' , 'bold'] + \ , 'cterm256': ['NONE', 'green' , 'bold'] + \ , 'cterm' : ['NONE', 'green' , 'bold'] + \ } +let s:target_hl_inc_cursor = { + \ 'gui' : ['magenta', 'NONE' , 'bold'] + \ , 'cterm256': ['magenta', 'NONE' , 'bold'] + \ , 'cterm' : ['magenta', 'NONE' , 'bold'] + \ } +let s:target_hl_move = { + \ 'gui' : ['magenta', 'white' , 'bold'] + \ , 'cterm256': ['magenta', 'white' , 'bold'] + \ , 'cterm' : ['magenta', '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! 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 ==# {} " }}}