I was writing a reStructuredText and I ran out of character for headings, that is too many levels. If you don’t understand, it’s fine. Basically, what I need is to make the heading marking characters - and . into = and - as seen in the following original text:

Heading 1
---------

blah-foobar... abc--def.

Heading 2
.........

Something

----

Hola.

If you have regular expression experience, you would suggest s/-/=/ for Heading 1, but that is problematic as you can see there is - and -- in text, also the horizontal rule ----.

Then, you would think, it’s easy to match just ^-\{5,\}$ should be sufficient to match or the heading marking characters. But how about replacement? You see the problem I encountered.

After reading the Vim help, I found out you can do s/// in s/// and problem would be solved. There may be other way or even ingenious method, but this what I have now:

%s/^-\{5,\}$/\=substitute(submatch(0), "-", "=", "g")/

It turns out we can actually do some coding inside the substitution operation. How awesome is that? The matching expression should be simple to understand, and replacement part is also quite coder-readable:

\=substitute(submatch(0), "-", "=", "g")

\= means Substitute with an expression. The expression here is another substitution with submatch(0) as input string, which is actually the matched string of s///, that’s something like ---------. With this second substitution, we can replace all the characters in a match string with some character we desire.

Note: You can actually perform an arithmetic operation like \=submatch(0) + 1 if the match is digits, see submatch() for more detail.

So, the outer substitution matches all heading marking characters and the inner substitution replaces those characters and pass to the outer substitution to replace the match.