Here is a solution which is not perfect but not that bad:
First add these lines to your .vimrc
:
function! ReJoinTags() range
set nowrapscan
let @/='<\(\k\+\)>\([^<]\|\n\)\{-}<\/\1>'
let initialLine = line(".")
normal ngnJ
if initialLine != line(".")
call ReJoinTags()
endif
endfunction
Put your cursor on the root tag of your xml and call the function with :call ReJoinTags()
The function does several things:
- First set
nowrapscan
so that a research will not wrap around the file.
- Set the search register to a regex which match only the content of tags which doesn't contains subtags (i.e. only the deepest tags). I'll detail the regex later.
- Get the current position of the cursor
- Go to the next match, select it and join the selection.
- Check if the cursor has moved and if so it means that a new tag has been joined so call the function again to try and join the next match.
This is not perfect but on my system from this file:
<context>
<p>Here is a paragraph about some stuff that happened
and someone did a nice printing that makes the text
break and stuff, which is nice unless you have to
it it, and now its a PITA.</p>
<p>Here is another paragraph. I suppose I could have
Googled to get some lorem ipsum text to copy paste
for this example, but that's not very fun and I wanted
an excuse to use the then how could I use the word
floccinaucinihilipilification?</p>
<p>Ignoring this paragraph would be absolute
floccinaucinihilipilification!</p>
<a>
<b>ldkfn sqkldfj lskjdfh
sdfkljh lsdkfjh</b>
<b>sdf sflj zelrfkj erfh
zer sdf sdf</b>
<b>a zerlfkj ezrlfk erf</b>
</a>
<a>
<b>
<c> sdf zerkj zer df
zeroi ferioj</c>
</b>
<b>ldkfn sqkldfj lskjdfh
sdfkljh lsdkfjh</b>
<b>sdf sflj zelrfkj erfh
zer sdf sdf</b>
</a>
</context>
I get this:
<context>
<p>Here is a paragraph about some stuff that happened and someone did a nice printing that makes the text break and stuff, which is nice unless you have to it it, and now its a PITA.</p>
<p>Here is another paragraph. I suppose I could have Googled to get some lorem ipsum text to copy paste for this example, but that's not very fun and I wanted an excuse to use the then how could I use the word floccinaucinihilipilification?</p>
<p>Ignoring this paragraph would be absolute floccinaucinihilipilification!</p>
<a>
<b>ldkfn sqkldfj lskjdfh sdfkljh lsdkfjh</b>
<b>sdf sflj zelrfkj erfh zer sdf sdf</b>
<b>a zerlfkj ezrlfk erf</b> </a>
<a>
<b>
<c> sdf zerkj zer df zeroi ferioj</c>
</b>
<b>ldkfn sqkldfj lskjdfh sdfkljh lsdkfjh</b>
<b>sdf sflj zelrfkj erfh zer sdf sdf</b> </a>
</context>
There seems to be a problem with some tags but it's still a beginning.
For the ones interested in the regex part, first feel free to tell me how to improve it: I'm far from being a regex guru so I'll be happy to learn more.
Now for the details:
<\(\k\+\)>\([^<]\|\n\)\{-}<\/\1>
< \k\+ > The name of a tag
<\(\k\+\)> Captures the name of a tag
\([^<]\|\n\)\{-}
\( \)\{-} Capture as few as possible occurences of the group
[^<]\|\n A group containing every character which is not '<' or is a new line
<\/\1> The closing tag