Skip to content

Commit 793792c

Browse files
committed
Improved smart-boundary-columns.
Behavior when dealing with whitespace is improved. * If origin column is solely whitespace, then the column selection will ONLY include whitespace. * If origin column is not solely whitespace, then the cursor will be set to the beginning of the word on each line when checking for boundaries, so that whitespace is not mistakenly included in the boundary assessment.
1 parent e0819c5 commit 793792c

File tree

1 file changed

+66
-30
lines changed

1 file changed

+66
-30
lines changed

plugin/textobj/word-column.vim

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,49 +5,86 @@ endif
55
function! TextObjWordBasedColumn(textobj)
66
let cursor_col = col(".")
77
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)
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+
let whitespace_only = s:whitespace_column_wanted(start_line, stop_line, cursor_col)
15+
1416
if (exists("g:textobj_word_column_no_smart_boundary_cols"))
1517
let col_bounds = [start_col, stop_col]
1618
else
17-
let col_bounds = s:find_smart_boundary_cols(start_line, stop_line, cursor_col, a:textobj)
19+
let col_bounds = s:find_smart_boundary_cols(start_line, stop_line, cursor_col, a:textobj, whitespace_only)
1820
endif
21+
1922
exec "keepjumps silent normal!" . start_line . "gg" . col_bounds[0] . "|" stop_line . "gg" . col_bounds[1] . "|"
2023
endfunction
2124

22-
function! s:find_smart_boundary_cols(start_line, stop_line, cursor_col, textobj)
25+
function! s:find_smart_boundary_cols(start_line, stop_line, cursor_col, textobj, whitespace_only)
2326
let col_bounds = []
2427
let index = a:start_line
28+
if a:whitespace_only
29+
let word_start = ""
30+
let s:col_bounds_fn = function("s:col_bounds_min")
31+
else
32+
let word_start = "lb"
33+
let s:col_bounds_fn = function("s:col_bounds_max")
34+
endif
2535

2636
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("'>")
37+
exec "keepjumps silent normal!" index . "gg" . a:cursor_col . "|" . word_start . "v" . a:textobj . "\<Esc>"
38+
let start_col = col("'<")
39+
let stop_col = col("'>")
40+
let col_bounds = s:col_bounds_fn(start_col, stop_col, col_bounds)
41+
let index = index + 1
42+
endwhile
3043

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
44+
return col_bounds
45+
endfunction
4146

47+
function! s:col_bounds_max(start_col, stop_col, col_bounds)
48+
if a:col_bounds == []
49+
return [a:start_col, a:stop_col]
50+
endif
51+
if a:start_col < a:col_bounds[0]
52+
let a:col_bounds[0] = a:start_col
53+
endif
54+
if a:stop_col > a:col_bounds[1]
55+
let a:col_bounds[1] = a:stop_col
56+
endif
57+
return a:col_bounds
58+
endfunction
59+
60+
function! s:col_bounds_min(start_col, stop_col, col_bounds)
61+
if a:col_bounds == []
62+
return [a:start_col, a:stop_col]
63+
endif
64+
if a:start_col > a:col_bounds[0]
65+
let a:col_bounds[0] = a:start_col
66+
endif
67+
if a:stop_col < a:col_bounds[1]
68+
let a:col_bounds[1] = a:stop_col
69+
endif
70+
return a:col_bounds
71+
endfunction
72+
73+
function! s:whitespace_column_wanted(start_line, stop_line, cursor_col)
74+
let index = a:start_line
75+
while index <= a:stop_line
76+
let char = getline(index)[a:cursor_col - 1]
77+
if char != " " && char != "\t"
78+
return 0
79+
end
4280
let index = index + 1
4381
endwhile
44-
45-
return col_bounds
82+
return 1
4683
endfunction
4784

4885
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
86+
let non_blank = getline(a:line_num + a:step) =~ "[^ \t]"
87+
let same_indent = s:indent_levell(a:line_num + a:step) == a:indent_level
5188
let is_not_comment = ! s:is_comment(a:line_num + a:step, a:start_col)
5289
if same_indent && non_blank && is_not_comment
5390
return s:find_boundary_row(a:line_num + a:step, a:start_col, a:indent_level, a:step)
@@ -70,11 +107,10 @@ if (!exists("g:skip_default_textobj_word_column_mappings"))
70107
nnoremap <silent> vaC :call TextObjWordBasedColumn("aW")<cr>
71108
nnoremap <silent> vic :call TextObjWordBasedColumn("iw")<cr>
72109
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>
110+
onoremap <silent> ac :call TextObjWordBasedColumn("aw")<cr>
111+
onoremap <silent> aC :call TextObjWordBasedColumn("aW")<cr>
112+
onoremap <silent> ic :call TextObjWordBasedColumn("iw")<cr>
113+
onoremap <silent> iC :call TextObjWordBasedColumn("iW")<cr>
78114
endif
79115

80116
let g:loaded_textobj_word_column = 1

0 commit comments

Comments
 (0)