I'm trying to write a vimscript function that moves the cursor all the way up or all the way down without changing the column. (similar to the way :set nostartofline
works).
It works, but when I tried to add a mapping for visual mode, it would exit visual mode.
Here is my script:
function! StraightDown()
let line=line('.')
let end=line('$')
exe "normal ".eval(end-line)."j"
endfunction
function! StraightUp()
let line=line('.')
exe "normal ".eval(line-1)."k"
endfunction
nnoremap <M-j> :<C-u>call StraightDown()<cr>
nnoremap <M-k> :<C-u>call StraightUp()<cr>
xnoremap <M-j> :<C-u>call StraightDown()<cr>
xnoremap <M-k> :<C-u>call StraightUp()<cr>
After experimenting with it, it seems like any command executed with normal ...
will leave visual mode unless it starts with v
.
One possible workaround I thought of is to add some more logic, and if I call the function in visual mode, add v
to the normal command. However, this doesn't work if I'm in visual line or visual block mode.
So really, my TL;DR question is how can I do a normal
command in visual mode without changing modes?
nostartofline
and usegg
andG
?set nostartofline
andgg
are two separate commands but I don't understand how it is a problem: simply putset nostartofline
in your vimrc and usegg
when you need it. Now if you'd like to keepstartofline
for other commands andnostartofline
only forgg
you could create a mapping like thatnnoremap gg :set nostartofline<CR>:normal! gg<CR>:set startofline<CR>
. Now I understand you want to get better at vimscript, I'm just suggesting a workaround for your original problem :-)