## 2.3. Emacs Editing Mode

If you are an Emacs user, you will find it most useful to think of emacs editing mode as a simplified Emacs with a single, one-line window. All of the basic commands are available for cursor motion, cut and paste, and search.

### 2.3.1. Basic Commands

Emacs-mode uses control keys for the most basic editing functions. If you aren't familiar with Emacs, you can think of these as extensions of the rudimentary "erase" character (usually backspace or DEL) that Unix provides through its interface to users' terminals. In fact, emacs-mode figures out what your erase character is and uses that as its delete-backward key. For the sake of consistency, we'll assume your erase character is DEL from now on; if it is CTRL-H or something else, you will need to make a mental substitution. The most basic control-key commands are shown in Table 2-1.

#### Table 2-1. Basic emacs-mode commands

Command | Description
--- | ---
CTRL-B | Move backward one character (without deleting)
CTRL-F | Move forward one character
DEL | Delete one character backward
CTRL-D | Delete one character forward
CTRL-Y | Retrieve ("yank") last item deleted

> WARNING: Remember that typing CTRL-D when your command line is empty may log you off!

The basic finger habits of emacs-mode are easy to learn, but they do require that you assimilate a couple of concepts that are peculiar to the Emacs editor.

The first of these is the use of CTRL-B and CTRL-F for backward and forward cursor motion. These keys have the advantage of being obvious mnemonics, but many people would rather use the arrow keys that are on just about every keyboard nowadays.

Unfortunately, emacs-mode doesn't use the arrow keys,[22] because the codes that they transmit to the computer aren't completely standardized; emacs-mode was designed to work on the widest variety of terminals possible without the heavy-duty customization that the full Emacs needs. Just about the only hardware requirements of emacs-mode are that the SPACE character overwrite the character on top of which it is typed, and that BACKSPACE moves to the left without overwriting the current character.

> [22] In fact, as described in Appendix B, starting with ksh93h, if your terminal uses ANSI-standard escape sequences for the arrow keys, you can use them.

In emacs-mode, the point (sometimes also called dot) is an imaginary place just to the left of the character the cursor is on. In the command descriptions in Table 2-1, some say "forward" while others say "backward." Think of forward as "to the right of point" and backward as "to the left of point."

For example, let's say you type in a line and, instead of typing ENTER, you type CTRL-B and hold it down so that it repeats. The cursor will move to the left until it is over the first character on the line, like this:

>     $ fgrep -l Bob < ~pete/wk/names

Now the cursor is on the `f`, and point is at the beginning of the line, just before the `f`. If you type DEL, nothing will happen because there are no characters to the left of point. However, if you press CTRL-D (the "delete character forward" command) you will delete the first letter:

>     $ grep -l Bob < ~pete/wk/names

Point is still at the beginning of the line. If this were the desired command, you could hit ENTER now and run it; you don't need to move the cursor back to the end of the line. However, if you wanted to, you could type CTRL-F repeatedly to get there:

>     $ grep -l Bob < ~pete/wk/names

At this point, typing CTRL-D wouldn't do anything, but hitting DEL would erase the final `s`. If you type DEL and decide you want the `s` back again, just press CTRL-Y to yank it back. If you think this example is silly, you're right in this particular case, but bear in mind that CTRL-Y undoes the last delete command of any kind, including the delete-word and delete-line commands that we will see shortly.[23]

> [23] Emacs users should note that this usage of CTRL-Y is different from the full editor, which doesn't save character deletes.

If you make multiple deletes in sequence, CTRL-Y brings back everything that you've deleted. Its memory goes back to the last keystroke that wasn't a delete; the deletes don't have to be of the same type. For example, if you type DEL SPACE DEL SPACE CTRL-D CTRL-K, typing CTRL-Y retrieves the result of the last three operations but not the first delete.

### 2.3.2. Word Commands

The basic commands are really all you need to get around a command line, but a set of more advanced commands lets you do it with fewer keystrokes. These commands operate on words rather than on single characters; emacs-mode defines a word to be a sequence of one or more alphanumeric characters or underscores. (For the rest of this discussion, it will help to think of the underscore as a letter, even though it really isn't.)

The word commands are shown in Table 2-2. Whereas the basic commands are all single characters, the word commands consist of two keystrokes, ESC followed by a letter. You will notice that the command ESC X, where X is any letter, often does for a word what CTRL-X does for a single character. The multiplicity of choices for delete-word-backward arises from the fact that your erase character could be either CTRL-H or DEL.

#### Table 2-2. Emacs-mode word commands

Command | Description
--- | ---
ESC b | Move one word backward
ESC f | Move one word forward
ESC DEL, ESC h, ESC CTRL-H | Delete one word backward
ESC d | Delete one word forward

To return to our example: if we type ESC b, point moves back a word. Since `/` is not an alphanumeric character, emacs-mode stops there:

>     $ grep -l Bob < ~pete/wk/names

The cursor is on the `n` in names, and point is between the `/` and the `n`. Now let's say we want to change the -l option's argument of this command from Bob to Dave. We need to move back on the command line, so we type ESC b two more times. This gets us here:

>     $ grep -l Bob < ~pete/wk/names

If we type ESC b again, we end up at the beginning of Bob:

>     $ grep -l Bob < ~pete/wk/names

Why? Remember that a word is defined as a sequence of alphanumeric characters only; therefore `<` is not a word, and the next word in the backward direction is Bob. We are now in the right position to delete Bob, so we type ESC d and get:

>     $ grep -l < ~pete/wk/names

Now we can type in the desired argument:

>     $ grep -l Dave< ~pete/wk/names

The CTRL-Y "undelete" command will retrieve an entire word, instead of a character, if a word was the last thing deleted.

### 2.3.3. Line Commands

There are still more efficient ways of moving around a command line in emacs-mode. A few commands deal with the entire line; they are shown in Table 2-3.

#### Table 2-3. Emacs-mode line commands

Command | Description
--- | ---
CTRL-A | Move to beginning of line
CTRL-E | Move to end of line
CTRL-K | Delete ("kill") forward to end of line
CTRL-C | Capitalize character after point

CTRL-C is often the "interrupt" key that Unix provides through its interface to your terminal. If this is the case, CTRL-C in emacs-mode will erase the entire line, as if CTRL-A and CTRL-K were pressed. On systems where the interrupt key is set to something else (often DEL), CTRL-C capitalizes the current character.

Using CTRL-A, CTRL-E, and CTRL-K should be straightforward. Remember that CTRL-Y will always undelete the last thing deleted, whether that was from a single delete command or several delete commands in a row. If you use CTRL-K, that could be quite a few characters.

### 2.3.4. Moving Around in the History File

Now we know how to get around the command line efficiently and make changes. But that doesn't address the original issue of recalling previous commands by accessing the history file. Emacs-mode has several commands for doing this, summarized in Table 2-4.

#### Table 2-4. Emacs-mode commands for moving through the history file

Command | Description
--- | ---
CTRL-P | Move to previous line
CTRL-N | Move to next line
CTRL-R | Search backward
ESC < | Move to first line of history file
ESC > | Move to last line of history file

CTRL-P is by far the one you will use most often -- it's the "I made a mistake; let me go back and fix it" key. You can use it as many times as you wish to scroll back through the history file. If you want to get back to the last command you entered, you can hold down CTRL-N until the Korn shell beeps at you, or just type ESC >. As an example, you hit ENTER to run the command above, but you get an error message telling you that your option letter was incorrect. You want to change it without retyping the whole thing. First, you would type CTRL-P to recall the bad command. You get it back with point at the end:

>     $ grep -l Dave < ~pete/wk/names

After CTRL-A, ESC f, two CTRL-Fs, and CTRL-D, you have:

>     $ grep -Dave < ~pete/wk/names

You decide to try -s instead of -l, so you type `s` and hit ENTER. You get the same error message, so you give up and look it up in the manual. You find out that the command you want is fgrep -- not grep -- after all. You sigh heavily and go back and find the fgrep command you typed in an hour ago. To do this, you type CTRL-R; whatever was on the line disappears and is replaced by `^R`. Then type `fgrep`, and you see this:

>     $ ^Rfgrep

Hit ENTER, and the shell searches backwards through the history file for a line containing "fgrep". If it doesn't find one, it beeps. But if it finds one, it displays it, and your "current line" will be that line (i.e., you will be somewhere in the middle of the history file, not at the end as usual):

>     $ fgrep -l Bob < ~pete/wk/names

Typing CTRL-R without an argument (i.e., just CTRL-R followed by ENTER) causes the shell to repeat your last backward search. If you try the fgrep command by hitting ENTER again, two things happen. First, of course, the command runs. Second, the executed command line is entered into the history file at the end, and your "current line" will be at the end as well. You will no longer be in the middle of the history file.

CTRL-P and CTRL-R are clearly the most important emacs-mode commands that deal with the history file, and you might use CTRL-N occasionally. The others are less useful, and we suspect that they were included mainly for compatibility with the full Emacs editor.

Emacs users should also note that the full editor's "deluxe" search capabilities, such as incremental and regular expression search, are not available in the Korn shell's emacs-mode -- with one minor exception: if you use CTRL-R and precede your search string with a ^ (caret character), it matches only commands that have the search string at the beginning of the line.

### 2.3.5. Filename and Variable Completion and Expansion

One of the most powerful (and typically underused) features of emacs-mode is its filename completion facility, inspired by similar features in the full Emacs editor, the C shell, and (originally) the old DEC TOPS-20 operating system.

The premise behind filename completion is that when you need to type a filename, you should not have to type more than is necessary to identify the file unambiguously. This is an excellent feature; there is an analogous one in vi-mode. We recommend that you get it under your fingers, since it will save you quite a bit of typing.

There are three commands in emacs-mode that relate to filename completion. The most important is TAB. (Emacs users will find this familiar; it is the same as minibuffer completion with the TAB key.) When you type in a word of text followed by TAB, the Korn shell attempts to complete the name of a file in the current directory. Then one of four things can happen:

1. If there is no file whose name begins with the word, the shell beeps and nothing further happens.

2. If there is exactly one way to complete the filename, and the file is a regular file, the shell types the rest of the filename and follows it with a space so you can type in more command arguments.

3. If there is exactly one way to complete the filename, and the file is a directory, the shell completes the filename and follows it with a slash.

4. If there is more than one way to complete the filename, the shell completes out to the longest common prefix among the available choices.

For example, assume you have a directory with the files program.c and problem.c. You want to compile the first of these by typing `cc program.c`. You type `cc pr` followed by TAB. This is an ambiguous prefix, since the prefix "pro" is common to both filenames, so the shell only completes out to `cc pro`. You need to type more letters to disambiguate, so you type `g` and hit TAB again. Then the shell completes out to "`cc program.c` ", leaving the extra space for you to type in other filenames or options.

A related command is ESC `*`, which expands the prefix to all possible choices. ESC `*` acts like the standard `*` shell wildcard character except that it expands the choices for you to see and does not execute the command. In the previous example, if you type ESC `*` instead of TAB, the shell will expand to "`cc problem.c program.c` ". If you type ESC `=` instead of ESC `*`, you will see a numbered list of expansions printed to standard error.

Starting with ksh93m, the ESC = command accepts a numeric prefix. When a prefix is provided, the shell treats it as the number of one of the commands shown by a previous ESC = listing and completes the filename. (An example is provided later in this chapter where the vi-mode version of this command is described.)

When TAB, ESC `*`, and ESC `=` are used on the first word of the command line, they expand aliases, functions, and commands. This very useful feature is known as command completion.

For backwards compatibility with ksh88 and versions of ksh93 prior to ksh93h, you may instead type ESC ESC for filename and command completion.

Starting with ksh93l, the editing modes understand ksh quoting rules; expansions are ignored inside quotes. However, if you have typed a leading quote but no closing quote yet, the completion commands do work. In addition, all three expansions work on variable names as well. (Variables are discussed in Chapter 4.) When ksh sees either a `$` or `"$` and part of a variable name, you may use any of the three expansions to see which variable names match what you've typed.

### 2.3.6. Miscellaneous Commands

Several miscellaneous commands complete emacs editing mode; they are shown in Table 2-5.

#### Table 2-5. Emacs-mode miscellaneous commands

Command | Description
--- | ---
CTRL-J | Same as ENTER.
CTRL-L | Redisplay the line.
CTRL-M | Same as ENTER.
CTRL-O | Same as ENTER, then display next line in history file.
CTRL-T | Transpose the characters on either side of point. This is like GNU Emacs.[24]
CTRL-U | Repeat the following command four times.
CTRL-V | Print the version of the Korn shell.
CTRL-W | Delete ("wipe") all characters between point and "mark." "Mark" is discussed later in this section.
CTRL-X CTRL-E | Invoke an editor -- usually the emacs program -- on the current command.
CTRL-X CTRL-X | Exchange point and mark.
CTRL-[ | Same as ESC (most keyboards).
CTRL-] x | Search forward on current line for x, where x is any character.
CTRL-@ | Set mark at point.
ESC c | Change word after point to all capital letters.
ESC l | Change word after point to all lowercase letters.
ESC p | Save all characters between point and mark as if they were deleted.
ESC . | Insert last word in previous command line after point.
ESC _ | Same as previous entry.
ESC CTRL-] x | Search backward for x, where x is any character.
ESC SPACE | Set mark at point.
ESC # | Prepend `#` (comment character) to the line and send it to the history file; useful for saving a command to be executed later without having to retype it. If the line already starts with a `#`, remove the leading `#` and any other comment characters that follow newlines in a multi-line command.

[24] This is a difference from ksh88, which transposes two characters to the right of point and moves point forward by one. CTRL-T behaves slightly differently if you put `set -o gmacs` (instead of `emacs`) in your .profile. In this case, it transposes the two characters to the left of point, leaving point unmoved. This is the only difference between emacs and gmacs modes; the latter conforms to the once-popular James Gosling version of the Emacs editor (a.k.a. Unipress Emacs, now no longer available).

Several of these commands may clash with terminal interface control keys on your system. CTRL-U is the default key for "kill line" on most versions of Unix. Modern Unix systems use CTRL-V and CTRL-W as default settings for the "quote next character" and "word erase" terminal interface functions, respectively. CTRL-V is particularly confusing, since it is meant to override other terminal interface control keys but has no effect on emacs-mode commands. However, emacs-mode works by directly interpreting every character you type, so the stty settings are largely ignored.

A few miscellaneous commands are worth discussing, even though they may not be among the most useful emacs-mode commands.

CTRL-O is useful for repeating a sequence of commands you have already entered. Just go back to the first command in the sequence and press CTRL-O instead of ENTER. This executes the command and brings up the next command in the history file. Press CTRL-O again to enter this command and bring up the next one. Repeat this until you see the last command in the sequence; then just hit ENTER.

CTRL-U, if it doesn't perform the line-delete function of your system's terminal interface, repeats the next command four times. If you type CTRL-U twice, the repeat factor becomes 16; for 3 CTRL-Us it's 64; and so on. CTRL-U is possibly most useful when navigating through your history file. If you want to recall a command that you entered a while ago, you could type CTRL-U CTRL-P to go back through the history file four lines at a time; you could think of this as a "fast rewind" through your command history.

Another possible use of CTRL-U is when you want to go from one end of a long pathname to the other. Unlike vi-mode, emacs-mode does not have a concept of "word" that is flexible enough to distinguish between pathnames and filename components. The emacs-mode word motion commands (ESC b and ESC f) move through a pathname only one component at a time, because emacs-mode treats the slash as a word separator. You can use CTRL-U to help get around this limitation. If you have a line that looks like this:

>     $ ls -l /a/very/long/pathname/filename

and you need to go back and change "very" to "really", you can type CTRL-U ESC b and your cursor will end up here:

>     $ ls -l /a/very/long/pathname/filename

Then you can make the change. First, get rid of "very" by typing CTRL-U CTRL-D:

>     $ ls -l /a//long/pathname/filename

Then insert the new text:

>     $ ls -l /a/really/long/pathname/filename

Judicious use of CTRL-U can save you a few keystrokes, but considering the small amount of information you manipulate when you edit command lines, it's probably not an incredibly vital feature. Often, holding down a key to repeat it is just as effective as CTRL-U. Because you'll probably have to use the stty command to redefine the terminal driver's line erase key before you can use CTRL-U, it's probably better to do without it.

The mark mentioned in the explanation of CTRL-W should be familiar to Emacs users, but its function in emacs-mode is a subset of that in the full editor. Emacs-mode keeps track of the place at which the last delete operation was performed (whether it was a character, word, line, or whatever); this place is called the mark. If nothing has been deleted on the current line, the mark defaults to the beginning of the line. You can also set the mark to where your cursor is by typing ESC SPACE (or, alternatively, CTRL-@). CTRL-X CTRL-X (CTRL-X hit twice) causes the Korn shell to swap point and mark, i.e., to move your cursor to where the mark is and reset mark to where your cursor was before you typed CTRL-X CTRL-X.

The mark concept is not extremely useful because of the small amount of "distance" to travel in command lines. But if you ever have to make a series of changes in the same place in a line, CTRL-X CTRL-X will take you back there. In the previous example, if you wanted to change "really" to "monumentally", one way would be to type CTRL-X CTRL-X to return to the beginning of "really":

>     $ ls -l /a/really/long/pathname/filename

Then you could type ESC d to delete "really" and make the change. Of course, you could do this faster by typing ESC DEL instead of CTRL-X CTRL-X and ESC d.

Of the case-changing commands, ESC l (letter ell) is useful when you hit the CAPS LOCK key by accident and don't notice it immediately. Since all-caps words aren't used too often in the Unix world, you may not use ESC c very often.

If it seems like there are too many synonyms for ENTER, bear in mind that CTRL-M is actually the same (ASCII) character as ENTER, and that CTRL-J is actually the same as newline, which Unix usually accepts in lieu of ENTER anyway.

ESC `.` and ESC _ are useful if you want to run several commands on a given file. The usual Unix convention is that a filename is the last argument to a command. Therefore you can save typing by just entering each command followed by SPACE and then typing ESC `.` or ESC _. For example, say you want to examine a file using more, so you type:

>     $ more myfilewithaverylongname

Then you decide you want to print it, using the print command lp. You can avoid typing the very long name by typing `lp` followed by a space and then ESC `.` or ESC _; the Korn shell inserts myfilewithaverylongname for you.

If you're a real Emacs expert and the built-in mode just isn't working for you, use CTRL-X CTRL-E to invoke the emacs editor program on your command line. When you exit the editor, if you actually made changes to the file, the shell executes the final command line.

### 2.3.7. Macro Expansion with Aliases

As you become accustomed to using emacs-mode, you may find that there are sequences of commands that you execute over and over again. Typing these commands repeatedly is difficult and time-wasting. It is better to define a macro for them. A macro is a short name that, when entered, expands into the full sequence of commands.

The Korn shell provides a macro facility, using the alias mechanism (described in the next chapter), that lets you set up a sequence of commands and then invoke that sequence with a single emacs-mode command. It works as follows: if you define an alias named _x, where x is a letter, then when you type ESC x, emacs-mode expands the alias, and reads it as input. The alias value may contain regular text, emacs-mode commands, or both.

For example, suppose that you want a command to capitalize the first letter of the current word. You could define an alias as follows:

>     alias _C='^[b^C'            Value is ESC b CTRL-C

Now, whenever you type ESC C, the shell moves to the beginning of the current word (ESC b), and then capitalizes the current letter (CTRL-C).

>     $ print here is a word     Type ESC C
>     $ print here is a Word

Copyright © 2003 O'Reilly & Associates. All rights reserved.