Skip to content
academia.sh

Lesson 20 / 20

Terminal Text Editors

The design line from line editor to screen editor, comparing modal and modeless editors, basic editing commands, and declaring an editor choice through an environment variable.

Contents

Files throughout the course were created with printf and redirection. That works for one-line files; it is not enough for changing a line in the middle of a script or adding two lines to a configuration file.

On a server with no graphical interface — the case for most remote sessions — editing is done in the terminal. This lesson covers the two design families of terminal editors and the choice between them.

The Line Editor

Terminal editors’ design comes from the era when printing terminals were used. There was no screen back then; output was printed on paper, and moving a cursor was not a thing. Editing was done with commands over line numbers.

This design’s representative, ed, is still defined in POSIX and still works. A complete session to add a line to the project script:

$ ed scripts/summary.sh
142
$
echo "raw measurement file: $(ls -1 "$HOME/project/data/raw" | wc -l)"
a
echo "current measurement: $(readlink "$HOME/project/data/current.csv")"
.
%p
#!/bin/sh
# Reports the count of measurement files in project/data/raw
echo "raw measurement file: $(ls -1 "$HOME/project/data/raw" | wc -l)"
echo "current measurement: $(readlink "$HOME/project/data/current.csv")"
w
215
q

The session should be read line by line. The 142 printed at open is the file’s byte count. The $ command prints the last line. a switches to append mode; the following lines are added to the file, and a lone period ends append mode. %p prints the entire file. w writes and reports the new byte count, q quits.

ed shows no prompt and prints only a question mark on error. This is inconvenient for everyday use, but matters for two reasons. First, its command language has been inherited in full by later editors. Second, ed can be driven from scripts through redirection, and this is sometimes the only option in rescue environments.

The Modal Screen Editor

Once screen terminals became widespread, a visual mode was added on top of the line editor: part of the file is shown on screen, and the cursor moves over it. This design was standardized in POSIX under the name vi and is expected to be present on every standard-conforming system.

The editor’s distinguishing feature is its modes. The same key does different things depending on the current mode:

Mode Function How to enter
Normal Navigation and editing commands Esc
Insert Typed characters go into the text i, a, o
Command line Line editor commands :

The design’s rationale is that keys become a language. Because letter keys do not enter characters in normal mode, all of them can be used as commands; commands themselves are built by combining an action with a motion. d is the delete action, w is a word-forward motion; dw deletes a word. 3dw deletes three words. Every learned motion can combine with every learned action.

The approach it is contrasted with is binding commands to modifier-key combinations. In that approach the number of commands is limited by the number of combinations, and combinations cannot be composed.

The modal design’s second gain is that it uses only basic characters: it works on terminals that do not send arrow keys or modifier combinations. This is a practical advantage for remote sessions and rescue consoles.

Its cost is that a command typed in insert mode gets mixed into the text. Mode confusion is the problem new users run into most, and its fix is fixed: when unsure, press Esc and return to normal mode.

The Smallest Survival Set

The commands needed to open, change, and save a file are few:

Command Function
i Enters insert mode before the cursor
a Enters insert mode after the cursor
o Opens a new line below and enters insert mode
Esc Returns to normal mode
h j k l Left, down, up, right
0 / $ Start of line / end of line
gg / G Start of file / end of file
x Deletes the character under the cursor
dd Deletes the current line
u Undoes the last change
/pattern Search forward; n for next match
:w Saves
:q Quits
:q! Quits, discarding changes
:wq Saves and quits

Commands beginning with a colon in the last four rows are the line editor’s commands. The inheritance shows here: :w and :q are the same commands as w and q in an ed session.

The same command language can also be run directly; the editor’s line mode can be driven from scripts:

$ printf '%s/file/count/\nwq\n' | ex -s /tmp/edit.sh
$ cat /tmp/edit.sh
#!/bin/sh
# Reports the count of measurement files in project/data/raw
echo "raw measurement count: $(ls -1 "$HOME/project/data/raw" | wc -l)"
echo "current measurement: $(readlink "$HOME/project/data/current.csv")"

The %s/old/new/ command makes the substitution on every line; wq saves and quits. Typing a colon in the screen editor and giving the same command produces the same result. A screen-based session cannot be shown as text, but the command language can, and that is what is shown here.

Modeless Editors

The second design family uses no modes: typed characters go straight into the text, commands are given with control-key combinations, and the available commands are listed continuously at the bottom of the screen.

The comparison runs along two axes:

Criterion Modal Modeless
Learning threshold High; the mode concept must be learned Low; commands are written on screen
Command composition Action and motion combine One command per combination
Guaranteed presence Defined in POSIX, expected on every system Separate package, may not be installed
Limited terminal Works with basic characters Needs control combinations

The third row is decisive in practice. A modeless editor may not be present on a bare system or in a rescue environment:

$ command -v vi ed nano
/usr/bin/vi
/usr/bin/ed
/usr/bin/nano

All three exist on this system; but only the first two can be assumed present. For this reason, the modal editor’s survival set should be learned regardless of which editor is preferred.

Declaring an Editor Preference

Many programs launch an editor when editing is needed: scheduled-task definitions, version control tools’ message screens, privileged file-editing tools. Which editor opens is read from environment variables.

$ echo "EDITOR=${EDITOR:-undefined}"
EDITOR=undefined
$ EDITOR=vi
$ export EDITOR
$ echo "EDITOR=$EDITOR"
EDITOR=vi

An assignment made without export becomes only the shell’s own variable and would not be passed to programs it runs; the environment distinction from the command path lesson applies directly here. For the setting to persist, it is written to the same place as the PATH change — the configuration file read at login.

Two variables are used: VISUAL for a full-screen editor, EDITOR for line-based environments. If both are defined, most programs prefer VISUAL; if only one will be defined, EDITOR is enough.

Summary

  • Terminal editors’ command language is inherited from the line editor designed for screenless terminals, and it is still visible in commands beginning with :.
  • In the modal editor, letter keys can be used as commands, so action and motion combine into a command language.
  • The command set needed to open, change, and save a file is small, and pressing Esc returns to normal mode when unsure.
  • Modeless editors have a low learning threshold but cannot be assumed present on every system.
  • Editor preference is declared through the VISUAL and EDITOR environment variables and is not passed to run programs unless exported.

Course Wrap-Up

The course progressed over a single directory tree. The tree was empty when set up; by the close it carries every operation performed on it:

$ scripts/summary.sh
raw measurement file: 4
current measurement: raw/measurement-03.csv

The whole course stands behind these two lines. For the script to run, it had to be on the search list and have its execute bit on. The files it counts were created, copied, and moved; the directory they were counted in was found through path resolution. The current measurement it reports is a symbolic link’s target. The whole tree was archived, compressed, synced to a remote machine; opened to a group and its shared directory protected with special permission bits.

The course’s takeaways sum up in retrospect as follows:

  • Navigation and file operations: The hierarchy’s logic, path resolution, creating, copying, moving, deleting, links, archiving, and transfer.
  • Permissions and ownership: Identity’s numeric representation, the nine permission bits and octal notation, changing ownership, privilege escalation, and the three special bits.
  • Package management: A package’s structure, dependency resolution, operation classes, and the repository’s chain of trust.

Alongside commands, a set of habits was built through the course, and these outlive the commands themselves: seeing a destructive command’s expansion before running it, listing an archive before opening it, trying a sync with a dry run first, verifying a transfer against its checksum, and taking a privilege in the narrowest scope possible.

The next course covers the layer this course deliberately left out: chaining commands together. The Shell Programming course builds input and output redirection, pipelines, variables, conditionals, and loops; commands run one at a time in this course turn there into scripts that can be run again. The word-splitting and expansion rules introduced in the shell lesson will form the foundation of that course’s grammar.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close