[comp.unix.shell] Built-in String Processing?

phd_ivo@gsbacd.uchicago.edu (10/28/90)

*************

I am running a csh with enhancements on my NeXT and on an HP-9000/8xx.
I have a macro to define my prompt to be the current directory, i.e.

	alias cd                'cd \!* && set prompt="\! ${cwd}> "'

Unfortunately, this gives me a rather long string, which starts with
'/Users/u/ivo/subdir' etc. I would like to get rid of the first x characters of
the ${cwd} variable in this macro, i.e. display only 'subdir' ( or even better,
only if the string starts with '/Users/u/ivo' ). How would I do this?

/ivo welch	ivo@next.agsm.ucla.edu

cedman@lynx.ps.uci.edu (Carl Edman) (10/28/90)

In article <1990Oct27.215051.14085@midway.uchicago.edu> phd_ivo@gsbacd.uchicago.edu writes:
   I am running a csh with enhancements on my NeXT and on an HP-9000/8xx.
   I have a macro to define my prompt to be the current directory, i.e.

	   alias cd                'cd \!* && set prompt="\! ${cwd}> "'

   Unfortunately, this gives me a rather long string, which starts with
   '/Users/u/ivo/subdir' etc. I would like to get rid of the first x characters of
   the ${cwd} variable in this macro, i.e. display only 'subdir' ( or even better,
   only if the string starts with '/Users/u/ivo' ). How would I do this?

Well, if you have any choice over your shell , you should have no problems
installing 'tcsh' instead. It is largly compatible and offers many neat
features csh doesn't have. Among these is the ability to set your prompt
to e.g. "%~> " (like I have). This will give you a full path if you are
somewhere outside your home directory, but if you are in it the entire path
to it will be replaced by "~" (logical, isn't it ?). i.e. if you are in
$HOME/Mail the prompt in the above example would be "~/Mail> ". If you
were in "/usr/local/lib/mh" the prompt would be "/usr/local/lib/mh> ".
This is only of the least of the many nice features of this shell. I
use it on most machines.

You can get a copy of the source to tcsh 5.19 (and maybe even a NeXT
executable) from "tesla.ee.cornell.edu". But beware: If you won't to
get a complete source for tcsh you will also have to have the source
to BSD 4.3 csh. Or maybe I kind soul somewhere on the net could take
pity to your plight (:-) and send you a complete source, if you can't
get the BSD 4.3 csh source.

	Carl Edman



Theorectial Physicist,N.:A physicist whose   | Send mail
existence is postulated, to make the numbers |  to
balance but who is never actually observed   | cedman@golem.ps.uci.edu
in the laboratory.                           | edmanc@uciph0.ps.uci.edu

kole@convex.com (John P. Kole) (10/28/90)

In article <1990Oct27.215051.14085@midway.uchicago.edu> phd_ivo@gsbacd.uchicago.edu writes:
> ...
>	alias cd                'cd \!* && set prompt="\! ${cwd}> "'
> ...
>'/Users/u/ivo/subdir' etc. I would like to get rid of the first x characters of
>the ${cwd} variable in this macro, i.e. display only 'subdir' ( or even better,
>only if the string starts with '/Users/u/ivo' ). How would I do this?

Try the ':t' modifier as follows:

	alias cd                'cd \!* && set prompt="\! ${cwd:t}> "'

bjaspan@athena.mit.edu (Barr3y Jaspan) (10/29/90)

In article <1990Oct27.215051.14085@midway.uchicago.edu>, phd_ivo@gsbacd.uchicago.edu writes:
|> *************
|> I am running a csh with enhancements on my NeXT and on an HP-9000/8xx.
|> I have a macro to define my prompt to be the current directory, i.e.
|> 
|> 	alias cd                'cd \!* && set prompt="\! ${cwd}> "'
|> 
|> Unfortunately, this gives me a rather long string...

I wrote a short little hack to deal with this about a year ago.  Basically, it
can do the following things:

1) Truncate the cwd to a specified number of directories.
2) Replace a specified directory prefix with a constant string.
3) Remove a specified number of characters from the remainder of the cwd
after replacing a prefix.

We use AFS extensively at Athena (which results in VERY long path names!) so
I can easily provide examples of all three of these "features":

cwd                                  my prompt is
===================================  ==================================

/mit/bjaspan                         ~bjaspan%
/afs/athena/user/b/bjaspan           ~bjaspan%
/afs/athena/astaff/FOO               astaff: FOO%
/afs/athena/astaff/kerberos/FOO      kerberos: FOO%
/one/two/three/four/five             .../two/three/four/five%

The aliases that do all this magic for me are as follows:

alias pcmd '/mit/bjaspan/${bindir}/prompt 4 $cwd $home 0 ~  \
   /afs/athena.mit.edu/user/b/bjaspan 0 ~ /afs/athena.mit.edu/user 3 ~ \
   /afs/athena/user 3 ~ /afs/sipb.mit.edu/project/sipbsrc 1 "sipbsrc: " \
   /afs/athena.mit.edu/astaff/project 1 "aproj: " \
   /afs/rel-eng.athena.mit.edu/project/release/current/source 1 "source: " \
   /source 1 "source: "'
alias cd_magic 'set noglob && set prompt = "<%m> `pcmd`% " && unset noglob'
alias cd 'cd \!* && cd_magic'
alias pushd 'pushd \!* && cd_magic'
alias popd 'popd \!* && cd_magic'

Note that I've just copied these from my .aliases file.  The program that
actually does the real work, called "prompt", is included below.  It is
a bare-bones program (compiles to 3K on a VAX) that does NO ERROR CHECKING.
This qualifies as a gross hack of the first order, which means I don't care
if it dumps core on you because it works for me.  :-)  Your mileage
may vary.  Feel free to send me bugs, though.

Barr3y Jaspan, bjaspan@athena.mit.edu

PS:  I don't read this newgroup regularly (someone forwarded your question to
me because he knew I had written a prompt hack) so send replies personally.

--- snip snip ---

#define MHT	10
#define USAGE	"Usage: prompt max_dirs cwd [ hometop offset text ... ]\n"

int left_bcopy(src, dest, len)
   char	*src, *dest;
   int	len;
{
     while (len--)
	  *dest++ = *src++;
}

main(argc, argv)
   int	argc;
   char	**argv;
{
     char	*cwd, *hometop[MHT], *hometop_text[MHT];
     int	cwd_len, hometop_len[MHT], hometop_offset[MHT];
     int	hometop_num, i, max_dirs, count;

     if (argc < 3) {
	  write(1, USAGE, strlen(USAGE));
	  exit(1);
     }

     hometop_num = i = 0;
     max_dirs = atoi(*++argv);
     cwd = *++argv;
     cwd_len = strlen(cwd);

     while ((hometop_num < MHT) && (hometop[hometop_num] = *++argv)) {
	  hometop_offset[hometop_num] = atoi(*++argv);
	  hometop_text[hometop_num] = *++argv;
	  hometop_len[hometop_num] = strlen(hometop[hometop_num]);
	  ++hometop_num;
     }

     while (i < hometop_num) {
	  if (strncmp(hometop[i], cwd, hometop_len[i])==0 &&
	      (cwd_len >= hometop_len[i]+hometop_offset[i])) {
	       left_bcopy(cwd+hometop_len[i]+hometop_offset[i], cwd,
			  cwd_len-hometop_len[i]);
	       cwd[cwd_len-hometop_len[i]] = '\0';
	       cwd_len = strlen(cwd);
	       write(1, hometop_text[i], strlen(hometop_text[i]));
	       break; }
	  ++i;
     }

     if (max_dirs) {
	  for (i=cwd_len, count=0; i>0; i--) {
	       if (*(cwd+i) == '/' && (++count == max_dirs)) {
		    write(1, "...", 3);
		    write(1, cwd+i, cwd_len-i);
		    return 0; }
	  }
     }

     write(1, cwd, cwd_len);
     return 0;
}

hirchert@harriett.ncsa.uiuc.edu (Kurt Hirchert) (10/30/90)

In article <1990Oct27.215051.14085@midway.uchicago.edu> phd_ivo@gsbacd.uchicago.edu writes:
>*************
>
>I am running a csh with enhancements on my NeXT and on an HP-9000/8xx.
>I have a macro to define my prompt to be the current directory, i.e.
>
>	alias cd                'cd \!* && set prompt="\! ${cwd}> "'
>
>Unfortunately, this gives me a rather long string, which starts with
>'/Users/u/ivo/subdir' etc. I would like to get rid of the first x characters of
>the ${cwd} variable in this macro, i.e. display only 'subdir' ( or even better,
>only if the string starts with '/Users/u/ivo' ). How would I do this?

The following is copied from my .cshrc .  On machines where I work regularly
under other directories, I include other sed substitutions.  The alias for
setprompt doesn't really need to be on three lines; it was organized this way
for purposes of inclusion in one of our local publications where really long
lines did not display well.  (Note that the quoting is set up to evaluate
hostname at the time the alias is defined, but to defer evaluation of of the
pwd/sed pipe until the alias is executed.)

# aliases for changing the prompt to include current directory
alias setprompt	'set prompt="("`pwd |'\
'sed -e "s|^$home|~|"'\
'`") "'\""`hostname` \\!% "\"
alias cd	"cd \!* ; setprompt"
alias chdir	"chdir \!* ; setprompt"
alias pushd	"pushd \!* ; setprompt"
alias popd	"popd \!* ; setprompt"
--
Kurt W. Hirchert     hirchert@ncsa.uiuc.edu
National Center for Supercomputing Applications

boyd@necisa.ho.necisa.oz (Boyd Roberts) (10/30/90)

In article <1990Oct27.215051.14085@midway.uchicago.edu>, phd_ivo@gsbacd.uchicago.edu writes:
> *************
> I am running a csh with enhancements on my NeXT and on an HP-9000/8xx.
> I have a macro to define my prompt to be the current directory, i.e.
> 
> 	alias cd                'cd \!* && set prompt="\! ${cwd}> "'
> 
> Unfortunately, this gives me a rather long string...
>

With a decent* shell you just go:

    cd()
    {
	builtin cd $1 &&
	case "$1" in
	'')
	    PS1="% " ;;
	..|*/..)
	    PS1="`basename \`/bin/pwd\``% " ;;
	/)
	    PS1="/% " ;;
	*/*)
	    PS1="`basename $1`% " ;;
	*)
	    PS1="$1% " ;;
	esac
    }



Boyd Roberts			boyd@necisa.ho.necisa.oz.au

``When the going gets wierd, the weird turn pro...''

* V8/V9

chet@cwns1.INS.CWRU.Edu (Chet Ramey) (10/31/90)

In article <1902@necisa.ho.necisa.oz> boyd@necisa.ho.necisa.oz (Boyd Roberts) writes:

$ With a decent* shell you just go:
$ 
$     cd()
$     {
$ 	builtin cd $1 &&
$ 	case "$1" in
$ 	'')
$ 	    PS1="% " ;;
$ 	..|*/..)
$ 	    PS1="`basename \`/bin/pwd\``% " ;;
$ 	/)
$ 	    PS1="/% " ;;
$ 	*/*)
$ 	    PS1="`basename $1`% " ;;
$ 	*)
$ 	    PS1="$1% " ;;
$ 	esac
$     }

$ * V8/V9

Don't be so elitist :-).  Bash can do this, too.  In fact, I stole this
some time ago for an example in the bash texinfo manual (which is not out
yet).  Bash doesn't make you jump through hoops quoting backquotes, either.
(so there! :-)

Chet

-- 
Chet Ramey			``As I recall, Doug was keen on boxing.  But
Network Services Group		  when he learned to walk, he took up puttin'
Case Western Reserve University	  the boot in the groin.''
chet@ins.CWRU.Edu

jms@tardis.Tymnet.COM (Joe Smith) (10/31/90)

In article <1990Oct27.215051.14085@midway.uchicago.edu> phd_ivo@gsbacd.uchicago.edu writes:
>	alias cd                'cd \!* && set prompt="\! ${cwd}> "'
>Unfortunately, this gives me a rather long string.

Use $variable:t to get the tail (the name after the last "/") and use
$variable:h to get the head (everything before the last "/").

alias cd    'cd \!*; set cwdh=$cwd:h; set prompt="($cwdh:t/$cwd:t) $myprompt"'
alias pushd 'pushd \!*; cd .'
alias popd  'popd \!*; cd .'

Or go read the Frequently Asked Questions posting in the "newuser" and
"announce" newsgroups.
-- 
Joe Smith (408)922-6220 | SMTP: jms@tardis.tymnet.com or jms@gemini.tymnet.com
BT Tymnet Tech Services | UUCP: ...!{ames,pyramid}!oliveb!tymix!tardis!jms
PO Box 49019, MS-C41    | BIX: smithjoe | 12 PDP-10s still running! "POPJ P,"
San Jose, CA 95161-9019 | humorous dislaimer: "My Amiga 3000 speaks for me."

stluka@software.org (Fred Stluka) (10/31/90)

In article <1990Oct29.160325.23250@ux1.cso.uiuc.edu> hirchert@harriett.ncsa.uiuc.edu (Kurt Hirchert) writes:
> 
> # aliases for changing the prompt to include current directory
> alias setprompt	'set prompt="("`pwd |'\
> 'sed -e "s|^$home|~|"'\
> '`") "'\""`hostname` \\!% "\"
> alias cd	"cd \!* ; setprompt"
> alias chdir	"chdir \!* ; setprompt"
> alias pushd	"pushd \!* ; setprompt"
> alias popd	"popd \!* ; setprompt"

Here's a trick I stumbled across while setting up my own
version of this a while back.

Try typing:

	dirs

If the directories that it reports are always in the form 
you want (on my Apollo, ~ is displayed instead of the long
pathname to my home directory), you can eliminate sed from
the pipeline in setprompt by using dirs instead of pwd as
the starting point.  

Example:

    alias setprompt \
    'set noglob;set d=(`dirs`);set prompt="$d[1] % ";unset noglob'
	
--Fred

Fred Stluka                          Internet: stluka@software.org
Software Productivity Consortium     UUNET:    ...!uunet!software!stluka
2214 Rock Hill Rd, Herndon VA 22070