Previous Section  < Day Day Up >  Next Section

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. 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. (Important: remember that typing CTRL-D when your command line is empty may log you off!) The basic keyboard 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.

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


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. You can also use the left and right cursor motion keys ("arrow" keys), but for the rest of this discussion we will use the control keys, as they work on all keyboards. 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 RETURN, 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:

$ [f]grep -l Duchess < ~cam/book/alice_in_wonderland

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:

$ [g]rep -l Duchess < ~cam/book/alice_in_wonderland

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

$ grep -l Duchess < ~cam/book/alice_in_wonderland[]

At this point, typing CTRL-D wouldn't do anything, but hitting DEL would erase the final d.

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 single characters; emacs-mode defines a word as a sequence of one or more alphanumeric characters.

The word commands are shown in Table 2-2. The basic commands are all single characters, whereas these 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. "Kill" is another word for "delete"; it is the standard term used in the readline library documentation for an "undoable" deletion.

Table 2-2. emacs-mode word commands

Command

Description

ESC-B

Move one word backward

ESC-F

Move one word forward

ESC-DEL

Kill one word backward

ESC-CTRL-H

Kill one word backward

ESC-D

Kill one word forward

CTRL-Y

Retrieve ("yank") last item killed


To return to our example: if we type ESC-B, point will move back a word. Since the underscore (_) is not an alphanumeric character, emacs-mode will stop there:

$ grep -l Duchess < ~cam/book/alice_in_[w]onderland

The cursor is on the w in wonderland, and point is between the _ and the w. Now let's say we want to change the -l option of this command from Duchess to Cheshire. We need to move back on the command line, so we type ESC-B four more times. This gets us here:

$ grep -l Duchess < ~[c]am/book/alice_in_wonderland

If we type ESC-B again, we end up at the beginning of Duchess:

$ grep -l [D]uchess < ~cam/book/alice_in_wonderland

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

$ grep -l []< ~cam/book/alice_in_wonderland

Now we can type in the desired argument:

$ grep -l Cheshire[]< ~cam/book/alice_in_wonderland

If you want Duchess back again you can use the CTRL-Y command. The CTRL-Y "yank" command will undelete a word if the word was the last thing deleted. In this case, CTRL-Y would insert Duchess at the point.

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

Kill forward to end of line


Using CTRL-A, CTRL-E, and CTRL-K should be straightforward. Remember that CTRL-Y will always undelete the last thing deleted; if you use CTRL-K, that could be quite a few characters.

2.3.4. Moving Around in the History List

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 list. emacs-mode has several commands for doing this, summarized in Table 2-4.

Table 2-4. emacs-mode commands for moving through the history list

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 list

ESC->

Move to last line of history list


CTRL-P and CTRL-N move you through the command history. If you have cursor motion keys (arrow keys) you can use them instead. The up-arrow is the same as CTRL-P and the down-arrow is the same as CTRL-N. For the rest of this discussion, we'll stick to using the control keys because they can be used on all keyboards.

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 list. If you want to get back to the last command you entered, you can hold down CTRL-N until bash beeps at you, or just type ESC->. As an example, you hit RETURN 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 Duchess < ~cam/book/alice_in_wonderland[]

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

$ grep -[]Duchess < ~cam/book/alice_in_wonderland

You decide to try -s instead of -l, so you type s and hit RETURN. 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 will disappear and be replaced by (reverse-i-search)`':. Then type fgrep, and you will see this:

$ (reverse-i-search)`fgrep': fgrep -l Duchess <~cam/book/ \

   alice_in_wonderland[]

The shell dynamically searches back through the command history each time you type a letter, looking for the current substring in the previous commands. In this example, when you typed f the shell would have printed the most recent command in the history with that letter in it. As you typed more letters, the shell narrowed the search until you ended up with the line displayed above. Of course, this may not have been the particular line you wanted. Typing CTRL-R again makes the shell search further back in the history list for a line with "fgrep" in it. If the shell doesn't find the substring again, it will beep.

If you try the fgrep command by hitting RETURN, two things will happen. First, of course, the command will run. Second, this line will be entered into the history list at the end, and your "current line" will be at the end as well. You will no longer be somewhere else in the command history.

Another handy trick to save typing if you have already done a search is to type CTRL-R twice in a row. This recalls the previous search string you typed in.[3]

[3] Not available in versions of bash prior to 2.05a.

CTRL-P, CTRL-N, and CTRL-R are clearly the most important emacs-mode commands that deal with the command history. The others are less useful but are included for compatibility with the full emacs editor.

2.3.5. Textual Completion

One of the most powerful (and typically underused) features of emacs-mode is its textual 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 textual completion is simple: you should have to type only as much of a filename, user name, function, etc., to identify it unambiguously. This is an excellent feature; there is an analogous one in vi-mode. We recommend that you take the time to learn it, since it will save you quite a bit of typing.

There are three commands in emacs-mode that relate to textual completion. The most important is TAB.[4] When you type in a word of text followed by TAB, bash will attempt to complete the name. Then one of four things can happen:

[4] emacs users will recognize this as minibuffer completion.

  1. If there is nothing whose name begins with the word, the shell will beep and nothing further will happen.

  2. If there is a command name in the search path, a function name, or a filename that the string uniquely matches, the shell will type the rest of it, followed by a space in case you want to type in more command arguments. Command name completion is only attempted when the word is in a command position (e.g., at the start of a line).

  3. If there is a directory that the string uniquely matches, the shell will complete the filename, followed by a slash.

  4. If there is more than one way to complete the name, the shell will complete out to the longest common prefix among the available choices. Commands in the search path and functions take precedence over filenames.

For example, assume you have a directory with the files tweedledee.c and tweedledum.c. You want to compile the first of these by typing cc tweedledee.c. You type cc twee followed by TAB. This is not an unambiguous prefix, since the prefix "twee" is common to both filenames, so the shell only completes out to cc tweedled. You need to type more letters to distinguish between them, so you type e and hit TAB again. Then the shell completes out to "cc tweedledee.c", leaving the extra space for you to type in other filenames or options.

If you didn't know what options were available after trying to complete cc twee, you could press TAB again. bash prints out the possible completions for you and presents your input line again:

$ cc tweedled

tweedledee.c  tweedledum.c

$ cc tweedled

A related command is ESC-?, which expands the prefix to all possible choices, listing them to standard output. Be aware that the completion mechanism doesn't necessarily expand to a filename. If there are functions and commands that satisfy the string you provide, the shell expands those first and ignores any files in the current directory. As we'll see, you can force completion to a particular type.

It is also possible to complete other environment entities. If the text being completed is preceded by a dollar sign ($), the shell attempts to expand the name to that of a shell variable (see Chapter 3, for a discussion of shell variables). If the text is preceded by a tilde (~), completion to a username is attempted; if preceded by an at sign (@), a hostname is attempted.

For example, suppose there was a username cameron on the system. If you wanted to change to this user's home directory, you could just use tilde notation and type the first few letters of the name, followed by a TAB:

$ cd ~ca

which would expand to:

$ cd ~cameron/

You can force the shell to complete to specific things. Table 2-5 lists the standard keys for these.

Table 2-5. Completion command

Command

Description

TAB

Attempt to perform general completion of the text

ESC-?

List the possible completions

ESC-/

Attempt filename completion

CTRL-X /

List the possible filename completions

ESC-~

Attempt username completion

CTRL-X ~

List the possible username completions

ESC-$

Attempt variable completion

CTRL-X $

List the possible variable completions

ESC-@

Attempt hostname completion

CTRL-X @

List the possible hostname completions

ESC-!

Attempt command completion

CTRL-X !

List the possible command completions

ESC-TAB

Attempt completion from previous commands in the history list


If you find that you are interested only in completing long filenames, you are probably better off using ESC-/ rather than TAB. This ensures that the result will be a filename and not a function or command name.

2.3.6. Miscellaneous Commands

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

Table 2-6. emacs-mode miscellaneous commands

Command

Description

CTRL-J

Same as RETURN

CTRL-L

Clears the screen, placing the current line at the top of the screen

CTRL-M

Same as RETURN

CTRL-O

Same as RETURN, then display next line in command history

CTRL-T

Transpose two characters on either side of point and move point forward by one

CTRL-U

Kills the line from the beginning to point

CTRL-V

Quoted insert

CTRL-[

Same as ESC (most keyboards)

ESC-C

Capitalize word after point

ESC-U

Change word after point to all capital letters

ESC-L

Change word after point to all lowercase letters

ESC-.

Insert last word in previous command line after point

ESC-_

Same as ESC-.


BSD-derived systems use CTRL-V and CTRL-W as default settings for the "quote next character" and "word erase" terminal interface functions, respectively.

A few of these 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 RETURN. This will execute the command and bring up the next command in the history list. 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 RETURN.

Of the case-changing commands, ESC-L 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 probably won't use ESC-U very often.

CTRL-V will cause the next character you type to appear in the command line as is; i.e., if it is an editing command (or an otherwise special character like CTRL-D), it will be stripped of its special meaning.

If it seems like there are too many synonyms for RETURN, bear in mind that CTRL-M is actually the same (ASCII) character as RETURN, and that CTRL-J is actually the same as LINEFEED, which UNIX usually accepts in lieu of RETURN 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, so you type the print command lp. You can avoid typing the very long name by typing lp followed by a space and then ESC-. or ESC-_; bash will insert myfilewithaverylongname for you.

    Previous Section  < Day Day Up >  Next Section