Skip to content

Commit

Permalink
Added block segment motions
Browse files Browse the repository at this point in the history
- Added EasyMotion support for segments
- Updated test case
- Updated doc

closes #1
  • Loading branch information
tweekmonster committed Mar 5, 2016
1 parent 65b15cb commit 5e02fce
Show file tree
Hide file tree
Showing 7 changed files with 557 additions and 207 deletions.
24 changes: 17 additions & 7 deletions autoload/braceless.vim
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ function! braceless#scan_head(pat, flag) abort
if stridx(a:flag, 'b') != -1
let c_line = docstring[0] - 1
else
let c_line = docstring[1] + 1
let c_line = docstring[1]
endif

if c_line < 1 || c_line > line('$')
Expand Down Expand Up @@ -395,7 +395,7 @@ function! braceless#select_block(pattern, ...)
let saved_view = winsaveview()
let c_line = s:best_indent(line('.'))
if c_line == 0
return 0
return [0, 0, 0, 0]
endif

let [pat, flag] = s:build_pattern(c_line, a:pattern, ignore_empty)
Expand All @@ -405,7 +405,7 @@ function! braceless#select_block(pattern, ...)

if head[0] == 0 || tail[0] == 0
call winrestview(saved_view)
return [c_line, c_line, head[0], tail[0]]
return [0, 0, head[0], tail[0]]
endif

" Finally begin the block search
Expand Down Expand Up @@ -478,9 +478,15 @@ function! braceless#get_block_lines(line, ...)
let pattern = braceless#get_pattern()
let saved = winsaveview()
let ignore_empty = 0
if a:0 != 0
let include_whitespace = 0

if a:0 > 0
let ignore_empty = a:1
endif

if a:0 > 1
let include_whitespace = a:2
endif
call cursor(a:line, col([a:line, '$']))
let block = braceless#select_block(pattern, ignore_empty)
call winrestview(saved)
Expand All @@ -496,17 +502,21 @@ function! braceless#get_block_lines(line, ...)
let block[0] = next_line
endif

if include_whitespace && block[1] < line('$')
let block[1] = nextnonblank(block[1] + 1) - 1
endif

return block
endfunction


function! braceless#get_parent_block_lines(line, ...)
function! braceless#get_parent_block_lines(...)
let saved = winsaveview()
let block = braceless#get_block_lines(a:line)
let block = call('braceless#get_block_lines', a:000)
let [indent_char, indent_len] = braceless#indent#space(block[2], -1)
call cursor(block[2], 0)
let sub = search('^'.indent_char.'{-,'.indent_len.'}\S', 'nbW')
let parent = braceless#get_block_lines(sub)
let parent = call('braceless#get_block_lines', [sub] + a:000[1:])
call winrestview(saved)
return [parent, block]
endfunction
Expand Down
18 changes: 18 additions & 0 deletions autoload/braceless/easymotion.vim
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,21 @@ function! braceless#easymotion#blocks(vmode, direction)

call EasyMotion#User(pat, a:vmode, a:direction, 1)
endfunction


" Easy motion for segments
function! braceless#easymotion#segments(vmode, direction)
let segments = braceless#segments#visible()

let top_lines = []
let bottom_lines = []
for segment in segments
call add(top_lines, '\%'.segment[0].'l')
call add(bottom_lines, '\%'.segment[1].'l')
endfor

let top_pat = join(top_lines, '\|')
let bottom_pat = join(bottom_lines, '\|')
let pat = '\%(\%('.top_pat.'\)\&\_^\s*\zs\S\)\|\%(\%('.bottom_pat.'\)\&\zs\S\_$\)'
call EasyMotion#User(pat, a:vmode, a:direction, 1)
endfunction
138 changes: 0 additions & 138 deletions autoload/braceless/movement.vim
Original file line number Diff line number Diff line change
Expand Up @@ -31,141 +31,3 @@ function! braceless#movement#block(direction, vmode, by_indent, count)
let i -= 1
endwhile
endfunction



" Note: I think everything below needs some refactoring.

" Positions the cursor after movement in function below
function! s:position_inner_block(pat, top)
if a:top
let top = braceless#scan_head(a:pat, 'nceb')[0]
if top == 0
let top = 1
else
let block = braceless#get_block_lines(top + 1)
if block[1] < line('.')
let top = nextnonblank(block[1] + 1)
else
let top = nextnonblank(top + 1)
endif
endif
let [_, indent_len] = braceless#indent#space(top, 0)
call cursor(top, indent_len + 1)
else
let bottom = braceless#scan_head(a:pat, 'nc')[0]
if bottom == 0
let bottom = prevnonblank(line('.'))
else
let block = braceless#get_block_lines(line('.'))
if block[1] < bottom
let bottom = prevnonblank(block[1])
else
let bottom = prevnonblank(bottom - 1)
endif
endif
call cursor(bottom, col([bottom, '$']) - 1)
endif
endfunction


" Returns the line of the next block boundary depending on direction. A block
" boundary is considered anything that's between block heads and block ends,
" and vice versa.
function! s:skip_boundary(pat, direction, start)
let flags = 'W'
if a:direction == -1
let flags .= 'b'
else
let flags .= 'e'
endif
let pos = getpos('.')[1:2]
let found = braceless#scan_head(a:pat, flags)[0]

if found == 0
if a:direction == -1
let l = prevnonblank(pos[0] - 1)
if l == 0
let l = 1
endif
else
let l = nextnonblank(pos[0] + 1)
if l == 0
let l = line('$')
endif
endif

call cursor(pos)
return l
endif

if a:direction == -1
let block = braceless#get_block_lines(found)
if block[0] != 0 && block[1] < pos[0]
let found = prevnonblank(block[1])
else
let prev_found = braceless#scan_head(a:pat, flags.'n')[0]
if abs(found - prev_found) <= 1
let found = s:skip_boundary(a:pat, a:direction, a:start)
else
let found = prevnonblank(found - 1)
endif
endif
else
let block = braceless#get_block_lines(pos[0])
let n = nextnonblank(block[1] + 1)
if n != 0 && n < found
" Too far beyond the current block
let found = nextnonblank(n - 1)
else
let next_found = braceless#scan_head(a:pat, flags.'n')[0]
if abs(next_found - found) <= 1
" Too close to another block head
let found = s:skip_boundary(a:pat, a:direction, a:start)
else
let found = nextnonblank(found + 1)
endif
endif
endif

call cursor(pos)
return found
endfunction


function! braceless#movement#inner_block(direction, vmode, inclusive, top)
if a:vmode == 'v'
normal! gv
endif

let pattern = braceless#get_pattern()
let pat = '^\s*'
if pattern.jump !~ '\\zs'
let pat .= '\zs'
endif
let pat .= pattern.jump

let c = a:inclusive ? v:count : v:count1
let pos = getpos('.')[1:2]
let flag = ''
let alt_flag = ''
if a:direction == -1
let flag = 'b'
let next_flag = 'nb'
else
let flag = 'e'
let next_flag = 'ne'
endif

let c_line = line('.')
while c > 0
let c_line = s:skip_boundary(pat, a:direction, c_line)
if c_line == 0
break
endif
call cursor(c_line, 0)
let c -= 1
endwhile

call s:position_inner_block(pat, a:top)
endfunction
Loading

0 comments on commit 5e02fce

Please sign in to comment.