Merge branch 'fix/repeat_inclusive' into master
This commit is contained in:
commit
0efcd3e21e
@ -12,9 +12,11 @@ set cpo&vim
|
|||||||
" }}}
|
" }}}
|
||||||
" Init: {{{
|
" Init: {{{
|
||||||
function! EasyMotion#init()
|
function! EasyMotion#init()
|
||||||
" Init Migemo Dictionary
|
" Store previous motion info
|
||||||
let s:previous = {}
|
let s:previous = {}
|
||||||
|
" Store previous operator-pending motion info for '.' repeat
|
||||||
let s:dot_repeat = {}
|
let s:dot_repeat = {}
|
||||||
|
" Prepare 1-key Migemo Dictionary
|
||||||
let s:migemo_dicts = {}
|
let s:migemo_dicts = {}
|
||||||
let s:EasyMotion_is_active = 0
|
let s:EasyMotion_is_active = 0
|
||||||
call EasyMotion#reset()
|
call EasyMotion#reset()
|
||||||
@ -52,21 +54,56 @@ function! EasyMotion#reset()
|
|||||||
\ 'bd_t' : 0,
|
\ 'bd_t' : 0,
|
||||||
\ 'find_bd' : 0,
|
\ 'find_bd' : 0,
|
||||||
\ }
|
\ }
|
||||||
|
" regexp: -> regular expression
|
||||||
|
" This value is used when multi input find motion. If this values is
|
||||||
|
" 1, input text is treated as regexp.(Default: escaped)
|
||||||
|
" bd_t: -> bi-directional 't' motion
|
||||||
|
" This value is used to re-define regexp only for bi-directional 't'
|
||||||
|
" motion
|
||||||
|
" find_bd: -> bi-directional find motion
|
||||||
|
" This value is used to recheck the motion is inclusive or exclusive
|
||||||
|
" because 'f' & 't' forward find motion is inclusive, but 'F' & 'T'
|
||||||
|
" backward find motion is exclusive
|
||||||
let s:current = {
|
let s:current = {
|
||||||
\ 'is_operator' : 0,
|
\ 'is_operator' : 0,
|
||||||
\ 'dot_repeat_target_cnt' : 0,
|
\ 'dot_repeat_target_cnt' : 0,
|
||||||
\ 'dot_prompt_user_cnt' : 0,
|
\ 'dot_prompt_user_cnt' : 0,
|
||||||
\ 'changedtick' : 0,
|
\ 'changedtick' : 0,
|
||||||
\ }
|
\ }
|
||||||
|
" is_operator:
|
||||||
|
" Store is_operator value first because mode(1) value will be
|
||||||
|
" changed by some operation.
|
||||||
|
" dot_* :
|
||||||
|
" These values are used when '.' repeat for automatically
|
||||||
|
" select marker/label characters.(Using count avoid recursive
|
||||||
|
" prompt)
|
||||||
|
" changedtick:
|
||||||
|
" :h b:changedtick
|
||||||
|
" This value is used to avoid side effect of overwriting buffer text
|
||||||
|
" which will change b:changedtick value. To overwrite g:repeat_tick
|
||||||
|
" value(defined tpope/vim-repeat), I can avoid this side effect of
|
||||||
|
" conflicting with tpope/vim-repeat
|
||||||
return ""
|
return ""
|
||||||
endfunction "}}}
|
endfunction "}}}
|
||||||
" Motion Functions: {{{
|
" Motion Functions: {{{
|
||||||
" -- Find Motion -------------------------
|
" -- Find Motion -------------------------
|
||||||
|
" Note: {{{
|
||||||
|
" num_strokes:
|
||||||
|
" The number of input characters. Currently provide 1, 2, or -1.
|
||||||
|
" '-1' means no limit.
|
||||||
|
" visualmode:
|
||||||
|
" Vim script couldn't detect the function is called in visual mode by
|
||||||
|
" mode(1), so tell whether it is in visual mode by argument explicitly
|
||||||
|
" direction:
|
||||||
|
" 0 -> forward
|
||||||
|
" 1 -> backward
|
||||||
|
" 2 -> bi-direction (handle forward & backward at the same time) }}}
|
||||||
function! EasyMotion#S(num_strokes, visualmode, direction) " {{{
|
function! EasyMotion#S(num_strokes, visualmode, direction) " {{{
|
||||||
if a:direction == 1
|
if a:direction == 1
|
||||||
let is_inclusive = 0
|
let is_inclusive = 0
|
||||||
else
|
else
|
||||||
" Handle bi-direction later
|
" Note: Handle bi-direction later because 'f' motion is inclusive but
|
||||||
|
" 'F' motion is exclusive
|
||||||
let is_inclusive = mode(1) ==# 'no' ? 1 : 0
|
let is_inclusive = mode(1) ==# 'no' ? 1 : 0
|
||||||
endif
|
endif
|
||||||
let s:flag.find_bd = a:direction == 2 ? 1 : 0
|
let s:flag.find_bd = a:direction == 2 ? 1 : 0
|
||||||
@ -78,7 +115,8 @@ function! EasyMotion#T(num_strokes, visualmode, direction) " {{{
|
|||||||
if a:direction == 1
|
if a:direction == 1
|
||||||
let is_inclusive = 0
|
let is_inclusive = 0
|
||||||
else
|
else
|
||||||
" Handle bi-direction later
|
" Note: Handle bi-direction later because 't' motion is inclusive but
|
||||||
|
" 'T' motion is exclusive
|
||||||
let is_inclusive = mode(1) ==# 'no' ? 1 : 0
|
let is_inclusive = mode(1) ==# 'no' ? 1 : 0
|
||||||
endif
|
endif
|
||||||
let s:flag.find_bd = a:direction == 2 ? 1 : 0
|
let s:flag.find_bd = a:direction == 2 ? 1 : 0
|
||||||
@ -326,6 +364,7 @@ function! EasyMotion#SelectPhraseDelete() "{{{
|
|||||||
endif
|
endif
|
||||||
endfunction "}}}
|
endfunction "}}}
|
||||||
" -- User Motion -------------------------
|
" -- User Motion -------------------------
|
||||||
|
" TODO: more improvement
|
||||||
function! EasyMotion#User(pattern, mode, direction) " {{{
|
function! EasyMotion#User(pattern, mode, direction) " {{{
|
||||||
let s:current.is_operator = mode(1) ==# 'no' ? 1: 0
|
let s:current.is_operator = mode(1) ==# 'no' ? 1: 0
|
||||||
let visualmode = match('\v([Vv])|(C-v)', a:mode) > 0 ? visualmode() : ''
|
let visualmode = match('\v([Vv])|(C-v)', a:mode) > 0 ? visualmode() : ''
|
||||||
@ -342,13 +381,17 @@ function! EasyMotion#Repeat(visualmode) " {{{
|
|||||||
let re = s:previous.regexp
|
let re = s:previous.regexp
|
||||||
let direction = s:previous.direction
|
let direction = s:previous.direction
|
||||||
let s:flag.within_line = s:previous.line_flag
|
let s:flag.within_line = s:previous.line_flag
|
||||||
|
let s:flag.bd_t = s:previous.bd_t_flag
|
||||||
let s:current.is_operator = mode(1) ==# 'no' ? 1: 0
|
let s:current.is_operator = mode(1) ==# 'no' ? 1: 0
|
||||||
|
" FIXME: is_inclusive value is inappropriate but handling this value is
|
||||||
|
" difficult and priorities is low because this motion maybe used usually
|
||||||
|
" as a 'normal' motion.
|
||||||
let is_inclusive = mode(1) ==# 'no' ? 1 : 0
|
let is_inclusive = mode(1) ==# 'no' ? 1 : 0
|
||||||
|
|
||||||
call s:EasyMotion(re, direction, a:visualmode ? visualmode() : '', is_inclusive)
|
call s:EasyMotion(re, direction, a:visualmode ? visualmode() : '', is_inclusive)
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
function! EasyMotion#DotRepeat(visualmode) " {{{
|
function! EasyMotion#DotRepeat(visualmode) " {{{
|
||||||
" Repeat previous motion with previous targets
|
" Repeat previous '.' motion with previous targets and operator
|
||||||
if s:dot_repeat ==# {}
|
if s:dot_repeat ==# {}
|
||||||
call s:Message("Previous motion doesn't exist")
|
call s:Message("Previous motion doesn't exist")
|
||||||
return
|
return
|
||||||
@ -358,6 +401,7 @@ function! EasyMotion#DotRepeat(visualmode) " {{{
|
|||||||
let direction = s:dot_repeat.direction
|
let direction = s:dot_repeat.direction
|
||||||
let is_inclusive = s:dot_repeat.is_inclusive
|
let is_inclusive = s:dot_repeat.is_inclusive
|
||||||
let s:flag.within_line = s:dot_repeat.line_flag
|
let s:flag.within_line = s:dot_repeat.line_flag
|
||||||
|
let s:flag.bd_t = s:dot_repeat.bd_t_flag
|
||||||
|
|
||||||
let s:current.is_operator = 1
|
let s:current.is_operator = 1
|
||||||
for cnt in range(v:count1)
|
for cnt in range(v:count1)
|
||||||
@ -366,7 +410,7 @@ function! EasyMotion#DotRepeat(visualmode) " {{{
|
|||||||
endfor
|
endfor
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
function! EasyMotion#NextPrevious(visualmode, direction) " {{{
|
function! EasyMotion#NextPrevious(visualmode, direction) " {{{
|
||||||
" Repeat previous motion with previous targets
|
" Move next/previous destination using previous motion regexp
|
||||||
if s:previous ==# {}
|
if s:previous ==# {}
|
||||||
call s:Message("Previous targets doesn't exist")
|
call s:Message("Previous targets doesn't exist")
|
||||||
return
|
return
|
||||||
@ -384,7 +428,8 @@ function! EasyMotion#NextPrevious(visualmode, direction) " {{{
|
|||||||
silent exec 'normal! gv'
|
silent exec 'normal! gv'
|
||||||
endif
|
endif
|
||||||
for i in range(v:count1)
|
for i in range(v:count1)
|
||||||
call searchpos(re, search_direction)
|
" Do not treat this motion as 'jump' motion
|
||||||
|
keepjumps call searchpos(re, search_direction)
|
||||||
endfor
|
endfor
|
||||||
call EasyMotion#reset()
|
call EasyMotion#reset()
|
||||||
" -- Activate EasyMotion ----------------- {{{
|
" -- Activate EasyMotion ----------------- {{{
|
||||||
@ -450,6 +495,7 @@ function! s:SetLines(lines, key) " {{{
|
|||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
" -- Get characters from user input ------
|
" -- Get characters from user input ------
|
||||||
function! s:GetChar() " {{{
|
function! s:GetChar() " {{{
|
||||||
|
" [[deprecated]] -> EasyMotion#command_line#GetInput()
|
||||||
let char = getchar()
|
let char = getchar()
|
||||||
if char == 27
|
if char == 27
|
||||||
" Escape key pressed
|
" Escape key pressed
|
||||||
@ -460,6 +506,7 @@ function! s:GetChar() " {{{
|
|||||||
return nr2char(char)
|
return nr2char(char)
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
function! s:GetSearchChar2(visualmode) " {{{
|
function! s:GetSearchChar2(visualmode) " {{{
|
||||||
|
" For selectlines and selectphrase
|
||||||
let chars = []
|
let chars = []
|
||||||
for i in [1, 2]
|
for i in [1, 2]
|
||||||
redraw
|
redraw
|
||||||
@ -480,6 +527,7 @@ function! s:GetSearchChar2(visualmode) " {{{
|
|||||||
return chars
|
return chars
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
function! s:GetSearchChar(visualmode) " {{{
|
function! s:GetSearchChar(visualmode) " {{{
|
||||||
|
" [[deprecated]] -> EasyMotion#command_line#GetInput()
|
||||||
call s:Prompt('Search for character')
|
call s:Prompt('Search for character')
|
||||||
|
|
||||||
let char = s:GetChar()
|
let char = s:GetChar()
|
||||||
@ -513,6 +561,10 @@ function! s:findMotion(num_strokes) "{{{
|
|||||||
return re
|
return re
|
||||||
endfunction "}}}
|
endfunction "}}}
|
||||||
function! s:convertRegep(input) "{{{
|
function! s:convertRegep(input) "{{{
|
||||||
|
" 1. regexp
|
||||||
|
" 2. migemo
|
||||||
|
" 3. smartsign
|
||||||
|
" 4. smartcase
|
||||||
let re = s:should_use_regexp() ? a:input : escape(a:input, '.$^~\[]')
|
let re = s:should_use_regexp() ? a:input : escape(a:input, '.$^~\[]')
|
||||||
|
|
||||||
if s:should_use_migemo(a:input)
|
if s:should_use_migemo(a:input)
|
||||||
@ -570,7 +622,7 @@ function! s:should_use_migemo(char) "{{{
|
|||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" TODO: use direction
|
" TODO: use direction to improve
|
||||||
if s:flag.within_line == 1
|
if s:flag.within_line == 1
|
||||||
let first_line = line('.')
|
let first_line = line('.')
|
||||||
let end_line = line('.')
|
let end_line = line('.')
|
||||||
@ -580,6 +632,7 @@ function! s:should_use_migemo(char) "{{{
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
" Skip folded line and check if text include multibyte haracters
|
||||||
for line in range(first_line, end_line)
|
for line in range(first_line, end_line)
|
||||||
if s:is_folded(line)
|
if s:is_folded(line)
|
||||||
continue
|
continue
|
||||||
@ -624,7 +677,7 @@ function! s:load_smart_dict() "{{{
|
|||||||
elseif exists('g:EasyMotion_use_smartsign_jp')
|
elseif exists('g:EasyMotion_use_smartsign_jp')
|
||||||
return g:EasyMotion#sticky_table#jp
|
return g:EasyMotion#sticky_table#jp
|
||||||
else
|
else
|
||||||
return ''
|
return {}
|
||||||
endif
|
endif
|
||||||
endfunction "}}}
|
endfunction "}}}
|
||||||
" -- Handle Visual Mode ------------------
|
" -- Handle Visual Mode ------------------
|
||||||
@ -687,6 +740,22 @@ function! s:should_use_wundo() "{{{
|
|||||||
" unless undolist is not empty
|
" unless undolist is not empty
|
||||||
return ! s:is_cmdwin() && undotree().seq_last != 0
|
return ! s:is_cmdwin() && undotree().seq_last != 0
|
||||||
endfunction "}}}
|
endfunction "}}}
|
||||||
|
function! EasyMotion#attach_active_autocmd() "{{{
|
||||||
|
" Reference: https://github.com/justinmk/vim-sneak
|
||||||
|
augroup plugin-easymotion-active
|
||||||
|
autocmd!
|
||||||
|
autocmd InsertEnter,WinLeave,BufLeave <buffer>
|
||||||
|
\ let s:EasyMotion_is_active = 0
|
||||||
|
\ | autocmd! plugin-easymotion-active * <buffer>
|
||||||
|
autocmd CursorMoved <buffer>
|
||||||
|
\ autocmd plugin-easymotion-active CursorMoved <buffer>
|
||||||
|
\ let s:EasyMotion_is_active = 0
|
||||||
|
\ | autocmd! plugin-easymotion-active * <buffer>
|
||||||
|
augroup END
|
||||||
|
endfunction "}}}
|
||||||
|
function! EasyMotion#is_active() "{{{
|
||||||
|
return s:EasyMotion_is_active
|
||||||
|
endfunction "}}}
|
||||||
"}}}
|
"}}}
|
||||||
" Grouping Algorithms: {{{
|
" Grouping Algorithms: {{{
|
||||||
let s:grouping_algorithms = {
|
let s:grouping_algorithms = {
|
||||||
@ -1140,12 +1209,19 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
" Store Regular Expression
|
" Store Regular Expression
|
||||||
let s:previous['regexp'] = a:regexp
|
let s:previous['regexp'] = a:regexp
|
||||||
let s:previous['direction'] = a:direction
|
let s:previous['direction'] = a:direction
|
||||||
let s:previous['line_flag'] = s:flag.within_line == 1 ? 1 : 0
|
|
||||||
let s:previous['is_inclusive'] = a:is_inclusive
|
|
||||||
let s:previous['operator'] = v:operator
|
let s:previous['operator'] = v:operator
|
||||||
|
|
||||||
|
" Note: 'is_inclusive' value could be changed later when
|
||||||
|
" bi-directional find motion depend on 'true' direction the cursor
|
||||||
|
" will move.
|
||||||
|
let s:previous['is_inclusive'] = a:is_inclusive
|
||||||
|
|
||||||
|
" For special motion flag
|
||||||
|
let s:previous['line_flag'] = s:flag.within_line
|
||||||
|
let s:previous['bd_t_flag'] = s:flag.bd_t " bi-directional t motion
|
||||||
endif
|
endif
|
||||||
" To avoid side effect of overwriting buffer for tpope/repeat
|
" To avoid side effect of overwriting buffer for tpope/repeat
|
||||||
" store current b:changedtick
|
" store current b:changedtick. Use this value later
|
||||||
let s:current.changedtick = b:changedtick
|
let s:current.changedtick = b:changedtick
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -1195,9 +1271,10 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
|
|
||||||
" Construct match dict {{{
|
" Construct match dict {{{
|
||||||
while 1
|
while 1
|
||||||
" Note: searchpos() has side effect which call jump cursor position.
|
" Note: searchpos() has side effect which jump cursor position.
|
||||||
" You can disable this side effect by add 'n' flags,
|
" You can disable this side effect by add 'n' flags,
|
||||||
" but in this case, it's better to allows jump side effect.
|
" but in this case, it's better to allows jump side effect
|
||||||
|
" to gathering matched targets coordinates.
|
||||||
let pos = searchpos(regexp, search_direction . search_at_cursor, search_stopline)
|
let pos = searchpos(regexp, search_direction . search_at_cursor, search_stopline)
|
||||||
let search_at_cursor = ''
|
let search_at_cursor = ''
|
||||||
|
|
||||||
@ -1229,6 +1306,8 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
" Reconstruct match dict
|
" Reconstruct match dict
|
||||||
if a:direction == 2
|
if a:direction == 2
|
||||||
" Forward
|
" Forward
|
||||||
|
|
||||||
|
" Jump back original position
|
||||||
if ! empty(a:visualmode)
|
if ! empty(a:visualmode)
|
||||||
keepjumps call cursor(c_pos[0], c_pos[1])
|
keepjumps call cursor(c_pos[0], c_pos[1])
|
||||||
else
|
else
|
||||||
@ -1242,6 +1321,7 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
let search_stopline = !empty(a:visualmode) ? c_pos[0] : orig_pos[0]
|
let search_stopline = !empty(a:visualmode) ? c_pos[0] : orig_pos[0]
|
||||||
endif
|
endif
|
||||||
while 1
|
while 1
|
||||||
|
" TODO: refactoring
|
||||||
let pos = searchpos(regexp, '', search_stopline)
|
let pos = searchpos(regexp, '', search_stopline)
|
||||||
" Reached end of search range
|
" Reached end of search range
|
||||||
if pos == [0, 0]
|
if pos == [0, 0]
|
||||||
@ -1284,6 +1364,7 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
endif
|
endif
|
||||||
"}}}
|
"}}}
|
||||||
|
|
||||||
|
" Attach specific key as marker to gathered matched coordinates
|
||||||
let GroupingFn = function('s:GroupingAlgorithm' . s:grouping_algorithms[g:EasyMotion_grouping])
|
let GroupingFn = function('s:GroupingAlgorithm' . s:grouping_algorithms[g:EasyMotion_grouping])
|
||||||
let groups = GroupingFn(targets, split(g:EasyMotion_keys, '\zs'))
|
let groups = GroupingFn(targets, split(g:EasyMotion_keys, '\zs'))
|
||||||
|
|
||||||
@ -1310,7 +1391,7 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
\ shade_hl_re,
|
\ shade_hl_re,
|
||||||
\ g:EasyMotion_hl_group_shade)
|
\ g:EasyMotion_hl_group_shade)
|
||||||
endif
|
endif
|
||||||
endif
|
|
||||||
if hlcurrent != 0
|
if hlcurrent != 0
|
||||||
call EasyMotion#highlight#add_highlight(
|
call EasyMotion#highlight#add_highlight(
|
||||||
\ '\%'. hlcurrent .'l.*',
|
\ '\%'. hlcurrent .'l.*',
|
||||||
@ -1321,19 +1402,19 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
\ '\%'. hlchar[0] .'l\%' . hlchar[1] .'c',
|
\ '\%'. hlchar[0] .'l\%' . hlchar[1] .'c',
|
||||||
\ g:EasyMotion_hl_line_group_shade)
|
\ g:EasyMotion_hl_line_group_shade)
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
" -- Jump back before prompt for visual scroll {{{
|
" -- Jump back before prompt for visual scroll {{{
|
||||||
" Because searchpos() change current cursor position and
|
" Because searchpos() change current cursor position and
|
||||||
" if you just use cursor([orig_num, orig_pos]) to jump back,
|
" if you just use cursor([orig_pos, orig_pos]) to jump back,
|
||||||
" current line will become center of window
|
" current line will become middle of line window
|
||||||
if ! empty(a:visualmode)
|
if ! empty(a:visualmode)
|
||||||
keepjumps call cursor(win_first_line,0)
|
keepjumps call cursor(win_first_line,0)
|
||||||
normal! zt
|
normal! zt
|
||||||
" for adjusting cursorline
|
" for adjusting cursorline
|
||||||
keepjumps call cursor(c_pos)
|
keepjumps call cursor(c_pos)
|
||||||
else
|
else
|
||||||
" for adjusting cursorline
|
|
||||||
keepjumps call cursor(orig_pos)
|
keepjumps call cursor(orig_pos)
|
||||||
endif
|
endif
|
||||||
"}}}
|
"}}}
|
||||||
@ -1348,65 +1429,94 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
"}}}
|
"}}}
|
||||||
|
|
||||||
" -- Update cursor position -------------- {{{
|
" -- Update cursor position -------------- {{{
|
||||||
|
" First, jump back cursor to original position
|
||||||
keepjumps call cursor(orig_pos[0], orig_pos[1])
|
keepjumps call cursor(orig_pos[0], orig_pos[1])
|
||||||
|
|
||||||
" Consider EasyMotion as jump motion :h jump-motion
|
" Consider EasyMotion as jump motion :h jump-motion
|
||||||
normal! m`
|
normal! m`
|
||||||
|
|
||||||
" Update selection {{{
|
" Update selection for visual mode {{{
|
||||||
if ! empty(a:visualmode)
|
if ! empty(a:visualmode)
|
||||||
exec 'normal! ' . a:visualmode
|
exec 'normal! ' . a:visualmode
|
||||||
endif
|
endif
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
|
" For bi-directional motion, checking again whether the motion is
|
||||||
|
" inclusive is necessary. This value will might be updated later
|
||||||
|
let is_inclusive_check = a:is_inclusive
|
||||||
|
" For bi-directional motion, store 'true' direction for dot repeat
|
||||||
|
" to handling inclusive/exclusive motion
|
||||||
|
if a:direction == 2
|
||||||
|
let true_direction =
|
||||||
|
\ EasyMotion#helper#is_greater_coords(orig_pos, coords) > 0 ?
|
||||||
|
\ 0 : 1
|
||||||
|
" forward : backward
|
||||||
|
else
|
||||||
|
let true_direction = a:direction
|
||||||
|
endif
|
||||||
|
|
||||||
if s:flag.dot_repeat == 1
|
if s:flag.dot_repeat == 1
|
||||||
" support dot repeat {{{
|
" support dot repeat {{{
|
||||||
" Use visual mode to emulate dot repeat
|
" Use visual mode to emulate dot repeat
|
||||||
normal! v
|
normal! v
|
||||||
|
|
||||||
|
" Deal with exclusive {{{
|
||||||
if s:dot_repeat.is_inclusive == 0
|
if s:dot_repeat.is_inclusive == 0
|
||||||
if s:dot_repeat.direction == 0 "Forward
|
" exclusive
|
||||||
|
if s:dot_repeat.true_direction == 0 "Forward
|
||||||
let coords[1] -= 1
|
let coords[1] -= 1
|
||||||
elseif s:dot_repeat.direction == 1 "Backward
|
elseif s:dot_repeat.true_direction == 1 "Backward
|
||||||
" Shift visual selection to left by making cursor one key
|
" Shift visual selection to left by making cursor one key
|
||||||
" left.
|
" left.
|
||||||
normal! hoh
|
normal! hoh
|
||||||
endif
|
endif
|
||||||
endif
|
endif "}}}
|
||||||
|
|
||||||
|
" Jump to destination
|
||||||
keepjumps call cursor(coords[0], coords[1])
|
keepjumps call cursor(coords[0], coords[1])
|
||||||
|
|
||||||
|
" Execute previous operator
|
||||||
let cmd = s:dot_repeat.operator
|
let cmd = s:dot_repeat.operator
|
||||||
if s:dot_repeat.operator ==# 'c'
|
if s:dot_repeat.operator ==# 'c'
|
||||||
let cmd .= getreg('.')
|
let cmd .= getreg('.')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
exec 'normal! ' . cmd
|
exec 'normal! ' . cmd
|
||||||
"}}}
|
"}}}
|
||||||
else
|
else
|
||||||
" Handle inclusive & exclusive {{{
|
" Handle inclusive & exclusive {{{
|
||||||
" Overwrite inclusive flag for special case
|
" Overwrite inclusive flag for special case {{{
|
||||||
let is_exclusive = 0
|
if s:flag.find_bd == 1 && true_direction == 1
|
||||||
if s:flag.find_bd == 1
|
" Note: For bi-directional find motion s(f) & t
|
||||||
" for bi-directional s(f) & t
|
" If true_direction is backward, the motion is 'exclusive'
|
||||||
let is_backward = EasyMotion#helper#is_greater_coords(orig_pos, coords) < 0
|
let is_inclusive_check = 0 " overwrite
|
||||||
if is_backward != 0
|
let s:previous.is_inclusive = 0 " overwrite
|
||||||
let is_exclusive = 1
|
endif "}}}
|
||||||
endif
|
if is_inclusive_check
|
||||||
endif
|
" Note: {{{
|
||||||
if a:is_inclusive == 1 && is_exclusive == 0
|
" Inclusive motion requires that we eat one more
|
||||||
" Exclusive motion requires that we eat one more
|
" character to the right by forcing the motion to inclusive
|
||||||
" character to the right if we're using
|
" if we're using a forward motion because
|
||||||
" a forward motion
|
" > :h exclusive
|
||||||
|
" > Note that when using ':' any motion becomes characterwise
|
||||||
|
" > exclusive.
|
||||||
|
" and EasyMotion use ':'
|
||||||
|
" See: h: o_v }}}
|
||||||
normal! v
|
normal! v
|
||||||
endif " }}}
|
endif " }}}
|
||||||
|
|
||||||
" Adjust screen for visual scroll {{{
|
" Adjust screen for visual scroll {{{
|
||||||
|
" Otherwise, cursor line will move middle line of window
|
||||||
if ! empty(a:visualmode)
|
if ! empty(a:visualmode)
|
||||||
keepjumps call cursor(win_first_line, 0)
|
keepjumps call cursor(win_first_line, 0)
|
||||||
normal! zt
|
normal! zt
|
||||||
endif "}}}
|
endif "}}}
|
||||||
|
|
||||||
|
" Jump to destination
|
||||||
keepjumps call cursor(coords[0], coords[1])
|
keepjumps call cursor(coords[0], coords[1])
|
||||||
|
|
||||||
" To avoid side effect of overwriting buffer {{{
|
" To avoid side effect of overwriting buffer {{{
|
||||||
" for tpope/vim-repeat
|
" for tpope/vim-repeat
|
||||||
|
" See: :h b:changedtick
|
||||||
if exists('g:repeat_tick')
|
if exists('g:repeat_tick')
|
||||||
if g:repeat_tick == s:current.changedtick
|
if g:repeat_tick == s:current.changedtick
|
||||||
let g:repeat_tick = b:changedtick
|
let g:repeat_tick = b:changedtick
|
||||||
@ -1420,15 +1530,17 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
" Store previous info for dot repeat {{{
|
" Store previous info for dot repeat {{{
|
||||||
let s:dot_repeat.regexp = a:regexp
|
let s:dot_repeat.regexp = a:regexp
|
||||||
let s:dot_repeat.direction = a:direction
|
let s:dot_repeat.direction = a:direction
|
||||||
let s:dot_repeat.line_flag = s:flag.within_line == 1 ? 1 : 0
|
let s:dot_repeat.line_flag = s:flag.within_line
|
||||||
let s:dot_repeat.is_inclusive = a:is_inclusive
|
let s:dot_repeat.is_inclusive = is_inclusive_check
|
||||||
let s:dot_repeat.operator = v:operator
|
let s:dot_repeat.operator = v:operator
|
||||||
|
let s:dot_repeat.bd_t_flag = s:flag.bd_t " Bidirectional t motion
|
||||||
|
let s:dot_repeat.true_direction = true_direction " Check inclusive
|
||||||
"}}}
|
"}}}
|
||||||
silent! call repeat#set("\<Plug>(easymotion-dotrepeat)")
|
silent! call repeat#set("\<Plug>(easymotion-dotrepeat)")
|
||||||
endif "}}}
|
endif "}}}
|
||||||
|
|
||||||
call s:Message('Jumping to [' . coords[0] . ', ' . coords[1] . ']')
|
call s:Message('Jumping to [' . coords[0] . ', ' . coords[1] . ']')
|
||||||
let s:EasyMotion_cancelled = 0
|
let s:EasyMotion_cancelled = 0 " Success
|
||||||
"}}}
|
"}}}
|
||||||
|
|
||||||
catch
|
catch
|
||||||
@ -1445,7 +1557,7 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
keepjumps call cursor(orig_pos[0], orig_pos[1])
|
keepjumps call cursor(orig_pos[0], orig_pos[1])
|
||||||
endif
|
endif
|
||||||
" }}}
|
" }}}
|
||||||
let s:EasyMotion_cancelled = 1
|
let s:EasyMotion_cancelled = 1 " Cancel
|
||||||
finally
|
finally
|
||||||
" -- Restore properties ------------------ {{{
|
" -- Restore properties ------------------ {{{
|
||||||
call s:RestoreValue()
|
call s:RestoreValue()
|
||||||
@ -1455,6 +1567,7 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
call EasyMotion#highlight#delete_highlight()
|
call EasyMotion#highlight#delete_highlight()
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
|
if s:EasyMotion_cancelled == 0 " Success
|
||||||
" -- Landing Highlight ------------------- {{{
|
" -- Landing Highlight ------------------- {{{
|
||||||
if g:EasyMotion_landing_highlight
|
if g:EasyMotion_landing_highlight
|
||||||
call EasyMotion#highlight#add_highlight(a:regexp, 'EasyMotionMoveHL')
|
call EasyMotion#highlight#add_highlight(a:regexp, 'EasyMotionMoveHL')
|
||||||
@ -1463,24 +1576,9 @@ function! s:EasyMotion(regexp, direction, visualmode, is_inclusive, ...) " {{{
|
|||||||
" -- Activate EasyMotion ----------------- {{{
|
" -- Activate EasyMotion ----------------- {{{
|
||||||
let s:EasyMotion_is_active = 1
|
let s:EasyMotion_is_active = 1
|
||||||
call EasyMotion#attach_active_autocmd() "}}}
|
call EasyMotion#attach_active_autocmd() "}}}
|
||||||
|
endif
|
||||||
endtry
|
endtry
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
function! EasyMotion#attach_active_autocmd() "{{{
|
|
||||||
" Reference: https://github.com/justinmk/vim-sneak
|
|
||||||
augroup plugin-easymotion-active
|
|
||||||
autocmd!
|
|
||||||
autocmd InsertEnter,WinLeave,BufLeave <buffer>
|
|
||||||
\ let s:EasyMotion_is_active = 0
|
|
||||||
\ | autocmd! plugin-easymotion-active * <buffer>
|
|
||||||
autocmd CursorMoved <buffer>
|
|
||||||
\ autocmd plugin-easymotion-active CursorMoved <buffer>
|
|
||||||
\ let s:EasyMotion_is_active = 0
|
|
||||||
\ | autocmd! plugin-easymotion-active * <buffer>
|
|
||||||
augroup END
|
|
||||||
endfunction "}}}
|
|
||||||
function! EasyMotion#is_active() "{{{
|
|
||||||
return s:EasyMotion_is_active
|
|
||||||
endfunction "}}}
|
|
||||||
"}}}
|
"}}}
|
||||||
" Call Init: {{{
|
" Call Init: {{{
|
||||||
call EasyMotion#init()
|
call EasyMotion#init()
|
||||||
|
Loading…
Reference in New Issue
Block a user