Vim as XML Editor: ed
And now for something completely different, just for the fun of it :)Let's explore the ways of Vim's grand-grandfather, the
standard Unix editor ed
.
Working with ed
is like walking in the
dark. Although you do have a flashlight, going by train or car would be
much more convenient.
But for certain tasks this ancient editor still is useful, for example when you want to show the editing steps to someone (every command is visible on the screen), or apply them automatically.
We'll use GNU ed, which might be on your
system already if you're on Linux.
$ ed --version
GNU ed version 0.2
Let's try to create a tiny XML file:
$ ed -p '§ '
§ <fruits>
?
§ h
Unknown command
§ q
$
The ? shows that there was an error, and
command h caused ed to print the error message.
q stands for quit.
Just like Vim,
ed
has modes. When started it's in
command mode. Input commands such as a (append) or
i (insert) make ed
switch to
input mode. So let's try it again:
$ ed -p '§ '
§ a
<fruits>
<fruit name="Mango"/>
<fruit name="Rsapberry"/>
</fruits>
.
§ w fruits.xml
71
§ q
$
The dot causes ed to switch back to command mode (it only has two).
-p '§ ' sets the prompt which indicates command
mode.
w and q are familiar from Vim.
I misspelled the name of the second fruit. I could have deleted the
rest of the line (with
[backspace]
) then complete it
correctly (the arrow keys don't work, at least here), but I
already had entered that line (pressed [enter]
). There are
various ways to correct it. We could change the whole line with
c
$ ed -p '§ ' fruits.xml
71
§ 3c
<fruit name="Raspberry"/>
.
§ wq
71
$ tee < fruits.xml
<fruits>
<fruit name="Mango"/>
<fruit name="Raspberry"/>
</fruits>
$
or we could substitute the erratic string:
$ ed -p '§ ' fruits.xml
71
§ 3s/Rsap/Rasp/p
<fruit name="Raspberry"/>
After the substitution command the changed line becomes the current
line. The p after the substitution prints the
new version of the line, and %p would have printed
whole document.
Now let's add some attributes to each fruit
element. We can walk through them with the G/regex/
command:
§ G/<fruit /
<fruit name="Mango"/>
s/fruit /&latin-name="Mangifera Indica" /p
<fruit latin-name="Mangifera Indica" name="Mango"/>
<fruit name="Raspberry"/>
s/fruit /&latin-name="Rubus Idaeus" /p
<fruit latin-name="Rubus Idaeus" name="Raspberry"/>
Let's double the indent:
§ g/^ /s/ \+/&&/
§ %p
<fruits>
<fruit latin-name="Mangifera Indica" name="Mango"/>
<fruit latin-name="Rubus Idaeus" name="Raspberry"/>
</fruits>
Pretty printing
... can be done like shown in the following example,
and makes it easier to enter many elements:
$ ed -p '§ '
§ a
<a><b ><c /> </b></a>
.
§ w pp.xml
22
§ e !xmllint --format %
xmllint --format pp.xml
53
§ %n
1 <?xml version="1.0"?>
2 <a>
3 <b>
4 <c/>
5 </b>
6 </a>
§ 4a
<d><e><f/></e></d>
.
§ w
72
§ e !xmllint --format %
xmllint --format pp.xml
104
§ %p
<?xml version="1.0"?>
<a>
<b>
<c/>
<d>
<e>
<f/>
</e>
</d>
</b>
</a>
§ wq
104
$