[net.unix-wizards] CSH script help needed

adamm%bbn-unix@sri-unix.UUCP (01/05/84)

From:  Adam Moskowitz <adamm@bbn-unix>

  Help !  I'm trying to make a command via some combination
of aliases and script files that will allow the following
scenario to take place :

  bbns /usr/adamm --> cd /usr/dir1/dir2/dir3
  bbns /usr/dir1/dir2/dir3 --> cat file1
  bbns /usr/dir1/dir2/dir3 --> wc file2
  bbns /usr/dir1/dir2/dir3 --> plugh /usr/adamm/dirA/dirB   # THIS ONE !
  bbns /usr/adamm/dirA/dirB --> vi fileX
  bbns /usr/adamm/dirA/dirB --> foo fileX
  bbns /usr/adamm/dirA/dirB --> plugh   # THIS ONE TOO !
  bbns /usr/dir1/dir2/dir3 -->

  where the --> and everything to the LEFT of it is the prompt.

  What I need is the stuff to do the 'plugh' command.  If I call it
with an arg, it should 'cd' to that place and remember where it came
from.  If I call it with no args, it should 'cd' me back to the last
place I 'plugh'd from (with an arg, of course).  The problem I've had
was that I couldn't find a way to get a shell script to leave me where
it 'cd'd to.  When I resorted to 'source'ing the script file, I couldn't
figure out how to pass args to the script.

  Please let me know if you have such a command or know how I can do this.
I'd be glad to re-distribute the results if/when I get them.

Thanx,
AdamM
(adamm@bbn-unix)

condict@csd1.UUCP (Michael Condict) (01/07/84)

All you need is a way to execute "source" commands with argument(s) after
the file name, right?  Well, to prove that this is completely straightforward
in the elegant and powerful mechanism loosely known as the C-shell (4.2bsd),
I hereby enclose a copy of my .cshrc file, which contains the desired alias
(called "so", below).  Use it with:

		so file [args]

With no args it is equivalent to "source file" (but a tad slower).
Note that, at no extra charge, I provide you with a one-line while loop and
a "cd" command that sources a .cdrc file upon entering a directory (the latter
is an optional accessory, but "while1" is needed by "so").

I posted this before as a puzzle, with no comments -- didn't think I'd ever
find that somebody actually wanted it!

Michael Condict    ...!cmcl2!csd1!condict

P.S. Neither I nor my heirs and/or creditors are responsible for the correct
     functioning of any part of this "code", especially if any character of it
     is changed.

P.P.S. This code memorializes the closest I've ever come to hacker's paradise.
       I can still feel the adrenaline coursing through my veins as I eradi-
       cated the last bug with a carefully placed "\\\'\''" ...
------------------------------------------------------------------------------
#
alias	l	'ls -l'
alias	m	'more'
alias	rm	'/bin/rm -i'
alias	h	history
#
# A one-line while loop (can be used in aliases):
alias	while1	'eval "if (" \!:1 ")'\
		    'eval \!:2:q \; while1 '\\\''\!:1:q'\\\' \\\''\!:2:q'\\\'\"
#
# Executes a source command with arguments (placed in argv, which is
# saved and restored) and with local variables (see local, below):
set stack = ("ENDFRAME")
alias	so	'set stack = ("ENDFRAME" $stack:q);'\
		'local argv;'\
		'set argv=(\!*);'\
		'if ($#argv == 0) source;'\
		'if ($#argv > 0) eval'\
		    \''set stack = (" " $stack:q);'\
		      '@ stack[1] = 1;'\
		      'if ("$argv[1]" =~ /*) @ stack[1] += $#path;'\
		      'while1 '\'\\\'\''$stack[1] <= $#path'\'\\\'\
			      \\\'\''if (-x "$path[$stack[1]]"/$argv[1])'\
					'@ stack[1] += $#path;'\
				'@ stack[1] += 1'\'\\\'\'' ;'\
		      '@ stack[1] -= (1 + $#path);'\
		      'if ($stack[1] > 0)'\
				'set argv[1] = "$path[$stack[1]]"/$argv[1];'\
		      'shift stack;'\
		      'eval "shift; source $argv[1]"'\'';'\
		'unlocal; shift stack'
#
# Use at top of an "so" file (see above) to declare local vars of the file
# (ones whose lifetime should coincide with the execution of the "so" file)
alias	local	'if ("\!:2*" != "") eval local \!:2*;'\
		'if (! $?\!{:1})'\
		    'set stack = ("unset \!:1" $stack:q);'\
		'if ($?\!{:1}) eval'\
		    \''set stack = ("shift stack;'\
				    'set \!:1 = ("\$"stack[1-$#\!{:1}]:q);'\
				    'set stack = ("\$"stack[$#\!{:1}-]:q)"'\
				    '$\!{:1}:q $stack:q);'\
		      'if ($#\!{:1} == 0) set stack[1] = "set \!:1 = ()"'\'
#
# Use to restore vars saved with local, above.  There must be an occurrence
# of "ENDFRAME" as a word in $stack:
alias	unlocal	'eval "$stack[1]"; shift stack;'\
		'if ("$stack[1]" != "ENDFRAME") eval unlocal'

#
# The following will act like cd but will execute file .cdrc
# (using 'so', above) if it is found in the
# new directory, with args consisting of the new dir followed by any
# additional args to cd:
#alias	cd	'set cd=(\!*);'\
#		'if ($#cd == 0) set cd = ~;'\
#		'eval chdir $cd[1]:q;'\
#		'if (-r .cdrc) eval so .cdrc '\''$cd:q'\''; unset cd'

----------------------------------------------------------------------------

terryl@teklabs.UUCP (Terry Laskodi) (01/08/84)

     Well, if you're using a 4.1-based CSH (or later), then there's a really
easy way to do it just with aliases!!! No C-shell scripts needed!!!

alias cd 'cd \!*;set prompt="$cwd"'
alias pushd 'pushd \!*;set prompt="$cwd"'
alias popd 'popd;set prompt="$cwd"'

     Quotes must be used exactly as above, but any other strings can be put
in the set prompt string.

thomas@utah-gr.UUCP (Spencer W. Thomas) (01/10/84)

1. The "plugh" command you show is pretty well covered by the pushd
   command in 4bsd and later c-shells.  If you are still in v7-land,
   the following should do it:

alias plugh 'if ( "\!*" == "" ) cd $prevdir;'\
	'if ( "\!*" != "" ) cd \!*;'\
	'set prevdir = $cwd'

alias cd 'cd \!*; set cwd=`pwd`'

2. To get your current directory in the prompt, the following aliases
will do it (assuming 4bsd csh, which automatically sets the cwd variable):

alias	cd	'cd \!*; setprompt'
alias	pd	'pushd \!*; setprompt'
alias	popd	'popd \!*; setprompt'
set baseprompt = bbna
alias	setprompt 'set prompt="$baseprompt $cwd >"'

A slightly fancier version takes into account your favorite csh
variables to abbreviate the directory name:
alias	sortset	source ~/bin/sortset
set	baseprompt = "$prompt:q"
alias	setprompt 'set prompt="["`echo $cwd | sed -f ~/.set`"]$baseprompt:q"'

This gives a prompt like
[$foo/bar] utah-gr>

The sortset script is given below.  It contains as special cases a few
variables that I do NOT want to see in my prompt.

set | awk '/^ds/ { next; }\
/^old/ { next; }\
/^cwd/ { next; }\
/	\// { if (NF == 2) print length($2), $0; }\
{ next; }' | sort -rn |\
	awk '{ if ($3 != "'${HOME}'") printf "s;%s;$%s;\n", $3, $2; }\
END { print "s;'${HOME}';~;"; }' >~/.set

=Spencer

toml@oliveb.UUCP (Dave Long) (01/10/84)

    Actually, if you're going to do this, and you are using 4.1BSD this
following stack-oriented command should provide a better arrangement.

In the .login or equivalent:
    set dsp=0
    set dr=""
    set ds=(. . . . . . . . . . . . . . . .)
In the .cshrc or equivalent:
    alias pushd   'set dr=\!*;cd $dr;@ dsp++;set ds[$dsp]=$dr'
    alias popd    'set ds[$dsp]=".";@ dsp--;set dr=$ds[$dsp];cd $dr'
    alias printd  'echo $ds'

    a sample session is as follows: (the '> ' is the prompt)
> pwd
/usr/foo
> pushd /usr/bletch
> printd
/usr/bletch . . . . . . . . . . . . .
> pwd
/usr/bletch
> pushd /usr/bletch/bar
> printd
/usr/bletch /usr/bletch/bar . . . . . . . . . .
> pwd
/usr/bletch/bar
> popd
> pwd
/usr/bletch
    .
    .
    .
						Dave Long
					{ucbvax,decvax}!decwrl!ios!oliveb!toml

dhb@rayssd.UUCP (01/13/84)

If you are using the newest version of csh (4.1 or later) then
what you want is the builtin command "pushd".  There is also a
"popd" command which puts you back and a "dirs" command which
prints out the contents of the directory stack.
-- 
	Dave Brierley
	Raytheon Co.; Portsmouth RI; (401)-847-8000 x4073
	...!decvax!brunix!rayssd!dhb
	...!allegra!rayssd!dhb
	...!linus!rayssd!dhb