Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!sri-unix!quintus!ok From: ok@quintus.UUCP (Richard A. O'Keefe) Newsgroups: comp.unix.wizards,comp.unix.questions Subject: Re: The whole prompt string thing (was: PS1 and the bourne shell...) Message-ID: <440@cresswell.quintus.UUCP> Date: Sun, 6-Dec-87 21:56:55 EST Article-I.D.: cresswel.440 Posted: Sun Dec 6 21:56:55 1987 Date-Received: Sat, 12-Dec-87 03:55:51 EST References: <279@caus-dp.UUCP> <1311@puff.wisc.edu> <137@anumb.UUCP> <1973@bloom-beacon.MIT.EDU> Organization: Quintus Computer Systems, Mountain View, CA Lines: 85 Summary: use the "." command Xref: mnetor comp.unix.wizards:5885 comp.unix.questions:5232 The task is to come up with some form of Bourne shell command such that {initial stuff} {arg} {final stuff} has the same effect as cd {arg} except that in addition it sets PS1 to something like "`pwd` > ". In this message I provide two solutions which should work in any reasonable Bourne shell (no aliases or shell functions). Since the directory is to be changed, the command ought to be executed by the current shell. The obvious thing to try is the "dot" command: . file reads commands from file and executes them in the current shell. The whole point of the "dot" command is to set environment variables. Unfortunately, you can't pass positional parameters this way, so you have to use environment variables. Let's reserve the variable "d" for this. Letting the file be called "sd", the total command will be d={arg} . sd It would be nice if . sd acted like cd without an argument. The rest is almost obvious. # beginning of script to make sd cat <<'EOF' >sd cd ${d:-$HOME} PS1="`pwd` > " unset d EOF chmod a=rx sd exit # end of script to make sd Why the "unset" command? Well, there is a fine point about keyword parameters which is not in the manual. The VSID says (Vol 2, p 105): The environment for any _simple-command_ may be augmented by prefixing it with one or more assignments to parameters. Thus: TERM=123 cmd (export TERM; TERM=123; cmd) (where cmd uses the value of the environmental variable TERM) are equivalent as far as the execution of cmd is concerned. The trouble with "dot" is that it is a "special command"; the SVID is not clear about in which respects "special commands" are _simple-commands_; for example in SVR1 special commands couldn't have I/O redirection. (In SVR2 and SVR3 they can.) It turns out that there is a difference between "special commands" and others with respect to keyword parameters. Keyword parameters are allowed on ANY _simple-command_, but var=val PROGRAM binds var to val for PROGRAM and does not change its global value. (let ((var val)) PROGRAM) var=val SPECIAL permanently sets var to val and then executes SPECIAL (progn (setq var val) SPECIAL) This is true in the 4.2, V.2, and V.3 systems I have tried. The relevance to sd is that d=directory . sd permanently changes d, so a later sd can't tell whether there was a d keyword argument or not. So I've made sd remove the binding for d. (unset arrived in SVR2, so on earlier Bourne shells, just forget it and put up with always specifying d.) This is not pretty, and it seems to me that keywords parameters should be local to special commands as well as to ordinary programs, just as you can now redirect I/O for special commands too. Summary: d=directory . sd should do the job in any reasonable Bourne shell. It looks odd, but can typically be typed without touching the shift key. There is another possibility. cat <<'EOF' >sd2 cd ${1:-$HOME} here=`pwd` echo "PS1='$here > ' ; cd $here" EOF You execute this with eval: eval `sd2 directory` You have to use the shift key for this one, but it is a general technique for doing anything you like and then updating the parent shell. I normally use a SUN, and have an alias set up which puts the current hostname and current directory into the title-bar of a window. Some terminals have a mode-line which can be set, and either of these methods could be used to set the mode-line rather than the prompt string.