2

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
  • That series of keystrokes doesn't look too bad to me, once you've taken into account the suggestions in @Biggybi's answer. There might well be a quicker way of getting to what you want yank than 16k0f(l, but impossible to tell without seeing the actual contents of your buffer.
    – Rich
    Commented Jun 11, 2020 at 11:06
  • PS for the i( and similar text objects, b works in place of (!
    – D. Ben Knoble
    Commented Jun 11, 2020 at 11:48
  • 1
    Love vi(p -- it never occurred to me to use p 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!
    – trent
    Commented Jun 11, 2020 at 19:31

3 Answers 3

4

jump to function call

16k is not ideal, it only works if you turn on 'relativenumber' and target function is visible.

  1. by search. /func_name or ?func_name . If they share the same name, you can place cursor at function name and use * or #.

  2. 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 run CocReference. You can create map 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:

  1. `. jump to last change.
  2. `^ jump to last insertion.
  3. gi continue last insertion.
  4. ctrl-o go to older cursor position in jump list. This won't work if you use 16k, as k doesn't change jump list.

This part is not related to your question, feel free to skip it

jump to function definition

  1. by lsp. If you use coc.nvim, you can use CocList 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)"

  2. by tag. If you update your tag files on the fly, you can use :tag func_tag, you can also use c-] to jump to tag under cursor. Otherwise you need a plugin ( e.g. fzf, ctrlp, ...) that support buffer tag jump.

5
  • 1
    Regarding #4, see my comment below the other question. . Great minds, as they say, think alike.
    – B Layer
    Commented Jun 11, 2020 at 11:14
  • 1
    this 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
    – DannyM
    Commented Jun 11, 2020 at 11:20
  • 1
    Yep. Good post. Have a vote.
    – B Layer
    Commented Jun 11, 2020 at 11:24
  • @thelmuxkriovar I misread your question, I thought you want to jump to function definition, sorry for that.
    – dedowsdi
    Commented Jun 11, 2020 at 11:44
  • @thelmuxkriovar See update for 1st part.
    – dedowsdi
    Commented Jun 11, 2020 at 12:10
3

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 16j0. This only works with 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.

4
  • 1
    I didn't know about <c-o>, that's good to know!
    – DannyM
    Commented Jun 11, 2020 at 9:28
  • 2
    But 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 doing ma if I'm about to do something like 16k.
    – B Layer
    Commented Jun 11, 2020 at 11:11
  • @BLayer Indeed, I did not realize. I'm editing it rn. Nice catch, thank you!
    – Biggybi
    Commented Jun 11, 2020 at 11:24
  • No problemo, señor!
    – B Layer
    Commented Jun 11, 2020 at 11:25
2

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@@.

3
  • 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)
    – DannyM
    Commented 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..
    – Kaz
    Commented Jun 12, 2020 at 16:01
  • You can record keystrokes with q<reg> where <reg> is a register like a. Finish recording with q. You can edit recordings by pasting the register into a buffer and then yanking back.
    – Kaz
    Commented Jun 12, 2020 at 16:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.