4

I'm familiar with vertical blocks, and I often ctrl+v down down down shift+I foobar esc to write foobar in various locations at once. This is useful if I want to replace <td> to <th> in a chain, for instance.

Since not all the text blocks are of equal size, I don't know how to do the same for </td> to </th>. I can think of selecting multiple lines as I did earlier, move to the end of the line with shift+a, maybe, move one to the left, delete a character with x, and type my h, but I don't know how to move my position(s) when I am in visual block mode.

Is there a way to select a position as active, and move as I usually would with my marker, choosing where to write?

In SublimeText3 I would do something like ctrl+d to select the cases I'm looking for (skipping with ctrl+k+d if necessary), moving to the end-of-line with end (home for the beginning of the line), and then moving with the arrow keys (alternatively with ctrl+arrow keys).

An example scenario:

<tr>
    <th>Language</th>
    <th>Oral</th>
    <th>Written</th>
    <th>Diplomas</th>
    <th>Notes</th>
</tr>

which I want to be

<tr>
    <td>Language</td>
    <td>Oral</td>
    <td>Written</td>
    <td>Diplomas</td>
    <td>Notes</td>
</tr>
5
  • I gues you want github.com/terryma/vim-multiple-cursors
    – dedowsdi
    Apr 16, 2019 at 13:37
  • Interesting plugin. I might take a look at it on my home machine. Is there a native way to do the same, or similar?
    – mazunki
    Apr 16, 2019 at 13:40
  • There is. But you need to provide a text sample. It's hard to understand what you really want.
    – dedowsdi
    Apr 16, 2019 at 13:43
  • I've added my scenario.
    – mazunki
    Apr 16, 2019 at 14:01
  • A few years ago we had a question about multiple cursors and I think it is pretty related to this one.
    – statox
    Apr 16, 2019 at 14:02

5 Answers 5

3

Aside from the suggested plugin vim-multiple-cursors, you have different options:

For example you can go on the parent tag (tr I guess?) and visual select in the tag:

vit

Then do a substitution in the tr tag only:

:'<,'>s/td/th/g

If you want to do a more complex change than a substitution, you can search for a pattern matching all the places you want to apply a change, go to the first one, do your change, and for all the other, if the change is atomic, use . to repeat it:

/td>
ceth<esc>
n.n.n.

The first command searches for a td> tag, the second cut until the end (ce) and types th, then leaves the insert mode. The third line goes to the next td (n), execute the second command (.) and this 3 times (do it as many times as you need of course, it is just an example).

If the change is more complex, you can also create a macro.

There is an interesting article about multiple cursor (or rather lack of) in Vim: https://medium.com/@schtoeffel/you-don-t-need-more-than-one-cursor-in-vim-2c44117d51db

7
  • I neither know how to do a substitution in a selected mode (vit is great to select my tags to apply it too, though!), nor how to use move my cursor after having found my matches with n Can you explain this?
    – mazunki
    Apr 16, 2019 at 13:59
  • For the first one, do a visual selection, then press : to enter in command mode, it will show: :\<,\> which means "type a command that I will run in a range (\< being the beginning of the selection and \> being the end. Your command would look like: :\<,\>s/td/th/g.
    – padawin
    Apr 16, 2019 at 14:01
  • When you do a search in Vim, you can then go from result to result of your search with the n key. I am updating my answer with an example.
    – padawin
    Apr 16, 2019 at 14:04
  • Interesting. Knowing RegEx, I find the substitution method really nice. What effect does the last /g mean? I assume global.
    – mazunki
    Apr 16, 2019 at 14:15
  • yes, global, especially in his case where he wants to replace both start and end td tags of the lines
    – padawin
    Apr 16, 2019 at 14:16
2

I know there has already answers. But i couldn't help to try something i just learned from @padawin's link.

  1. /th> search th>
  2. cgntd> change th> to td>
  3. ......... repeat 9 times with 9 dots. You can just press the button, don't lift it.

check :h gn

update

If your text doesn't contain th, place your cursor under th, you can replace word under cursor like this:

  1. *#cgntd
    • * set @/ to \v<th>, search forward
    • # search backward, restore cursor, you can also use N if you want.
    • cgntd replace next match (or the one under cursor) to td
  2. .........
    • repeat, You can hold . , don't release
1
  • Indeed, I just played a bit with it too, it is definitely promising! I'll try to keep it in mind.
    – padawin
    Apr 16, 2019 at 14:45
1

Building on padawin’s answer, I would go to the <tr> tag, vit, and then

:s-<\(/\)?th>-<\1td>-g

To do the replacement. If your text doesn’t contain th, then :s/th/td/g is simpler.

Alternately, with tpope’s surround plugin, on each th, do cst<td>. Combined with tpope’s repeat, you can do this for one line and repeat on each with the . command, or even :g/<th>/normal f>lcst<td>

1

I use surround.vim which makes changing tags easier, e.g. cst<td>. Combine this with :normal and a visual mode makes this pretty easy. Just visually select the lines with V then run:

:norm cst<td>

For more help see:

:h :range
:h :norm
:h V
1
  • Nice to see a similar idea ;)
    – D. Ben Knoble
    Apr 17, 2019 at 2:42
0

Note: Not an answer anymore after your last update to the question, but perhaps still useful to know.


Try it like this:

  1. Goto end of first line.
  2. Hit <Ctrl-V>$
  3. Move down
  4. Hit Afoobar<esc>

With the $ you hit in step 2, the visual block selection is always till end-of-line. Even if one of the following lines is shorter.

2
  • This works if I delete all the end-of-line > tags in the html, and add them in the foobar. I tried tricking it with I, but that worked out wrong. Can I somehow tell it to move one position to the left?
    – mazunki
    Apr 16, 2019 at 13:52
  • @mazunki I don't think this is possible. I would do it with search/replace. See the answer from D. Ben Knoble.
    – Ralf
    Apr 16, 2019 at 14:25

Your Answer

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

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