Skip to content

Commit e0819c5

Browse files
committed
Added smart boundary columns.
The idea is that the longest word in the logical column will dictate the width of the column. This is as opposed to the current way it works, which is the word that you are currently on dictating the width of the column. This is experimental, and there are some problems with the current implementation. * I had to using normal mapping instead of visual mapping. With vmap, I lose the cursor column by the time the function is called. * Triggering the function while on whitespace doesn't always give desireable results. I think I'm going to have to make the plugin "whitespace aware".
1 parent 69c30da commit e0819c5

File tree

1 file changed

+61
-27
lines changed

1 file changed

+61
-27
lines changed

plugin/textobj/word-column.vim

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,79 @@ if (exists("g:loaded_textobj_word_column"))
22
finish
33
endif
44

5-
function! TextObjWordBasedColumn()
6-
let startcol = col("'<")
7-
let stopcol = col("'>")
8-
let linenum = line(".")
9-
let indentlevel = s:indent_level(".")
10-
let startline = s:find_boundary_row(linenum, startcol, indentlevel, -1)
11-
let stopline = s:find_boundary_row(linenum, startcol, indentlevel, 1)
12-
exec "silent normal!" startline . "gg" . startcol . "|" stopline . "gg" . stopcol . "|"
5+
function! TextObjWordBasedColumn(textobj)
6+
let cursor_col = col(".")
7+
exec "silent normal! v" . a:textobj . "\<Esc>"
8+
let start_col = col("'<")
9+
let stop_col = col("'>")
10+
let line_num = line(".")
11+
let indent_level = s:indent_levell(".")
12+
let start_line = s:find_boundary_row(line_num, start_col, indent_level, -1)
13+
let stop_line = s:find_boundary_row(line_num, start_col, indent_level, 1)
14+
if (exists("g:textobj_word_column_no_smart_boundary_cols"))
15+
let col_bounds = [start_col, stop_col]
16+
else
17+
let col_bounds = s:find_smart_boundary_cols(start_line, stop_line, cursor_col, a:textobj)
18+
endif
19+
exec "keepjumps silent normal!" . start_line . "gg" . col_bounds[0] . "|" stop_line . "gg" . col_bounds[1] . "|"
1320
endfunction
1421

15-
function! s:find_boundary_row(linenum, startcol, indentlevel, step)
16-
let nonblank = getline(a:linenum + a:step) =~ "[^ \t]"
17-
let sameindent = s:indent_level(a:linenum + a:step) == a:indentlevel
18-
let is_not_comment = ! s:is_comment(a:linenum + a:step, a:startcol)
19-
if sameindent && nonblank && is_not_comment
20-
return s:find_boundary_row(a:linenum + a:step, a:startcol, a:indentlevel, a:step)
22+
function! s:find_smart_boundary_cols(start_line, stop_line, cursor_col, textobj)
23+
let col_bounds = []
24+
let index = a:start_line
25+
26+
while index <= a:stop_line
27+
exec "keepjumps silent normal!" index . "gg" . a:cursor_col . "|v" . a:textobj . "\<Esc>"
28+
let start_col = col("'<")
29+
let stop_col = col("'>")
30+
31+
if index == a:start_line
32+
let col_bounds = [start_col, stop_col]
33+
else
34+
if start_col < col_bounds[0]
35+
let col_bounds[0] = start_col
36+
endif
37+
if stop_col > col_bounds[1]
38+
let col_bounds[1] = stop_col
39+
endif
40+
endif
41+
42+
let index = index + 1
43+
endwhile
44+
45+
return col_bounds
46+
endfunction
47+
48+
function! s:find_boundary_row(line_num, start_col, indent_level, step)
49+
let non_blank = getline(a:line_num + a:step) =~ "[^ \t]"
50+
let same_indent = s:indent_levell(a:line_num + a:step) == a:indent_level
51+
let is_not_comment = ! s:is_comment(a:line_num + a:step, a:start_col)
52+
if same_indent && non_blank && is_not_comment
53+
return s:find_boundary_row(a:line_num + a:step, a:start_col, a:indent_level, a:step)
2154
else
22-
return a:linenum
55+
return a:line_num
2356
endif
2457
endfunction
2558

26-
function! s:indent_level(linenum)
27-
let line = getline(a:linenum)
59+
function! s:indent_levell(line_num)
60+
let line = getline(a:line_num)
2861
return match(line, "[^ \t]")
2962
endfunction
3063

31-
function! s:is_comment(linenum, column)
32-
return synIDattr(synIDtrans(synID(a:linenum, a:column, 1)),"name") == "Comment"
64+
function! s:is_comment(line_num, column)
65+
return synIDattr(synIDtrans(synID(a:line_num, a:column, 1)),"name") == "Comment"
3366
endfunction
3467

3568
if (!exists("g:skip_default_textobj_word_column_mappings"))
36-
vnoremap <silent> ac <Esc>vaw:call TextObjWordBasedColumn()<cr>
37-
vnoremap <silent> aC <Esc>vaW:call TextObjWordBasedColumn()<cr>
38-
vnoremap <silent> ic <Esc>viw:call TextObjWordBasedColumn()<cr>
39-
vnoremap <silent> iC <Esc>viW:call TextObjWordBasedColumn()<cr>
40-
onoremap <silent> ac :normal vac<cr>
41-
onoremap <silent> aC :normal vaC<cr>
42-
onoremap <silent> ic :normal vic<cr>
43-
onoremap <silent> iC :normal viC<cr>
69+
nnoremap <silent> vac :call TextObjWordBasedColumn("aw")<cr>
70+
nnoremap <silent> vaC :call TextObjWordBasedColumn("aW")<cr>
71+
nnoremap <silent> vic :call TextObjWordBasedColumn("iw")<cr>
72+
nnoremap <silent> viC :call TextObjWordBasedColumn("iW")<cr>
73+
74+
onoremap <silent> ac :call TextObjWordBasedColumn("aw")<cr>
75+
onoremap <silent> aC :call TextObjWordBasedColumn("aW")<cr>
76+
onoremap <silent> ic :call TextObjWordBasedColumn("iw")<cr>
77+
onoremap <silent> iC :call TextObjWordBasedColumn("iW")<cr>
4478
endif
4579

4680
let g:loaded_textobj_word_column = 1

0 commit comments

Comments
 (0)