Reputation: 4963
Say I've written code that references the x dimension. What is the best way to get vim to duplicate a line of code replacing all references to x to y and to z (best being the most clear method).
Input:
length_x = X_vec.dot(X_vec)**.5
Desired Output:
length_x = X_vec.dot(X_vec)**.5
length_y = Y_vec.dot(Y_vec)**.5
length_z = Z_vec.dot(Z_vec)**.5
Here's my best so far.
function SwitchXtoYZ()
:normal yy
:normal p
:normal! V
:s/X/Y/ge
:normal! V
:s/x/y/ge
:normal p
:normal! V
:s/X/Z/ge
:normal! V
:s/x/z/ge
endfunction
command XtoYZ exec SwitchXtoYZ() | :normal `.
It works, but I feel this is not very vim-y. Bonus points if the cursor returns to where it was before the command XtoYZ was issued (it currently goes the beginning of the second inserted line).
Upvotes: 1
Views: 271
Reputation: 5112
The : at the beginning of each line is optional, as are the :normal! V
lines.
You are leveraging the Normal commands that you know, which is a good way to start, but IMHO you get cleaner code if you use more Command-mode (ex) commands and functions. I would do something like this:
function! SwitchXtoYZ()
let save_cursor = getpos(".")
copy .
s/X/Y/ge
s/x/y/ge
-copy .
s/X/Z/ge
s/x/z/ge
call setpos('.', save_cursor)
endfun
command! XtoYZ call SwitchXtoYZ()
:help function-list
:help getpos()
:help :call
:help :exec
Upvotes: 1
Reputation: 195029
You don't need a function to do that, a macro would be fine for your requirement. Also you can define a macro in your vimrc too, if you like, so that you can have it everytime you open vim.
here is the macro:
qqv<Esc>Y2p:s/x/y/gi<Enter>n:s//z/gi<Enter>`<q
so it was recorded and saved in register q
, you can @q
to replay it.
explain it a little:
qq " start recording into q
v<esc> " enter visual mode and exit. to let `< work
Y2p " yank current line and paste twice below
:s/x/y/gi<Enter> " x->y sub, case insensitive
n " go to next x (here we could use j too)
:s//z/gi<Enter> " do another sub x->z
`< " back to the old cursor position
q " end recording
if you want to X->Y
and x->y
, just remove the i
flag and add two more :s
Upvotes: 1