Is there a smart pwd display program?

Barr3y Jaspan bjaspan at athena.mit.edu
Thu Apr 18 07:02:28 AEST 1991


In article <1991Apr15.170910.28160 at ux1.cso.uiuc.edu>, jbn35564 at uxa.cso.uiuc.edu (J.B. Nicholson) writes:
|> I'm writing a function for KSH that shows you your current working directory
|> using tilde notation:
|>
|> [ examples deleted ]

You might be interested in a hack I wrote called (surprise!) 'prompt'. 
Essentially, it takes a list of path/replacement pairs and replaces the
matching part of any path with its replacement.  It also truncates the final
path to a specified number of components.  Here is how I use it (with csh or
tcsh):

alias pcmd '~bjaspan/${bindir}/prompt 4 $cwd $home 0 ~ 
  /afs/athena.mit.edu/user/b/bjaspan 0 ~ /afs/athena.mit.edu/user 3 ~
  /afs/sipb.mit.edu/project/sipbsrc 1 "sipbsrc: "'
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'

(Obviously, we use AFS here.)  The arguments to prompt mean:
	o only display a total of four components of the final path, after
	  replacement
	o $cwd is in the alias literally, so it gets expanded at each 
	  invokation, thus passing the current working dir to the program
	
The rest are actually triples, "path-offset-replacement".  Any current path
beginning with "path" is replaced by "replacement", and "offset" characters
are deleted from the remaining componenets (if there aren't that many
characters left, nothing happens).  Here is a transcript demonstrating the
program's behavior (with commentary):

~% cd
# $home is replaced by ~ with 0 chars deleted
~% cd src
# only the specified components are removed from the path
~/src% cd /afs/sipb.mit.edu/project/sipbsrc/
# offset==1 for sipbsrc, and since there aren't that many more characters,
# nothing happens here
/afs/sipb.mit.edu/project/sipbsrc% cd src
# Now there are more characters, so 1 (the leading /) is deleted.
sipbsrc: src% cd lib/elisp/gnus-dist/attic
# Only four components are shown
sipbsrc: .../lib/elisp/gnus-dist/attic% cd /afs/athena.mit.edu/user
# /afs/athena.mit.edu/user deletes three characters, and there aren't that many
/afs/athena.mit.edu/user% cd t
# Still not enough characters
/afs/athena.mit.edu/user/t% cd tytso
# Now there are, so replace the text with ~ and delete the 3 chars
~tytso%

(Note for the sharp eyed:  yes, there is a <%m> in the prompt to display the
hostname, and yes, it works.  I deleted it so everything would fit on one
line.)

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

Anyway, the best thing about this program is its size -- about 3K on a vax
running bsd (and similarly small on other machines).  It uses one syscall
(write) and one library function (strlen).  It provides its own bcopy() in
case yours doesn't do overlapping regions (although, clearly, any bcopy
should, and could probably be done better in assembly).

Note: your mileage may vary.  If you find problems, feel free to tell me but I
may or may not care to fix them.  It works for me.  :-)  Oh, and I don't
usually read this newsgroup...

Barr3y Jaspan, bjaspan at mit.edu
Watchmaker Computing

---- 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;
}





-- 
Barr3y Jaspan, bjaspan at mit.edu



More information about the Comp.unix.shell mailing list