Jest Phulin
Jest Phulin

Reputation: 121

How do I renumber a list in vim?

I wrote a section of a webpage that had the following bit...

<span id="item01">   some first presented text</span>
<span id="item02">   some other text, presented second</span>
<span id="item03">   more text</span>
....
<span id="item15">  last bit of text.</span>

I then realized that it should have been numbered from 14 to 0, not 1 to 15. (Yes, bad design on my part, not planning out the JavaScript first.)

Question. Is there an easy way in vim to do math on the numbers in a regular expression? What I would like to do is a search on the text "item[00-99]", and have it return the text "item(15-original number)"

The search seems easy enough -- /item([0-9][0-9])/ (parentheses to put the found numbers into a buffer), but is it even possible to do math on this?
Macro for making numbered lists in vim? gives a way to number something from scratch, but I'm looking for a renumbering method.

Upvotes: 8

Views: 1394

Answers (4)

Boris Brodski
Boris Brodski

Reputation: 8715

Another interesting way is to use g<CTRL-a> (:help v_g_CTRL-A for more information)

Start from

<span id="item01">   some first presented text</span>
<span id="item02">   some other text, presented second</span>
<span id="item03">   more text</span>
....
<span id="item15">  last bit of text.</span>

Use visual block mode to reset all numbers to 00:

  • <CTRL-V> select all numbers
  • r0 replace all numbers with zeros

You should be seen:

<span id="item00">   some first presented text</span>
<span id="item00">   some other text, presented second</span>
<span id="item00">   more text</span>
....
<span id="item00">  last bit of text.</span>

Now restore your block select with gv or just select all lines with V and press g<CTRL+a>

<span id="item01">   some first presented text</span>
<span id="item02">   some other text, presented second</span>
<span id="item03">   more text</span>
....
<span id="item015">  last bit of text.</span>

Unfortunately one last clean up is needed here. As you can see, all two digit numbers get 0 in front. Use visual block mode <CTRL+v> again to select and remove unwanted zeros.

<span id="item01">   some first presented text</span>
<span id="item02">   some other text, presented second</span>
<span id="item03">   more text</span>
....
<span id="item15">  last bit of text.</span>

Now you are done :)

Upvotes: 7

Sato Katsura
Sato Katsura

Reputation: 3086

You might want to take a look at the VisIncr plugin. It adds support for increasing / decreasing columns of numbers, dates, and day names, in various formats. Quite handy when you have to deal with these kind of things.

Upvotes: 2

JJoao
JJoao

Reputation: 5347

If you have vim with perl (many distributions have that by default), you can use :perldo commands to do it. (@Marth solution is better)

:perldo s/(?<=item)(\d+)/15 - $1/e

Upvotes: 2

Marth
Marth

Reputation: 24812

:%s/item\zs\d\+/\=15 - submatch(0)/

will do what you want.
Breaking it down:

  • item\zs\d\+: match numbers after item (the \zs indicates the beginning of the match)
  • \=: indicate that the replace is an expression
  • 15 - submatch(0): returns 15 minus the number matched

Upvotes: 12

Related Questions