Vim Macros for Editing DocBook Documents

Macros for key mappings, tags and entities that can be used with DocBook/XML and other similar markup languages.
Modifying the Macros

DocBook is a vast markup language offering many tags, and most projects use only a subset of the available tags. The bindings above were developed for marking up LJ articles. Your use of DocBook probably will focus on a different set of tags, so you probably need to change the templates and key bindings.

The file tagtmps.vim contains the templates inserted by the <F2> key. Listing 2 shows the template for the article tag.

Listing 2. Article Tag Template

let g:Template_article ="<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\"?><CR>"
                       \."<!DOCTYPE article SYSTEM \"docbookx.dtd\"><CR><CR>"

All templates are stored in global string variables whose names start with Template_ and end with the tag to which the template corresponds. The g: prefix in the variable name makes it a global variable. Long strings can be placed on multiple lines by prefixing the second and subsequent lines with a backslash (\) and using the dot (.) concatenation operator to append the lines together. Each string piece is contained within double quotes. Double-quoted strings understand the usual C escape sequences. You can modify the existing templates or add new ones for other tags by following the described naming sequence. Within a template the sequence -:- is used to specify where you want the cursor to be placed after the template is inserted. The macro automatically removes this string after inserting the macro.

If you want to change the function keys used to execute the macros, modify the following lines in the file mfuncs.vim:

let s:InsertTagTemplateKey   = "<F2>"
let s:InsertSymbolKey        = "<F3>"
let s:InsertForeignCharKey   = "<F4>"
let s:InsertStartTagKey      = "<F5>"
let s:InsertEndTagKey        = "<F6>"
let s:TagWordKey             = "<F7>"
let s:TagRangeKey            = "<F7>"
let s:ChangeTagKey           = "<F8>"

If you want to change the tag-keys, symbol-keys or foreign-char-keys that follow the functions keys or change the tags associated with the keys, change the corresponding lines in maps.vim. For example, to change b so it is associated with the tag <book> rather than the tag <emphasis role="bold">, look for the following line in maps.vim:

call MapTagKey("b", 0, 0, "emphasis", " role=\"bold\"")

and change it to:

call MapTagKey("b", 1, 1, "book", "")

The function MapTagKey is defined in mfuncs.vim. Its prototype is:

function! MapTagKey(key, snewline, enewline, tag, stagx)

Its parameters are explained in Table 5.

Table 5. MapTagKey Parameters

keyKeystroke(s) to bind the tag key to (for example, <F2>key).
snewlineOne if the start tag should be placed on a new line, zero otherwise.
enewlineOne if the end tag should be placed on a new line, zero otherwise.
tagThe tag associated with the key.
stagxExtra attributes that should be placed in the start tag.

The function MapTagKey merely sets up and executes a number of Vim nmap and imap commands to make the appropriate key bindings. Similarily, symbol-keys and foreign-char-keys are mapped by the functions MapSymbolKey and MapForeignCharKey. These functions each take two arguments, the key and the text to insert. For example:

call MapSymbolKey("3", "&frac34;")
call MapForeignCharKey("b", "&beta;")

Near the bottom of the file maps.vim are a handful of Vim nmap commands for binding the tag manipluation and movement keys, including delete tag, change tag and move tag. All of these bindings call the functions defined in the file tfuncs.vim.

nmap <S-F8> :call DeleteTag()^M          " Delete tag at cursor.
nmap <F9> :call CursorLeftByTag()^M      " Move left by tags.
nmap <F10> :call MoveTagLeft()^M         " Move tag left of preceding word.
nmap <F11> :call MoveTagRight()^M        " Move tag right of following word.
nmap <F12> :call CursorRightByTag()^M    " Move right by tags.

nmap <S-F9> :call TightenTagLeft()^M     " Delete whitespace left of tag.
nmap <S-F10> :call InsertStringLeftOfTag(" ")^M
                                         " Insert space to the left of tag.
nmap <S-F11> :call InsertStringRightOfTag(" ")^M
                                         " Insert space to the right of tag.
nmap <S-F12> :call TightenTagRight()^M   " Delete whitespace right of tag.

If you cat this file, these lines are going to look strange, and in some editors, all the lines are going to break right after the closing parentheses in the call. If you look at it with vim, you can see that the closing parentheses are followed by ^M, a carriage return. When you cat the file, this causes part of the line to be erased. Some editors cause a line break here. These mappings work in command mode and the ^M ends the command.


Mitch Frazier is an Associate Editor for Linux Journal.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Re: Vim Macros for Editing DocBook Documents

Anonymous's picture

i copied the 4 macro files in the article, but i get the following errors when doing, ":so maps.vim"...

i xb

i xc [CDATA[-:-]]?-:-3xi
Error detected while processing function MapTagKey:
line 57:
E121: Undefined variable: etag
E15: Invalid expression: "imap " . s:InsertEndTagKey . a:key . eicmd . etag
line 58:
E121: Undefined variable: etag
E15: Invalid expression: "nmap " . s:InsertEndTagKey . a:key . encmd . etag
line 61:
E121: Undefined variable: etag
E116: Invalid arguments for function escape(etag, """)
E15: Invalid expression: escape(etag, """)

it sort of just gets worse from there...

Re: Vim Macros for Editing DocBook Documents

Anonymous's picture

It works now when downoading the files from the LJ server.

But there is a bug that inserts closing tags...

For example:

<F2><n> produces:


<F2><p> produces:



If this could be fixed it would really make editing a lot easier so plz look over the code and post an update :-)

Morten Damsgaard-Madsen

Where is the linuxjournal ser

Anonymous's picture

Where is the linuxjournal server that you downloaded the files from?

Pablo's picture

Re: Vim Macros for Editing DocBook Documents

Anonymous's picture

As usual the socurce of errors is right in front of the computer ;-).

The script works as expected - I just forgot that I had the xml.vim script installed which interacts with these macros in funny ways...

Nice work!


Re: Vim Macros for Editing DocBook Documents

Anonymous's picture

I use Vim 6.2 and I get the same error.

If you observe the error shown, it says that a variable is undefined.

If you look into mfuncs.vim, you will see that "etags" is defined
in a conditional statement and used anyway subsequently.
Therefore, in the cases where the conditional statement is missed,
"etags" is undefined subsequently.

The author should have a look at the code one again and post here an update.

Re: Vim Macros for Editing DocBook Documents

Anonymous's picture

Same goes for me: the version of vim I use is 6.3. Maybe the macros of this article are meant for an older version ?

Geek Guide
The DevOps Toolbox

Tools and Technologies for Scale and Reliability
by Linux Journal Editor Bill Childers

Get your free copy today

Sponsored by IBM

Upcoming Webinar
8 Signs You're Beyond Cron

Scheduling Crontabs With an Enterprise Scheduler
11am CDT, April 29th
Moderated by Linux Journal Contributor Mike Diehl

Sign up now

Sponsored by Skybot