From c175751b501a3a4cb40ad4787340a597ea769be4 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Thu, 15 Apr 1999 18:05:35 +0000 Subject: Initial revision --- Doc/intro.ms | 2701 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2701 insertions(+) create mode 100644 Doc/intro.ms (limited to 'Doc/intro.ms') diff --git a/Doc/intro.ms b/Doc/intro.ms new file mode 100644 index 000000000..5024b9bfd --- /dev/null +++ b/Doc/intro.ms @@ -0,0 +1,2701 @@ +.nr PI 0 +.nr LL 6.5i +.de Ds +.DS I .5i +.ft C +.ps 9 +.vs 11 +.ss 11 +.. +.de De +.DE +.ft R +.ps +.vs +.ss +.. +.de Sh +.SH +\\$1 +.XS +\\$1 +.XE +.. +.nr HM 4i +.ce 99 +.ps 18 +.vs 20 +.ss 20 +\f3An Introduction to the Z Shell\fP + +.ps 14 +.vs 16 +.ss 16 +\f2Paul Falstad +pf@software.com + +Bas de Bakker +bas@phys.uva.nl\fP +.ce 0 +.nr HM 1i +.pn 1 +.bp +.\" This blank page on the reverse of the cover. +.sv |1i +.pn 1 +.bp +.TL +An Introduction to the Z Shell +.AU +Paul Falstad +pf@software.com +.AU +Bas de Bakker +bas@phys.uva.nl +.PP +.Sh "Introduction" +.PP +\fBzsh\fP is a shell designed for interactive use, although it is also +a powerful scripting language. Many of the useful features of bash, +ksh, and tcsh were incorporated into \fBzsh\fP; many original features were +added. This document details some of the unique features of \fBzsh\fP. It +assumes basic knowledge of the standard UNIX shells; the intent is to +show a reader already familiar with one of the other major shells what +makes \fBzsh\fP more useful or more powerful. This document is not at all +comprehensive; read the manual entry for a description of the shell +that is complete and concise, although somewhat overwhelming and +devoid of examples. +.PP +The text will frequently mention options that you can set to change +the behaviour of \fBzsh\fP. You can set these options with the +command +.Ds +%\0setopt\0\fIoptionname\fC +.De +and unset them again with +.Ds +%\0unsetopt\0\fIoptionname\fC +.De +Case is ignored in option names, as are embedded underscores. +.Sh "Filename Generation" +.PP +Otherwise known as \fIglobbing\fP, filename generation +is quite extensive in \fBzsh\fP. Of course, it has all the +basics: +.Ds +%\0ls +Makefile\0\0\0file.pro\0\0\0foo.o\0\0\0\0\0\0main.o\0\0\0\0\0q.c\0\0\0\0\0\0\0\0run234\0\0\0\0\0stuff +bar.o\0\0\0\0\0\0foo\0\0\0\0\0\0\0\0link\0\0\0\0\0\0\0morestuff\0\0run123\0\0\0\0\0run240\0\0\0\0\0sub +file.h\0\0\0\0\0foo.c\0\0\0\0\0\0main.h\0\0\0\0\0pipe\0\0\0\0\0\0\0run2\0\0\0\0\0\0\0run303 +%\0ls\0*.c +foo.c\0\0q.c +%\0ls\0*.[co] +bar.o\0\0\0foo.c\0\0\0foo.o\0\0\0main.o\0\0q.c +%\0ls\0foo.? +foo.c\0\0foo.o +%\0ls\0*.[^c] +bar.o\0\0\0file.h\0\0foo.o\0\0\0main.h\0\0main.o +%\0ls\0*.[^oh] +foo.c\0\0q.c +.De +Also, if the \fIEXTENDEDGLOB\fP option is set, +some new features are activated. +For example, the \fC^\fP character negates the pattern following it: +.Ds +%\0setopt\0extendedglob +%\0ls\0-d\0^*.c +Makefile\0\0\0file.pro\0\0\0link\0\0\0\0\0\0\0morestuff\0\0run2\0\0\0\0\0\0\0run303 +bar.o\0\0\0\0\0\0foo\0\0\0\0\0\0\0\0main.h\0\0\0\0\0pipe\0\0\0\0\0\0\0run234\0\0\0\0\0stuff +file.h\0\0\0\0\0foo.o\0\0\0\0\0\0main.o\0\0\0\0\0run123\0\0\0\0\0run240\0\0\0\0\0sub +%\0ls\0-d\0^*.* +Makefile\0\0\0link\0\0\0\0\0\0\0pipe\0\0\0\0\0\0\0run2\0\0\0\0\0\0\0run240\0\0\0\0\0stuff +foo\0\0\0\0\0\0\0\0morestuff\0\0run123\0\0\0\0\0run234\0\0\0\0\0run303\0\0\0\0\0sub +%\0ls\0-d\0^Makefile +bar.o\0\0\0\0\0\0foo\0\0\0\0\0\0\0\0link\0\0\0\0\0\0\0morestuff\0\0run123\0\0\0\0\0run240\0\0\0\0\0sub +file.h\0\0\0\0\0foo.c\0\0\0\0\0\0main.h\0\0\0\0\0pipe\0\0\0\0\0\0\0run2\0\0\0\0\0\0\0run303 +file.pro\0\0\0foo.o\0\0\0\0\0\0main.o\0\0\0\0\0q.c\0\0\0\0\0\0\0\0run234\0\0\0\0\0stuff +%\0ls\0-d\0*.^c +\&.rhosts\0\0\0bar.o\0\0\0\0\0file.h\0\0\0\0file.pro\0\0foo.o\0\0\0\0\0main.h\0\0\0\0main.o +.De +An expression of the form +\fC<\fIx\fR\-\fIy\fC>\fR +matches a range of integers: +.Ds +%\0ls\0run<200-300> +run234\0\0run240 +%\0ls\0run<300-400> +run303 +%\0ls\0run<-200> +run123\0\0run2 +%\0ls\0run<300-> +run303 +%\0ls\0run<> +run123\0\0run2\0\0\0\0run234\0\0run240\0\0run303 +.De +The \fINUMERICGLOBSORT\fP option will sort files with numbers +according to the number. This will not work with \fCls\fP as it +resorts its arguments: +.Ds +%\0setopt\0numericglobsort +%\0echo\0run<> +run2\0run123\0run234\0run240\0run303 +.De +Grouping is possible: +.Ds +%\0ls\0(foo|bar).* +bar.o\0\0foo.c\0\0foo.o +%\0ls\0*.(c|o|pro) +bar.o\0\0\0\0\0file.pro\0\0foo.c\0\0\0\0\0foo.o\0\0\0\0\0main.o\0\0\0\0q.c +.De +Also, the string \fC**/\fP forces a recursive search of +subdirectories: +.Ds +%\0ls\0-R +Makefile\0\0\0file.pro\0\0\0foo.o\0\0\0\0\0\0main.o\0\0\0\0\0q.c\0\0\0\0\0\0\0\0run234\0\0\0\0\0stuff +bar.o\0\0\0\0\0\0foo\0\0\0\0\0\0\0\0link\0\0\0\0\0\0\0morestuff\0\0run123\0\0\0\0\0run240\0\0\0\0\0sub +file.h\0\0\0\0\0foo.c\0\0\0\0\0\0main.h\0\0\0\0\0pipe\0\0\0\0\0\0\0run2\0\0\0\0\0\0\0run303 + +morestuff: + +stuff: +file\0\0xxx\0\0\0yyy + +stuff/xxx: +foobar + +stuff/yyy: +frobar +%\0ls\0**/*bar +stuff/xxx/foobar\0\0stuff/yyy/frobar +%\0ls\0**/f* +file.h\0\0\0\0\0\0\0\0\0\0\0\0foo\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0foo.o\0\0\0\0\0\0\0\0\0\0\0\0\0stuff/xxx/foobar +file.pro\0\0\0\0\0\0\0\0\0\0foo.c\0\0\0\0\0\0\0\0\0\0\0\0\0stuff/file\0\0\0\0\0\0\0\0stuff/yyy/frobar +%\0ls\0*bar* +bar.o +%\0ls\0**/*bar* +bar.o\0\0\0\0\0\0\0\0\0\0\0\0\0stuff/xxx/foobar\0\0stuff/yyy/frobar +%\0ls\0stuff/**/*bar* +stuff/xxx/foobar\0\0stuff/yyy/frobar +.De +.PP +It is possible to exclude certain files from the patterns using +the ~ character. A pattern of the form \fC*.c~bar.c\fP lists all +files matching \fC*.c\fP, except for the file \fCbar.c\fP. +.Ds +%\0ls\0*.c +foo.c\0\0\0\0foob.c\0\0\0\0bar.c +%\0ls\0*.c~bar.c +foo.c\0\0\0\0foob.c +%\0ls\0*.c~f* +bar.c +.De +.PP +One can add a number of \fIqualifiers\fP to the end of +any of these patterns, to restrict matches to certain +file types. A qualified pattern is of the form +.DS +\fIpattern\fC(\fR...\fC)\fR +.De +with single-character qualifiers inside the parentheses. +.Ds +%\0alias\0l='ls\0-dF' +%\0l\0* +Makefile\0\0\0\0foo*\0\0\0\0\0\0\0\0main.h\0\0\0\0\0\0q.c\0\0\0\0\0\0\0\0\0run240 +bar.o\0\0\0\0\0\0\0foo.c\0\0\0\0\0\0\0main.o\0\0\0\0\0\0run123\0\0\0\0\0\0run303 +file.h\0\0\0\0\0\0foo.o\0\0\0\0\0\0\0morestuff/\0\0run2\0\0\0\0\0\0\0\0stuff/ +file.pro\0\0\0\0link@\0\0\0\0\0\0\0pipe\0\0\0\0\0\0\0\0run234\0\0\0\0\0\0sub +%\0l\0*(/) +morestuff/\0\0stuff/ +%\0l\0*(@) +link@ +%\0l\0*(*) +foo*\0\0\0\0\0\0\0\0link@\0\0\0\0\0\0\0morestuff/\0\0stuff/ +%\0l\0*(x) +foo*\0\0\0\0\0\0\0\0link@\0\0\0\0\0\0\0morestuff/\0\0stuff/ +%\0l\0*(X) +foo*\0\0\0\0\0\0\0\0link@\0\0\0\0\0\0\0morestuff/\0\0stuff/ +%\0l\0*(R) +bar.o\0\0\0\0\0\0\0foo*\0\0\0\0\0\0\0\0link@\0\0\0\0\0\0\0morestuff/\0\0run123\0\0\0\0\0\0run240 +file.h\0\0\0\0\0\0foo.c\0\0\0\0\0\0\0main.h\0\0\0\0\0\0pipe\0\0\0\0\0\0\0\0run2\0\0\0\0\0\0\0\0run303 +file.pro\0\0\0\0foo.o\0\0\0\0\0\0\0main.o\0\0\0\0\0\0q.c\0\0\0\0\0\0\0\0\0run234\0\0\0\0\0\0stuff/ +.De +Note that \fC*(x)\fP and \fC*(*)\fP both match executables. +\fC*(X)\fP matches files executable by others, as opposed to +\fC*(x)\fP, which matches files executable by the owner. +\fC*(R)\fP and \fC*(r)\fP match readable files; +\fC*(W)\fP and \fC*(w)\fP, which checks for writable files. +\fC*(W)\fP is especially important, since it checks for world-writable +files: +.Ds +%\0l\0*(w) +bar.o\0\0\0\0\0\0\0foo*\0\0\0\0\0\0\0\0link@\0\0\0\0\0\0\0morestuff/\0\0run123\0\0\0\0\0\0run240 +file.h\0\0\0\0\0\0foo.c\0\0\0\0\0\0\0main.h\0\0\0\0\0\0pipe\0\0\0\0\0\0\0\0run2\0\0\0\0\0\0\0\0run303 +file.pro\0\0\0\0foo.o\0\0\0\0\0\0\0main.o\0\0\0\0\0\0q.c\0\0\0\0\0\0\0\0\0run234\0\0\0\0\0\0stuff/ +%\0l\0*(W) +link@\0\0\0run240 +%\0l\0-l\0link\0run240 +lrwxrwxrwx\0\01\0pfalstad\0\0\0\0\0\0\010\0May\023\018:12\0link\0->\0/usr/bin/ +-rw-rw-rw-\0\01\0pfalstad\0\0\0\0\0\0\0\00\0May\023\018:12\0run240 +.De +If you want to have all the files of a certain type as well as all +symbolic links pointing to files of that type, prefix the qualifier +with a \fC-\fP: +.Ds +%\0l\0*(-/) +link@\0\0\0\0\0\0\0morestuff/\0\0stuff/ +.De +You can filter out the symbolic links with the \fC^\fP character: +.Ds +%\0l\0*(W^@) +run240 +%\0l\0*(x) +foo*\0\0\0\0\0\0\0\0link@\0\0\0\0\0\0\0morestuff/\0\0stuff/ +%\0l\0*(x^@/) +foo* +.De +To find all plain files, you can use \fC.\fP: +.Ds +%\0l\0*(.) +Makefile\0\0file.h\0\0\0\0foo*\0\0\0\0\0\0foo.o\0\0\0\0\0main.o\0\0\0\0run123\0\0\0\0run234\0\0\0\0run303 +bar.o\0\0\0\0\0file.pro\0\0foo.c\0\0\0\0\0main.h\0\0\0\0q.c\0\0\0\0\0\0\0run2\0\0\0\0\0\0run240\0\0\0\0sub +%\0l\0*(^.) +link@\0\0\0\0\0\0\0morestuff/\0\0pipe\0\0\0\0\0\0\0\0stuff/ +%\0l\0s*(.) +stuff/\0\0\0sub +%\0l\0*(p) +pipe +%\0l\0-l\0*(p) +prw-r--r--\0\01\0pfalstad\0\0\0\0\0\0\0\00\0May\023\018:12\0pipe +.De +\fC*(U)\fP matches all files owned by you. +To search for all files not owned by you, use \fC*(^U)\fP: +.Ds +%\0l\0-l\0*(^U) +-rw-------\0\01\0subbarao\0\0\0\0\0\0\029\0May\023\018:13\0sub +.De +This searches for setuid files: +.Ds +%\0l\0-l\0*(s) +-rwsr-xr-x\0\01\0pfalstad\0\0\0\0\0\0\016\0May\023\018:12\0foo* +.De +This checks for a certain user's files: +.Ds +%\0l\0-l\0*(u[subbarao]) +-rw-------\0\01\0subbarao\0\0\0\0\0\0\029\0May\023\018:13\0sub +.De +.Sh "Startup Files" +.PP +There are five startup files that \fBzsh\fP will read commands from: +.Ds +$ZDOTDIR/.zshenv +$ZDOTDIR/.zprofile +$ZDOTDIR/.zshrc +$ZDOTDIR/.zlogin +$ZDOTDIR/.zlogout +.De +If \fBZDOTDIR\fP is not set, then the value of \fBHOME\fP is used; +this is the usual case. +.\".KE <--- missing .KS or .KF above +.PP +\&\fC.zshenv\fP is sourced on all invocations of the shell, +unless the \fC-f\fP option is set. It should contain commands to set +the command search path, plus other important environment +variables. +\&\fC.zshenv\fP should not contain commands that produce output +or assume the shell is attached to a tty. +.PP +\&\fC.zshrc\fP is sourced in interactive shells. It should contain +commands to set up aliases, functions, options, key bindings, etc. +.PP +\&\fC.zlogin\fP is sourced in login shells. It should contain +commands that should be executed only in login shells. +\&\fC.zlogout\fP is sourced when login shells exit. +\&\fC.zprofile\fP is similar to \fC.zlogin\fP, except that it is sourced before +\&\fC.zshrc\fP. +\&\fC.zprofile\fP is meant as an alternative to \fC.zlogin\fP for +ksh fans; +the two are not intended to be used together, although this +could certainly be done if desired. +\&\fC.zlogin\fP is not the place for alias definitions, options, environment +variable settings, etc.; +as a general rule, it should not change the shell environment +at all. Rather, it should be used to set the terminal type +and run a series of external commands (\fCfortune\fP, \fCmsgs\fP, etc). +.Sh "Shell Functions" +.PP +\fBzsh\fP also allows you to create your own commands by defining shell +functions. For example: +.Ds +%\0yp\0()\0{ +>\0\0\0\0\0\0\0ypmatch\0$1\0passwd.byname +>\0} +%\0yp\0pfalstad +pfalstad:*:3564:35:Paul\0John\0Falstad:/u/pfalstad:/usr/princeton/bin/zsh +.De +This function looks up a user in the NIS password map. +The \fC$1\fP expands to the first argument to \fCyp\fP. +The function could have been equivalently defined in one of the following +ways: +.Ds +%\0function\0yp\0{ +>\0\0\0\0\0\0\0ypmatch\0$1\0passwd.byname +>\0} +%\0function\0yp\0()\0{ +>\0\0\0\0\0\0\0ypmatch\0$1\0passwd.byname +>\0} +%\0function\0yp\0()\0ypmatch\0$1\0passwd.byname +.De +Note that aliases are expanded when the function definition is +parsed, not when the function is executed. For example: +.Ds +%\0alias\0ypmatch=echo +%\0yp\0pfalstad +pfalstad:*:3564:35:Paul\0John\0Falstad:/u/pfalstad:/usr/princeton/bin/zsh +.De +Since the alias was defined after the function was parsed, it has +no effect on the function's execution. +However, if we define the function again with the alias in place: +.Ds +%\0function\0yp\0()\0{\0ypmatch\0$1\0passwd.byname\0} +%\0yp\0pfalstad +pfalstad\0passwd.byname +.De +it is parsed with the new alias definition in place. +Therefore, in general you must define aliases before functions. +.\".KE <--- missing .KS or .KF above +.PP +We can make the function take multiple arguments: +.Ds +%\0unalias\0ypmatch +%\0yp\0()\0{ +>\0\0\0\0\0\0\0for\0i +>\0\0\0\0\0\0\0do\0ypmatch\0$i\0passwd.byname +>\0\0\0\0\0\0\0done +>\0} +%\0yp\0pfalstad\0subbarao\0sukthnkr +pfalstad:*:3564:35:Paul\0John\0Falstad:/u/pfalstad:/usr/princeton/bin/zsh +subbarao:*:3338:35:Kartik\0Subbarao:/u/subbarao:/usr/princeton/bin/zsh +sukthnkr:*:1267:35:Rahul\0Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh +.De +The \fCfor i\fP loops through each of the function's arguments, +setting \fCi\fP equal to each of them in turn. +We can also make the function do something sensible +if no arguments are given: +.Ds +%\0yp\0()\0{ +>\0\0\0\0\0\0\0if\0((\0$#\0==\00\0)) +>\0\0\0\0\0\0\0then\0echo\0usage:\0yp\0name\0...;\0fi +>\0\0\0\0\0\0\0for\0i;\0do\0ypmatch\0$i\0passwd.byname;\0done +>\0} +%\0yp +usage:\0yp\0name\0... +%\0yp\0pfalstad\0sukthnkr +pfalstad:*:3564:35:Paul\0John\0Falstad:/u/pfalstad:/usr/princeton/bin/zsh +sukthnkr:*:1267:35:Rahul\0Sukthankar:/u/sukthnkr:/usr/princeton/bin/tcsh +.De +\fC$#\fP is the number of arguments supplied to the function. +If it is equal to zero, we print a usage message; otherwise, +we loop through the arguments, and \fCypmatch\fP all of them. +.\".KE <--- missing .KS or .KF above +.PP +Here's a function that selects a random line from a file: +.Ds +%\0randline\0()\0{ +>\0\0\0\0\0\0\0integer\0z=$(wc\0-l\0<$1) +>\0\0\0\0\0\0\0sed\0-n\0$[RANDOM\0%\0z\0+\01]p\0$1 +>\0} +%\0randline\0/etc/motd +PHOENIX\0WILL\0BE\0DOWN\0briefly\0Friday\0morning,\05/24/91\0from\08\0AM\0to +%\0randline\0/etc/motd +SunOS\0Release\04.1.1\0(PHOENIX)\0#19:\0Tue\0May\014\019:03:15\0EDT\01991 +%\0randline\0/etc/motd +|\0Please\0use\0the\0"msgs"\0command\0to\0read\0announcements.\0\0Refer\0to\0the\0\0\0| +%\0echo\0$z + +% +.De +\fCrandline\fP has a local variable, \fCz\fP, that holds the number of +lines in the file. \fC$[RANDOM % z + 1]\fP expands to a random number +between 1 and \fCz\fP. An expression of the form \fC$[\fR...\fC]\fR +expands to the value of the arithmetic expression within the brackets, +and the \fBRANDOM\fP variable returns a random number each time it +is referenced. \fC%\fP is the modulus operator, as in C. +Therefore, \fCsed -n $[RANDOM%z+1]p\fP picks a random line from its +input, from 1 to \fCz\fP. +.PP +Function definitions can be viewed with the \fCfunctions\fP builtin: +.Ds +%\0functions\0randline +randline\0()\0{ +\0\0\0\0\0\0\0\0integer\0z=$(wc\0-l\0<$1) +\0\0\0\0\0\0\0\0sed\0-n\0$[RANDOM\0%\0z\0+\01]p\0$1 + +} +%\0functions +yp\0()\0{ +\0\0\0\0\0\0\0\0if\0let\0$#\0==\00\0 +\0\0\0\0\0\0\0\0 +\0\0\0\0\0\0\0\0then +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0echo\0usage:\0yp\0name\0... +\0\0\0\0\0\0\0\0 +\0\0\0\0\0\0\0\0fi +\0\0\0\0\0\0\0\0for\0i +\0\0\0\0\0\0\0\0do +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ypmatch\0$i\0passwd.byname +\0\0\0\0\0\0\0\0 +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0done + +} +randline\0()\0{ +\0\0\0\0\0\0\0\0integer\0z=$(wc\0-l\0<$1) +\0\0\0\0\0\0\0\0sed\0-n\0$[RANDOM\0%\0z\0+\01]p\0$1 + +} +.De +Here's another one: +.Ds +%\0cx\0()\0{\0chmod\0+x\0$*\0} +%\0ls\0-l\0foo\0bar +-rw-r--r--\0\01\0pfalstad\0\0\0\0\0\0\029\0May\024\004:38\0bar +-rw-r--r--\0\01\0pfalstad\0\0\0\0\0\0\029\0May\024\004:38\0foo +%\0cx\0foo\0bar +%\0ls\0-l\0foo\0bar +-rwxr-xr-x\0\01\0pfalstad\0\0\0\0\0\0\029\0May\024\004:38\0bar +-rwxr-xr-x\0\01\0pfalstad\0\0\0\0\0\0\029\0May\024\004:38\0foo +.De +Note that this could also have been implemented as an alias: +.Ds +%\0chmod\0644\0foo\0bar +%\0alias\0cx='chmod\0+x' +%\0cx\0foo\0bar +%\0ls\0-l\0foo\0bar +-rwxr-xr-x\0\01\0pfalstad\0\0\0\0\0\0\029\0May\024\004:38\0bar +-rwxr-xr-x\0\01\0pfalstad\0\0\0\0\0\0\029\0May\024\004:38\0foo +.De +.PP +Instead of defining a lot of functions in your \fC.zshrc\fP, +all of which you may not use, +it is often better to use the \fCautoload\fP builtin. +The idea is, you create a directory where function +definitions are stored, declare the names in +your \fC.zshrc\fP, and tell the shell where to look for them. +Whenever you reference a function, the shell +will automatically load it into memory. +.Ds +%\0mkdir\0/tmp/funs +%\0cat\0>/tmp/funs/yp +ypmatch\0$1\0passwd.byname +^D +%\0cat\0>/tmp/funs/cx +chmod\0+x\0$* +^D +%\0FPATH=/tmp/funs +%\0autoload\0cx\0yp +%\0functions\0cx\0yp +undefined\0cx\0() +undefined\0yp\0() +%\0chmod\0755\0/tmp/funs/{cx,yp} +%\0yp\0egsirer +egsirer:*:3214:35:Emin\0Gun\0Sirer:/u/egsirer:/bin/sh +%\0functions\0yp +yp\0()\0{ +\0\0\0\0\0\0\0\0ypmatch\0$1\0passwd.byname +} +.De +This idea has other benefits. By adding a \fC#!\fP header +to the files, you can make them double as shell scripts. +(Although it is faster to use them as functions, since a +separate process is not created.) +.Ds +%\0ed\0/tmp/funs/yp +25 +i +#!\0/usr/local/bin/zsh +. +w +42 +q +%\0\0cd\0src +~/src> +.De +the shell will print the current directory in the prompt, +using the \fC~\fP character. +However, \fBzsh\fP is smarter than most other shells in this respect: +.Ds +~/src>\0cd\0~subbarao +~subbarao>\0cd\0~maruchck +~maruchck>\0cd\0lib +~maruchck/lib>\0cd\0fun +~maruchck/lib/fun>\0foo=/usr/princeton/common/src +~maruchck/lib/fun>\0cd\0~foo +~foo>\0cd\0.. +/usr/princeton/common>\0cd\0src +~foo>\0cd\0news/nntp +~foo/news/nntp>\0cd\0inews +~foo/news/nntp/inews> +.De +Note that \fBzsh\fP prints \fIother\fP users' directories +in the form \fC~user\fP. Also note that you can +set a parameter and use it as a directory name; +\fBzsh\fP will act as if \fCfoo\fP is a user +with the login directory \fC/usr/princeton/common/src\fP. +This is convenient, especially if you're sick of seeing +prompts like this: +.Ds +phoenix:/usr/princeton/common/src/X.V11R4/contrib/clients/xv/docs> +.De +If you get stuck in this position, you can give the current +directory a short name, like this: +.Ds +/usr/princeton/common/src/news/nntp/inews>\0inews=$PWD +/usr/princeton/common/src/news/nntp/inews>\0echo\0~inews +/usr/princeton/common/src/news/nntp/inews +~inews> +.De +When you reference a directory in the form \fC~inews\fP, +the shell assumes that you want the directory displayed +in this form; thus simply typing \fCecho ~inews\fP or +\fCcd ~inews\fP causes the prompt to be shortened. +You can define a shell function for this purpose: +.Ds +~inews>\0namedir\0()\0{\0$1=$PWD\0;\0\0:\0~$1\0} +~inews>\0cd\0/usr/princeton/bin +/usr/princeton/bin>\0namedir\0pbin +~pbin>\0cd\0/var/spool/mail +/var/spool/mail>\0namedir\0spool +~spool>\0cd\0.msgs +~spool/.msgs> +.De +You may want to add this one-line function to your \fC.zshrc\fP. + +\fBzsh\fP can also put the current directory in your title bar, +if you are using a windowing system. +One way to do this is with the \fCchpwd\fP function, which is +automatically executed by the shell whenever you change +directory. If you are using xterm, this will work: +.Ds +chpwd\0()\0{\0print\0-Pn\0'^[]2;%~^G'\0} +.De +The \fC-P\fP option tells \fCprint\fP to treat its arguments like a prompt +string; otherwise the \fC%~\fP would not be expanded. +The \fC-n\fP option suppresses the terminating newline, as with \fCecho\fP. +.PP +If you are using an IRIS \fCwsh\fP, do this: +.Ds +chpwd\0()\0{\0print\0-Pn\0'\e2201.y%~\e234'\0} +.De +The \fCprint -D\fP command has other uses. For example, to +print the current directory to standard output in short form, +you can do this: +.Ds +%\0print\0-D\0$PWD +~subbarao/src +.De +and to print each component of the path in short form: +.Ds +%\0print\0-D\0$path +/bin\0/usr/bin\0~locbin\0~locbin/X11\0~/bin +.De +.Sh "Directory Stacks" +.PP +If you use csh, you may know about directory stacks. +The \fCpushd\fP command puts the current directory on the +stack, and changes to a new directory; the \fCpopd\fP command +pops a directory off the stack and changes to it. +.Ds +phoenix%\0cd\0 +phoenix%\0PROMPT='Z\0%~>\0' +Z\0~>\0pushd\0/tmp +/tmp\0~ +Z\0/tmp>\0pushd\0/usr/etc +/usr/etc\0/tmp\0~ +Z\0/usr/etc>\0pushd\0/usr/bin +/usr/bin\0/usr/etc\0/tmp\0~ +Z\0/usr/bin>\0popd +/usr/etc\0/tmp\0~ +Z\0/usr/etc>\0popd +/tmp\0~ +Z\0/tmp>\0pushd\0/etc +/etc\0/tmp\0~ +Z\0/etc>\0popd\0 +/tmp\0~ +.De +\fBzsh\fP's directory stack commands work similarly. One +difference is the way \fCpushd\fP is handled if no arguments +are given. As in csh, this exchanges the top two elements +of the directory stack: +.Ds +Z\0/tmp>\0dirs +/tmp\0~ +Z\0/tmp>\0pushd +~\0/tmp +.De +unless the stack only has one entry: +.Ds +Z\0~>\0popd +/tmp +Z\0/tmp>\0dirs +/tmp +Z\0/tmp>\0pushd +~\0/tmp +Z\0~> +.De +or unless the \fIPUSHDTOHOME\fP option is set: +.Ds +Z\0~>\0setopt\0pushdtohome +Z\0~>\0pushd +~\0~\0/tmp +.De +.PP +As an alternative to using directory stacks in this manner, +we can get something like a \fIdirectory history\fP +by setting a few more options and parameters: +.Ds +~>\0DIRSTACKSIZE=8 +~>\0setopt\0autopushd\0pushdminus\0pushdsilent\0pushdtohome +~>\0alias\0dh='dirs\0-v' +~>\0cd\0/tmp +/tmp>\0cd\0/usr +/usr>\0cd\0bin +/usr/bin>\0cd\0../pub +/usr/pub>\0dh +0\0\0\0\0\0\0\0/usr/pub +1\0\0\0\0\0\0\0/usr/bin +2\0\0\0\0\0\0\0/usr +3\0\0\0\0\0\0\0/tmp +4\0\0\0\0\0\0\0~ +/usr/pub>\0cd\0-3 +/tmp>\0dh +0\0\0\0\0\0\0\0/tmp +1\0\0\0\0\0\0\0/usr/pub +2\0\0\0\0\0\0\0/usr/bin +3\0\0\0\0\0\0\0/usr +4\0\0\0\0\0\0\0~ +/tmp>\0ls\0=2/df +/usr/bin/df +/tmp>\0cd\0-4 +~> +.De +Note that \fC=2\fP expanded to the second directory in the +history list, and that \fCcd -3\fP recalled the third +directory in the list. +.PP +You may be wondering what all those options do. +\fIAUTOPUSHD\fP made \fCcd\fP act like \fCpushd\fP. +(\fCalias cd=pushd\fP is not sufficient, for various reasons.) +\fIPUSHDMINUS\fP swapped the meaning of \fCcd +1\fP and +\fCcd -1\fP; we want them to mean the opposite of what they mean in csh, +because it makes more sense in this scheme, and it's easier to type: +.Ds +~>\0dh +0\0\0\0\0\0\0\0~ +1\0\0\0\0\0\0\0/tmp +2\0\0\0\0\0\0\0/usr/pub +3\0\0\0\0\0\0\0/usr/bin +4\0\0\0\0\0\0\0/usr +~>\0unsetopt\0pushdminus +~>\0cd\0+1 +/tmp>\0dh +0\0\0\0\0\0\0\0/tmp +1\0\0\0\0\0\0\0~ +2\0\0\0\0\0\0\0/usr/pub +3\0\0\0\0\0\0\0/usr/bin +4\0\0\0\0\0\0\0/usr +/tmp>\0cd\0+2 +/usr/pub> +.De +\fIPUSHDSILENT\fP keeps the shell from printing +the directory stack each time we do a \fCcd\fP, +and \fIPUSHDTOHOME\fP we mentioned earlier: +.Ds +/usr/pub>\0unsetopt\0pushdsilent +/usr/pub>\0cd\0/etc +/etc\0/usr/pub\0/tmp\0~\0/usr/bin\0/usr +/etc>\0cd +~\0/etc\0/usr/pub\0/tmp\0~\0/usr/bin\0/usr +~>\0unsetopt\0pushdtohome +~>\0cd +/etc\0~\0/usr/pub\0/tmp\0~\0/usr/bin\0/usr +/etc> +.De +\fBDIRSTACKSIZE\fP keeps the directory stack +from getting too large, much like \fIHISTSIZE\fP: +.Ds +/etc>\0setopt\0pushdsilent +/etc>\0cd\0/ +/>\0cd\0/ +/>\0cd\0/ +/>\0cd\0/ +/>\0cd\0/ +/>\0cd\0/ +/>\0cd\0/ +/>\0cd\0/ +/>\0dh +0\0\0\0\0\0\0\0/ +1\0\0\0\0\0\0\0/ +2\0\0\0\0\0\0\0/ +3\0\0\0\0\0\0\0/ +4\0\0\0\0\0\0\0/ +5\0\0\0\0\0\0\0/ +6\0\0\0\0\0\0\0/ +7\0\0\0\0\0\0\0/ +.De +.Sh "Command/Process Substitution" +.PP +Command substitution in \fBzsh\fP can take two forms. +In the traditional form, a command enclosed in +backquotes (\fC`\fP...\fC`\fP) is replaced on the command line with its output. +This is the form used by the older shells. +Newer shells (like \fBzsh\fP) also provide another form, +\fC$(\fR...\fC)\fR. This form is much easier to nest. +.Ds +%\0ls\0-l\0`echo\0/vmunix` +-rwxr-xr-x\0\01\0root\0\0\0\0\0\01209702\0May\014\019:04\0/vmunix +%\0ls\0-l\0$(echo\0/vmunix) +-rwxr-xr-x\0\01\0root\0\0\0\0\0\01209702\0May\014\019:04\0/vmunix +%\0who\0|\0grep\0mad +subbarao\0ttyt7\0\0\0May\023\015:02\0\0\0(mad55sx15.Prince) +pfalstad\0ttyu1\0\0\0May\023\016:25\0\0\0(mad55sx14.Prince) +subbarao\0ttyu6\0\0\0May\023\015:04\0\0\0(mad55sx15.Prince) +pfalstad\0ttyv3\0\0\0May\023\016:25\0\0\0(mad55sx14.Prince) +%\0who\0|\0grep\0mad\0|\0awk\0'{print\0$2}' +ttyt7 +ttyu1 +ttyu6 +ttyv3 +%\0cd\0/dev;\0ls\0-l\0$(who\0| +>\0grep\0$(echo\0mad)\0| +>\0awk\0'{\0print\0$2\0}') +crwx-w----\0\01\0subbarao\0\020,\0\071\0May\023\018:35\0ttyt7 +crw--w----\0\01\0pfalstad\0\020,\0\081\0May\023\018:42\0ttyu1 +crwx-w----\0\01\0subbarao\0\020,\0\086\0May\023\018:38\0ttyu6 +crw--w----\0\01\0pfalstad\0\020,\0\099\0May\023\018:41\0ttyv3 +.De +Many common uses of command substitution, however, are +superseded by other mechanisms of \fBzsh\fP: +.Ds +%\0ls\0-l\0`tty` +crw-rw-rw-\0\01\0root\0\0\0\0\0\020,\0\028\0May\023\018:35\0/dev/ttyqc +%\0ls\0-l\0$TTY +crw-rw-rw-\0\01\0root\0\0\0\0\0\020,\0\028\0May\023\018:35\0/dev/ttyqc +%\0ls\0-l\0`which\0rn` +-rwxr-xr-x\0\01\0root\0\0\0\0\0\0\0172032\0Mar\0\06\018:40\0/usr/princeton/bin/rn +%\0ls\0-l\0=rn +-rwxr-xr-x\0\01\0root\0\0\0\0\0\0\0172032\0Mar\0\06\018:40\0/usr/princeton/bin/rn +.De +A command name with a \fC=\fP prepended is replaced with its full +pathname. This can be very convenient. If it's not convenient +for you, you can turn it off: +.Ds +%\0ls +=foo\0\0\0\0=bar +%\0ls\0=foo\0=bar +zsh:\0foo\0not\0found +%\0setopt\0noequals +%\0ls\0=foo\0=bar +=foo\0\0\0\0=bar +.De +.PP +Another nice feature is process substitution: +.Ds +%\0who\0|\0fgrep\0-f\0=(print\0-l\0root\0lemke\0shgchan\0subbarao) +root\0\0\0\0\0console\0May\019\010:41 +lemke\0\0\0\0ttyq0\0\0\0May\022\010:05\0\0\0(narnia:0.0) +lemke\0\0\0\0ttyr7\0\0\0May\022\010:05\0\0\0(narnia:0.0) +lemke\0\0\0\0ttyrd\0\0\0May\022\010:05\0\0\0(narnia:0.0) +shgchan\0\0ttys1\0\0\0May\023\016:52\0\0\0(gaudi.Princeton.) +subbarao\0ttyt7\0\0\0May\023\015:02\0\0\0(mad55sx15.Prince) +subbarao\0ttyu6\0\0\0May\023\015:04\0\0\0(mad55sx15.Prince) +shgchan\0\0ttyvb\0\0\0May\023\016:51\0\0\0(gaudi.Princeton.) +.De +A command of the form \fC=(\fR...\fC)\fR is replaced with the name of a \fIfile\fP +containing its output. (A command substitution, on the other +hand, is replaced with the output itself.) +\fCprint -l\fP is like \fCecho\fP, excepts that it prints its arguments +one per line, the way \fCfgrep\fP expects them: +.Ds +%\0print\0-l\0foo\0bar +foo +bar +.De +We could also have written: +.Ds +%\0who\0|\0fgrep\0-f\0=(echo\0'root +>\0lemke +>\0shgchan +>\0subbarao') +.De +Using\0process\0substitution, +you\0can\0edit\0the\0output\0of\0a\0command: +.Ds +%\0ed\0=(who\0|\0fgrep\0-f\0~/.friends) +355 +g/lemke/d +w\0/tmp/filbar +226 +q +%\0cat\0/tmp/filbar +root\0\0\0\0\0console\0May\019\010:41 +shgchan\0\0ttys1\0\0\0May\023\016:52\0\0\0(gaudi.Princeton.) +subbarao\0ttyt7\0\0\0May\023\015:02\0\0\0(mad55sx15.Prince) +subbarao\0ttyu6\0\0\0May\023\015:04\0\0\0(mad55sx15.Prince) +shgchan\0\0ttyvb\0\0\0May\023\016:51\0\0\0(gaudi.Princeton.) +.De +or easily read archived mail: +.Ds +%\0mail\0-f\0=(zcat\0~/mail/oldzshmail.Z) +"/tmp/zsha06024":\084\0messages,\00\0new,\043\0unread +>\0\01\0\0U\0\0TO:\0pfalstad,\0zsh\0(10) +\0\0\02\0\0U\0\0nytim!tim@uunet.uu.net,\0Re:\0Zsh\0on\0Sparc1\0/SunOS\04.0.3 +\0\0\03\0\0U\0\0JAM%TPN@utrcgw.utc.com,\0zsh\0fix\0(15) +\0\0\04\0\0U\0\0djm@eng.umd.edu,\0way\0to\0find\0out\0if\0running\0zsh?\0(25) +\0\0\05\0\0U\0\0djm@eng.umd.edu,\0Re:\0way\0to\0find\0out\0if\0running\0zsh?\0(17) +\0\0\06\0\0\0r\0djm@eng.umd.edu,\0Meta\0.\0(18) +\0\0\07\0\0U\0\0jack@cs.glasgow.ac.uk,\0Re:\0problem\0building\0zsh\0(147) +\0\0\08\0\0U\0\0nytim!tim@uunet.uu.net,\0Re:\0Zsh\0on\0Sparc1\0/SunOS\04.0.3 +\0\0\09\0\0\0\0\0ursa!jmd,\0Another\0fix...\0(61) +\0\010\0\0U\0\0pplacewa@bbn.com,\0Re:\0v18i084:\0Zsh\02.00\0-\0A\0small\0complaint\0(36) +\0\011\0\0U\0\0lubkin@cs.rochester.edu,\0POSIX\0job\0control\0(34) +\0\012\0\0U\0\0yale!bronson!tan@uunet.UU.NET +\0\013\0\0U\0\0brett@rpi.edu,\0zsh\0(36) +\0\014\0\0S\0\0subbarao,\0zsh\0sucks!!!!\0(286) +\0\015\0\0U\0\0snibru!d241s008!d241s013!ala@relay.EU.net,\0zsh\0(165) +\0\016\0\0U\0\0nytim!tim@uunet.UU.NET,\0Re:\0Zsh\0on\0Sparc1\0/SunOS\04.0.3 +\0\017\0\0U\0\0subbarao,\0zsh\0is\0a\0junk\0shell\0(43) +\0\018\0\0U\0\0amaranth@vela.acs.oakland.edu,\0zsh\0(33) +43u/84\01:\0x +%\0ls\0-l\0/tmp/zsha06024 +/tmp/zsha06024\0not\0found +.De +Note that the shell creates a temporary file, and deletes it +when the command is finished. +.Ds +%\0diff\0=(ls)\0=(ls\0-F) +3c3 +<\0fortune +--- +>\0fortune* +10c10 +<\0strfile +--- +>\0strfile* +.De +If you read \fBzsh\fP's man page, you may notice that \fC<(\fR...\fC)\fR +is another form of process substitution which is similar to +\fC=(\fR...\fC)\fR. +There is an important difference between the two. +In the \fC<(\fR...\fC)\fR case, the shell creates a named pipe (FIFO) +instead of a file. This is better, since it does not +fill up the file system; but it does not work in all cases. +In fact, if we had replaced \fC=(\fR...\fC)\fR with \fC<(\fR...\fC)\fR in +the examples above, all of them would have stopped working +except for \fCfgrep -f <(\fR...\fC)\fR. +You can not edit a pipe, or open it as a mail folder; +\fCfgrep\fP, however, has no problem with reading +a list of words from a pipe. +You may wonder why \fCdiff <(foo) bar\fP doesn't work, since +\fCfoo | diff - bar\fP works; this is because \fCdiff\fP creates +a temporary file if it notices that one of its arguments +is \fC-\fP, and then copies its standard input to the temporary +file. +.PP +\fC>(\fR...\fC)\fR is just like \fC<(\fR...\fC)\fR except that the +command between the parentheses will get its input from the named +pipe. +.Ds +%\0dvips\0-o\0>(lpr)\0zsh.dvi +.De +.Sh "Redirection" +.PP +Apart from all the regular redirections like the Bourne shell has, +\fBzsh\fP can do more. You can send the output of a command to more +than one file, by specifying more redirections like +.Ds +%\0echo\0Hello\0World\0>file1\0>file2 +.De +and the text will end up in both files. Similarly, you can send the +output to a file and into a pipe: +.Ds +%\0make\0>\0make.log\0|\0grep\0Error +.De +The same goes for input. You can make the input of a command come +from more than one file. +.Ds +%\0sort\0 >(\fR...\fC)\fR. +.Ds +%\0find\0/\0-name\0games\02>\0>(grep\0-v\0'Permission'\0>\0realerrors) +.De +The above redirection will actually be implemented with a regular +pipe, not a temporary named pipe. +.Sh "Aliasing" +.PP +Often-used commands can be abbreviated with an alias: +.Ds +%\0alias\0uc=uncompress +%\0ls +hanoi.Z +%\0uc\0hanoi +%\0ls +hanoi +.De +or commands with certain desired options: +.Ds +%\0alias\0fm='finger\0-m' +%\0fm\0root +Login\0name:\0root\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0In\0real\0life:\0Operator +Directory:\0/\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Shell:\0/bin/csh +On\0since\0May\019\010:41:15\0on\0console\0\0\0\0\03\0days\05\0hours\0Idle\0Time +No\0unread\0mail +No\0Plan. + +%\0alias\0lock='lock\0-p\0-60000' +%\0lock +lock:\0/dev/ttyr4\0on\0phoenix.\0timeout\0in\060000\0minutes +time\0now\0is\0Fri\0May\024\004:23:18\0EDT\01991 +Key:\0 + +%\0alias\0l='ls\0-AF' +%\0l\0/ +\&.bash_history\0\0\0\0\0\0\0\0\0\0\0\0\0\0kadb* +\&.bashrc\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0lib@ +\&.cshrc\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0licensed/ +\&.exrc\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0lost+found/ +\&.login\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0macsyma +\&\fR... +.De +Aliases can also be used to replace old commands: +.Ds +%\0alias\0grep=egrep\0ps=sps\0make=gmake +%\0alias\0whoami='echo\0root' +%\0whoami +root +.De +or to define new ones: +.Ds +%\0cd\0/ +%\0alias\0sz='ls\0-l\0|\0sort\0-n\0+3\0|\0tail\0-10' +%\0sz +drwxr-sr-x\0\07\0bin\0\0\0\0\0\0\0\0\0\03072\0May\023\011:59\0etc +drwxrwxrwx\026\0root\0\0\0\0\0\0\0\0\05120\0May\024\004:20\0tmp +drwxr-xr-x\0\02\0root\0\0\0\0\0\0\0\0\08192\0Dec\026\019:34\0lost+found +drwxr-sr-x\0\02\0bin\0\0\0\0\0\0\0\0\014848\0May\023\018:48\0dev +-r--r--r--\0\01\0root\0\0\0\0\0\0\0140520\0Dec\026\020:08\0boot +-rwxr-xr-x\0\01\0root\0\0\0\0\0\0\0311172\0Dec\026\020:08\0kadb +-rwxr-xr-x\0\01\0root\0\0\0\0\0\01209695\0Apr\016\015:33\0vmunix.old +-rwxr-xr-x\0\01\0root\0\0\0\0\0\01209702\0May\014\019:04\0vmunix +-rwxr-xr-x\0\01\0root\0\0\0\0\0\01209758\0May\021\012:23\0vmunix.new.kernelmap.old +-rwxr-xr-x\0\01\0root\0\0\0\0\0\01711848\0Dec\026\020:08\0vmunix.org +%\0cd +%\0alias\0rable='ls\0-AFtrd\0*(R)'\0nrable='ls\0-AFtrd\0*(^R)' +%\0rable +README\0\0\0\0\0\0func/\0\0\0\0\0\0\0bin/\0\0\0\0\0\0\0\0pub/\0\0\0\0\0\0\0\0News/\0\0\0\0\0\0\0src/ +nicecolors\0\0etc/\0\0\0\0\0\0\0\0scr/\0\0\0\0\0\0\0\0tmp/\0\0\0\0\0\0\0\0iris/\0\0\0\0\0\0\0zsh* +%\0nrable +Mailboxes/\0\0mail/\0\0\0\0\0\0\0notes +.De +(The pattern \fC*(R)\fP matches all readable files in the current +directory, and \fC*(^R)\fP matches all unreadable files.) +.PP +Most other shells have aliases of this kind (\fIcommand\fP aliases). +However, \fBzsh\fP also has \fIglobal\fP aliases, which are substituted +anywhere on a line. +Global aliases can be used to abbreviate frequently-typed +usernames, hostnames, etc. +.Ds +%\0alias\0-g\0me=pfalstad\0gun=egsirer\0mjm=maruchck +%\0who\0|\0grep\0me +pfalstad\0ttyp0\0\0\0May\024\003:39\0\0\0(mickey.Princeton) +pfalstad\0ttyp5\0\0\0May\024\003:42\0\0\0(mickey.Princeton) +%\0fm\0gun +Login\0name:\0egsirer\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0In\0real\0life:\0Emin\0Gun\0Sirer +Directory:\0/u/egsirer\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Shell:\0/bin/sh +Last\0login\0Thu\0May\023\019:05\0on\0ttyq3\0from\0bow.Princeton.ED +New\0mail\0received\0Fri\0May\024\002:30:28\01991; +\0\0unread\0since\0Fri\0May\024\002:30:27\01991 +%\0alias\0-g\0phx=phoenix.princeton.edu\0warc=wuarchive.wustl.edu +%\0ftp\0warc +Connected\0to\0wuarchive.wustl.edu. +.De +Here are some more interesting uses. +.Ds +%\0alias\0-g\0M='|\0more'\0GF='|\0fgrep\0-f\0~/.friends' +%\0who\0M\0\0\0#\0\fIpipes\0the\0output\0of\0\fCwho\fI\0through\0\fCmore +%\0who\0GF\0\0#\0\fIsee\0if\0your\0friends\0are\0on\fC +%\0w\0GF\0\0\0\0#\0\fIsee\0what\0your\0friends\0are\0doing +.De +Another example makes use of \fBzsh\fP's process substitution. +If you run NIS, and you miss being able to do this: +.Ds +%\0grep\0pfalstad\0/etc/passwd +.De +you can define an alias that will seem more natural +than \fCypmatch pfalstad passwd\fP: +.Ds +%\0alias\0-g\0PASS='<(ypcat\0passwd)' +%\0grep\0pfalstad\0PASS +pfalstad:*:3564:35:Paul\0John\0Falstad:/u/pfalstad:/usr/princeton/bin/zsh +.De +If you're really crazy, you can even call it \fC/etc/passwd\fP: +.Ds +%\0alias\0-g\0/etc/passwd='<(ypcat\0passwd)' +%\0grep\0pfalstad\0/etc/passwd +pfalstad:*:3564:35:Paul\0John\0Falstad:/u/pfalstad:/usr/princeton/bin/zsh +.De +The last example shows one of the perils of global aliases; +they have a lot of potential to cause confusion. +For example, if you defined a global alias called \fC|\fP (which is +possible), \fBzsh\fP would begin to act very strangely; every pipe +symbol would be replaced with the text of your alias. +To some extent, global aliases are like macros in C; +discretion is advised in using them and in choosing names for them. +Using names in all caps is not a bad idea, especially +for aliases which introduce shell metasyntax (like \fCM\fP and \fCGF\fP +above). +.PP +Note that \fBzsh\fP aliases are not like csh aliases. The syntax for +defining them is different, and they do not have arguments. +All your favorite csh aliases will probably not work under \fBzsh\fP. +For example, if you try: +.Ds +alias\0rm\0mv\0'\e!*\0/tmp/wastebasket' +.De +no aliases will be defined, but \fBzsh\fP will not report an error. +In csh, this line defines an alias that makes \fCrm\fP safe---files +that are \fCrm\fP'd will be moved to a temporary directory instead of +instantly destroyed. In \fBzsh\fP's syntax, however, this line asks +the shell to print any existing alias definitions for \fCrm\fP, +\fCmv\fP, or \fC!*\ /tmp/wastebasket\fP. Since there are none, most +likely, the shell will not print anything, although \fCalias\fP will +return a nonzero exit code. The proper syntax is this: +.Ds +alias\0rm='mv\0\e!*\0/tmp/wastebasket' +.De +However, this won't work either: +.Ds +%\0rm\0foo.dvi +zsh:\0no\0matches\0found:\0!* +.De +While this makes \fCrm\fP safe, it is certainly not what the user +intended. In \fBzsh\fP, you must use a shell function for this: +.Ds +%\0unalias\0rm +%\0rm\0()\0{\0mv\0$*\0/tmp/wastebasket\0} +%\0rm\0foo.dvi +%\0ls\0/tmp/wastebasket +foo.dvi +.De +While this is much cleaner and easier to read (I hope you will +agree), it is not csh-compatible. Therefore, a script to convert +csh aliases and variables has been provided. You should only need to use it +once, to convert all your csh aliases and parameters to \fBzsh\fP format: +.Ds +%\0csh +csh>\0alias +l\0\0\0\0\0\0\0ls\0-AF +more\0\0\0\0less +on\0\0\0\0\0\0last\0-2\0!:1\0;\0who\0|\0grep\0!:1 +csh>\0exit +%\0c2z\0>neat_zsh_aliases +%\0cat\0neat_zsh_aliases +alias\0l='ls\0-AF' +alias\0more='less' +on\0()\0{\0last\0-2\0$1\0;\0who\0|\0grep\0$1\0} +\&... +.De +The first two aliases were converted to regular \fBzsh\fP aliases, while +the third, since it needed to handle arguments, was converted to +a function. \fCc2z\fP can convert most aliases to \fBzsh\fP format without +any problems. However, if you're using some really arcane csh tricks, +or if you have an alias with a name like \fCdo\fP (which is reserved +in \fBzsh\fP), you may have to fix some of the aliases by hand. +.PP +The \fCc2z\fP script checks your csh setup, and produces a list +of \fBzsh\fP commands which replicate your aliases and parameter settings +as closely as possible. You could include its output in your +startup file, \fC.zshrc\fP. +.Sh "History" +.PP +There are several ways to manipulate history in \fBzsh\fP. +One way is to use csh-style \fC!\fP history: +.Ds +%\0/usr/local/bin/!:0\0!-2*:s/foo/bar/\0>>!$ +.De +If you don't want to use this, you can turn it off +by typing \fCsetopt nobanghist\fP. If you are afraid of accidentally +executing the wrong command you can set the \fIHISTVERIFY\fP option. +If this option is set, commands that result from history expansion +will not be executed immediately, but will be put back into the editor +buffer for further consideration. +.PP +If you're not familiar with \fC!\fP history, here follows some +explanation. History substitutions always start with a \fC!\fP, +commonly called \*Qbang\*U. After the \fC!\fP comes an (optional) +designation of which \*Qevent\*U (command) to use, then a colon, and +then a designation of what word of that command to use. For example, +\fC!-\fIn\fR refers to the command \fIn\fP commands ago. +.Ds +%\0ls +foo\0\0bar +%\0cd\0foo +%\0!-2 +ls +baz\0\0bam +.De +No word designator was used, which means that the whole command +referred to was repeated. Note that the shell will echo the result of +the history substitution. The word designator can, among other +things, be a number indicating the argument to use, where \fC0\fP is +the command. +.Ds +%\0/usr/bin/ls\0foo +foo +%\0!:0\0bar +/usr/bin/ls\0bar +bar +.De +In this example, no event designator was used, which tells \fBzsh\fP +to use the previous command. A \fC$\fP specifies the last argument +.Ds +%\0mkdir\0/usr/local/lib/emacs/site-lisp/calc +%\0cd\0!:$ +cd\0/usr/local/lib/emacs/site-lisp/calc +.De +If you use more words of the same command, only the first \fC!\fP +needs an event designator. +.Ds +%\0make\0prig\0>>\0make.log +make:\0***\0No\0rule\0to\0make\0target\0`prig'.\0\0Stop. +%\0cd\0src +%\0!-2:0\0prog\0>>\0!:$ +make\0prog\0>>\0make.log +.De +This is different from csh, where a bang with no event designator +always refers to the previous command. If you actually like this +behaviour, set the \fICSHJUNKIEHISTORY\fP option. +.Ds +%\0setopt\0cshjunkiehistory +%\0!-2:0\0prog2\0>>\0!:$ +make\0prog2\0>>\0cshjunkiehistory +.De +Another way to use history is to use the \fCfc\fP command. For +example, if you type an erroneous command: +.Ds +%\0for\0i\0in\0`cat\0/etc/clients`\0 +\0do\0 +\0rpu\0$i\0 +\0done +zsh:\0command\0not\0found:\0rpu +zsh:\0command\0not\0found:\0rpu +zsh:\0command\0not\0found:\0rpu +\&\fR... +.De +typing \fCfc\fP will execute an editor on this command, allowing +you to fix it. (The default editor is \fCvi\fP, by the way, +not \fCed\fP). +.Ds +%\0fc +49 +/rpu/s//rup/p +\0rup\0$i\0 +w +49 +q +for\0i\0in\0`cat\0/etc/clients`\0 +\0do\0 +\0rup\0$i\0 +\0done +\0\0\0\0\0\0\0\0beam\0\0\0\0up\0\02\0days,\010:17,\0\0\0\0load\0average:\00.86,\00.80,\00.50 +\0\0\0\0\0\0\0\0\0bow\0\0\0\0up\0\04\0days,\0\08:41,\0\0\0\0load\0average:\00.91,\00.80,\00.50 +\0\0\0\0\0\0\0\0burn\0\0\0\0up\0\0\0\0\0\0\0\0\0\017:18,\0\0\0\0load\0average:\00.91,\00.80,\00.50 +\0\0\0\0\0\0\0burst\0\0\0\0up\0\09\0days,\0\01:49,\0\0\0\0load\0average:\00.95,\00.80,\00.50 +\0\0\0\0\0\0\0\0\0tan\0\0\0\0up\0\0\0\0\0\0\0\0\0\011:14,\0\0\0\0load\0average:\00.91,\00.80,\00.50 +\0\0\0\0\0\0\0bathe\0\0\0\0up\0\03\0days,\017:49,\0\0\0\0load\0average:\01.84,\01.79,\01.50 +\0\0\0\0\0\0\0\0bird\0\0\0\0up\0\01\0day,\0\0\09:13,\0\0\0\0load\0average:\01.95,\01.82,\01.51 +\0\0\0\0\0\0bonnet\0\0\0\0up\0\02\0days,\021:18,\0\0\0\0load\0average:\00.93,\00.80,\00.50 +\&\fR... +.De +A variant of the \fCfc\fP command is \fCr\fP, which redoes the last +command, with optional changes: +.Ds +%\0echo\0foo +foo +%\0r +echo\0foo +foo + +%\0echo\0foo +foo +%\0r\0foo=bar +echo\0bar +bar +.De +.Sh "Command Line Editing" +.PP +\fBzsh\fP's command line editor, \fBZLE\fP, is quite powerful. +It is designed to emulate either emacs or vi; the default +is emacs. To set the bindings for vi mode, type \fCbindkey -v\fP. If +your \fBEDITOR\fP or \fBVISUAL\fP environment variable is vi, +\fBzsh\fP will use vi emulation by default. You can then switch to +emacs mode with \fCbindkey -e\fP. +.PP +In addition to basic editing, the shell allows you to +recall previous lines in the history. In emacs mode, +this is done with \fI^P\fP (control-P) or (on many terminals) with the +cursor-up key: +.Ds +%\0ls\0~ +-\0\0\0\0\0\0\0\0\0\0\0README\0\0\0\0\0\0file\0\0\0\0\0\0\0\0mail\0\0\0\0\0\0\0\0pub\0\0\0\0\0\0\0\0\0tmp +Mailboxes\0\0\0bin\0\0\0\0\0\0\0\0\0func\0\0\0\0\0\0\0\0nicecolors\0\0scr\0\0\0\0\0\0\0\0\0zsh +News\0\0\0\0\0\0\0\0etc\0\0\0\0\0\0\0\0\0iris\0\0\0\0\0\0\0\0notes\0\0\0\0\0\0\0src +%\0echo\0foobar +foobar +%\0\fI^P\fC +%\0echo\0foobar\fI^P\fC +%\0ls\0~_ +.De +Pressing \fI^P\fP once brings up the previous line (\fCecho foobar\fP); +pressing it again brings up the line before that (\fCls ~\fP). +The cursor is left at the end of the line, allowing you to +edit the line if desired before executing it. +In many cases, \fBZLE\fP eliminates the need for the \fCfc\fP command, +since it is powerful enough to handle even multiline commands: +.Ds +%\0for\0i\0in\0a\0b\0c\0d\0e +>\0do +>\0echo\0$i +>\0done +a +b +c +d +e +%\0\fI^P\fC +%\0for\0i\0in\0a\0b\0c\0d\0e\0 +\0do\0 +\0echo\0$i\0 +\0done_ +.De +Now you can just move up to the part you want to change... +.Ds +%\0for\0i\0in\0\kxa\l'|\nxu\(ul'\0b\0c\0d\0e +\0do\0 +\0echo\0$i\0 +\0done +.De +change it, and execute the new command. +.Ds +%\0for\0i\0in\0f\0g\0h\0i\0j +\0do\0 +\0echo\0$i\0 +\0done +f +g +h +i +j +.De +Also, you can search the history for a certain command using +\fIESC-P\fP, this will look for the last command that started with the +(part of the) word at the beginning of the current line. Hitting +\fIESC-P\fP another time gets you the command before that, etc. +.Ds +%\0set\0\fIESC-P\fC +%\0setopt\0autolist\0\fIESC-P\fC +%\0setopt\0nocorrect_ +.De +Another way is to do an incremental search, emacs-style: +.Ds +%\0\fI^R\fC +%\0_ +i-search: + +%\0l\kxs\l'|\nxu\(ul'\0/usr/bin +i-search:\0l + +%\0date\0>\0foofile\kx.\l'|\nxu\(ul'c +i-search:\0le +.De +Suppose you have retrieved an old history event in one of these ways +and would like to execute several consecutive old commands starting +with this one. \fC^O\fP will execute the current command and then put +the next command from the history into the editor buffer. Typing +\fC^O\fP several times will therefore reexecute several consecutive +commands from the history. Of course, you can edit some of those +commands in between. +.PP +In addition to completion (see below), \fITAB\fP performs expansion if +possible. +.Ds +%\0ls\0*.c\fITAB\fC +%\0ls\0foofile.c\0fortune.c\0rnd.c\0strfile.c\0unstr.c_ +.De +For example, suppose you have a bunch of weird files in an important +directory: +.Ds +%\0ls +\0\0*\0*\0*\0\0\0\0\0\0\0;\0&\0%\0$??foo\0\0dspfok\0\0\0\0\0\0\0\0foo.c +\0\0!"foo"!\0\0\0\0\0\0\0`\0\e\0`\0\0\0\0\0\0\0\0\0foo\0\0\0\0\0\0\0\0\0\0\0rrr +.De +You want to remove them, but you don't want to damage \fCfoo.c\fP. +Here is one way to do this: +.Ds +%\0rm\0*\fITAB\fC +%\0rm\0\e\0\e\0\e*\e\0\e*\e\0\e*\e\0\e\0\e\0\0\e!\e"foo\e"\e!\0\e;\e\0\e&\e\0%\e\0\e$' +'' +'foo\0\e`\e\0\e\e\e\0\e`\0dspfok\0foo\0foo.c\0rrr_ +.De +When you expand \fC*\fP, \fBzsh\fP inserts the names of all the files +into the editing buffer, with proper shell quoting. +Now, just move back and remove \fCfoo.c\fP from the buffer: +.Ds +%\0rm\0\e\0\e\0\e*\e\0\e*\e\0\e*\e\0\e\0\e\0\0\e!\e"foo\e"\e!\0\e;\e\0\e&\e\0%\e\0\e$' +'' +'foo\0\e`\e\0\e\e\e\0\e`\0dspfok\0foo\0\kxr\l'|\nxu\(ul'rr +.De +and press return. +Everything except \fCfoo.c\fP will be deleted from the directory. If +you do not want to actually expand the current word, but would like to +see what the matches are, type \fC^Xg\fP. +.Ds +%\0rm\0f*\fI^Xg\fP +foo\0\0\0\0foo.c +%\0rm\0f*_ +.De +Here's another trick; let's say you have typed this command in: +.Ds +%\0gcc\0-o\0x.out\0foob.c\0-g\0-Wpointer-arith\0-Wtrigraphs_ +.De +and you forget which library you want. You need to escape +out for a minute and check by typing +\fCls /usr/lib\fP, 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 \fBzsh\fP, you can put the line on the \fIbuffer stack\fP, using +\fIESC-Q\fP, and type some other commands. The next time a prompt is printed, +the \fCgcc\fP 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, \fIESC-Q\fP again and look +for some other libraries whose names you forgot). +.PP +A similar situation: what if you forget the option to gcc that +finds bugs using AI techniques? You could either use \fIESC-Q\fP +again, and type \fCman gcc\fP, or you could press \fIESC-H\fP, which +essentially does the same thing; it puts the current line on +the buffer stack, and executes the command \fCrun-help gcc\fP, +where \fCrun-help\fP is an alias for \fCman\fP. +.PP +Another interesting command is \fIESC-A\fP. 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: +.Ds +%\0cc\0grok.c\0-g\0-lc\0-lgl\0-lsun\0-lmalloc\0-Bstatic\0-o\0b.out +%\0cc\0fubar.c\0-g\0-lc\0-lgl\0-lsun\0-lmalloc\0-Bstatic\0-o\0b.out +%\0cc\0fooble.c\0-g\0-lc\0-lgl\0-lsun\0-lmalloc\0-Bstatic\0-o\0b.out +.De +.PP +The \fIESC-'\fP command is useful for managing the shell's quoting +conventions. Let's say you want to print this string: +.Ds +don't\0do\0that;\0type\0'rm\0-rf\0\e*',\0with\0a\0\e\0before\0the\0*. +.De +All that is necessary is to type it into the editing buffer: +.Ds +%\0don't\0do\0that;\0type\0'rm\0-rf\0\e*',\0with\0a\0\e\0before\0the\0*. +.De +press \fIESC-'\fP (escape-quote): +.Ds +%\0'don'\e''t\0do\0that;\0type\0'\e''rm\0-rf\0\e*'\e'',\0with\0a\0\e\0before\0the\0*.' +.De +then move to the beginning and add the \fCecho\fP command. +.Ds +%\0echo\0'don'\e''t\0do\0that;\0type\0'\e''rm\0-rf\0\e*'\e'',\0with\0a\0\e\0before\0the\0*.' +don't\0do\0that;\0type\0'rm\0-rf\0\e*',\0with\0a\0\e\0before\0the\0*. +.De +Let's say you want to create an alias to do this \fCecho\fP command. +This can be done by recalling the line with \fI^P\fP and pressing +\fIESC-'\fP again: +.Ds +%\0'echo\0'\e''don'\e''\e'\e'''\e''t\0do\0that;\0type\0'\e''\e'\e'''\e''rm\0-rf +\e*'\e''\e'\e'''\e'',\0with\0a\0\e\0before\0the\0*.'\e''' +.De +and then move to the beginning and add the command to create +an alias. +.Ds +%\0alias\0zoof='echo\0'\e''don'\e''\e'\e'''\e''t\0do\0that;\0type\0'\e''\e'\e'''\e''rm +-rf\0\e*'\e''\e'\e'''\e'',\0with\0a\0\e\0before\0the\0*.'\e''' +%\0zoof +don't\0do\0that;\0type\0'rm\0-rf\0\e*',\0with\0a\0\e\0before\0the\0*. +.De +If one of these fancy editor commands changes your command line in a +way you did not intend, you can undo changes with \fC^_\fP, if you can +get it out of your keyboard, or \fC^X^U\fP, otherwise. +.PP +Another use of the editor is to edit the value of variables. +For example, an easy way to change your path is to use +the \fCvared\fP command: +.Ds +%\0vared\0PATH +>\0/u/pfalstad/scr:/u/pfalstad/bin/sun4:/u/maruchck/scr:/u/subbarao/bin:/u/maruc +hck/bin:/u/subbarao/scripts:/usr/princeton/bin:/usr/ucb:/usr/bin:/bin:/usr/host +s:/usr/princeton/bin/X11:/./usr/lang:/./usr/etc:/./etc +.De +You can now edit the path. When you press return, the contents +of the edit buffer will be assigned to \fBPATH\fP. +.Sh "Completion" +.PP +Another great \fBzsh\fP feature is completion. If you hit \fITAB\fP, \fBzsh\fP +will complete all kinds of stuff. Like commands or filenames: +.Ds +%\0comp\fITAB\fC +%\0compress\0_ + +%\0ls\0nic\fITAB\fC +%\0ls\0nicecolors\0_ + +%\0ls\0/usr/pr\fITAB\fC +%\0ls\0/usr/princeton/_ + +%\0ls\0-l\0=com\fITAB\fC +%\0ls\0-l\0=compress\0_ +.De +If the completion is ambiguous, the editor will beep. If you find +this annoying, you can set the \fINOLISTBEEP\fP option. Completion +can even be done in the middle of words. To use this, you will have +to set the \fICOMPLETEINWORD\fP option: +.Ds +%\0setopt\0completeinword +%\0ls\0/usr/p\kxt\l'|\nxu\(ul'on\fITAB\fC +%\0ls\0/usr/prince\kxt\l'|\nxu\(ul'on/ +%\0setopt\0alwaystoend +%\0ls\0/usr/p\kxt\l'|\nxu\(ul'on\fITAB\fC +%\0ls\0/usr/princeton/_ +.De +You can list possible completions by pressing \fI^D\fP: +.Ds +%\0ls\0/vmu\fITAB\0\(embeep\(em\fC +%\0ls\0/vmunix_ +%\0ls\0/vmunix\fI^D\fC +vmunix\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0vmunix.old\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 +vmunix.new.kernelmap.old\0\0vmunix.org +.De +Or, you could just set the \fIAUTOLIST\fP option: +.Ds +%\0setopt\0autolist +%\0ls\0/vmu\fITAB\0\(embeep\(em\fC +vmunix\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0vmunix.old\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 +vmunix.new.kernelmap.old\0\0vmunix.org +%\0ls\0/vmunix_ +.De +If you like to see the types of the files in these lists, like in +\fCls\ -F\fP, you can set the \fILISTTYPES\fP option. Together with +\fIAUTOLIST\fP you can use \fILISTAMBIGUOUS\fP. This will only list +the possibilities if there is no unambiguous part to add: +.Ds +%\0setopt\0listambiguous +%\0ls\0/vmu\fITAB\0\(embeep\(em\fC +%\0ls\0/vmunix_\fITAB\0\(embeep\(em\fC +vmunix\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0vmunix.old\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 +vmunix.new.kernelmap.old\0\0vmunix.org +.De +If you don't want several of these listings to scroll the screen so +much, the \fIALWAYSLASTPROMPT\fP option is useful. If set, you can +continue to edit the line you were editing, with the completion +listing appearing beneath it. +.PP +Another interesting option is \fIMENUCOMPLETE\fP. This affects the +way \fITAB\fP works. Let's look at the \fC/vmunix\fP example again: +.Ds +%\0setopt\0menucomplete +%\0ls\0/vmu\fITAB\fC +%\0ls\0/vmunix\fITAB\fC +%\0ls\0/vmunix.new.kernelmap.old\fITAB\fC +%\0ls\0/vmunix.old_ +.De +Each time you press \fITAB\fP, it displays the next possible completion. +In this way, you can cycle through the possible completions until +you find the one you want. +.PP +The \fIAUTOMENU\fP option makes a nice compromise between this method +of completion and the regular method. If you set this option, +pressing \fITAB\fP once completes the unambiguous part normally, +pressing the \fITAB\fP key repeatedly after an ambiguous completion +will cycle through the possible completions. +.PP +Another option you could set is \fIRECEXACT\fP, which causes +exact matches to be accepted, even if there are other possible +completions: +.Ds +%\0setopt\0recexact +%\0ls\0/vmu\fITAB\0\(embeep\(em\fC +vmunix\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0vmunix.old\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 +vmunix.new.kernelmap.old\0\0vmunix.org +%\0ls\0/vmunix_\fITAB\fC +%\0ls\0/vmunix\0_ +.De +To facilitate the typing of pathnames, a slash will be added whenever +a directory is completed. Some computers don't like the spurious +slashes at the end of directory names. In that case, the +\fIAUTOREMOVESLASH\fP option comes to rescue. It will remove these +slashes when you type a space or return after them. +.PP +The \fIfignore\fP variable lists suffixes of files to ignore +during completion. +.Ds +%\0ls\0foo\fITAB\0\(embeep\(em\fC +foofile.c\0\0foofile.o +%\0fignore=(\0.o\0\e~\0.bak\0.junk\0) +%\0ls\0foo\fITAB\fP +%\0ls\0foofile.c\0_ +.De +Since \fCfoofile.o\fP has a suffix that is in the \fCfignore\fP list, +it was not considered a possible completion of \fCfoo\fP. +.PP +Username completion is also supported: +.Ds +%\0ls\0~pfal\fITAB\fC +%\0ls\0~pfalstad/_ +.De +and parameter name completion: +.Ds +%\0echo\0$ORG\fITAB\fC +%\0echo\0$ORGANIZATION\0_ +%\0echo\0${ORG\fITAB\fC +%\0echo\0${ORGANIZATION\0_ +.De +Note that in the last example a space is added after the completion as +usual. But if you want to add a colon or closing brace, you probably +don't want this extra space. Setting the \fIAUTOPARAMKEYS\fP option +will automatically remove this space if you type a colon or closing +brace after such a completion. +.PP +There is also option completion: +.Ds +%\0setopt\0nocl\fITAB\fC +%\0setopt\0noclobber\0_ +.De +and binding completion: +.Ds +%\0bindkey\0'^X^X'\0pu\fITAB\fC +%\0bindkey\0'^X^X'\0push-line\0_ +.De +The \fCcompctl\fP command is used to control completion of the +arguments of specific commands. For example, to specify that certain +commands take other commands as arguments, you use \fCcompctl -c\fP: +.Ds +%\0compctl\0-c\0man\0nohup +%\0man\0upt\fITAB\fC +%\0man\0uptime\0_ +.De +To specify that a command should complete filenames, you should use +\fCcompctl -f\fP. This is the default. It can be combined with \fC-c\fP, +as well. +.Ds +%\0compctl\0-cf\0echo +%\0echo\0upt\fITAB\fC +%\0echo\0uptime\0_ + +%\0echo\0fo\fITAB\fC +%\0echo\0foo.c +.De +Similarly, use \fC-o\fP to specify options, \fC-v\fP to specify +variables, and \fC-b\fP to specify bindings. +.Ds +%\0compctl\0-o\0setopt\0unsetopt +%\0compctl\0-v\0typeset\0vared\0unset\0export +%\0compctl\0-b\0bindkey +.De +You can also use \fC-k\fP to specify a custom list of keywords to use +in completion. After the \fC-k\fP comes either the name of an array +or a literal array to take completions from. +.Ds +%\0ftphosts=(ftp.uu.net\0wuarchive.wustl.edu) +%\0compctl\0-k\0ftphosts\0ftp +%\0ftp\0wu\fITAB\fC +%\0ftp\0wuarchive.wustl.edu\0_ + +%\0compctl\0-k\0'(cpirazzi\0subbarao\0sukthnkr)'\0mail\0finger +%\0finger\0cp\fITAB\fC +%\0finger\0cpirazzi\0_ +.De +To better specify the files to complete for a command, use the +\fC-g\fP option which takes any glob pattern as an argument. Be sure +to quote the glob patterns as otherwise they will be expanded when the +\fCcompctl\fP command is run. +.Ds +%\0ls +letter.tex\0\0letter.dvi\0\0letter.aux\0\0letter.log\0\0letter.toc +%\0compctl\0-g\0'*.tex'\0latex +%\0compctl\0-g\0'*.dvi'\0xdvi\0dvips +%\0latex\0l\fITAB\fC +%\0latex\0letter.tex\0_ +%\0xdvi\0l\fITAB\fC +%\0xdvi\0letter.dvi\0_ +.De +Glob patterns can include qualifiers within parentheses. To rmdir +only directories and cd to directories and symbolic links pointing to +them: +.Ds +%\0compctl\0-g\0'*(-/)'\0cd +%\0compctl\0-g\0'*(/)'\0rmdir +.De +RCS users like to run commands on files which are not in the current +directory, but in the RCS subdirectory where they all get \fC,v\fP +suffixes. They might like to use +.Ds +%\0compctl\0-g\0'RCS/*(:t:s/\e,v//)'\0co\0rlog\0rcs +%\0ls\0RCS +builtin.c,v\0\0lex.c,v\0\0\0\0\0\0zle_main.c,v +%\0rlog\0bu\fITAB\fC +%\0rlog\0builtin.c\0_ +.De +The \fC:t\fP modifier keeps only the last part of the pathname and the +\fC:s/\e,v//\fP will replace any \fC,v\fP by nothing. +.PP +The \fC-s\fP flag is similar to \fC-g\fP, but it uses all expansions, +instead of just globbing, like brace expansion, parameter substitution +and command substitution. +.Ds +%\0compctl\0-s\0'$(setopt)'\0unsetopt +.De +will only complete options which are actually set to be arguments to +\fCunsetopt\fP. +.PP +Sometimes a command takes another command as its argument. You can +tell \fBzsh\fP to complete commands as the first argument to such a +command and then use the completion method of the second command. The +\fC-l\fP flag with a null-string argument is used for this. +.Ds +%\0compctl\0-l\0''\0nohup\0exec +%\0nohup\0comp\fITAB\fC +%\0nohup\0compress\0_ +%\0nohup\0compress\0fil\fITAB\fC +%\0nohup\0compress\0filename\0_ +.De +Sometimes you would like to run really complicated commands to find +out what the possible completions are. To do this, you can specify a +shell function to be called that will assign the possible completions +to a variable called reply. Note that this variable must be an array. +Here's another (much slower) way to get the completions for \fCco\fP +and friends: +.Ds +%\0function\0getrcs\0{ +>\0reply=() +>\0for\0i\0in\0RCS/* +>\0\0\0do +>\0\0\0reply=($reply[*]\0$(basename\0$i\0,v)) +>\0\0\0done +>\0} +%\0compctl\0-K\0getrcs\0co\0rlog\0rcs +.De +Some command arguments use a prefix that is not a part of the things +to complete. The kill builtin command takes a signal name after a +\fC-\fP. To make such a prefix be ignored in the completion process, +you can use the \fC-P\fP flag. +.Ds +%\0compctl\0-P\0-\0-k\0signals\0kill +%\0kill\0-H\fITAB\fP +%\0kill\0-HUP\0_ +.De +TeX is usually run on files ending in \fC.tex\fP, but also sometimes +on other files. It is somewhat annoying to specify that the arguments +of TeX should end in \fC.tex\fP and then not be able to complete these +other files. Therefore you can specify things like \*QComplete to +files ending in \fC.tex\fP if available, otherwise complete to any +filename.\*U. This is done with \fIxor\fPed completion: +.Ds +%\0compctl\0-g\0'*.tex'\0+\0-f\0tex +.De +The \fC+\fP tells the editor to only take the next thing into account +if the current one doesn't generate any matches. If you have not +changed the default completion, the above example is in fact +equivalent to +.Ds +%\0compctl\0-g\0'*.tex'\0+\0tex +.De +as a lone \fC+\fP at the end is equivalent to specifying the default +completion after the \fC+\fP. This form of completion is also +frequently used if you want to run some command only on a certain type +of files, but not necessarily in the current directory. In this case +you will want to complete both files of this type and directories. +Depending on your preferences you can use either of +.Ds +%\0compctl\0-g\0'*.ps'\0+\0-g\0'*(-/)'\0ghostview +%\0compctl\0-g\0'*.ps\0*(-/)'\0ghostview +.De +where the first one will only complete directories (and symbolic links +pointing to directories) if no postscript file matches the already +typed part of the argument. +.Sh "Extended completion" +.PP +If you play with completion, you will soon notice that you would like +to specify what to complete, depending on what flags you give to the +command and where you are on the command line. For example, a command +could take any filename argument after a \fC-f\fP flag, a username +after a \fC-u\fP flag and an executable after a \fC-x\fP flag. This +section will introduce you to the ways to specify these things. To +many people it seems rather difficult at first, but taking the trouble +to understand it can save you lots of typing in the end. Even I keep +being surprised when \fBzsh\fP manages to complete a small or even +empty prefix to the right file in a large directory. +.PP +To tell \fBzsh\fP about these kinds of completion, you use \*Qextended +completion\*U by specifying the \fC-x\fP flag to compctl. The +\fC-x\fP flag takes a list of patterns/flags pairs. The patterns +specify when to complete and the flags specify what. The flags are +simply those mentioned above, like \fC-f\fP or \fC-g \fIglob +pattern\fR. +.PP +As an example, the \fCr[\fIstring1\fC,\fIstring2\fC]\fR pattern +matches if the cursor is after something that starts with +\fIstring1\fP and before something that starts with \fIstring2\fP. +The \fIstring2\fP is often something that you do not want to match +anything at all. +.Ds +%\0ls +foo1\0\0\0bar1\0\0\0foo.Z\0\0bar.Z +%\0compctl\0-g\0'^*.Z'\0-x\0'r[-d,---]'\0-g\0'*.Z'\0--\0compress +%\0compress\0f\fITAB\fP +%\0compress\0foo1\0_ +%\0compress\0-d\0f\fITAB\fP +%\0compress\0-d\0foo.Z\0_ +.De +In the above example, if the cursor is after the \fC-d\fP the pattern +will match and therefore \fBzsh\fP uses the \fC-g *.Z\fP flag that will only +complete files ending in \fC.Z\fP. Otherwise, if no pattern matches, +it will use the flags before the \fC-x\fP and in this case complete +every file that does not end in \fC.Z\fP. +.PP +The \fCs[\fIstring\fC]\fR pattern matches if the current word starts +with \fIstring\fP. The \fIstring\fP itself is not considered to be +part of the completion. +.Ds +%\0compctl\0-x\0's[-]'\0-k\0signals\0--\0kill +%\0kill\0-H\fITAB\fP +%\0kill\0-HUP\0_ +.De +The \fCtar\fP command takes a tar file as an argument after the +\fC-f\fP option. The \fCc[\fIoffset\fC,\fIstring\fC]\fR pattern +matches if the word in position \fIoffset\fP relative to the current +word is \fIstring\fP. More in particular, if \fIoffset\fP is -1, it +matches if the previous word is \fIstring\fP. This suggests +.Ds +%\0compctl\0-f\0-x\0'c[-1,-f]'\0-g\0'*.tar'\0--\0tar +.De +But this is not enough. The \fC-f\fP option could be the last of a +longer string of options. \fCC[\fR...\fC,\fR...\fC]\fR is just like +\fCc[\fR...\fC,\fR...\fC]\fR, except that it uses glob-like pattern +matching for \fIstring\fP. So +.Ds +%\0compctl\0-f\0-x\0'C[-1,-*f]'\0-g\0'*.tar'\0--\0tar +.De +will complete tar files after any option string ending in an \fCf\fP. +But we'd like even more. Old versions of tar used all options as the +first argument, but without the minus sign. This might be +inconsistent with option usage in all other commands, but it is still +supported by newer versions of \fCtar\fP. So we would also like to +complete tar files if the first argument ends in an \fCf\fP and we're +right behind it. +.PP +We can `and' patterns by putting them next to each other with a space +between them. We can `or' these sets by putting comma's between them. +We will also need some new patterns. \fCp[\fInum\fC]\fR will match if +the current argument (the one to be completed) is the \fInum\fPth +argument. \fCW[\fIindex\fC,\fIpattern\fC]\fR will match if the +argument in place \fIindex\fP matches the \fIpattern\fP. This gives +us +.Ds +%\0compctl\0-f\0-x\0'C[-1,-*f]\0,\0W[1,*f]\0p[2]'\0-g\0'*.tar'\0--\0tar +.De +In words: If the previous argument is an option string that ends in an +\fCf\fP, or the first argument ended in an \fCf\fP and it is now the +second argument, then complete only filenames ending in \fC.tar\fP. +.PP +All the above examples used only one set of patterns with one +completion flag. You can use several of these pattern/flag pairs +separated by a \fC-\fP. The first matching pattern will be used. +Suppose you have a version of \fCtar\fP that supports compressed files +by using a \fC-Z\fP option. Leaving the old tar syntax aside for a +moment, we would like to complete files ending in \fC.tar.Z\fP if a +\fC-Z\fP option has been used and files ending in \fC.tar\fP +otherwise, all this only after a \fC-f\fP flag. Again, the \fC-Z\fP +can be alone or it can be part of a longer option string, perhaps the +same as that of the \fC-f\fP flag. Here's how to do it; note the +backslash and the secondary prompt which are not part of the +\fCcompctl\fP command. +.Ds +%\0compctl\0-f\0-x\0'C[-1,-*Z*f]\0,\0R[-*Z*,---]\0C[-1,-*f]'\0-g\0'*.tar.Z'\0-\0\e +>\0'C[-1,-*f]'\0-g\0'*.tar'\0--\0tar +.De +The first pattern set tells us to match if either the previous +argument was an option string including a \fCZ\fP and ending in an +\fCf\fP or there was an option string with a \fCZ\fP somewhere and the +previous word was any option string ending in an \fCf\fP. If this is +the case, we need a compressed tar file. Only if this is not the case +the second pattern set will be considered. By the way, +\fCR[\fIpattern1\fC,\fIpattern2\fC]\fR is just like +\fCr[\fR...\fC,\fR...\fC]\fR except that it uses pattern matching with +shell metacharacters instead of just strings. +.PP +You will have noticed the \fC--\fP before the command name. This ends +the list of pattern/flag pairs of \fC-x\fP. It is usually used just +before the command name, but you can also use an extended completion +as one part of a list of xored completions, in which case the \fC--\fP +appears just before one of the \fC+\fP signs. +.PP +Note the difference between using extended completion as part of a +list of xored completions as in +.Ds +%\0ls +foo\0\0bar +%\0compctl\0-x\0'r[-d,---]'\0-g\0'*.Z'\0--\0+\0-g\0'^*.Z'\0compress +%\0compress\0-d\0f\fITAB\fP +%\0compress\0-d\0foo\0_ +.De +and specifying something before the \fC-x\fP as in +.Ds +%\0compctl\0-g\0'^*.Z'\0-x\0'r[-d,---]'\0-g\0'*.Z'\0--\0compress +%\0compress\0-d\0f\fITAB\fP +%\0compress\0-d\0f_ +.De +In the first case, the alternative glob pattern (\fC^*.Z\fP) will be +used if the first part does not generate any possible completions, +while in the second case the alternative glob pattern will only be +used if the \fCr[\fR...\fC]\fR pattern doesn't match. +.Sh "Bindings" +.PP +Each of the editor commands we have seen was actually a function bound +by default to a certain key. The real names of the commands are: +.Ds +\fCexpand-or-complete\0\0\0\fITAB\fR +\fCpush-line\0\0\0\0\0\0\0\0\0\0\0\0\fIESC-Q\fR +\fCrun-help\0\0\0\0\0\0\0\0\0\0\0\0\0\fIESC-H\fR +\fCaccept-and-hold\0\0\0\0\0\0\fIESC-A\fR +\fCquote-line\0\0\0\0\0\0\0\0\0\0\0\fIESC-'\fR +.De +These bindings are arbitrary; you could change them if you want. +For example, to bind \fCaccept-line\fP to \fI^Z\fP: +.Ds +%\0bindkey\0'^Z'\0accept-line +.De +Another idea would be to bind the delete key to \fCdelete-char\fP; +this might be convenient if you use \fI^H\fP for backspace. +.Ds +%\0bindkey\0'^?'\0delete-char +.De +Or, you could bind \fI^X\fP\fI^H\fP to \fCrun-help\fP: +.Ds +%\0bindkey\0'^X^H'\0run-help +.De +Other examples: +.Ds +%\0bindkey\0'^X^Z'\0universal-argument +%\0bindkey\0'\0'\0magic-space +%\0bindkey\0-s\0'^T'\0'uptime +>\0' +%\0bindkey\0'^Q'\0push-line-or-edit +.De +\fCuniversal-argument\fP multiplies the next command by 4. +Thus \fI^X\fP\fI^Z\fP\fI^W\fP might delete the last four words on the line. +If you bind space to \fCmagic-space\fP, then csh-style history +expansion is done on the line whenever you press the space bar. +.PP +Something that often happens is that I am typing a multiline command +and discover an error in one of the previous lines. In this case, +\fCpush-line-or-edit\fP will put the entire multiline construct into +the editor buffer. If there is only a single line, it is equivalent +to \fCpush-line\fP. +.PP +The \fC-s\fP flag to \fCbindkey\fP specifies that you are binding the key +to a string, not a command. Thus \fCbindkey -s '^T' 'uptime\en'\fP +lets you VMS lovers get the load average whenever you press \fI^T\fP. +.PP +If you have a NeXT keyboard, the one with the \fC|\fP and \fC\e\fP keys +very inconveniently placed, the following +bindings may come in handy: +.Ds +%\0bindkey\0-s\0'\ee/'\0'\e\e' +%\0bindkey\0-s\0'\ee='\0'|' +.De +Now you can type \fIALT-/\fP to get a backslash, and \fIALT-=\fP to +get a vertical bar. This only works inside \fBzsh\fP, of course; +\fCbindkey\fP has no effect on the key mappings inside \fCtalk\fP +or \fCmail\fP, etc. +.PP +Some people like to bind \fC^S\fP and \fC^Q\fP to editor commands. +Just binding these has no effect, as the terminal will catch them and +use them for flow control. You could unset them as stop and start +characters, but most people like to use these for external commands. +The solution is to set the \fINOFLOWCONTROL\fP option. This will +allow you to bind the start and stop characters to editor commands, +while retaining their normal use for external commands. +.Sh "Parameter Substitution" +.PP +In \fBzsh\fP, parameters are set like this: +.Ds +%\0foo=bar +%\0echo\0$foo +bar +.De +Spaces before or after the \fC=\fP are frowned upon: +.Ds +%\0foo\0=\0bar +zsh:\0command\0not\0found:\0foo +.De +Also, \fCset\fP doesn't work for setting parameters: +.Ds +%\0set\0foo=bar +%\0set\0foo\0=\0bar +%\0echo\0$foo + +% +.De +Note that no error message was printed. This is because both +of these commands were perfectly valid; the \fCset\fP builtin +assigns its arguments to the \fIpositional parameters\fP +(\fC$1\fP, \fC$2\fP, etc.). +.Ds +%\0set\0foo=bar +%\0echo\0$1 +foo=bar +%\0set\0foo\0=\0bar +%\0echo\0$3\0$2 +bar\0= +.De +If you're really intent on using the csh syntax, define a +function like this: +.Ds +%\0set\0()\0{ +>\0\0\0\0eval\0"$1$2$3" +>\0} +%\0set\0foo\0=\0bar +%\0set\0fuu=brrr +%\0echo\0$foo\0$fuu +bar\0brrr +.De +But then, of course you can't use the form of \fCset\fP with +options, like \fCset -F\fP (which turns off filename generation). +Also, the \fCset\fP command by itself won't list all the parameters +like it should. +To get around that you need a \fCcase\fP statement: +.Ds +%\0set\0()\0{ +>\0\0\0\0case\0$1\0in +>\0\0\0\0-*|+*|'')\0builtin\0set\0$*\0;; +>\0\0\0\0*)\0eval\0"$1$2$3"\0;; +>\0\0\0\0esac +>\0} +.De +For the most part, this should make csh users happy. +.PP +The following sh-style operators are supported in \fBzsh\fP: +.Ds +%\0unset\0null +%\0echo\0${foo-xxx} +bar +%\0echo\0${null-xxx} +xxx +%\0unset\0null +%\0echo\0${null=xxx} +xxx +%\0echo\0$null +xxx +%\0echo\0${foo=xxx} +bar +%\0echo\0$foo +bar +%\0unset\0null +%\0echo\0${null+set} + +%\0echo\0${foo+set} +set +.De +Also, csh-style \fC:\fP modifiers may be appended to a parameter +substitution. +.Ds +%\0echo\0$PWD +/home/learning/pf/zsh/zsh2.00/src +%\0echo\0$PWD:h +/home/learning/pf/zsh/zsh2.00 +%\0echo\0$PWD:h:h +/home/learning/pf/zsh +%\0echo\0$PWD:t +src +%\0name=foo.c +%\0echo\0$name +foo.c +%\0echo\0$name:r +foo +%\0echo\0$name:e +c +.De +The equivalent constructs in ksh (which are also supported in \fBzsh\fP) +are a bit more general and easier to remember. +When the shell expands \fC${foo#\fR\fIpat\fR\fC}\fR, +it checks to see if \fIpat\fP matches a substring at the beginning +of the value +of \fCfoo\fP. If so, it removes that portion of \fCfoo\fP, using the shortest +possible match. +With \fC${foo##\fR\fIpat\fR\fC}\fR, the longest possible match is removed. +\fC${foo%\fR\fIpat\fR\fC}\fR and \fC${foo%%\fR\fIpat\fR\fC}\fR remove the match +from the end. +Here are the ksh equivalents of the \fC:\fP modifiers: +.Ds +%\0echo\0${PWD%/*} +/home/learning/pf/zsh/zsh2.00 +%\0echo\0${PWD%/*/*} +/home/learning/pf/zsh +%\0echo\0${PWD##*/} +src +%\0echo\0${name%.*} +foo +%\0echo\0${name#*.} +c +.De +\fBzsh\fP also has upper/lowercase modifiers: +.Ds +%\0xx=Test +%\0echo\0$xx:u +TEST +%\0echo\0$xx:l +test +.De +and a substitution modifier: +.Ds +%\0echo\0$name:s/foo/bar/ +bar.c +%\0ls +foo.c\0\0\0\0foo.h\0\0\0\0foo.o\0\0\0\0foo.pro +%\0for\0i\0in\0foo.*;\0mv\0$i\0$i:s/foo/bar/ +%\0ls +bar.c\0\0\0\0bar.h\0\0\0\0bar.o\0\0\0\0bar.pro +.De +There is yet another syntax to modify substituted parameters. You can +add certain modifiers in parentheses after the opening brace like: +.Ds +${(\fImodifiers\fC)\fIparameter\fC} +.De +For example, \fCo\fP sorts the words resulting from the expansion: +.Ds +%\0echo\0${path} +/usr/bin\0/usr/bin/X11\0/etc +%\0echo\0${(o)path} +/etc\0/usr/bin\0/usr/bin/X11 +.De +One possible source of confusion is the fact that in \fBzsh\fP, +the result of parameter substitution is \fInot\fP split into +words. Thus, this will not work: +.Ds +%\0srcs='glob.c\0exec.c\0init.c' +%\0ls\0$srcs +glob.c\0exec.c\0init.c\0not\0found +.De +This is considered a feature, not a bug. +If splitting were done by default, as it is in most other shells, +functions like this would not work properly: +.Ds +$\0ll\0()\0{\0ls\0-F\0$*\0} +$\0ll\0'fuu\0bar' +fuu\0not\0found +bar\0not\0found + +%\0ll\0'fuu\0bar' +fuu\0bar\0not\0found +.De +Of course, a hackish workaround is available in sh (and \fBzsh\fP): +.Ds +%\0setopt\0shwordsplit +%\0ll\0()\0{\0ls\0-F\0"$@"\0} +%\0ll\0'fuu\0bar' +fuu\0bar\0not\0found +.De +If you like the sh behaviour, \fBzsh\fP can accomodate you: +.Ds +%\0ls\0${=srcs} +exec.c\0\0glob.c\0\0init.c +%\0setopt\0shwordsplit +%\0ls\0$srcs +exec.c\0\0glob.c\0\0init.c +.De +Another way to get the \fC$srcs\fP trick to work is to use an array: +.Ds +%\0unset\0srcs +%\0srcs=(\0glob.c\0exec.c\0init.c\0)\0\0 +%\0ls\0$srcs +exec.c\0\0glob.c\0\0init.c +.De +or an alias: +.Ds +%\0alias\0-g\0SRCS='exec.c\0glob.c\0init.c' +%\0ls\0SRCS +exec.c\0\0glob.c\0\0init.c +.De +Another option that modifies parameter expansion is +\fIRCEXPANDPARAM\fP: +.Ds +%\0echo\0foo/$srcs +foo/glob.c\0exec.c\0init.c +%\0setopt\0rcexpandparam +%\0echo\0foo/$srcs +foo/glob.c\0foo/exec.c\0foo/init.c +%\0echo\0foo/${^srcs} +foo/glob.c\0foo/exec.c\0foo/init.c +%\0echo\0foo/$^srcs +foo/glob.c\0foo/exec.c\0foo/init.c +.De +.Sh "Shell Parameters" +.PP +The shell has many predefined parameters that may be +accessed. Here are some examples: +.Ds +%\0sleep\010\0& +[1]\03820 +%\0echo\0$! +3820 +%\0set\0a\0b\0c +%\0echo\0$# +3 +%\0echo\0$ARGC +3 +%\0(\0exit\020\0)\0;\0echo\0$? +20 +%\0false;\0echo\0$status +1 +.De +(\fC$?\fP and \fC$status\fP are equivalent.) +.Ds +%\0echo\0$HOST\0$HOSTTYPE +dendrite\0sun4 +%\0echo\0$UID\0$GID +701\060 +%\0cd\0/tmp +%\0cd\0/home +%\0echo\0$PWD\0$OLDPWD +/home\0/tmp +%\0ls\0$OLDPWD/.getwd\0 +/tmp/.getwd +.De +\fC~+\fP and \fC~-\fP are short for \fC$PWD\fP and \fC$OLDPWD\fP, respectively. +.Ds +%\0ls\0~-/.getwd +/tmp/.getwd +%\0ls\0-d\0~+/learning +/home/learning +%\0echo\0$RANDOM +4880 +%\0echo\0$RANDOM +11785 +%\0echo\0$RANDOM +2062 +%\0echo\0$TTY +/dev/ttyp4 +%\0echo\0$VERSION +zsh\0v2.00.03 +%\0echo\0$USERNAME +pf +.De +.PP +The \fCcdpath\fP variable sets the search path for the \fCcd\fP command. +If you do not specify \fC.\fP somewhere in the path, it is assumed to +be the first component. +.Ds +%\0cdpath=(\0/usr\0~\0~/zsh\0) +%\0ls\0/usr +5bin\0\0\0\0\0\0\0\0\0dict\0\0\0\0\0\0\0\0\0lang\0\0\0\0\0\0\0\0\0net\0\0\0\0\0\0\0\0\0\0sccs\0\0\0\0\0\0\0\0\0sys +5include\0\0\0\0\0etc\0\0\0\0\0\0\0\0\0\0lector\0\0\0\0\0\0\0nserve\0\0\0\0\0\0\0services\0\0\0\0\0tmp +5lib\0\0\0\0\0\0\0\0\0export\0\0\0\0\0\0\0lib\0\0\0\0\0\0\0\0\0\0oed\0\0\0\0\0\0\0\0\0\0share\0\0\0\0\0\0\0\0ucb +adm\0\0\0\0\0\0\0\0\0\0games\0\0\0\0\0\0\0\0local\0\0\0\0\0\0\0\0old\0\0\0\0\0\0\0\0\0\0skel\0\0\0\0\0\0\0\0\0ucbinclude +bin\0\0\0\0\0\0\0\0\0\0geac\0\0\0\0\0\0\0\0\0lost+found\0\0\0openwin\0\0\0\0\0\0spool\0\0\0\0\0\0\0\0ucblib +boot\0\0\0\0\0\0\0\0\0hosts\0\0\0\0\0\0\0\0macsyma_417\0\0pat\0\0\0\0\0\0\0\0\0\0src\0\0\0\0\0\0\0\0\0\0xpg2bin +demo\0\0\0\0\0\0\0\0\0include\0\0\0\0\0\0man\0\0\0\0\0\0\0\0\0\0princeton\0\0\0\0stand\0\0\0\0\0\0\0\0xpg2include +diag\0\0\0\0\0\0\0\0\0kvm\0\0\0\0\0\0\0\0\0\0mdec\0\0\0\0\0\0\0\0\0pub\0\0\0\0\0\0\0\0\0\0swap\0\0\0\0\0\0\0\0\0xpg2lib +%\0cd\0spool +/usr/spool +%\0cd\0bin +/usr/bin +%\0cd\0func +~/func +%\0cd\0 +%\0cd\0pub +%\0pwd +/u/pfalstad/pub +%\0ls\0-d\0/usr/pub +/usr/pub +.De +\fBPATH\fP and \fBpath\fP both set the search path for commands. +These two variables are equivalent, except that one is a string +and one is an array. If the user modifies \fBPATH\fP, the shell +changes \fBpath\fP as well, and vice versa. +.Ds +%\0PATH=/bin:/usr/bin:/tmp:. +%\0echo\0$path +/bin\0/usr/bin\0/tmp\0. +%\0path=(\0/usr/bin\0.\0/usr/local/bin\0/usr/ucb\0) +%\0echo\0$PATH +/usr/bin:.:/usr/local/bin:/usr/ucb +.De +The same is true of \fBCDPATH\fP and \fBcdpath\fP: +.Ds +%\0echo\0$CDPATH +/usr:/u/pfalstad:/u/pfalstad/zsh +%\0CDPATH=/u/subbarao:/usr/src:/tmp +%\0echo\0$cdpath +/u/subbarao\0/usr/src\0/tmp +.De +In general, predefined parameters with names in all lowercase are +arrays; assignments to them take the form: +.Ds +\fIname\fR\fC=(\fR\0\fIelem\fR\0...\\0\fC)\fR +.De +Predefined parameters with names in all uppercase are strings. If +there is both an array and a string version of the same parameter, the +string version is a colon-separated list, like \fBPATH\fP. +.PP +\fBHISTFILE\fP is the name of the history file, where the history +is saved when a shell exits. +.Ds +%\0zsh +phoenix%\0HISTFILE=/tmp/history +phoenix%\0SAVEHIST=20 +phoenix%\0echo\0foo +foo +phoenix%\0date +Fri\0May\024\005:39:35\0EDT\01991 +phoenix%\0uptime +\0\05:39am\0\0up\04\0days,\020:02,\0\040\0users,\0\0load\0average:\02.30,\02.20,\02.00 +phoenix%\0exit +%\0cat\0/tmp/history +HISTFILE=/tmp/history +SAVEHIST=20 +echo\0foo +date +uptime +exit +%\0HISTSIZE=3 +%\0history +\0\0\028\0\0rm\0/tmp/history +\0\0\029\0\0HISTSIZE=3 +\0\0\030\0\0history +.De +If you have several incantations of \fBzsh\fP running at the same +time, like when using the X window system, it might be preferable to +append the history of each shell to a file when a shell exits instead +of overwriting the old contents of the file. You can get this +behaviour by setting the \fIAPPENDHISTORY\fP option. +.PP +In \fBzsh\fP, if you say +.Ds +%\0>file +.De +the command \fCcat\fP is normally assumed: +.Ds +%\0>file +foo!\0\0\0\0 +^D +%\0cat\0file +foo! +.De +Thus, you can view a file simply by typing: +.Ds +%\0file +%\0ls\0-l\0file +-rw-r--r--\0\01\0pfalstad\0\0\0\0\0\0\0\00\0May\024\005:41\0file +.De +If \fCNULLCMD\fP is unset, the shell reports an error if no +command is specified (like csh). +.Ds +%\0unset\0NULLCMD +%\0>file +zsh:\0redirection\0with\0no\0command +.De +Actually, \fBREADNULLCMD\fP is used whenever you have a null command +reading input from a single file. Thus, you can set \fBREADNULLCMD\fP +to \fCmore\fP or \fCless\fP rather than \fCcat\fP. Also, if you +set \fBNULLCMD\fP to \fC:\fP for sh compatibility, you can still read +files with \fC< file\fP if you leave \fBREADNULLCMD\fP set to \fCmore\fP. +.Sh "Prompting" +.PP +The default prompt for \fBzsh\fP is: +.Ds +phoenix%\0echo\0$PROMPT +%m%#\0 +.De +The \fC%m\fP stands for the short form of the current hostname, +and the \fC%#\fP stands for a \fC%\fP or a \fC#\fP, depending on whether +the shell is running as root or not. +\fBzsh\fP supports many other control sequences +in the \fBPROMPT\fP variable. +.Ds +%\0PROMPT='%/>\0' +/u/pfalstad/etc/TeX/zsh> + +%\0PROMPT='%~>\0'\0\0\0 +~/etc/TeX/zsh>\0 + +%\0PROMPT='%h\0%~>\0' +6\0~/etc/TeX/zsh>\0 +.De +\fC%h\fP\0represents\0the\0number\0of\0current\0history\0event. +.Ds +%\0PROMPT='%h\0%~\0%M>\0' +10\0~/etc/TeX/zsh\0apple-gunkies.gnu.ai.mit.edu>\0 + +%\0PROMPT='%h\0%~\0%m>\0' +11\0~/etc/TeX/zsh\0apple-gunkies>\0 + +%\0PROMPT='%h\0%t>\0' +12\06:11am>\0 + +%\0PROMPT='%n\0%w\0tty%l>' +pfalstad\0Fri\024\0ttyp0> +.De +\fBPROMPT2\fP is used in multiline commands, like for-loops. The +\fC%_\fP escape sequence was made especially for this prompt. It is +replaced by the kind of command that is being entered. +.Ds +%\0PROMPT2='%_>\0' +%\0for\0i\0in\0foo\0bar +for> + +%\0echo\0'hi +quote> +.De +Also available is the \fBRPROMPT\fP parameter. +If this is set, the shell puts a prompt on the \fIright\fP side +of the screen. +.Ds +%\0RPROMPT='%t' +%\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\06:14am + +%\0RPROMPT='%~' +%\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0~/etc/TeX/zsh + +%\0PROMPT='%l\0%T\0%m[%h]\0'\0RPROMPT='\0%~' +p0\06:15\0phoenix[5]\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0~/etc/TeX/zsh +.De +These special escape sequences can also be used with the +\fC-P\fP option to \fCprint\fP: +.Ds +%\0print\0-P\0%h\0tty%l +15\0ttyp1 +.De +.PP +The \fBPOSTEDIT\fP parameter is printed whenever the editor exits. +This can be useful for termcap tricks. To highlight the prompt +and command line while leaving command output unhighlighted, try this: +.Ds +%\0POSTEDIT=`echotc\0se` +%\0PROMPT='%S%%\0' +.De +.Sh "Login/logout watching" +.PP +You can specify login or logout events to monitor +by setting the \fBwatch\fP variable. +Normally, this is done by specifying a list of usernames. +.Ds +%\0watch=(\0pfalstad\0subbarao\0sukthnkr\0egsirer\0) +.De +The \fClog\fP command reports all people logged in +that you are watching for. +.Ds +%\0log +pfalstad\0has\0logged\0on\0p0\0from\0mickey. +pfalstad\0has\0logged\0on\0p5\0from\0mickey. +%\0\fR...\fC +subbarao\0has\0logged\0on\0p8\0from\0phoenix. +%\0\fR...\fC +subbarao\0has\0logged\0off\0p8\0from\0phoenix. +%\0\fR...\fC +sukthnkr\0has\0logged\0on\0p8\0from\0dew. +%\0\fR...\fC +sukthnkr\0has\0logged\0off\0p8\0from\0dew. +.De +If you specify hostnames with an \fC@\fP prepended, +the shell will watch for all users logging in from +the specified host. +.Ds +%\0watch=(\0@mickey\0@phoenix\0) +%\0log +djthongs\0has\0logged\0on\0q2\0from\0phoenix. +pfalstad\0has\0logged\0on\0p0\0from\0mickey. +pfalstad\0has\0logged\0on\0p5\0from\0mickey. +.De +If you give a tty name with a \fC%\fP prepended, the shell +will watch for all users logging in on that tty. +.Ds +%\0watch=(\0%ttyp0\0%console\0) +%\0log +root\0has\0logged\0on\0console\0from\0. +pfalstad\0has\0logged\0on\0p0\0from\0mickey. +.De +The format of the reports may also be changed. +.Ds +%\0watch=(\0pfalstad\0gettes\0eps\0djthongs\0jcorr\0bdavis\0) +%\0log +jcorr\0has\0logged\0on\0tf\0from\0128.112.176.3:0. +jcorr\0has\0logged\0on\0r0\0from\0128.112.176.3:0. +gettes\0has\0logged\0on\0p4\0from\0yo:0.0. +djthongs\0has\0logged\0on\0pe\0from\0grumpy:0.0. +djthongs\0has\0logged\0on\0q2\0from\0phoenix. +bdavis\0has\0logged\0on\0qd\0from\0BRUNO. +eps\0has\0logged\0on\0p3\0from\0csx30:0.0. +pfalstad\0has\0logged\0on\0p0\0from\0mickey. +pfalstad\0has\0logged\0on\0p5\0from\0mickey. +%\0WATCHFMT='%n\0on\0tty%l\0from\0%M' +%\0log +jcorr\0on\0ttytf\0from\0128.112.176.3:0. +jcorr\0on\0ttyr0\0from\0128.112.176.3:0. +gettes\0on\0ttyp4\0from\0yo:0.0 +djthongs\0on\0ttype\0from\0grumpy:0.0 +djthongs\0on\0ttyq2\0from\0phoenix.Princeto +bdavis\0on\0ttyqd\0from\0BRUNO.pppl.gov +eps\0on\0ttyp3\0from\0csx30:0.0 +pfalstad\0on\0ttyp0\0from\0mickey.Princeton +pfalstad\0on\0ttyp5\0from\0mickey.Princeton +%\0WATCHFMT='%n\0fm\0%m' +%\0log +jcorr\0fm\0128.112.176.3:0 +jcorr\0fm\0128.112.176.3:0 +gettes\0fm\0yo:0.0 +djthongs\0fm\0grumpy:0.0 +djthongs\0fm\0phoenix +bdavis\0fm\0BRUNO +eps\0fm\0csx30:0.0 +pfalstad\0fm\0mickey +pfalstad\0fm\0mickey +%\0WATCHFMT='%n\0%a\0at\0%t\0%w.' +%\0log +jcorr\0logged\0on\0at\03:15pm\0Mon\020. +jcorr\0logged\0on\0at\03:16pm\0Wed\022. +gettes\0logged\0on\0at\06:54pm\0Wed\022. +djthongs\0logged\0on\0at\07:19am\0Thu\023. +djthongs\0logged\0on\0at\07:20am\0Thu\023. +bdavis\0logged\0on\0at\012:40pm\0Thu\023. +eps\0logged\0on\0at\04:19pm\0Thu\023. +pfalstad\0logged\0on\0at\03:39am\0Fri\024. +pfalstad\0logged\0on\0at\03:42am\0Fri\024. +.De +If you have a \fC.friends\fP file in your home directory, +a convenient way to make \fBzsh\fP watch for all your friends +is to do this: +.Ds +%\0watch=(\0$(<\0~/.friends)\0) +%\0echo\0$watch +subbarao\0maruchck\0root\0sukthnkr\0\fR... +.De +If watch is set to \fCall\fP, then all users logging in or out +will be reported. +.Sh "Options" +.PP +Some options have already been mentioned; here are a few more: +.PP +Using the \fIAUTOCD\fP option, you can simply type the name +of a directory, and it will become the current directory. +.Ds +%\0cd\0/ +%\0setopt\0autocd +%\0bin +%\0pwd +/bin +%\0../etc +%\0pwd +/etc +.De +With \fICDABLEVARS\fP, if the argument to \fCcd\fP is the name of a +parameter whose value is a valid directory, it will become +the current directory. +.Ds +%\0setopt\0cdablevars +%\0foo=/tmp +%\0cd\0foo +/tmp +.De +\fICORRECT\fP turns on spelling correction for commands, +and the \fICORRECTALL\fP option turns on spelling correction +for all arguments. +.Ds +%\0setopt\0correct +%\0sl +zsh:\0correct\0`sl'\0to\0`ls'\0[nyae]?\0y +%\0setopt\0correctall +%\0ls\0x.v11r4 +zsh:\0correct\0`x.v11r4'\0to\0`X.V11R4'\0[nyae]?\0n +/usr/princton/src/x.v11r4\0not\0found +%\0ls\0/etc/paswd +zsh:\0correct\0to\0`/etc/paswd'\0to\0`/etc/passwd'\0[nyae]?\0y +/etc/passwd +.De +If you press \fCy\fP +when the shell asks you if you want to correct a word, it will +be corrected. If you press \fCn\fP, it will be left alone. +Pressing \fCa\fP aborts the command, and pressing \fCe\fP brings the line +up for editing again, in case you agree the word is spelled wrong +but you don't like the correction. +.PP +Normally, a quoted expression may contain a newline: +.Ds +%\0echo\0' +>\0foo +>\0' + +foo + +% +.De +With \fICSHJUNKIEQUOTES\fP set, this is illegal, as it is +in csh. +.Ds +%\0setopt\0cshjunkiequotes +%\0ls\0'foo +zsh:\0unmatched\0' +.De +\fIGLOBDOTS\fP lets files beginning with a \fC.\fP be matched without +explicitly specifying the dot. +.Ds +%\0ls\0-d\0*x* +Mailboxes +%\0setopt\0globdots +%\0ls\0-d\0*x* +\&.exrc\0\0\0\0\0\0\0\0\0.pnewsexpert\0\0.xserverrc +\&.mushexpert\0\0\0.xinitrc\0\0\0\0\0\0Mailboxes +.De +\fIHISTIGNOREDUPS\fP prevents the current line from being +saved in the history if it is the same as the previous one; +\fIHISTIGNORESPACE\fP prevents the current line from being +saved if it begins with a space. +.Ds +%\0PROMPT='%h>\0' +39>\0setopt\0histignoredups +40>\0echo\0foo +foo +41>\0echo\0foo +foo +41>\0echo\0foo +foo +41>\0echo\0bar +bar +42>\0setopt\0histignorespace +43>\0\0echo\0foo +foo +43>\0\0echo\0fubar +fubar +43>\0\0echo\0fubar +fubar +.De +\fIIGNOREBRACES\fP turns off csh-style brace expansion. +.Ds +%\0echo\0x{y{z,a},{b,c}d}e +xyze\0xyae\0xbde\0xcde +%\0setopt\0ignorebraces +%\0echo\0x{y{z,a},{b,c}d}e +x{y{z,a},{b,c}d}e +.De +\fIIGNOREEOF\fP forces the user to type \fCexit\fP or \fClogout\fP, +instead of just pressing \fI^D\fP. +.Ds +%\0setopt\0ignoreeof +%\0^D +zsh:\0use\0'exit'\0to\0exit. +.De +\fIINTERACTIVECOMMENTS\fP turns on interactive comments; +comments begin with a \fC#\fP. +.Ds +%\0setopt\0interactivecomments +%\0date\0#\0this\0is\0a\0comment +Fri\0May\024\006:54:14\0EDT\01991 +.De +\fINOBEEP\fP makes sure the shell never beeps. +.PP +\fINOCLOBBER\fP prevents you from accidentally +overwriting an existing file. +.Ds +%\0setopt\0noclobber +%\0cat\0/dev/null\0>~/.zshrc +zsh:\0file\0exists:\0/u/pfalstad/.zshrc +.De +If you really do want to clobber a file, you can use the +\fC>!\fP operator. +To make things easier in this case, the \fC>\fP is stored in +the history list as a \fC>!\fP: +.Ds +%\0cat\0/dev/null\0>!\0~/.zshrc +%\0cat\0/etc/motd\0>\0~/.zshrc +zsh:\0file\0exists:\0/u/pfalstad/.zshrc +%\0!! +cat\0/etc/motd\0>!\0~/.zshrc +%\0\fR... +.De +\fIRCQUOTES\fP lets you use a more elegant method for including +single quotes in a singly quoted string: +.Ds +%\0echo\0'"don'\e''t\0do\0that."' +"don't\0do\0that." +%\0echo\0'"don''t\0do\0that."' +"dont\0do\0that." +%\0setopt\0rcquotes +%\0echo\0'"don''t\0do\0that."' +"don't\0do\0that." +.De +Finally, +\fISUNKEYBOARDHACK\fP wins the award for the strangest option. +If a line ends with \fC`\fP, and there are an odd number of them +on the line, the shell will ignore the trailing \fC`\fP. This +is provided for keyboards whose RETURN key is too small, +and too close to the \fC`\fP key. +.Ds +%\0setopt\0sunkeyboardhack +%\0date` +Fri\0May\024\006:55:38\0EDT\01991 +.De +.Sh "Closing Comments" +.PP +I (Bas de Bakker) would be happy to receive mail if anyone has any +tricks or ideas to add to this document, or if there are some points +that could be made clearer or covered more thoroughly. Please notify +me of any errors in this document. +.if o \{\ +.bp +.sv 1i +.\} +.pn 1 +.bp +.PX -- cgit 1.4.1