Skip to main content

Section D.7 vi, vim

Subsection D.7.1 Using vi and PreTeXt together

Any smart editor, and vi is no exception, allows the addition of new commands to make repetitive tasks easier. Since creating documents with PreTeXt markup often is repetitive, it makes sense to explore the techniques of creating additional commands in vi to make editing easier.

The expectation for this section is that the reader is able to use vi to create and edit files, but no greater depth of knowledge is assumed. The term vi is meant to be inclusive, that is, it includes vim, gvim and the like.

Subsubsection D.7.1.1 Modes of vi: Command, Normal, and Insert

One of the most fundamental properties of vi is that every editing task may be accomplished using the keyboard. For different editing contexts, it is advantageous to have the keyboard strokes have different meaning; these different interpretations are called the modes of vi.

Here are the pertinent modes of vi:

  • Normal mode: This mode is for changing position within the file. For example, j moves down, 2w moves forward two words, and -2} moves backwards two paragraphs. It is also used for block operations on text: -3dd is used to delete three previous lines, or 2.yy will yank the next two sentences. Usually vi starts in normal mode.

  • Insert mode: This mode is for inserting new text into the file. Typing Galloping Gertie leapt into the air. causes that text to be inserted at the current position in the file.

  • Command mode: This mode is to execute commands. Typing /abc in normal mode initiates a forward search for the first occurrence of “abc” via the command mode. Similarly :w will use command mode to write out the current working material (buffer) to the disk.

Now a quick review of the keys used to move between modes: From a given position in a file in Normal mode, using i or a will change to Insert mode and insert text before or after that position. Similarly, I or A will insert text in front of or directly following the current line, and O or o will insert text above or below the current line. Returning to Normal mode is done using Esc.

If /, ?, or : is typed when in normal mode, a small one-line window opens up (called the command line) to receive text. This entered text is terminated by Enter. The / or ? initiates a forward or backward search for the entered text. The : sends the entered text to the vi program for further processing.

Figure D.7.1 show the keys used to move between modes.

Figure D.7.1. Keys for moving between different modes in vi

An exclamation point prefix ! in Command mode sends that command to the operating system. For example, entering :!date will cause the results of the operating system command date to be displayed on the command line. In addition the percent character % gets expanded to the name of the file being edited. If your operating system uses ls -l to list file information, then :!ls -l % will give the properties of the file being edited.

Subsubsection D.7.1.2 Using :set

The Command mode in vi allows users to change their interaction with the editor. (Remember that entering : changes to Command mode, and any text string entered in Command mode is terminated by Enter.) For example, entering :set number will cause line numbers to appear on the left. They are not in the file itself, of course, but are there for the convenience of the user. Entering :set nonumber will remove these line numbers. Similarly :set autoindent will cause a new line to preserve the indentation of the previous one and :set expandtab will replace the tab character by an appropriate number of spaces (both are very useful for writing PreTeXt documents). Some useful set commands are given in Table D.7.2.

Table D.7.2. Some useful parameters for the set command
Command Resulting change
:set autoindent A new line preserves indentation
:set expandtab Inserted tabs converted to spaces
:set rows\(=\)n Set number of lines displayed
:set columns\(=\)n Set the display size of each line
:set list Show tabs and carriage returns
:set tabstops\(=\)n Tab inserts \(n\) spaces
:set Show all current settings

Subsubsection D.7.1.3 A little editing etiquette

The xml files used with PreTeXt are ordinary text files. This makes it easy for coauthors to email them back and forth in order to expand and improve the content. There are a few potential problems, and hence some useful precautions.

  • If a Tab is entered and not expanded to spaces, different editors may display the text with different alignments.

  • If there are extra spaces at the end of a line, there may be odd line wrapping.

Fortunately, these are easy to avoid.

  • A tab character may be found in the usual manner for searches: : / Tab will find the next tab; it can be removed and replaced by spaces.

  • A space before the end of a line can be found with the search : / Space $ (vi will interpret $ as the end of a line rather than as a dollar sign). The spaces at the end of the line can then be removed.

There is another feature of vi that is helpful in this respect. Using :set list will make the tab and end of line characters visual as ^I and $. This makes the appropriate deletions easy. It is good editing etiquette to do so.

Subsubsection D.7.1.4 Abbreviations

The :abbreviation command allows the replacement of longer expressions by shorter ones. Try this: in Command mode enter

:abbreviate ups University of Puget Sound

and then (in Insert mode) type

I enjoyed my visit to the ups.

If all goes well, the abbreviation is expanded and the text is

I enjoyed my visit to the University of Puget Sound.

Now suppose you want to write My favourite letter of the Greek alphabet is upsilon. Looks like trouble with the last word, but in fact all is well. Abbreviations are not expanded until the next character after the abbreviation is read. If the next character after the abbreviation is either a letter or a number, no expansion takes place. Careful observation of the original example reveals that the abbreviation is not expanded until the period is entered. Here is another example: You want to write I love pushups. What about the end of the last word? No problem! The ups is expanded only if it is at the beginning of a word.

Amusingly enough, when in Command mode, the abbreviate command can itself be abbreviated to ab.

The choice of an abbreviation is essentially arbitrary. However, if desiring an abbreviation within “I enjoyed my visit to the Technische Hogeschool Eindhoven”, it would be folly to use :ab the Technische Hogeschool Eindhoven. The abbreviation should be mnemonic, but avoid actual words.

Now consider the following problem: what if the Enter key is one of the desired characters in the abbreviation? Since that key terminates Command mode, it appears impossible. Not so! The characters <enter> (that's seven of them) will be replaced by a single character equivalent to Enter.

There are other characters that are treated in the same manner:

Table D.7.3. Text equivalents to keyboard entries
Desired key Text equivalent (not case sensitive)
Enter <enter> or <cr>
Backspace <bs>
Insert <ins>
Delete <del>
Esc <esc>
<left>
<right>
<up>
<down>
Home <home>
End <end>
Ctrl+x <C-x>
Alt + y <M-y>

Here is a useful PreTeXt example: Define the abbreviation

            ab gm <m></m><left><left><left><left>
            

and then enter (in Insert mode)

It follows from gm\log(\theta)=0 that gm\theta=1.

It will (almost) be expanded to

            It follows from <m>\log(\theta)=0</m> that <m>\theta=1</m>.
            

That's “almost” because it is necessary to move the cursor past the </m> when leaving the mathematics input. It's pretty easy to see how this abbreviation works. The first seven characters <m></m> are expanded unchanged and then the cursor moves to the left four times to put it right where it needs to be to enter the mathematics. Careful observation will reveal a little trick used in this example: gm is followed by a \ and so terminated the abbreviation correctly. If the variable were \(x\text{,}\) then inputting gmx would not work. A workaround: enter a Space after the gm. This terminates the abbreviation and it will work as desired. (Actually, there will be an extra space before the \(x\text{,}\) which causes no ill effect, but if true perfection is desired, using gmSpace Backspace will eliminate it.)

When :ab is used, it is in effect in all modes. When abbreviations are for Input mode only (as is the present case), then iab: may be used and is usually preferable.

Here is another useful (nonmathematical) example. Define (for use in Input mode)

:iab gp <p><cr></p><up>.

Then entering “gpEnter” on a new line will create three lines appearing like:

<p>

</p>

That is, the first and third line start and end a paragraph and the cursor, represented by | is at the beginning of the second line. If autoindent is set, (see Table D.7.2), the line indentations are preserved. With this definition, the frequent task of starting a new paragraph appropriately formatted may be carried out using only three key strokes.

A further example:

:iab gcom <!--<CR><CR>--><Up>

is useful to entering comments. Starting a line with “gcom Tab” will help create nicely indented comments.

Want to know what abbreviations are in effect? Just enter :ab and they will be listed.

Subsubsection D.7.1.5 Maps

Maps, like abbreviations, are shortcuts that save extra key strokes. There is a difference in method: the map command uses key bindings that (re)define the meanings of key strokes. For example, inputting (while in Normal mode) :map <C-X> :w<CR> will define (map) the Ctrl +X key combination so that it is equivalent to typing the rest of the definition, :w<CR>. This three-key sequence, of course, just changes to Command mode, writes the current buffer to disk, and returns to Normal mode.

Presumably this newly defined key binding is meant to be invoked in Normal mode. To do so in Insert mode would be a mistake; to avoid this, there is an nmap command that defines key binding for Normal mode only. Similarly, there is an imap command for Insert mode only. Thus defining a key binding using :nmap <C-X> :w<CR> will make it valid only in Normal mode. Unlike abbreviations, the binding takes effect the moment the key is pressed.

There is a cute technique to use the same binding in Normal and Insert modes. The key binding :imap <C-X> <esc><C-X>a defines a binding for Insert mode. The first character, <esc>, changes to Normal mode; the next character, <C-X>, will use the the Normal mode definition of <C-X>. The final character a returns to the previous position in Insert mode.

We can make special use of the special characters ! and % as described at the end of Subsubsection D.7.1.1.

The author using PreTeXt usually edits an xml file, say myfile.xml . This file is then processed using xsltproc in conjunction with an xsl file, say myfile.xsl. Often the xsl file is pretext-html.xsl or pretext-latex.xsl. The usual command used by the author is xsltproc myfile.xsl myfile.xml. With this in mind, we could define a map: :nmap <C-X> !xsltproc myfile.xsl myfile.xml<CR> so that the xml file could be processed with a single keystroke. Even better: :nmap <C-X> :w<cr>:!xsltproc myfile.xsl %<CR> defines a map that first writes the file being edited to disk and then processes it with xsltproc. This command is independent of the particular file being edited.

A final somewhat complicated but very useful definition:

            imap <C-A> <Esc>yiwi<<Esc>ea></<Esc>pa><Esc>F<i
            

which is a truly cryptic sequence of key strokes. Here is what they do:

Table D.7.4.
Key strokes Interpretation
<esc> Leave input mode
yiw Save (yank) word above cursor
i< Insert <
<esc> Go to to Normal mode
e Move to end of word
a></<esc> append ></ and return to Normal mode
p Paste the saved word
a><Esc> append > and leave Insert mode
F< Move to preceding <
i Go to Insert mode

The effect of this map: Entering abc<C-A> will change abc to <abc>|</abc> where | is the position of the cursor.

To list all of your defined maps, just use :map.

Subsubsection D.7.1.6 Saving abbreviations and maps

The abbreviations and maps defined during an editing session disappear when the session is over. There are a number of ways to retain them over different sessions.

  • Ephemeral use in one file: For most versions of vi, after entering Command mode the history may be accessed using the \(\uparrow\) key. Backing up to the previous definition of an abbreviation or map and pressing Enter will reinstate the definition. The line can also be edited if changes are desired (very useful while developing new abbreviations and maps). This history is preserved between editing sessions.

  • Repeated use in several files in one directory: The abbreviations and maps can be saved in a text file, say mymaps.txt. A line within the file might look like

    :ab ups University of Puget Sound
    Vi is then started with the -s mymaps.txt option to initialize the definitions.

  • Repeated use for files in different directories: Put the abbreviations and maps in the file .vimrc (_vimrc for Windows) in your home directory.