zsh's command line editor, ZLE, is quite powerful. It is
designed to emulate either emacs or vi; the default is emacs. To set
the bindings for vi mode, type
In addition to basic editing, the shell allows you to recall previous lines in the history. In emacs mode, this is done with ^P (control-P):
% ls ~ - README file mail pub tmp Mailboxes bin func nicecolors scr zsh News etc iris notes src % echo foobar foobar % ^P % echo foobar^P % ls ~_
Pressing ^P once brings up the previous line (
pressing it again brings up the line before that (
ls ~). The
cursor is left at the end of the line, allowing you to edit the line if
desired before executing it. In many cases, ZLE eliminates the
need for the
fc command, since it is powerful enough to handle
even multiline commands:
% for i in a b c d e > do > echo $i > done a b c d e % ^P % for i in a b c d e do echo $i done_
Now you can just move up to the part you want to change...
% for i in a_ b c d e do echo $i done
change it, and execute the new command.
% for i in f g h i j do echo $i done f g h i j
Also, you can search the history for a certain command using ESC-P:
% set ESC-P % setopt autolist ESC-P % setopt nocorrect_
Another way is to do an incremental search, emacs-style:
% ^R % _ i-search: % l_s /usr/bin i-search: l % date > foofil_e.c i-search: le
Another useful feature of the editor is command and filename completion.
% compTAB % compress _ % ls /nicTAB % ls /nicecolors _ % ls /usr/prTAB % ls /usr/princeton/_ % ls -l =comTAB % ls -l =compress _
If the completion is ambiguous, the editor will beep. You can list possible completions by pressing ^D:
% ls /vmuTAB beep % ls /vmunix_ % ls /vmunix^D vmunix vmunix.old vmunix.new.kernelmap.old vmunix.org
Or, you could just set the
% setopt autolist % ls /vmuTAB beep vmunix vmunix.old vmunix.new.kernelmap.old vmunix.org % ls /vmunix_
Another option you could set is
RECEXACT, which causes exact
matches to be accepted, even if there are other possible
% setopt recexact % ls /vmuTAB beep vmunix vmunix.old vmunix.new.kernelmap.old vmunix.org % ls /vmunix_TAB % ls /vmunix _
fignore variable lists suffixes of files to ignore during
% ls fooTAB beep foofile.c foofile.o % fignore=( .o \~ .bak .junk ) % ls fooTAB % ls foofile.c _
foofile.o has a suffix that is in the
it was not considered a possible completion of
Username completion is also supported:
% ls ~pfalTAB % ls ~pfalstad/_
and parameter name completion:
% echo $ORGTAB % echo $ORGANIZATION _
and hostname completion, if you give the shell a list of hosts to complete:
% hosts=( phoenix.princeton.edu uunet.uu.net nic.ddn.mil > diskfarm.princeton.edu gnu.ai.mit.edu > eniac.seas.upenn.edu ) % telnet diskTAB % telnet diskfarm.princeton.edu _ % ftp uuTAB % ftp uunet.uu.net _ % mail subbarao@phTAB % mail firstname.lastname@example.org _
and option completion:
% setopt noclTAB % setopt noclobber _
and binding completion:
% bindkey '^X^X' puTAB % bindkey '^X^X' push-line _
compctl command is used to control how completion works. For
example, to specify that certain commands show take commands as
arguments, you use
% compctl -c man nohup % man uptTAB % man uptime _
To specify that a command should complete filenames, you should use
compctl -f. This is the default. It can be combined with
-c, as well.
% compctl -cf echo % echo uptTAB % echo uptime _ % echo foTAB % echo foo.c
-h to specify hostnames,
-o to specify
-v to specify variables, and
-b to specify
% compctl -h rlogin % compctl -hfc rsh % compctl -b bindkey
You can also use
-k to specify a custom list of keywords to use
% ftphosts=(ftp.uu.net wuarchive.wustl.edu) % compctl -k ftphosts ftp % ftp wuTAB % ftp wuarchive.wustl.edu _ % friends=(cpirazzi subbarao sukthnkr) % compctl -k friends mail finger su % finger cpTAB % finger cpirazzi _
In addition to completion, TAB performs expansion if possible.
% ls *.cTAB % ls foofile.c fortune.c rnd.c strfile.c unstr.c_
For example, suppose you have a bunch of weird files in an important directory:
% ls * * * ; & % $??foo dspfok foo.c !"foo"! ` \ ` foo rrr
You want to remove them, but you don't want to damage
Here is one way to do this:
% rm *TAB % rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$' 'foo \`\ \\\ \` dspfok foo foo.c rrr_
When you expand *, zsh inserts the names of all the files into the
editing buffer, with proper shell quoting. Now, just move back and
foo.c from the buffer:
% rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$' 'foo \`\ \\\ \` dspfok foo \kxr\l'|\nxu\(ul'rr
and press return. Everything except
foo.c will be deleted from
Here's another trick; let's say you have typed this command in:
% gcc -o x.out foob.c -g -Wpointer-arith -Wtrigraphs_
and you forget which library you want. You need to escape out for a
minute and check by typing
ls /usr/lib, or some other such
command; but you don't want to retype the whole command again, and you
can't press return now because the current command is incomplete. In
zsh, you can put the line on the buffer stack, using ESC-Q,
and type some other commands. The next time a prompt is printed, the
gcc line will be popped off the stack and put in the editing
buffer automatically; you can then enter the proper library name and
press return (or, ESC-Q again and look for some other
libraries whose names you forgot).
A similar situation: what if you forget the option to gcc that finds
bugs using AI techniques? You could either use ESC-Q again,
man gcc, or you could press ESC-H, which
essentially does the same thing; it puts the current line on the buffer
stack, and executes the command
run-help gcc, where
run-help is an alias for
Another interesting command is ESC-A. This executes the current line, but retains it in the buffer, so that it appears again when the next prompt is printed. Also, the cursor stays in the same place. This is useful for executing a series of similar commands:
% cc grok.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out % cc fubar.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out % cc fooble.c -g -lc -lgl -lsun -lmalloc -Bstatic -o b.out
The ESC-' command is useful for managing the shell's quoting conventions. Let's say you want to print this string:
don't do that; type 'rm -rf \*', with a \ before the *.
All that is necessary is to type it into the editing buffer:
% don't do that; type 'rm -rf \*', with a \ before the *.
press ESC-' (escape-quote):
% 'don'\"t do that; type '\"rm -rf \*'\", with a \ before the *.'
then move to the beginning and add the
% echo 'don'\"t do that; type '\"rm -rf \*'\", with a \ before the *.' don't do that; type 'rm -rf \*', with a \ before the *.
Let's say you want to create an alias to do this
This can be done by recalling the line with ^P and pressing
% 'echo '\"don'\"\'\"'\"t do that; type '\"\'\"'\"rm -rf \*'\"\'\"'\", with a \ before the *.'\"'
and then move to the beginning and add the command to create an alias.
% alias zoof='echo '\"don'\"\'\"'\"t do that; type '\"\'\"'\" rm -rf \*'\"\'\"'\", with a \ before the *.'\"' % zoof don't do that; type 'rm -rf \*', with a \ before the *.
Another interesting option is
MENUCOMPLETE. This affects the way
TAB works. Let's look at the
/vmunix example again:
% setopt menucomplete % ls /vmuTAB % ls /vmunixTAB % ls /vmunix.new.kernelmap.oldTAB % ls /vmunix.old_
Each time you press TAB, it displays the next possible completion. In this way, you can cycle through the possible completions until you find the one you want.
AUTOMENU option makes a nice compromise between this method
of completion and the regular method. If you set this option, pressing
the TAB key repeatedly after an ambiguous completion will cycle
through the possible completions.