home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / unix / shell / 3142 < prev    next >
Encoding:
Text File  |  1992-07-27  |  11.5 KB  |  317 lines

  1. Newsgroups: comp.unix.shell
  2. Path: sparky!uunet!wupost!zaphod.mps.ohio-state.edu!rpi!newsserver.pixel.kodak.com!laidbak!tellab5!nucsrl!ddsw1!dattier
  3. From: dattier@ddsw1.mcs.com (David W. Tamkin)
  4. Subject: Ron Heiby's ksh pushd and popd
  5. Message-ID: <1992Jul24.191246.11410@ddsw1.mcs.com>
  6. Organization: Contributor Account at ddsw1, Chicago, Illinois  60657
  7. Date: Fri, 24 Jul 1992 19:12:46 GMT
  8. X-Disclaimer:  Material posted in this article is the sole responsibility of
  9.                 the poster and does not represent MCSNet or the system owners.
  10. Lines: 305
  11.  
  12. The subject of pushd and popd in ksh came up in this newsgroup a few weeks
  13. back, and I just discovered the following old post from Ron Heiby in my
  14. files.  Naturally, I didn't remember it beforehand nor come across it until
  15. I'd written my own routines.  Oh well.  Mr. Heiby's post follows.
  16.  
  17. [The rest of this article is by Ron Heiby; please fix your attributions
  18.  if you follow up to it.  --DWT]
  19. ___________
  20.  
  21. If my records are complete, I posted this article in December of
  22. 1986, while working for AT&T.  Then, with modifications in December of
  23. 1987, while working for Motorola.  Since then, Ksh-88 has been
  24. released and I've seen quite a few articles asking to do lots of stuff
  25. with the prompt string.  So, here it is again, modified for Ksh-88 a
  26. bit and enhanced in some other minor ways.  If you are still using an
  27. older version of Ksh, UPGRADE!  Enjoy!
  28.  
  29. A while ago [from the perspective of someone writing in December of
  30. 1986], there were several messages posted to Usenet which showed ways
  31. to include various information into a Korn Shell PS1 prompt.  I
  32. thought that a number of these were real clever and incorporated them
  33. into my own environment.
  34.  
  35. Now that Motorola Microcomputer Division [now the Motorola Computer
  36. Group] is selling the Korn Shell for our Delta Series of 68020-based
  37. systems, I thought I'd share this generally.
  38.  
  39. Relatively little here is my own invention, but I can no longer say
  40. who had every idea.  I did put a lot of work into integrating
  41. everything together so that it would all work in a coordinated
  42. fashion.  The time stamp stuff is from Korn.  The "autoload" stuff
  43. [originally used] for functions (pshd, popd, etc.) as well as the
  44. original versions of those functions is from a Usenet article by Avi
  45. E. Gross in 10/84.  [This has since been absorbed in slightly
  46. different form into standard Ksh-88.]  I have made some readability
  47. and efficiency enhancements to the originals, as well as merging them
  48. into the rest of the stuff here.  I pulled out the large blocks of
  49. comments in Avi's original to improve the performance in my running
  50. copy and keep the original intact elsewhere so I can figure out what's
  51. going on.  As to the prompt-resetting code, I know there were at least
  52. three different people (plus me) who contributed to what is merged
  53. together here, but I lost the original Usenet articles.  Thanks,
  54. whoever you are.
  55.  
  56. I've tried to put this is into a form that you can easily install into
  57. your own environment.  I mostly did it to see if I could.  Since then,
  58. it has proved useful enough for me to keep it as my normal
  59. environment.
  60.  
  61. One could easily turn up one's nose at all this, if one really likes the "$ "
  62. prompt, as this is about as far from that as you can get.  The normal prompt
  63. when logged in and in your home directory is:   host: hh:mm:ss [~]
  64.                                                 nn>
  65. After "cd /usr/src/cmd/vi", it is:              host: hh:mm:ss [src/cmd/vi]
  66.                                                 nn>
  67. After "pshd /usr", it is:                       host: hh:mm:ss 1: [/usr]
  68.                                                 nn>
  69. After "popd", it is back to:                    host: hh:mm:ss [src/cmd/vi]
  70.                                                 nn>
  71. After invoking a sub-shell (ksh):               host: hh:mm:ss [src/cmd/vi]
  72.                                                 nn>>
  73.  
  74. The "host" is the output of the "uname" command.  I added the host
  75. name to the prompt to make it more obvious to whom I was "talking" in
  76. the face of "cu" and "rlogin" and windowing terminals.  The "nn" is
  77. the ksh history number.  hh:mm:ss is the time.  As you can see, up to
  78. the last three directories in your current directory are included.  If
  79. you are in a subdirectory of your home directory, your home directory
  80. path counts as a single directory and is represented with a tilde (~).
  81. If you are using Shell Layers (shl), the layer name "foo" or number
  82. "(n)" is displayed as part of the prompt, too.  If the uid of the user
  83. is 0 (root), then a pound sign (#) is used instead of a greater-than
  84. (>) to indicate nesting of sub-shells.  The prompt was split into two
  85. lines because the escape sequences to highlight a non-zero return code
  86. get counted as printable characters and so fewer characters from the
  87. command you are entering are visible in the line.
  88.  
  89. Good luck trying to change any of it without breaking something else.
  90. I am currently running ksh "Version 11/16/88e".
  91.  
  92. Even if you don't use this, it makes an interesting exercise to figure
  93. out how everything works.  After doing so, you'll have a very good
  94. understanding of ksh programming.
  95.  
  96. Ron.
  97.  
  98. --------- This goes in your .profile --------
  99. #       environment for fancy prompt
  100. export PSSHL PS1="!$ " FPATH=~/ksh
  101.  
  102. -------- This goes in your $ENV file ---------
  103. # All this good stuff needed for interactive shells only.
  104. # Guard it with appropriate tests for better effeciency of startup.
  105. # Here's a good example of this:
  106. #       case "$-" in
  107. #       *c*)    # Stuff for -c, command line shells goes here.
  108. #               :
  109. #               ;;
  110. #       *)      # Stuff for for non -c, (interactive) shells.
  111. #               :
  112. #               ;;
  113. #       esac
  114. #
  115. #               Set prompt string portion for Shell Layers layer.
  116. TTY=$(tty)
  117. if [ "$TTY" != "${TTY#*sxt}" -a "${SHDEPTH:-}" = ">" ]
  118. then
  119.         export PSSHL=$PS1
  120. fi
  121. unset TTY
  122. #
  123. #               Set System name string for fancy prompt
  124. UNAME=$(uname)
  125. #
  126. #               Set standout strings for fancy prompt
  127. : ${SMSO:=$(tput smso)} ${RMSO:=$(tput rmso)}
  128. #
  129. #               Set up for time stamping
  130. typeset -RZ2 _x1 _x2 _x3
  131. let SECONDS=$(date '+3600*%H+60*%M+%S')
  132. TIME='"${_d[(_x1=(SECONDS/3600)%24)==(_x2=(SECONDS/60)%60)==(_x3=SECONDS%60)]}$_x1:$_x2:$_x3"'
  133. #
  134. #               Define the replacement for the "cd" builtin
  135. function ch {
  136.         if cd ${*:-''}
  137.         then
  138.                 resetps1
  139.         else
  140.                 return 1
  141.         fi
  142. }
  143. alias cd=ch     # make it easy to use
  144.  
  145. function resetps1 {
  146.         typeset _dir=$PWD
  147.         typeset _dirt=${_dir#$HOME}     # directory tail
  148.         if [ "${_dirt}" != "${_dir}" ]
  149.         then
  150.                 _dir="~${_dirt}"
  151.         fi
  152.         typeset front=${_dir%/*/*/*}
  153.         : ${front:=x}
  154.         case ${pushlevel:-0} in
  155.         0)      PS1="${UNAME}: ${TIME} ${PSSHL:-}${SMSO:-}\${?#0}${RMSO:-}[${_dir#$front/}]
  156. !$SHDEPTH ";;
  157.         *)      PS1="${UNAME}: ${TIME} $pushlevel: ${PSSHL:-}${SMSO:-}\${?#0}${RMSO:-}[${_dir#$front/}]
  158. !$SHDEPTH ";;
  159.         esac
  160. }
  161. # Functions related to push and pop routines
  162. alias   dirs='echo "\t0: $PWD"' \
  163.         popd='echo "You have never pushed any levels.\nYou remain at $PWD."'
  164. #
  165. #               Check for uid 0 (root)
  166. id=$(id)
  167. id=${id#uid=}
  168. id=${id%%\(*}
  169. if [ id -eq 0 ]
  170. then
  171.         export SHDEPTH=${SHDEPTH:-}'#'
  172. else
  173.         export SHDEPTH=${SHDEPTH:-}'>'
  174. fi
  175. # Set special colors
  176. case $TERM in
  177. mskermc)
  178.         case $id in
  179.         0)      color=37 ;;
  180.         501)    color=31 ;;
  181.         *)      color=35 ;;
  182.         esac
  183.         SMSO="[41;33m" RMSO="[44;${color}m[1m"
  184.         unset color
  185.         ;;
  186. tm229|tm229g)
  187.         case $id in
  188.         0)      color=33 ;;
  189.         501)    color=37 ;;
  190.         *)      color=35 ;;
  191.         esac
  192.         SMSO="[41;33m" RMSO="[40;${color}m[1m"
  193.         unset color
  194.         ;;
  195. *)
  196.         ;;
  197. esac
  198. unset id
  199. resetps1
  200.  
  201. -------- This is ~/ksh/pshd, linked to ~/ksh/pshpwd and ~/ksh/poppwd  ---------
  202. unalias popd dirs
  203. integer pushlevel=0
  204.  
  205. function pshd
  206. {
  207.     dirsave[pushlevel]="$PWD"           # save the name of the current dir
  208.     promptsave[pushlevel]="$PS1"        # save the current prompt
  209.     if [ pushlevel = 0 ]
  210.     then
  211.         pushprompt="$PS1"
  212.     fi
  213.     ch ${1:-$HOME} 2> /dev/null
  214.     case $? in
  215.       0)                                # "cd" succeeded.
  216.         let pushlevel=pushlevel+1
  217.         pwd                             # show the current directory
  218.         : ${2:+`ls -Fx $3 $4 $5 $6 $7 $8 $9 >/dev/tty`}
  219.         resetps1
  220.         ;;
  221.       *)                                # "cd" failed
  222.         print "Can't change to $1, aborting"
  223.         return 1
  224.         ;;
  225.     esac
  226. }                                       # END of pshd
  227.  
  228. function popd
  229. {
  230.     integer levels=${1:-1}
  231.  
  232.     if (( pushlevel-levels>=0 ))
  233.       then
  234.         let pushlevel=pushlevel-levels
  235.       else
  236.         print "Can't pop that many levels. Your choices were:"
  237.         dirs
  238.         print "You are being returned to your original level"
  239.         let pushlevel=0
  240.     fi
  241.  
  242.     ch ${dirsave[$pushlevel]}
  243.     pwd                 # show the user where they are.
  244.     : ${2:+`ls -Fx $3 $4 $5 $6 $7 $8 $9 >/dev/tty`}
  245.     PS1="${promptsave[$pushlevel]}"
  246. }
  247.  
  248. function dirs
  249. {
  250.     integer level=$pushlevel
  251.     integer lowest=$level-${1:-$level}
  252.     if [ lowest -lt 0 ]
  253.         then
  254.             lowest=0
  255.     fi
  256.     print "     $level: $PWD"
  257.     while [ level -gt lowest ]
  258.     do
  259.         let level=level-1
  260.         print " $level: ${dirsave[$level]}"
  261.     done
  262.     unset level lowest
  263. }
  264.  
  265. function pshpwd
  266. {
  267. print $PWD  "${@:-}" >~/.current-pwd
  268. }
  269.  
  270. function poppwd
  271. {
  272. print $(<~/.current-pwd)
  273. }
  274.  
  275. ---- start of pshd family documentation ----
  276. # In brief, this routine is called in the form of:
  277. #       . ~/ksh/psh-pop.ksh name arg1 arg2 arg3 ...
  278. # and has to do the following:
  279. #               - Unalias all five related alias names.
  280. #               - Declare all five function bodies using those names.
  281. #               - Run the function that invoked this file, using the provided
  282. #                 arguments.
  283.  
  284. # The first time one of these aliases is used, it needs to be "loaded". From
  285. # then on, each one represents a loaded function, and runs smoothly. The
  286. # advantages are that your .env is about a hundred lines smaller, and these
  287. # functions are only defined when used.
  288.  
  289. # The first three routines are used to maintain and examine a directory stack
  290. # of traversals through the file system. They are:
  291. #       pshd [directory] [ls-indicator] [ls-arg] [ls-arg] [ls-arg]
  292. #       popd [levels]    [ls-indicator] [ls-arg] [ls-arg] [ls-arg]
  293. #       dirs [levels]
  294.  
  295. # These are different than other versions of pshd that have been posted to
  296. # the net. Both pshd and popd have an optional first argument that tells
  297. # which directory to go to, or how many levels to backtrack. If a second
  298. # argument is specified (any string will do) then an "ls -C" is done after
  299. # the action is completed. Any additional arguments are passed to ls. For
  300. # example, "pshd /usr/spool/uucp l -l -a -t" will change the directory to
  301. # /usr/spool/uucp and then do an "ls -C -l -a -t" to show full descriptions
  302. # of all files in that directory in the orer that they were last changed.
  303. # The "-C" argument is used to force our version of ls to columnate the
  304. # output (even if it is going into a pipeline).
  305.  
  306. # The next two routines are used to share information about the current
  307. # directory # between two windows on a DMD/BLIT or just to save the value
  308. # for later. Only one value is currently supported. They are:
  309. #       pshpwd [additional text]
  310. #       poppwd
  311. # Poppwd is often used in constructs like "cp *.c `poppwd`"
  312.  
  313. Ron Heiby mcdchg!heiby   Moderator: mod.newprod & mod.os.unix
  314.  
  315. Ron Heiby, heiby@chg.mcd.mot.com        Moderator: comp.newprod
  316. "Wrong is wrong, even when it helps you." Popeye
  317.