3

Sometimes I have a bunch of lines, where there's a column clearly indicating some commonality between them, which in general doesn't go far beyond that column; this is an example, I think general enough:

...
what  1: and then
who   2: there's
when  3: some other
where 4: text
ok?   5: on these lines
...

I want to insert the characterwise text from a register (say the text is text from some register,) in those five lines, right after the space which follows the :, so that the result looks like this:

...
what  1: text from some register,and then
who   2: text from some register,there's
when  3: text from some register,some other
where 4: text from some register,text
ok?   5: text from some register,on these lines
...

If I with the cursor on the second a in the file I hit Ctrl-V4jP, the letters a, t, s, t, o are deleted, just like :h v_p describes.

5
  • Wow. Why does this question deserve a downvote? – Enlico Nov 24 '20 at 8:24
  • 1
    I can't really explain why someone downvoted the question, but I do see some problems on it myself. Talking about the lines from the first file: "the lines are not necessarily so much similar." How so? How different can they be? Why not give a better example to illustrate how different they are? What are the similarities you can actually count on? Then on the second file, why mention it at all if you seem to only want a single line from it? And why make the other lines so similar (originally the same)? I think there's quite a bit of ambiguity in the question, recommend addressing it. – filbranden Nov 26 '20 at 4:27
  • 1
    If the objective is to put the contents of the default register where a . currently is, then my answer would be :%norm f.P which I think is actually really neat... But since the question has many problems that I detailed above, I decided not to post an answer, since I couldn't really tell whether this was exactly what was being requested... Please clarify your question if you can. I'd post an answer (and upvote the question) if the question was well defined and well phrased. – filbranden Nov 26 '20 at 4:32
  • 1
    @filbranden, I've updated the question. Do you think it is clearer and more concise now? – Enlico Nov 26 '20 at 10:55
  • That's much clearer, thanks! I still think you could call out some parts very explicitly, such as the fact that the colons are all aligned to the same column, and that there's always a single space after the colons, but the mention of the shortcomings of block visual mode make that somewhat understood. Upvoted, and I'll definitely post an answer too. Thank you! – filbranden Nov 27 '20 at 0:42
2

I tend to like using :normal with a range for this kind of edit.

Using :normal with a range is often similar to using a macro, but it can be more convenient in cases when:

  • You want a single modification per line. (A macro can be more flexible in selecting what to modify.)
  • You can express the whole command using only alpha-numeric characters (no need to enter special keys such as a sequence involving Ctrl or the Esc key.)
  • You don't need visual feedback while coming up with the sequence of commands (since you're writing them in the Ex command-line, instead of recording them while seeing what they do, which is how macros work.)
  • There's at most one insertion (mostly so that you don't need to issue an Esc at the end of the insertion; ending a :normal with an insertion will implicitly issue an Esc at the end of the command execution.)

In this case, you can simply forward to the first : in a line (with f:), then move another character right (with l), so you're on the space after the colon, and then use p to put the contents of the default register.

Putting it all together:

:%normal f:lp

This will execute this command for every line in the buffer. You can use a more specific range if you desire to do so. You can even use a Visual selection to decide which lines to act upon and then simply use:

:'<,'>normal f:lp

Note that when you press : from Visual mode, Vim will automatically add the :'<,'> part, so you only need to type the normal f:lp then.

One advantage of this approach using :normal over a Visual Block selection is that this approach will work regardless of whether the : characters are all aligned to the same column or not. As long as there's uniformity of being the first : character and always followed by a single space, this approach will work.

1
  • 1
    Accepting this because of the last paragraph which gives invaluable insight into possible uses of visual mode, even though in the case that the :s are all in the same column my self answer seems to be a far easier way. – Enlico Nov 27 '20 at 6:30
2

Would it be possible to try it with a macro?

  1. Perform your yank command as you first describe (0y$).
  2. Move the cursor to the first period where you want to "put" the yanked line.
  3. Press q and then another key to store the macro (e.g. push q again)
  4. Press P and then j for the macro keys.
  5. Press q again to stop the macro recording.
  6. For the rest of the lines, when over the ., press @q to execute the macro. You can also press 3@q I believe to execute it three times in succession.

Hope that helps!

1
  • I know of macros, but they don't go in muscle memory (the faulty approach I described in my question goes there, except at most for the 3, which you need time to work out), and muscle memory is important for such a basic task. I've used macros, but for pretty complicated things. +1 nonetheless. – Enlico Nov 23 '20 at 15:58
2

Wow, actually it's easier than I thought!

:h v_p reads

The previously selected text is put in the unnamed register.

therefore probably the best way to do what I want is Ctrl-V3jPp, or even Ctrl-V3jpp (because P and p seem to do the same in block-visual mode), where the latter p puts back what the former p deleted, right at the place it is needed.

2

This is a good point to highlight a shortcoming of P (or the equivalent p) in Visual Block mode (more generally, in Visual mode.) It replaces the selected text, so it's not a great fit for this use case.

While you can work around it, perhaps a more straightforward alternative would be to use Visual-block Insert and then use Ctrl+R to insert the contents of the default register, from Insert mode. (See :help i_CTRL-R for more details.)

Putting it all together:

  1. Place the cursor on the a of and in the first line, then use Ctrl+V, 4, j to create a Visual Block selection on the proper column, spanning all lines where the contents should be inserted.
  2. Use I to start Visual-block Insert at the start of every line in the block.
  3. Use Ctrl+R, " to insert the contents of the default register, from Insert mode.
  4. Optionally, add another space after the comma, or insert more text if you'd like.
  5. Leave Visual-block Insert by pressing Esc. At that moment, that same insertion will be replicated to every line in the block.

One advantage of this approach is that you get to insert more text around the default register, which is useful in your particular example since it allows to easily add a trailing space after the comma, without having to modify the default register first to add that space.

1

Would you try this?

:%s/: \zs/\=@+

If you want space after the comma set your clipboard register before running the above command:

:let @+='text from some register, '
1
  • 1
    Very nice! Also good is to use Ctrl+R + on the replacement side, to get the contents of the register. That makes it even easier to prepend or append more text around it (e.g. add a trailing space.) – filbranden Dec 24 '20 at 17:12
0

Easiest way to do it is to:

  1. Move to the first letter of the word you want to change.
  2. Go in visual block mode (ctrl-v).
  3. Then j to select all the lines.
  4. Then hit $, once the selection is made.
  5. Hit c type your new word and finally hit <Esc>.

Explanation:

  • `ctrl-v: enter visual block mode.
  • j: move down 1 line.
  • $: move to end of line.
  • c: (small "c") change (in this case, it acts like changeword.)
  • <Esc>: return to normal mode.

NB: This works for words at the end of lines. If all the words are in the middle of a line, use cw instead.

1
  • 1
    Even in the original formulation of the question I had written that the text (text, not just one word) I wanted to put was from another file; furthermore toward the end I wrote that the first step I attempted was to yank the text from the second file. This should apparent that I don't want to type my new text manually, but I want to put it from a register. The updated question should make all of this more apparent. – Enlico Nov 26 '20 at 14:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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