1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
" Falling motions for Vim. "Falling" means moving the cursor down until it hits
" text that doesn't match a pattern.
" Returns an expression to be used in normal mode that results in the falling
" motion. The semantics are as follows:
"
" The motion moves in the direction given by a:dir (which must be 'j' or 'k').
" The motion moves while the character under the cursor does not match the
" pattern, then it moves while the character under the cursor matches the
" pattern stopping when the character under the cursor does not match the
" pattern once again.
"
" ex.
"
" fall#fall('j', '^\s*$')
"
" for
"
" | t⌷is is some text
" | this is some other text
" |
" |
" | this is some bottom text
" | this is some other bottom text
"
" will return an expression to update the cursor position to:
"
" | this is some text
" | this is some other text
" |
" |
" | t⌷is is some bottom text
" | this is some other bottom text
"
" This works pretty well for navigating around languages that use indentation
" and lack braces for bodies, i.e. vimscript, ruby. Less well for python, but
" still okay.
function! fall#fall(dir, pattern) abort
let i = 0
let n = 0
if a:dir == 'j'
let delta = 1
else
let delta = -1
endif
let line = line('.')
let column = col('.')
let c = v:count
if c == 0
let c = 1
endif
while i < c
let match = matchstr(getline(line), '\%' . column . 'c.')
while ! (match =~ a:pattern)
let n += 1
let line += delta
if line <= 0 || line >= line('$')
return "m'" . n . a:dir
endif
let match = matchstr(getline(line), '\%' . column . 'c.')
endwhile
while (match =~ a:pattern)
let n += 1
let line += delta
if line <= 0 || line >= line('$')
return "m'" . n . a:dir
endif
let match = matchstr(getline(line), '\%' . column . 'c.')
endwhile
let i += 1
endwhile
return "m'" . n . a:dir
endfunction
function! fall#visual_same_character(dir)
let start_line = line(".")
let line = start_line
let column = col(".")
let char_to_match = matchstr(getline(line), '\%' . column . 'c.')
let expr = ""
if a:dir =~ 'k'
while line > 1
let line -= 1
if matchstr(getline(line), '\%' . column . 'c.') != char_to_match
break
endif
let expr .= 'k'
endwhile
endif
if a:dir == 'jk'
let expr .= 'o'
let line = start_line
endif
if a:dir =~ 'j'
while line <= line("$")
let line += 1
if matchstr(getline(line), '\%' . column . 'c.') != char_to_match
break
endif
let expr .= 'j'
endwhile
endif
return expr
endfunction
function! fall#visual_vertical_word(dir, def_class)
let start_line = line(".")
let line = start_line
let column = col(".")
let start_char = matchstr(getline(line), '\%' . column . 'c.')
if (start_char =~# '\s')
let class = '\s'
elseif (start_char =~# a:def_class)
let class = a:def_class
else
return ""
endif
let expr = ""
if a:dir =~ 'k'
while line > 1
let line -= 1
if ! (matchstr(getline(line), '\%' . column . 'c.') =~# class)
break
endif
let expr .= 'k'
endwhile
endif
if a:dir == 'jk'
let expr .= 'o'
let line = start_line
endif
if a:dir =~ 'j'
while line <= line("$")
let line += 1
if ! (matchstr(getline(line), '\%' . column . 'c.') =~# class)
break
endif
let expr .= 'j'
endwhile
endif
return expr
endfunction
|