If I want to replace something inside a group of parentheses (like say a function call) with something I've yanked I currently do: vi(p
this obviously isn't an excessive use of the keyboard, however I'm always looking for ways to improve, especially with things like the case I encountered yesterday where I needed to copy the arguments used in a function call a few lines above into another one. I ended up having to do something 16k0f(lyi(16j0f(lvi(p
which is probably longer than it should've been in my opinion. Can this be optimized? Is there a way to do that with less key presses?
3 Answers
jump to function call
16k
is not ideal, it only works if you turn on 'relativenumber'
and target function is visible.
by search.
/func_name
or?func_name
. If they share the same name, you can place cursor at function name and use*
or#
.by lsp reference. This works if target function is the same as current one. If you use
coc.nvim
, you can use this command:
com CocReference exec "norm \<plug>(coc-references)"
, place your cursor at function name and runCocReference
. You can createmap
for it if you believe you will use it a lot.
copy args
assume your current line is:
func(arg0, arg1, ...)
^
use %
to move cursor to )
, then copy args, by yi)
, one don't need to move cursor inside ()
to use i)
or i(
.
jump back
There are many ways to jump back:
`.
jump to last change.`^
jump to last insertion.gi
continue last insertion.ctrl-o
go to older cursor position in jump list. This won't work if you use16k
, ask
doesn't change jump list.
This part is not related to your question, feel free to skip it
jump to function definition
by lsp. If you use
coc.nvim
, you can useCocList symbol
to jump to function interactively. If you want to jump to function definition under cursor, you can use
com CocDefinition exec "norm \<plug>(coc-definition)"
by tag. If you update your tag files on the fly, you can use
:tag func_tag
, you can also usec-]
to jump to tag under cursor. Otherwise you need a plugin ( e.g.fzf
,ctrlp
, ...) that support buffer tag jump.
-
1Regarding #4, see my comment below the other question. . Great minds, as they say, think alike.– B LayerCommented Jun 11, 2020 at 11:14
-
1this is great stuff, I didn't know about the majority of this, I will definitely use all of those from now on, it's extremely useful– DannyMCommented Jun 11, 2020 at 11:20
-
1
-
@thelmuxkriovar I misread your question, I thought you want to jump to function definition, sorry for that.– dedowsdiCommented Jun 11, 2020 at 11:44
-
I don't think there's much to improve your sequence.
You could use <c-o>
to jump back to the first function instead of .
This only works with 16j0
jumps
though (e.g /
, check :h :jump-motions
), so 16j
won't do.
If you use coc
, you can use [m
and ]m
to jump to the next/previous method.
Also, once you've searched a parenthesis with f(
, you could just use ;
to find it again.
-
1
-
2But
k
isn't a jump motion so <c-o> won't take you back, right? See:h jump-motions
for the valid moves. I've gotten in the habit of doingma
if I'm about to do something like16k
.– B LayerCommented Jun 11, 2020 at 11:11 -
@BLayer Indeed, I did not realize. I'm editing it rn. Nice catch, thank you!– BiggybiCommented Jun 11, 2020 at 11:24
-
Instead of vi(, the sequence vib is faster. b is more reachable and doesn't require shift.
Some Lisp programmers remap their [] keys to insert parentheses.
The problem with 16k0f(lyi(16j0f(lvi(p
isn't the length so much as the specificity. For each instance where you want to do this, you have to measure the correct distance. Maybe it will be 14 lines next time.
If you're doing a lot of propagation of arguments, record a macro for it: one which finds the arguments in the current line and yanks them, and one which finds the current arguments and replaces them. One could be invoked as @q and the other as @p, say. These recordings could be robust such that they don't care where the cursor is in the current line (have them begin with 0
).
How you move around among the lines is a separate problem. For that you can use searches.
foo(x_new, y_new);
// [ 13 lines of code ]
bar(x, y); // want to make this x_new, y_new
Starting on the foo
line, we execute our @q recording to capture x_new, y_new
. Then move to bar
using, say /barEnter. Then execute the @p recording to identify x, y
and replace with the capture. How long those two are doesn't matter so much, because we are only using two-and-a-half keystrokes to run them.
The recorded macros could take steps to preserve the yank buffer (avoid the swapping behavior of p). Then it will be possible to do this:
a(x, y); // want to make this x_new, y_new
b(x, y); // likewise
c(x, y); // likewise
Having captured the replacement parameters, we can then just use our @p on the first line, and then repeat this pattern: j@@.
-
I didn't know about vib, that's extremely useful, is it possible to record macros in vimrc directly or do I have to define a function for it? (my vim skills aren't as great as I'd like them to be, haha)– DannyMCommented Jun 12, 2020 at 8:52
-
I did not know about the i( alias for ib. I think it's newer since the last time I looked at that doc? It may be easier to remember for some people..– KazCommented Jun 12, 2020 at 16:01
-
You can record keystrokes with
q<reg>
where <reg> is a register likea
. Finish recording withq
. You can edit recordings by pasting the register into a buffer and then yanking back.– KazCommented Jun 12, 2020 at 16:03
16k0f(l
, but impossible to tell without seeing the actual contents of your buffer.vi(p
-- it never occurred to me to usep
in visual mode that way. Usually I end up walking up the undo tree a couple steps to get back the thing that I accidentally evicted from""
(because I can never remember how to use"0
-"9
and"-
). Thanks!