1. Introduction
The vi editor is ubiquitous, especially in Linux and Unix environments. It’s useful to beginners, as well as power users.
In this tutorial, we discuss an advanced topic, namely text objects in vi. First, we go over the editor’s basic modes and operations. Next, we explore character groups and briefly explain the grammar of vi. After that, we see how basic text object operations are performed. Finally, we look at ways to create our own custom text objects.
Here, we use vi and Vi (editor) as aliases for both the Vi and Vim editors.
We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It is POSIX-compliant and should work in any such environment.
2. Basic vi
To reiterate, the Vi editor has three modes:
- visual
- command
- insert
Immediately after the start, vi is in visual mode. To go into command mode, we use : (colon). On the other hand, with one of several characters such as i, a, and o, we can transition to insert mode. Finally, going back to visual mode is most commonly done via Esc (escape).
Of course, since its description defines it as a text editor, Vi supports many basic and easily-accessible capabilities.
For starters, we can visualize, traverse, write, delete. In addition, we might want to select, cut, copy, paste, search and replace.
While the first group can work with single characters, like regular editors usually do, the second one would be wasted on them. For example, we can use the arrow keys to move the cursor left and right by one character, but cutting and pasting a single character is rarely helpful.
3. Character Grouping
To edit quickly, we might want to work on a logical group of characters. For instance, the text is often split into paragraphs. To that end, some common operations recognize groups of characters as text objects:
- character
- word
- sentence
- line
- paragraph
- other text objects
We already discussed single characters as the norm: they are easy to define and isolate. But, on the other hand, the boundaries for higher-order groups can be unclear.
Do we only use whitespace characters as word separators, or do any non-alphanumeric characters work as well? What’s a line ending?
The Vi editor spares us all these details by including operands, which help distinguish between such objects.
4. Text Object Operation Grammar
Apart from the character groups we already discussed, many operations in vi work on or with specific predefined objects:
- va” – Visually select All content within and including “” of a DOUBLE QUOTEd string
- ya’ – Yank/copy All content within and including ” of a SINGLE QUOTEd string
- ci( – Change content Inside but not including () of a string in PARENTHESES
- di[ – Delete content Inside but not including [] of a string in SQUARE BRACKETs
These examples demonstrate the Vi editor’s grammar for text object operations. First, we have an action: here v for visual selection, y for yank/copy, c for change, d for delete.
After the action, we have a text object or a motion, which specifies what we act on. Let’s explore each.
5. Text Objects and Motions
In fact, all of the examples thus far used concrete surrounding characters to isolate parts of data. However, the Vi editor has many defined motions and text objects.
Importantly, we can explore the exact descriptions with the :help text-objects and :help object-motions commands within the editor.
5.1. Character
While characters are just the atoms of text editing and thus most operations, there are motions that use them as markers for bigger actions. For example, we can use dt- (Delete To DASH) to delete everything up to the next dash.
5.2. Words
We specify words with w:
- cw – Change content from current cursor position up to the next Word
- daw – Delete All content of and around the Word at the current cursor position
Note how the first example distinguishes a word as a motion (pointer to a direction or position) versus the second using a word as the actual action text object.
5.3. Sentence
Sentences use the character s. Furthermore, a sentence ends at a period, exclamation point, or question mark, followed by whitespace.
Indeed, to select this entire sentence, we just place the cursor on one of its words (from I to the ending) and use vis to get everything, excluding the trailing punctuation and whitespace.
In addition, there are the ( and ) motions, which allow us to use a command like d( to delete everything from the current cursor position to the beginning of the current sentence.
5.4. Paragraph
We work on paragraphs via p. They are surrounded by empty lines and usually benefit the most from the beginning and end markers.
For example, we can place the cursor at the comma in this sentence, and d} will leave only “For example”. All of the following text in the paragraph, including this sentence, will vanish.
What if we want to define a new text object?
6. Custom Text Objects and Motions
Since vi supports scripting, we can create or simulate many complex behaviors. Furthermore, there is also an out-of-the-box mechanism for custom selections.
6.1. Command Mappings
Scripting in the Vi editor is commonly done by adding lines to the vimrc configuration file:
xnoremap il g_o^
onoremap il :normal vil
In this example, we use xnoremap to map il in visual mode to the command g_o^. The latter instructs vi to:
- g_ (Go and select to the _ last non-space character of the line)
- o (move the cursor to the Other side of the selection, without changing it)
- ^ (select to the ^ beginning of the line)
The second line maps il in operator-pending mode to vil (now vg_o^) in normal mode. Thus, we have il for use like any other inside-command.
Alternatively, we can define objects on a per-session basis.
6.2. Marks
The Vi editor has 26 marks available. Each mark saves the current cursor position for future reference. We set marks with m, followed by a lower-case letter. Once set, we can use two commands in conjunction with a mark’s letter:
- ‘ (apostrophe) – go to a mark line’s beginning
- ` (backtick) – go to a mark’s position
These combinations represent movements so that they can be used in other commands. For example, by marking the beginning and end of a custom text segment with ma and MB, respectively, we can `av`b to select it or `ad`b to delete it.
Actually, marks are much more versatile, so that we can use the :help mark-motions command to check them out in-depth.
7. Summary
In this tutorial, we explored text objects and how to use them in the Vi editor. While there are many, here is a good and concise vi cheat sheet, which covers much of what we discussed, as well as a lot more.
In conclusion, one can even play a game to learn the intricacies of this classical editor.