[net.unix] Useful csh prompts?

jmturn@cca-unix.ARPA (10/02/85)

A lifelong ambition of mine has been to have csh give me the current
time as my prompt (Ok, current time, and history number, to get greedy).

Would this involve source modification of csh? Or can I massage it?


                           Save Your Vertical Blanking Intervals 
                           for Big Cash Prizes!

                           James Turner
                           (The Ringworld Engineer)

---------------------------------------------------
|   ARPA    | ringwld!jmturn@CCA-UNIX.ARPA        |
---------------------------------------------------
|           |  decvax  \                          |
|           |  sri-unix \                         |
|   UUCP    |            !cca!ringwld!jmturn      |
|           |  ima      /                         |
|           |  linus   /                          |
---------------------------------------------------
|   MAIL    | 329 Ward Street; Newton, MA 02159   |
---------------------------------------------------

bill@ur-cvsvax.UUCP (Bill Vaughn) (10/04/85)

> A lifelong ambition of mine has been to have csh give me the current
> time as my prompt (Ok, current time, and history number, to get greedy).
> 
> Would this involve source modification of csh? Or can I massage it?
> 
>                            James Turner
>                            (The Ringworld Engineer)
> 
If one has the source code one might as well do it there. 
Here are some diffs for sh.c and sh.dir.c which will give you the
time and/or current directory in your prompt (and of course the event
number).  I was originally doing this with very cumbersome aliases
but I decided that if the '\!' has special meaning in the prompt why
not other characters as well.  It works like a charm.  In fact, I had only
added '@' to serve as a code for 'pwd'. It took me only a few minutes
to install a change to display the time (code = '&'). Thanks for the idea.

You really only have to change /usr/src/csh/sh.c and remake to install
these changes. However, given that my original intention concerned putting
the 'pwd' in the prompt, I needed to make some changes in /usr/src/csh/sh.dir.c
to eliminate some redundancies.  These changes supress the printing of the
'pwd' after the 'pushd' or 'popd' commands.  The 'dirs' command can do that
if you really want it. I use aliases.  I also changed the output of the dirs
command so that using 'pd +n' is easier. The fix posted by Chris Berten
(pixutl!chris) almost a year ago to this day  concerning the correct display
of the 'pwd' for directories thru symbolic links is in there too; i.e. if, say,
/usr/sys@->/sys then a 'cd /usr/sys ; pwd' displays /sys and NOT /usr/sys)

The following diffs are against the original distribution code with those diffs
irrelevant to present purposes deleted.  Hence your line numbers may vary.
I've also included some aliases I find useful in conjunction with these changes.
Enjoy!

*** orgs/sh.c	Thu Oct  3 14:45:10 1985
--- sh.c	Thu Oct  3 22:46:50 1985
***************
*** 2,5
  
  #include "sh.h"
  #include <sys/ioctl.h>
  /*

--- 4,8 -----
  
  #include "sh.h"
+ #include "sh.dir.h"
  #include <sys/ioctl.h>
  /*
***************
*** 18,21
  char	HIST = '!';
  char	HISTSUB = '^';
  bool	nofile;
  bool	reenter;

--- 26,32 -----
  char	HIST = '!';
  char	HISTSUB = '^';
+ char	CWD = '@';
+ char	BKSL = '\\';
+ char	TME = '&';
  bool	nofile;
  bool	reenter;
***************
*** 739,750
  			if (fseekp == feobp)
  				if (!whyles)
! 					for (cp = value("prompt"); *cp; cp++)
! 						if (*cp == HIST)
! 							printf("%d", eventno + 1);
! 						else {
! 							if (*cp == '\\' && cp[1] == HIST)
! 								cp++;
! 							putchar(*cp | QUOTE);
! 						}
  				else
  					/*

--- 754,758 -----
  			if (fseekp == feobp)
  				if (!whyles)
! 					doprompt();
  				else
  					/*
***************
*** 841,844
  }
  
  dosource(t)
  	register char **t;

--- 849,875 -----
  }
  
+ doprompt()
+ {
+ 	char *cp;
+ 
+ 	for (cp = value("prompt"); *cp; cp++) {
+ 		if (*cp == HIST)
+ 			printf("%d",eventno+1);
+ 		else if (*cp == CWD)
+ 			printf("%s",dcwd->di_name);
+ 		else if (*cp == TME) {
+ 			long l = (long)time(0);
+ 			struct tm *t = (struct tm *)localtime(&l);
+ 			printf("%02d:%02d",t->tm_hour,t->tm_min);
+ 		}
+ 		else {
+ 			char c = *(cp + 1);
+ 			if (*cp == BKSL && (c == HIST || c == CWD || c == TME))
+ 				cp++;
+ 			putchar(*cp | QUOTE);
+ 		}
+ 	}
+ }
+ 
  dosource(t)
  	register char **t;

*** orgs/sh.dir.c	Wed Mar 27 13:27:00 1985
--- sh.dir.c		Thu Oct  3 16:02:06 1985
***************
*** 14,17
  static	char *fakev[] = { "dirs", NOSTR };
  
  /*
   * dinit - initialize current working directory

--- 16,22 -----
  static	char *fakev[] = { "dirs", NOSTR };
  
+ #define	PRENABLE 0	/* change this back to 1 for old behavior */
+ #define PRDISABLE 0
+ 
  /*
   * dinit - initialize current working directory
***************
*** 38,42
  	dhead.di_next = dhead.di_prev = dp;
  	dp->di_next = dp->di_prev = &dhead;
! 	printd = 0;
  	dnewcwd(dp);
  }

--- 43,47 -----
  	dhead.di_next = dhead.di_prev = dp;
  	dp->di_next = dp->di_prev = &dhead;
! 	printd = PRDISABLE;
  	dnewcwd(dp);
  }
***************
*** 51,54
  	bool lflag;
  	char *hp = value("home");
  
  	if (*hp == '\0')

--- 56,60 -----
  	bool lflag;
  	char *hp = value("home");
+ 	register i;
  
  	if (*hp == '\0')
***************
*** 62,65
  		lflag = 0;
  	dp = dcwd;
  	do {
  		if (dp == &dhead)

--- 68,72 -----
  		lflag = 0;
  	dp = dcwd;
+ 	i = 0;
  	do {
  		if (dp == &dhead)
***************
*** 65,69
  		if (dp == &dhead)
  			continue;
! 		if (!lflag && hp != NOSTR) {
  			dtildepr(hp, dp->di_name);
  		} else

--- 72,77 -----
  		if (dp == &dhead)
  			continue;
! 		printf("%d:",i++);	/* This helps with pd +n commands */
! 		if (!lflag && hp != NOSTR)
  			dtildepr(hp, dp->di_name);
  		else
***************
*** 67,71
  		if (!lflag && hp != NOSTR) {
  			dtildepr(hp, dp->di_name);
! 		} else
  			printf("%s", dp->di_name);
  		printf(" ");

--- 75,79 -----
  		if (!lflag && hp != NOSTR)
  			dtildepr(hp, dp->di_name);
! 		else
  			printf("%s", dp->di_name);
  		printf("\n");
***************
*** 69,73
  		} else
  			printf("%s", dp->di_name);
! 		printf(" ");
  	} while ((dp = dp->di_prev) != dcwd);
  	printf("\n");

--- 77,81 -----
  		else
  			printf("%s", dp->di_name);
! 		printf("\n");
  	} while ((dp = dp->di_prev) != dcwd);
  }
***************
*** 71,75
  		printf(" ");
  	} while ((dp = dp->di_prev) != dcwd);
- 	printf("\n");
  }
  

--- 79,82 -----
  		printf("\n");
  	} while ((dp = dp->di_prev) != dcwd);
  }
  
***************
*** 93,97
  	register struct directory *dp;
  
! 	printd = 0;
  	if (*++v == NOSTR) {
  		if ((cp = value("home")) == NOSTR || *cp == 0)

--- 100,104 -----
  	register struct directory *dp;
  
! 	printd = PRDISABLE;
  	if (*++v == NOSTR) {
  		if ((cp = value("home")) == NOSTR || *cp == 0)
***************
*** 101,105
  		cp = savestr(cp);
  	} else if ((dp = dfind(*v)) != 0) {
! 		printd = 1;
  		if (chdir(dp->di_name) < 0)
  			Perror(dp->di_name);

--- 108,112 -----
  		cp = savestr(cp);
  	} else if ((dp = dfind(*v)) != 0) {
! 		printd = PRENABLE;
  		if (chdir(dp->di_name) < 0)
  			Perror(dp->di_name);
***************
*** 130,133
  	register char **cdp;
  	struct varent *c;
  	
  	cp = globone(cp);

--- 137,141 -----
  	register char **cdp;
  	struct varent *c;
+ 	char *realdname();
  	
  	cp = globone(cp);
***************
*** 143,147
  			strcat(buf, cp);
  			if (chdir(buf) >= 0) {
! 				printd = 1;
  				xfree(cp);
  				cp = savestr(buf);

--- 151,155 -----
  			strcat(buf, cp);
  			if (chdir(buf) >= 0) {
! 				printd = PRENABLE;
  				xfree(cp);
  				cp = savestr(buf);
***************
*** 157,161
  				xfree(cp);
  				cp = savestr(dp);
! 				printd = 1;
  				goto gotcha;
  			}

--- 165,169 -----
  				xfree(cp);
  				cp = savestr(dp);
! 				printd = PRENABLE;
  				goto gotcha;
  			}
***************
*** 173,176
  		cp = dp;
  	}
  	dcanon(cp);
  	return (cp);

--- 181,185 -----
  		cp = dp;
  	}
+ 	cp = realdname(cp);
  	dcanon(cp);
  	return (cp);
***************
*** 187,191
  	register struct directory *dp;
  
! 	printd = 1;
  	if (*++v == NOSTR) {
  		if ((dp = dcwd->di_prev) == &dhead)

--- 196,200 -----
  	register struct directory *dp;
  
! 	printd = PRENABLE;
  	if (*++v == NOSTR) {
  		if ((dp = dcwd->di_prev) == &dhead)
***************
*** 257,261
  	register struct directory *dp, *p;
  
! 	printd = 1;
  	if (*++v == NOSTR)
  		dp = dcwd;

--- 266,270 -----
  	register struct directory *dp, *p;
  
! 	printd = PRENABLE;
  	if (*++v == NOSTR)
  		dp = dcwd;
***************
*** 274,279
  	if (dp == dcwd)
  		dnewcwd(p);
- 	else
- 		dodirs(fakev);
  	dfree(dp);
  }

--- 283,286 -----
  	if (dp == dcwd)
  		dnewcwd(p);
  	dfree(dp);
  }
***************
*** 357,359
  	if (printd)
  		dodirs(fakev);
  }

--- 364,379 -----
  	if (printd)
  		dodirs(fakev);
+ }
+ 
+ char *realdname(d)
+ 	char *d;
+ {
+ 	struct stat st;
+ 	char *getwd();
+ 	char path[BUFSIZ];
+ 
+ 	lstat(d, &st);
+ 	if((st.st_mode & S_IFMT) != S_IFLNK)
+ 		return(d);
+ 	return(savestr(getwd(path)));
  }
*********************

Some useful aliases:

alias d dirs
alias pd pushd
alias pp popd
alias cd 'pushd \!* ; prune'
alias pdd 'pushd ; dirs'
alias ppd 'popd ; dirs'
alias cdd 'pushd \!* ; prune ; dirs'
#
# The prune alias keeps the directory stack a constant size
#
alias prune 'set zqk = `dirs` ; @ zqk = $#zqk - 1 ; if($zqk \!= 0) popd +$zqk ; unset zqk'

 _________________________________
 \          Bill Vaughn          /
  \  Center for Visual Science  /
  /   University of Rochester   \
 /seismo!rochester!ur-cvsvax!bill\
/  ur-cvsvax!bill@rochester.arpa  \
-----------------------------------

olson@fortune.UUCP (Dave Olson) (10/07/85)

Getting the time in the csh prompt means modification to the source.
The mods are relatively minor, but are too big to patch in.

The more general way would be to have the prompt routine (I forget the
name offhand) do back quote interpretation.  I took the easier
route, and modified the routine to replace occurrences of $T in
$prompt, with the time in the form HH:MM.  If you or others would
like the mod's I can mail them.

	Dave Olson, Fortune Systems
	UUCP: {ihnp4,ucbvax!dual}!fortune!olson
	ARPA: dual!fortune!olson@BERKELEY

avolio@decuac.UUCP (Frederick M. Avolio) (10/10/85)

In article <229@ur-cvsvax.UUCP>, bill@ur-cvsvax.UUCP (Bill Vaughn) writes:
> > A lifelong ambition of mine has been to have csh give me the current
> > time as my prompt (Ok, current time, and history number, to get greedy).
> > 
> If one has the source code one might as well do it there. 
>    ....  I was originally doing this with very cumbersome aliases
>                           ...  It works like a charm.  In fact, I had only
> added '@' to serve as a code for 'pwd'.

I do not mean to belittle the code changes made by Bill, as they are very
nice.  I also realize that the original poster wanted the *time* in the
prompt and the only way to do this so that the current time always shows up
is in the source code.  But, if one only wants the current directory as
part of the csh prompt, I'd use the following (which are by no means
cumbersome aliases).

                 alias cd 'cd !* ; set prompt="[$cwd]: "'
		 alias popd 'popd ; set prompt="[$cwd]: "'
		 alias pushd 'pushd !* ; set prompt="[$cwd]: "'

avolio@decuac.UUCP (Frederick M. Avolio) (10/10/85)

In article <229@ur-cvsvax.UUCP>, bill@ur-cvsvax.UUCP (Bill Vaughn) writes:
> > A lifelong ambition of mine has been to have csh give me the current
> > time as my prompt (Ok, current time, and history number, to get greedy).
> > 
> If one has the source code one might as well do it there. 
>    ....  I was originally doing this with very cumbersome aliases
>                           ...  It works like a charm.  In fact, I had only
> added '@' to serve as a code for 'pwd'.

    I do not mean to belittle the code changes made by Bill, as they
are very nice.  I also realize that the original poster wanted the
*time* in the prompt and the only way to do this so that the current
time always shows up is to change the source code.  But many do not
have sources, and if one only wants the current directory as part of
the csh prompt, I'd use the following (which are by no means
cumbersome aliases).

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