Skip to content
This repository was archived by the owner on Nov 4, 2025. It is now read-only.

Commit f3d122d

Browse files
authored
Merge pull request #24 from elythyr/improvement-preserve-cursor-position
Improvement preserve cursor position
2 parents 878e9c8 + 7afc8ac commit f3d122d

File tree

2 files changed

+148
-10
lines changed

2 files changed

+148
-10
lines changed

autoload/argwrap.vim

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,6 @@ function! argwrap#initSetting(name, value) abort
235235
endfunction
236236

237237
function! argwrap#toggle()
238-
let l:cursor = getpos('.')
239-
240238
let l:linePrefix = argwrap#getSetting('line_prefix')
241239
let l:padded = argwrap#getSetting('padded_braces')
242240
let l:tailComma = argwrap#getSetting('tail_comma')
@@ -260,19 +258,11 @@ function! argwrap#toggle()
260258
let l:container = argwrap#extractContainer(l:range)
261259
if l:range.lineStart == l:range.lineEnd
262260
call argwrap#hooks#execute('pre_wrap', l:range, l:container, l:arguments)
263-
264261
call argwrap#wrapContainer(l:range, l:container, l:arguments, l:wrapBrace, l:tailComma, l:tailCommaBraces, l:tailIndentBraces, l:linePrefix, l:commaFirst, l:commaFirstIndent)
265-
let l:cursor[1] = l:range.lineStart + 1
266-
267262
call argwrap#hooks#execute('post_wrap', l:range, l:container, l:arguments)
268263
else
269264
call argwrap#hooks#execute('pre_unwrap', l:range, l:container, l:arguments)
270-
271265
call argwrap#unwrapContainer(l:range, l:container, l:arguments, l:padded)
272-
let l:cursor[1] = l:range.lineStart
273-
274266
call argwrap#hooks#execute('post_unwrap', l:range, l:container, l:arguments)
275267
endif
276-
277-
call setpos('.', l:cursor)
278268
endfunction
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
function! s:extractCursorPositionForUnwrappedArguments(range, arguments) abort " {{{
2+
let l:cursorColumn = col('.')
3+
let l:lineText = getline(a:range.lineStart)
4+
let l:position = {}
5+
6+
let l:argumentNumber = 0
7+
for argument in a:arguments
8+
let l:argumentNumber += 1
9+
let l:argumentStart = stridx(l:lineText, argument)
10+
let l:argumentEnd = l:argumentStart + len(argument)
11+
12+
if l:cursorColumn <= l:argumentStart
13+
let l:cursorColumn = l:argumentStart + 1
14+
endif
15+
16+
if l:argumentEnd < l:cursorColumn
17+
if l:lineText[l:cursorColumn - 1:] =~ '\v^,' " Cursor on the separator
18+
if !argwrap#getSetting('comma_first')
19+
let l:cursorColumn = l:argumentEnd + 1
20+
else
21+
let l:position.argumentNumber = l:argumentNumber + 1
22+
let l:position.column = -1
23+
24+
break
25+
endif
26+
elseif l:lineText[l:cursorColumn - 1:] =~ '\v^\s+,' " Cursor before the separator
27+
let l:cursorColumn = l:argumentEnd
28+
endif
29+
endif
30+
31+
if l:cursorColumn <= l:argumentEnd + 1
32+
let l:position.argumentNumber = l:argumentNumber
33+
let l:position.column = l:cursorColumn - l:argumentStart
34+
35+
break
36+
end
37+
endfor
38+
39+
" If the position was not found it's because the cursor is after the last
40+
" argument
41+
if empty(l:position)
42+
let l:position.argumentNumber = l:argumentNumber
43+
let l:position.column = l:argumentEnd - l:argumentStart
44+
endif
45+
46+
return l:position
47+
endfunction " }}}
48+
49+
function! s:extractCursorPositionForWrappedArguments(range, arguments) abort " {{{
50+
let l:position = {}
51+
let l:isCommaFirst = argwrap#getSetting('comma_first')
52+
let l:cursorColumn = col('.')
53+
let l:cursorArgumentNumber = line('.') - a:range.lineStart
54+
" In case the cursor is on the start line
55+
let l:cursorArgumentNumber = min([len(a:arguments), l:cursorArgumentNumber])
56+
" In case the cursor is on the end line
57+
let l:cursorArgumentNumber = max([1, l:cursorArgumentNumber])
58+
let l:argumentLine = getline('.')
59+
let l:argumentText = a:arguments[l:cursorArgumentNumber - 1]
60+
let l:argumentStart = stridx(l:argumentLine, l:argumentText)
61+
let l:argumentEnd = l:argumentStart + len(l:argumentText)
62+
let l:position.argumentNumber = l:cursorArgumentNumber
63+
let l:position.column = l:cursorColumn - l:argumentStart
64+
65+
if l:cursorColumn <= l:argumentStart
66+
let l:position.column = 1
67+
68+
if l:isCommaFirst
69+
if l:argumentLine[l:cursorColumn - 1:] =~ '\v^,' " Cursor on the separator
70+
" The cursor should be placed on the separtor
71+
let l:position.argumentNumber -= 1
72+
let l:position.column = len(a:arguments[l:position.argumentNumber - 1]) + 1
73+
elseif l:argumentLine[l:cursorColumn - 1:] =~ '\v^\s+,' " Cursor before the separator
74+
" The cursor should be placed on the end of the previous argument
75+
let l:position.argumentNumber -= 1
76+
let l:position.column = len(a:arguments[l:position.argumentNumber - 1])
77+
endif
78+
endif
79+
endif
80+
81+
if l:argumentEnd < l:cursorColumn
82+
let l:position.column = len(l:argumentText)
83+
84+
if !l:isCommaFirst
85+
if l:argumentLine[l:cursorColumn - 1:] =~ '\v^\s+,' " Cursor before the separator
86+
" The cursor should be placed on the end of the current argument
87+
elseif l:argumentLine[l:cursorColumn - 1:] =~ '\v^,' " Cursor on the separator
88+
" The cursor should be placed on the separator
89+
let l:position.column += 1
90+
endif
91+
endif
92+
endif
93+
94+
return l:position
95+
endfunction " }}}
96+
97+
function! s:getCursorPositionForWrappedArguments(range, container, arguments) abort " {{{
98+
let l:line = a:range.lineStart + a:container.cursor.argumentNumber
99+
let l:argumentStart = stridx(getline(l:line), a:arguments[a:container.cursor.argumentNumber - 1])
100+
let l:column = l:argumentStart + a:container.cursor.column
101+
102+
return {'line': l:line, 'column': l:column}
103+
endfunction " }}}
104+
105+
function! s:getCursorPositionForUnwrappedArguments(range, container, arguments) abort " {{{
106+
let l:line = a:range.lineStart
107+
let l:column = a:range.colStart
108+
109+
" For each arguments before the one where the cursor must be positioned
110+
for index in range(a:container.cursor.argumentNumber - 1)
111+
" Add the length of the argument + 2 for the separator ', '
112+
let l:column += len(a:arguments[index]) + 2
113+
endfor
114+
115+
let l:column += a:container.cursor.column
116+
117+
return {'line': l:line, 'column': l:column}
118+
endfunction " }}}
119+
120+
function! s:setCursorPosition(position) abort " {{{
121+
let l:curpos = getcurpos()
122+
let l:curpos[1] = a:position.line
123+
let l:curpos[2] = a:position.column
124+
125+
call setpos('.', l:curpos)
126+
endfunction " }}}
127+
128+
function! argwrap#hooks#000_curpos#pre_wrap(range, container, arguments) abort " {{{
129+
let a:container.cursor = s:extractCursorPositionForUnwrappedArguments(a:range, a:arguments)
130+
endfunction " }}}
131+
132+
function! argwrap#hooks#000_curpos#pre_unwrap(range, container, arguments) abort " {{{
133+
let a:container.cursor = s:extractCursorPositionForWrappedArguments(a:range, a:arguments)
134+
endfunction " }}}
135+
136+
function! argwrap#hooks#000_curpos#post_wrap(range, container, arguments) abort " {{{
137+
let l:position = s:getCursorPositionForWrappedArguments(a:range, a:container, a:arguments)
138+
139+
call s:setCursorPosition(l:position)
140+
endfunction " }}}
141+
142+
function! argwrap#hooks#000_curpos#post_unwrap(range, container, arguments) abort " {{{
143+
let l:position = s:getCursorPositionForUnwrappedArguments(a:range, a:container, a:arguments)
144+
145+
call s:setCursorPosition(l:position)
146+
endfunction " }}}
147+
148+
" vim: ts=2 sw=2 et fdm=marker

0 commit comments

Comments
 (0)