This one will clear out all empty lines within <pre>
blocks:
:%s_<pre>\zs\_.\{-}\ze</pre>_\=substitute(submatch(0), '\n\n\@=', '', 'g')_g
WTF:
:%s_
: starts a substitution command over all lines in the buffer. You can use any character after the s
; using one that you're not using within the pattern (in this case _
) means you don't have to escape it within the pattern.
<pre>\zs\_.\{-}\ze</pre>
: minimal, multiline match of all characters within <pre>
blocks.
_
: delimits the match string from the replacement
\=
: putting this at the beginning of the replacement indicates that the replacement is a vimscript expression to be evaluated.
substitute(submatch(0), '\n\n\@=', '', 'g')
:
- The replacement expression is a
substitute(...)
function call.
submatch(0)
: this gives the full outer match, in this case everything between \zs
and \ze
.
\n\n\@=
: this RE matches any newline that's followed by a newline, without actually advancing past that second newline. The \@=
element is known as a "zero-width lookahead assertion"; :help /\@
will give you more details.
- the rest of it is pretty simple, just replace the newline with nothing for all occurrences. Note that the second newline (the one spotted by the lookahead) isn't considered part of the match and so doesn't get replaced (at least, not until the next iteration, when it will be replaced if it's followed by a third consecutive newline).
Finally, _g
just closes the expression with a g
flag to indicate that all instances should be replaced. I think the mnemonic is "global".