pfalstad@phoenix.princeton.edu (Paul Falstad) (05/29/91)
Submitted-by: Paul Falstad <pfalstad@phoenix.princeton.edu> Posting-number: Volume 20, Issue 23 Archive-name: zsh2.00/patch03b Patch-To: zsh2.00: Volume 18, Issue 84-98 #!/bin/sh # patch03b # do not concatenate these parts, unpack them in order with /bin/sh # file doc/zshintro.tex continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 2; then echo Please unpack part "$Scheck" next! exit 1 else exit 0 fi ) < _shar_seq_.tmp || exit 1 if test ! -f _shar_wnt_.tmp; then echo 'x - still skipping doc/zshintro.tex' else echo 'x - continuing file doc/zshintro.tex' sed 's/^X//' << 'SHAR_EOF' >> 'doc/zshintro.tex' && 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 @M@ and @GF@ above). \par Note that zsh 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 zsh. For example, if you try: \beg alias rm mv '\!* /tmp/wastebasket' \end no aliases will be defined, but zsh will not report an error. In csh, this line defines an alias that makes @rm@ safe---files that are @rm@'d will be moved to a temporary directory instead of instantly destroyed. In zsh's syntax, however, this line asks the shell to print any existing alias definitions for @rm@, @mv@, or @!* /tmp/wastebasket@. Since there are none, most likely, the shell will not print anything, although @alias@ will return a nonzero exit code. The proper syntax is this: \beg alias rm='mv \!* /tmp/wastebasket' \end However, this won't work either: \beg % rm foo.dvi zsh: no matches found: !* \end While this makes @rm@ safe, it is certainly not what the user intended. In zsh, you must use a shell function for this: \beg % unalias rm % rm () { mv $* /tmp/wastebasket } % rm foo.dvi % ls /tmp/wastebasket foo.dvi \end 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 has been provided. You should only need to use it once, to convert all your csh aliases to zsh format: \beg % csh csh> source ~/.neat_aliases csh> alias l ls -AF more less on last -2 !:1 ; who | grep !:1 csh> alias | ctoz alias l='ls -AF' alias more='less' on () { last -2 $1 ; who | grep $1 } csh> alias | ctoz > ~/.neat_zsh_aliases csh> exit \end The first two aliases were converted to regular zsh aliases, while the third, since it needed to handle arguments, was converted to a function. @ctoz@ can convert most aliases to zsh format without any problems. However, if you're using some really arcane csh tricks, or if you have an alias with a name like @do@ (which is reserved in zsh), you may have to fix some of the aliases by hand. \beginsection History X There are several ways to manipulate history in zsh. One way is to use csh-style @!@ history: \beg % /usr/local/bin/!:0 !-2*:s/foo/bar/ >>!$ \end If you don't want to use this, you can turn it off by typing @setopt nobanghist@. \par Another way is to use the @fc@ command. For example, if you type an erroneous command: \beg % for i in `cat /etc/clients` X do X rpu $i X done zsh: command not found: rpu zsh: command not found: rpu zsh: command not found: rpu @dot \end typing @fc@ will execute an editor on this command, allowing you to fix it. (The default editor is @vi@, by the way, not @ed@). \beg % fc 49 /rpu/s//rup/p X rup $i w 49 q for i in `cat /etc/clients` X do X rup $i X done X beam up 2 days, 10:17, load average: 0.86, 0.80, 0.50 X bow up 4 days, 8:41, load average: 0.91, 0.80, 0.50 X burn up 17:18, load average: 0.91, 0.80, 0.50 X burst up 9 days, 1:49, load average: 0.95, 0.80, 0.50 X tan up 11:14, load average: 0.91, 0.80, 0.50 X bathe up 3 days, 17:49, load average: 1.84, 1.79, 1.50 X bird up 1 day, 9:13, load average: 1.95, 1.82, 1.51 X bonnet up 2 days, 21:18, load average: 0.93, 0.80, 0.50 @dot \end A variant of the @fc@ command is @r@, which redoes the last command, with optional changes: \beg % echo foo foo % r echo foo foo X % echo foo foo % r foo=bar echo bar bar \end \beginsection Command Line Editing X zsh's command line editor, {\sl 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 @bindkey -v@. \par In addition to basic editing, the shell allows you to recall previous lines in the history. In emacs mode, this is done with \c{P} (control-P): \beg % ls ~ - README file mail pub tmp Mailboxes bin func nicecolors scr zsh News etc iris notes src % echo foobar foobar % @C P % echo foobar@C P % ls ~@ecurs \end Pressing \c{P} once brings up the previous line (@echo foobar@); 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, {\sl ZLE} eliminates the need for the @fc@ command, since it is powerful enough to handle even multiline commands: \beg % for i in a b c d e > do > echo $i > done a b c d e % @C P % for i in a b c d e X do X echo $i X done@ecurs \end Now you can just move up to the part you want to change... \beg % for i in @curs a b c d e X do X echo $i X done \end change it, and execute the new command. \beg % for i in f g h i j X do X echo $i X done f g h i j \end Also, you can search the history for a certain command using \e{P}: \beg % set @E P % setopt autolist @E P % setopt nocorrect@ecurs \end Another way is to do an incremental search, emacs-style: \beg % @C R % @ecurs i-search: @space % l@curs s /usr/bin i-search: l @space % date > foofile@curs .c i-search: le \end Another useful feature of the editor is command and filename completion. \def\beep{{\it --beep--}} \beg % comp@TAB % compress @ecurs @space % ls /nic@TAB % ls /nicecolors @ecurs @space % ls /usr/pr@TAB % ls /usr/princeton/@ecurs \end If the completion is ambiguous, the editor will beep. You can list possible completions by pressing \c{D}: \beg % ls /vmu@TAB @beep % ls /vmunix@ecurs % ls /vmunix@C D vmunix vmunix.old vmunix.new.kernelmap.old vmunix.org \end Or, you could just set the \opt{AUTOLIST} option: \beg % setopt autolist % ls /vmu@TAB @beep vmunix vmunix.old vmunix.new.kernelmap.old vmunix.org % ls /vmunix@ecurs \end Another option you could set is \opt{RECEXACT}, which causes exact matches to be accepted, even if there are other possible completions: \beg % setopt recexact % ls /vmu@TAB @beep vmunix vmunix.old vmunix.new.kernelmap.old vmunix.org % ls /vmunix@ecurs @TAB % ls /vmunix @ecurs \end The \opt{fignore} variable lists suffixes of files to ignore during completion. \beg % ls foo@TAB @beep foofile.c foofile.o X % fignore=( .o \~ .bak .junk ) % ls foo@TAB % ls foofile.c @ecurs \end Since @foofile.o@ has a suffix that is in the @fignore@ list, it was not considered a possible completion of @foo@. \goodbreak \par Username completion is also supported: \beg % ls ~pfal@TAB % ls ~pfalstad/@ecurs \end \par In addition to completion, \TAB\ performs expansion if possible. \beg % ls *.c@TAB % ls foofile.c fortune.c rnd.c strfile.c unstr.c@ecurs \end For example, suppose you have a bunch of weird files in an important directory: \beg % ls X * * * ; & % $??foo dspfok foo.c X !"foo"! ` \ ` foo rrr \end You want to remove them, but you don't want to damage @foo.c@. Here is one way to do this: \beg % rm *@TAB % rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$' '' 'foo \`\ \\\ \` dspfok foo foo.c rrr@ecurs \end When you expand @*@, zsh inserts the names of all the files into the editing buffer, with proper shell quoting. Now, just move back and remove @foo.c@ from the buffer: \beg % rm \ \ \*\ \*\ \*\ \ \ \!\"foo\"\! \;\ \&\ %\ \$' '' 'foo \`\ \\\ \` dspfok foo @curs rrr \end and press return. Everything except @foo.c@ will be deleted from the directory. \par Here's another trick; let's say you have typed this command in: \beg % gcc -o x.out foob.c -g -Wpointer-arith -Wtrigraphs@ecurs \end 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 {\it buffer stack}, using \c{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, \c{Q} again and look for some other libraries whose names you forgot). \par A similar situation: what if you forget the option to gcc that finds bugs using AI techniques? You could either use \c{Q} again, and type @man gcc@, or you could press \e{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 @man@. \par Another interesting command is \e{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: \beg % 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 \end \par The \e{'} command is useful for managing the shell's quoting conventions. Let's say you want to print this string: \beg don't do that; type 'rm -rf \*', with a \ before the *. \end All that is necessary is to type it into the editing buffer: \beg % don't do that; type 'rm -rf \*', with a \ before the *. \end press \e{'} (escape-quote): \beg % 'don'\''t do that; type '\''rm -rf \*'\'', with a \ before the *.' \end then move to the beginning and add the @echo@ command. \beg % echo 'don'\''t do that; type '\''rm -rf \*'\'', with a \ before the *.' don't do that; type 'rm -rf \*', with a \ before the *. \end Let's say you want to create an alias to do this @echo@ command. This can be done by recalling the line with \c{P} and pressing \e{'} again: \beg % 'echo '\''don'\''\'\'''\''t do that; type '\''\'\'''\''rm -rf \*'\''\'\'''\'', with a \ before the *.'\''' \end and then move to the beginning and add the command to create an alias. \beg % 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 *. \end \par Another interesting option is @menucomplete@. This affects the way \TAB\ works. Let's look at the @/vmunix@ example again: \beg % setopt menucomplete % ls /vmu@TAB % ls /vmunix@TAB % ls /vmunix.new.kernelmap.old@TAB % ls /vmunix.old@ecurs \end 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. \beginsection Bindings X Each of the above editor commands was actually a function bound by default to a certain key. The real names of the commands are: \begindisplay @expand-or-complete @\TAB\cr @push-line @\c{Q}\cr @run-help @\e{H}\cr @accept-and-hold @\e{A}\cr @quote-line @\e{'}\cr \enddisplay These bindings are arbitrary; you could change them if you want. For example, to bind @accept-line@ to \c{Z}: \beg % bindkey '^Z' accept-line \end Another idea would be to bind the delete key to @delete-char@; this might be convenient if you use \c{H} for backspace. \beg % bindkey '^?' delete-char \end Or, you could bind \c{X}\c{H} to @run-help@: \beg % bindkey '^X^H' run-help \end Other examples: \beg % bindkey '^X^Z' universal-argument % bindkey ' ' magic-space % bindkey -s '^T' 'uptime > ' \end @universal-argument@ multiplies the next command by 4. Thus \c{X}\c{Z}\c{W} might delete the last four words on the line. If you bind space to @magic-space@, then csh-style history expansion is done on the line whenever you press the space bar. \par The @-s@ flag to @bindkey@ specifies that you are binding the key to a string, not a command. Thus \hbox{@bindkey -s@} @'^T' 'uptime\n'@ lets you get the load average whenever you press \c{T}. \par If you have a NeXT keyboard, the one with the @|@ and @\@ keys very inconveniently placed, the following bindings may come in handy: \beg % bindkey -s '\e/' '\\' % bindkey -s '\e=' '|' \end Now you can type {\sl ALT-/} to get a backslash, and {\sl ALT-=} to get a vertical bar. This only works inside zsh, of course; @bindkey@ has no effect on the key mappings inside @talk@ or @mail@, etc. \par 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 @vared@ command: \beg % vared PATH > /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 \end You can now edit the path. When you press return, the contents of the edit buffer will be assigned to \parm{PATH}. \beginsection Parameter Substitution X In zsh, parameters are set like this: \beg % foo=bar % echo $foo bar \end Spaces before or after the @=@ are frowned upon: \beg % foo = bar zsh: command not found: foo \end Also, @set@ doesn't work for setting parameters: \beg % set foo=bar % set foo = bar % echo $foo @space % \end Note that no error message was printed. This is because both of these commands were perfectly valid; the @set@ builtin assigns its arguments to the {\it positional parameters} (@$1@, @$2@, etc.). \beg % set foo=bar % echo $1 foo=bar % set foo = bar % echo $3 $2 bar = \end If you're really intent on using the csh syntax, define a function like this: \beg % set () { > eval "$1$2$3" > } % set foo = bar % set fuu=brrr % echo $foo $fuu bar brrr \end But then, of course you can't use the form of @set@ with options, like @set -F@ (which turns off filename generation). Also, the @set@ command by itself won't list all the parameters like it should. To get around that you need a @case@ statement: \beg % set () { > case $1 in > -*|+*|'') builtin set $* ;; > *) eval "$1$2$3" ;; > esac > } \end For the most part, this should make csh users happy. \par The following sh-style operators are supported in zsh: \beg % unset null % echo ${foo-xxx} bar % echo ${null-xxx} xxx % unset null % echo ${null=xxx} xxx % echo $null xxx % echo ${foo=xxx} bar % echo $foo bar % unset null % echo ${null+set} X % echo ${foo+set} set \end Also, csh-style @:@ modifiers may be appended to a parameter substitution. \beg % echo $PWD /home/learning/pf/zsh/zsh2.00/src % echo $PWD:h /home/learning/pf/zsh/zsh2.00 % echo $PWD:h:h /home/learning/pf/zsh % echo $PWD:t src % name=foo.c % echo $name foo.c % echo $name:r foo % echo $name:e c \end The equivalent constructs in ksh (which are also supported in zsh) are a bit more general and easier to remember. When the shell expands @${foo#@{\it pat}@}@, it checks to see if {\it pat} matches a substring at the beginning of the value of @foo@. If so, it removes that portion of @foo@, using the shortest possible match. With @${foo##@{\it pat}@}@, the longest possible match is removed. @${foo%@{\it pat}@}@ and @${foo%%@{\it pat}@}@ remove the match from the end. Here are the ksh equivalents of the @:@ modifiers: \beg % echo ${PWD%/*} /home/learning/pf/zsh/zsh2.00 % echo ${PWD%/*/*} /home/learning/pf/zsh % echo ${PWD##*/} src % echo ${name%.*} foo % echo ${name#*.} c \end zsh also has upper/lowercase modifiers: \beg % xx=Test % echo $xx:u TEST % echo $xx:l test \end and a substitution modifier: \beg % echo $name:s/foo/bar/ bar.c % ls foo.c foo.h foo.o foo.pro % for i in foo.*; mv $i $i:s/foo/bar/ % ls bar.c bar.h bar.o bar.pro \end One possible source of confusion is the fact that in zsh, the result of parameter substitution is {\it not} split into words. Thus, this will not work: \beg % srcs='glob.c exec.c init.c' % ls $srcs glob.c exec.c init.c not found \end 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: \beg $ ll () { ls -F $* } $ ll 'fuu bar' fuu not found bar not found @space % ll 'fuu bar' fuu bar not found \end Of course, a hackish workaround is available in sh (and zsh): \beg % setopt shwordsplit % ll () { ls -F "$@@" } % ll 'fuu bar' fuu bar not found \end If you like the sh behaviour, zsh can accomodate you: \beg % ls ${=srcs} exec.c glob.c init.c % setopt shwordsplit % ls $srcs exec.c glob.c init.c \end Another way to get the @$srcs@ trick to work is to use an array: \beg % unset srcs % srcs=( glob.c exec.c init.c ) % ls $srcs exec.c glob.c init.c \end or an alias: \beg % alias -g SRCS='exec.c glob.c init.c' % ls SRCS exec.c glob.c init.c \end Another option that modifies parameter expansion is \opt{RCEXPANDPARAM}: \beg % echo foo/$srcs foo/glob.c exec.c init.c % setopt rcexpandparam % echo foo/$srcs foo/glob.c foo/exec.c foo/init.c % echo foo/${^srcs} foo/glob.c foo/exec.c foo/init.c % echo foo/$^srcs foo/glob.c foo/exec.c foo/init.c \end \beginsection Shell Parameters X The shell has many predefined parameters that may be accessed. Here are some examples: \beg % sleep 10 & [1] 3820 % echo $! 3820 % set a b c % echo $# 3 % echo $ARGC 3 % ( exit 20 ) ; echo $? 20 % false; echo $status 1 \end (@$?@ and @$status@ are equivalent.) \beg % echo $HOST $HOSTTYPE dendrite sun4 % echo $UID $GID 701 60 % cd /tmp % cd /home % echo $PWD $OLDPWD /home /tmp % ls $OLDPWD/.getwd /tmp/.getwd \end @~+@ and @~-@ are short for @$PWD@ and @$OLDPWD@, respectively. \beg % ls ~-/.getwd /tmp/.getwd % ls -d ~+/learning /home/learning % echo $RANDOM 4880 % echo $RANDOM 11785 % echo $RANDOM 2062 % echo $TTY /dev/ttyp4 % echo $VERSION zsh v2.00.03 % echo $USERNAME pf \end \filbreak The @cdpath@ variable sets the search path for the @cd@ command. It is assumed that @.@ is the first component of the path. \beg % cdpath=( /usr ~ ~/zsh ) % ls /usr 5bin dict lang net sccs sys 5include etc lector nserve services tmp 5lib export lib oed share ucb adm games local old skel ucbinclude bin geac lost+found openwin spool ucblib boot hosts macsyma_417 pat src xpg2bin demo include man princeton stand xpg2include diag kvm mdec pub swap xpg2lib % cd spool /usr/spool % cd bin /usr/bin % cd func ~/func % cd % cd pub % pwd /u/pfalstad/pub % ls -d /usr/pub /usr/pub \end \parm{PATH} and \parm{path} 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 \parm{PATH}, the shell changes \parm{path} as well, and vice versa. \beg % PATH=/bin:/usr/bin:/tmp:. % echo $path /bin /usr/bin /tmp . % path=( /usr/bin . /usr/local/bin /usr/ucb ) % echo $PATH /usr/bin:.:/usr/local/bin:/usr/ucb \end The same is true of \parm{CDPATH} and \parm{cdpath}: \beg % echo $CDPATH /usr:/u/pfalstad:/u/pfalstad/zsh % CDPATH=/u/subbarao:/usr/src:/tmp % echo $cdpath /u/subbarao /usr/src /tmp \end In general, parameters with names in all lowercase are arrays; assignments to them take the form: \begindisplay \hbox{{\it name}@=(@ {\it elem} \dot\ @)@} \enddisplay 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 \parm{PATH}. \par\filbreak \parm{HISTFILE} is the name of the history file, where the history is saved when a shell exits. \beg % zsh phoenix% HISTFILE=/tmp/history phoenix% SAVEHIST=20 phoenix% echo foo foo phoenix% date Fri May 24 05:39:35 EDT 1991 phoenix% uptime X 5:39am up 4 days, 20:02, 40 users, load average: 2.30, 2.20, 2.00 phoenix% exit % cat /tmp/history HISTFILE=/tmp/history SAVEHIST=20 echo foo date uptime exit % HISTSIZE=3 % history X 28 rm /tmp/history X 29 HISTSIZE=3 X 30 history \end \par In zsh, if you say \beg % >file \end the command @cat@ is normally assumed: \beg % >file foo! ^D % cat file foo! \end Thus, you can view a file simply by typing: \beg % <file foo! \end However, this is not csh or sh compatible. To correct this, change the value of the parameter \parm{NULLCMD}, which is @cat@ by default. \beg % NULLCMD=: % >file % ls -l file -rw-r--r-- 1 pfalstad 0 May 24 05:41 file \end If @NULLCMD@ is unset, the shell reports an error if no command is specified (like csh). \beg % unset NULLCMD % >file zsh: redirection with no command \end \beginsection Prompting X The default prompt for zsh is: \beg phoenix% echo $PROMPT %m%# \end The @%m@ stands for the short form of the current hostname, and the @%#@ stands for a @%@ or a @#@, depending on whether the shell is running as root or not. zsh supports many other control sequences in the \parm{PROMPT} variable. \beg % PROMPT='%/> ' /u/pfalstad/etc/TeX/zsh> @space % PROMPT='%~> ' ~/etc/TeX/zsh> @space % PROMPT='%h %~> ' 6 ~/etc/TeX/zsh> \end @%h@ represents the number of current history event. \beg % PROMPT='%h %~ %M> ' 10 ~/etc/TeX/zsh apple-gunkies.gnu.ai.mit.edu> @space % PROMPT='%h %~ %m> ' 11 ~/etc/TeX/zsh apple-gunkies> @space % PROMPT='%h %t> ' 12 6:11am> @space % PROMPT='%n %w tty%l>' pfalstad Fri 24 ttyp0> \end Also available is the \parm{RPROMPT} parameter. If this is set, the shell puts a prompt on the {\it right} side of the screen. \par \halign{\indent#\hfill&\hfill#\cr @% RPROMPT='%t'@&\cr @%@&@6:14am@\cr &\cr @% RPROMPT='%~'@&\cr @%@&@~/etc/TeX/zsh@\cr &\cr @% PROMPT='%l %T %m[%h] ' RPROMPT=' %~'@&\cr @p0 6:15 phoenix[5]@&@~/etc/TeX/zsh@\cr} \par These special escape sequences can also be used with the @-P@ option to @print@: \beg % print -P %h tty%l 15 ttyp1 \end \beginsection Login/logout watching X You can specify login or logout events to monitor by setting the \parm{watch} variable. Normally, this is done by specifying a list of usernames. \beg % watch=( pfalstad subbarao sukthnkr egsirer ) \end The @log@ command reports all people logged in that you are watching for. \beg % log pfalstad has logged on p0 from mickey. pfalstad has logged on p5 from mickey. % @dot subbarao has logged on p8 from phoenix. % @dot subbarao has logged off p8 from phoenix. % @dot sukthnkr has logged on p8 from dew. % @dot sukthnkr has logged off p8 from dew. \end If you specify hostnames with an @@ prepended, the shell will watch for all users logging in from the specified host. \beg % watch=( @@mickey @@phoenix ) % log djthongs has logged on q2 from phoenix. pfalstad has logged on p0 from mickey. pfalstad has logged on p5 from mickey. \end If you give a tty name with a @%@ prepended, the shell will watch for all users logging in on that tty. \beg % watch=( %ttyp0 %console ) % log root has logged on console from . pfalstad has logged on p0 from mickey. \end \vfill\eject The format of the reports may also be changed. \beg % watch=( pfalstad gettes eps djthongs jcorr bdavis ) % log jcorr has logged on tf from 128.112.176.3:0. jcorr has logged on r0 from 128.112.176.3:0. gettes has logged on p4 from yo:0.0. djthongs has logged on pe from grumpy:0.0. djthongs has logged on q2 from phoenix. bdavis has logged on qd from BRUNO. eps has logged on p3 from csx30:0.0. pfalstad has logged on p0 from mickey. pfalstad has logged on p5 from mickey. % WATCHFMT='%n on tty%l from %M' % log jcorr on ttytf from 128.112.176.3:0. jcorr on ttyr0 from 128.112.176.3:0. gettes on ttyp4 from yo:0.0 djthongs on ttype from grumpy:0.0 djthongs on ttyq2 from phoenix.Princeto bdavis on ttyqd from BRUNO.pppl.gov eps on ttyp3 from csx30:0.0 pfalstad on ttyp0 from mickey.Princeton pfalstad on ttyp5 from mickey.Princeton % WATCHFMT='%n fm %m' % log jcorr fm 128.112.176.3:0 jcorr fm 128.112.176.3:0 gettes fm yo:0.0 djthongs fm grumpy:0.0 djthongs fm phoenix bdavis fm BRUNO eps fm csx30:0.0 pfalstad fm mickey pfalstad fm mickey % WATCHFMT='%n %a at %t %w.' % log jcorr logged on at 3:15pm Mon 20. jcorr logged on at 3:16pm Wed 22. gettes logged on at 6:54pm Wed 22. djthongs logged on at 7:19am Thu 23. djthongs logged on at 7:20am Thu 23. bdavis logged on at 12:40pm Thu 23. eps logged on at 4:19pm Thu 23. pfalstad logged on at 3:39am Fri 24. pfalstad logged on at 3:42am Fri 24. \end If you have a @.friends@ file in your home directory, a convenient way to make zsh watch for all your friends is to do this: \beg % watch=( $(< ~/.friends) ) % echo $watch subbarao maruchck root sukthnkr @dot \end If watch is set to @all@, then all users logging in or out will be reported. \beginsection Options X Some options have already been mentioned; here are a few more: \beg % cd / % setopt autocd % bin % pwd /bin % ../etc % pwd /etc \end Using the \opt{AUTOCD} option, you can simply type the name of a directory, and it will become the current directory. \beg % setopt cdablevars % foo=/tmp % cd foo /tmp \end With \opt{CDABLEVARS}, if the argument to @cd@ is the name of a parameter whose value is a valid directory, it will become the current directory. \par \opt{CORRECT} turns on spelling correction for commands, and the \opt{CORRECTALL} option turns on spelling correction for all arguments. \beg % setopt correct % sl zsh: correct to `ls' (y/n)? y % setopt correctall % ls /usr/princton/src/x.v11r4 zsh: correct to `/usr/princeton/src/X.V11R4' (y/n)? n /usr/princton/src/x.v11r4 not found % ls /etc/paswd zsh: correct to `/etc/passwd' (y/n)? y /etc/passwd \end Normally, a quoted expression may contain a newline: \beg % echo ' > foo > ' @space foo @space % \end With \opt{CSHJUNKIEQUOTES} set, this is illegal, as it is in csh. \beg % setopt cshjunkiequotes % ls 'foo zsh: unmatched ' \end \opt{GLOBDOTS} lets files beginning with a @.@ be matched without explicitly specifying the dot. \beg % ls -d *x* Mailboxes % setopt globdots % ls -d *x* .exrc .pnewsexpert .xserverrc .mushexpert .xinitrc Mailboxes \end \opt{HISTIGNOREDUPS} prevents the current line from being saved in the history if it is the same as the previous one; \opt{HISTIGNORESPACE} prevents the current line from being saved if it begins with a space. \beg % PROMPT='%h> ' 39> setopt histignoredups 40> echo foo foo 41> echo foo foo 41> echo foo foo 41> echo bar bar 42> setopt histignorespace 43> echo foo foo 43> echo fubar fubar 43> echo fubar fubar \end \opt{IGNOREBRACES} turns off csh-style brace expansion. \beg % echo x{y{z,a},{b,c}d}e xyze xyae xbde xcde % setopt ignorebraces % echo x{y{z,a},{b,c}d}e x{y{z,a},{b,c}d}e \end \opt{IGNOREEOF} forces the user to type @exit@ or @logout@, instead of just pressing \c{D}. \beg % setopt ignoreeof % ^D zsh: use 'exit' to exit. \end \opt{INTERACTIVECOMMENTS} turns on interactive comments; comments begin with a @#@. \beg % setopt interactivecomments % date # this is a comment Fri May 24 06:54:14 EDT 1991 \end \opt{NOCLOBBER} prevents the I/O redirection operators from overwriting an existing file. \beg % setopt noclobber % cat /dev/null >~/.zshrc zsh: file exists: /u/pfalstad/.zshrc \end Finally, \opt{SUNKEYBOARDHACK} wins the award for the strangest option. If a line ends with @`@, and there are an odd number of them on the line, the shell will ignore the trailing @`@. This is provided for keyboards whose RETURN key is too small, and too close to the @`@ key. \beg % setopt sunkeyboardhack % date` Fri May 24 06:55:38 EDT 1991 \end \beginsection Closing Comments X I 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. \bye SHAR_EOF echo 'File doc/zshintro.tex is complete' && chmod 0644 doc/zshintro.tex || echo 'restore of doc/zshintro.tex failed' Wc_c="`wc -c < 'doc/zshintro.tex'`" test 56686 -eq "$Wc_c" || echo 'doc/zshintro.tex: original size 56686, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi rm -f _shar_seq_.tmp echo You have unpacked the last part of zshintro.tex exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.