Skip to content

Implement support for n/l modifiers via targets.vim #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
.PHONY: test-dependencies tests

tests:
dependencies/vim-vspec/bin/prove-vspec -d . -d dependencies/vim-textobj-user
dependencies/vim-vspec/bin/prove-vspec -d . -d dependencies/vim-textobj-user -d dependencies/targets.vim

test-dependencies:
-mkdir dependencies
-git clone https://github.com/kana/vim-vspec dependencies/vim-vspec
-git clone https://github.com/kana/vim-textobj-user dependencies/vim-textobj-user
-git clone https://github.com/wellle/targets.vim dependencies/targets.vim
51 changes: 51 additions & 0 deletions autoload/textobj/toplevel.vim
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,57 @@ function! textobj#toplevel#select_a()
endfunction


function! textobj#toplevel#target_new(args)
return {
\ 'genFuncs': {
\ 'c': function('textobj#toplevel#target_current'),
\ 'n': function('textobj#toplevel#target_next'),
\ 'l': function('textobj#toplevel#target_last'),
\ },
\ 'modFuncs': {
\ 'i': function('textobj#toplevel#modify_to_linewise'),
\ 'a': function('textobj#toplevel#select_trailing_whitespace'),
\ }}
endfunction

function! textobj#toplevel#target_current(args, opts, state)
if !a:opts.first | return | endif

return s:encode_targets(s:select_in_toplevel(line('.')))
endfunction

function! textobj#toplevel#target_next(args, opts, state)
let start = s:find_toplevel_end(line('.'))
let start = nextnonblank(s:below(start))

return s:encode_targets(s:select_in_toplevel(start))
endfunction

function! textobj#toplevel#target_last(args, opts, state)
let cursor_pos = line('.')
let [start, end] = s:select_in_toplevel(cursor_pos)
if (start <= cursor_pos && cursor_pos <= end)
return s:encode_targets(s:select_in_toplevel(s:above(start)))
else
return s:encode_targets([start, end])
endif
endfunction

function! s:encode_targets(range)
return [a:range[0], 1,
\ a:range[1], len(getline(a:range[1])) + 1]
endfunction

function! textobj#toplevel#modify_to_linewise(target, args)
let a:target.linewise = 1
endfunction

function! textobj#toplevel#select_trailing_whitespace(target, args)
let a:target.linewise = 1
let [a:target.sl, a:target.el] = s:select_surrounding_blank_lines([a:target.sl, a:target.el])
endfunction


function! s:encode_linerange(range)
let [start_linenr, end_linenr] = a:range
return ['V',
Expand Down
4 changes: 4 additions & 0 deletions plugin/textobj/toplevel.vim
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ call textobj#user#plugin('toplevel', {
\ }
\ })


autocmd User targets#sources call targets#sources#register('toplevel', function('textobj#toplevel#target_new'))
autocmd User targets#mappings#plugin call targets#mappings#extend({'T': {'toplevel': [{}]}})

let g:loaded_textobj_toplevel = 1
1 change: 0 additions & 1 deletion t/basics.vim
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
runtime! plugin/textobj/*.vim
version


describe 'The plugin'
Expand Down
10 changes: 3 additions & 7 deletions t/common.vim
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
function! ExecuteViTFromLine(linenr)
execute "normal! " . a:linenr . "G"
execute "normal V\<Plug>(textobj-toplevel-i)\<Esc>"
return [line("'<"), line("'>")]
endfunction
runtime! plugin/textobj/*.vim

function! ExecuteVaTFromLine(linenr)
function! ExecuteTextObjFromLine(linenr, modifier)
execute "normal! " . a:linenr . "G"
execute "normal V\<Plug>(textobj-toplevel-a)\<Esc>"
execute "normal V" . a:modifier . "T\<Esc>"
return [line("'<"), line("'>")]
endfunction

Expand Down
72 changes: 72 additions & 0 deletions t/target-toplevel.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
source t/common.vim
runtime! plugin/targets.vim


describe 'Target n modifiers'
before
call SetBufferContents([
\ 'import lib1',
\ 'import lib2',
\ '',
\ '',
\ '@cache',
\ 'def fn(i):',
\ '',
\ ' \"ok\"',
\ '',
\ ' return fn(i-1)',
\ '',
\ '@cache',
\ 'def test2(i):',
\ ' \"ok\"',
\ ' return test2(i-1)',
\ ])
end

it 'in selects first function from first imports'
Expect ExecuteTextObjFromLine(1, 'in') to_select_lines [5, 10]
Expect ExecuteTextObjFromLine(2, 'in') to_select_lines [5, 10]
end

it 'in selects second function from first function'
for linenr in range(5, 10)
Expect ExecuteTextObjFromLine(linenr, 'in') to_select_lines [12, 15]
endfor
end
end

describe 'Target l modifiers'
before
call SetBufferContents([
\ 'import lib1',
\ 'import lib2',
\ '',
\ '',
\ '@cache',
\ 'def fn(i):',
\ '',
\ ' \"ok\"',
\ '',
\ ' return fn(i-1)',
\ '',
\ '@cache',
\ 'def test2(i):',
\ ' \"ok\"',
\ ' return test2(i-1)',
\ '',
\ 'fn(2)',
\ ])
end

it 'il selects imports from first function'
for linenr in range(5, 10)
Expect ExecuteTextObjFromLine(linenr, 'il') to_select_lines [1, 2]
endfor
end

it 'il selects first function from second function'
for linenr in range(12, 15)
Expect ExecuteTextObjFromLine(linenr, 'il') to_select_lines [5, 10]
endfor
end
end
51 changes: 25 additions & 26 deletions t/textobj-toplevel.vim
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
source t/common.vim
source plugin/textobj/*.vim


describe 'Two groups of imports'
Expand All @@ -17,12 +16,12 @@ describe 'Two groups of imports'
end

it 'selects the first group of imports'
Expect ExecuteViTFromLine(3) to_select_lines [3, 4]
Expect ExecuteViTFromLine(4) to_select_lines [3, 4]
Expect ExecuteTextObjFromLine(3, 'i') to_select_lines [3, 4]
Expect ExecuteTextObjFromLine(4, 'i') to_select_lines [3, 4]
end

it 'selects the third import'
Expect ExecuteViTFromLine(7) to_select_lines [7, 7]
Expect ExecuteTextObjFromLine(7, 'i') to_select_lines [7, 7]
end
end

Expand Down Expand Up @@ -50,24 +49,24 @@ describe 'Python example'
end

it 'selects the correct individual import'
Expect ExecuteViTFromLine(1) to_select_lines [1, 2]
Expect ExecuteViTFromLine(2) to_select_lines [1, 2]
Expect ExecuteTextObjFromLine(1, 'i') to_select_lines [1, 2]
Expect ExecuteTextObjFromLine(2, 'i') to_select_lines [1, 2]
end

it 'selects the entire first function'
for linenr in range(5, 10)
Expect ExecuteViTFromLine(linenr) to_select_lines [5, 10]
Expect ExecuteTextObjFromLine(linenr, 'i') to_select_lines [5, 10]
endfor
end

it 'selects the entire second function'
for linenr in range(12, 15)
Expect ExecuteViTFromLine(linenr) to_select_lines [12, 15]
Expect ExecuteTextObjFromLine(linenr, 'i') to_select_lines [12, 15]
endfor
end

it 'selects the invocation of a function'
Expect ExecuteViTFromLine(17) to_select_lines [17, 17]
Expect ExecuteTextObjFromLine(17, 'i') to_select_lines [17, 17]
end
end

Expand Down Expand Up @@ -98,19 +97,19 @@ describe 'C++ example'
end

it 'selects the two includes'
Expect ExecuteViTFromLine(1) to_select_lines [1, 2]
Expect ExecuteViTFromLine(2) to_select_lines [1, 2]
Expect ExecuteTextObjFromLine(1, 'i') to_select_lines [1, 2]
Expect ExecuteTextObjFromLine(2, 'i') to_select_lines [1, 2]
end

it 'selects the entire first function'
for linenr in range(5, 11)
Expect ExecuteViTFromLine(linenr) to_select_lines [5, 11]
Expect ExecuteTextObjFromLine(linenr, 'i') to_select_lines [5, 11]
endfor
end

it 'selects the entire second function'
for linenr in range(13, 20)
Expect ExecuteViTFromLine(linenr) to_select_lines [13, 20]
Expect ExecuteTextObjFromLine(linenr, 'i') to_select_lines [13, 20]
endfor
end
end
Expand Down Expand Up @@ -143,36 +142,36 @@ describe 'Readme example'

it 'selects the entire first function'
for linenr in range(1, 7)
Expect ExecuteViTFromLine(linenr) to_select_lines [1, 7]
Expect ExecuteTextObjFromLine(linenr, 'i') to_select_lines [1, 7]
endfor
end

it 'selects the entire second function'
for linenr in range(9, 15)
Expect ExecuteViTFromLine(linenr) to_select_lines [9, 15]
Expect ExecuteTextObjFromLine(linenr, 'i') to_select_lines [9, 15]
endfor
end

it 'selects the invocation of a function'
Expect ExecuteViTFromLine(18) to_select_lines [18, 19]
Expect ExecuteViTFromLine(19) to_select_lines [18, 19]
Expect ExecuteTextObjFromLine(18, 'i') to_select_lines [18, 19]
Expect ExecuteTextObjFromLine(19, 'i') to_select_lines [18, 19]
end

it 'selects the trailing whitespace after first function'
for linenr in range(1, 7)
Expect ExecuteVaTFromLine(linenr) to_select_lines [1, 8]
Expect ExecuteTextObjFromLine(linenr, 'a') to_select_lines [1, 8]
endfor
end

it 'selects the trailing whitespace after second function'
for linenr in range(9, 17)
Expect ExecuteVaTFromLine(linenr) to_select_lines [9, 17]
Expect ExecuteTextObjFromLine(linenr, 'a') to_select_lines [9, 17]
endfor
end

it 'selects the preceding whitespace before the two function calls'
Expect ExecuteVaTFromLine(18) to_select_lines [16, 19]
Expect ExecuteVaTFromLine(19) to_select_lines [16, 19]
Expect ExecuteTextObjFromLine(18, 'a') to_select_lines [16, 19]
Expect ExecuteTextObjFromLine(19, 'a') to_select_lines [16, 19]
end

end
Expand All @@ -189,8 +188,8 @@ describe 'Edgecase with only indented lines'
end

it 'selects all the lines until the top of the file'
Expect ExecuteViTFromLine(3) to_select_lines [1, 4]
Expect ExecuteViTFromLine(4) to_select_lines [1, 4]
Expect ExecuteTextObjFromLine(3, 'i') to_select_lines [1, 4]
Expect ExecuteTextObjFromLine(4, 'i') to_select_lines [1, 4]
end
end

Expand All @@ -202,7 +201,7 @@ describe 'Edgecase with blank file'
end

it 'selects the blank line'
Expect ExecuteViTFromLine(1) to_select_lines [1, 1]
Expect ExecuteTextObjFromLine(1, 'i') to_select_lines [1, 1]
end
end

Expand All @@ -215,7 +214,7 @@ describe 'Edgecase with only unindented lines'
end

it 'selects all unindented lines'
Expect ExecuteViTFromLine(1) to_select_lines [1, 2]
Expect ExecuteViTFromLine(2) to_select_lines [1, 2]
Expect ExecuteTextObjFromLine(1, 'i') to_select_lines [1, 2]
Expect ExecuteTextObjFromLine(2, 'i') to_select_lines [1, 2]
end
end