[comp.lang.perl] ksh & perl approach to pruning long pwd prompts

root@ttsi.lonestar.org (System) (04/25/91)

A recent spate of articles (in comp.unix.shell) about pwd style 
prompting and how to prune long paths piqued my interest.  I got 
to playing around and came up with a ksh / perl solution to pruning 
long paths.

This produces ~ notation for home directory.  So I get

    ~>
    ~/sub/dir>

instead of

    //blast/user/mse>
    //blast/user/mse/sub/dir>
    
(where blast is my node name).  Paths not rooted from the home directory
convert to something like:

    blast:/usr/local/src>

A really long path is shortened by successively pruning leading path 
components until the length is less than a user-specified size.
Pruned components are replaced with "..." as in

    blast:.../src/epoch-3.2>

The perl script 'prunepwd' below manages the pruning.  I don't claim
this to be particularly efficient but on an Apollo 400, it takes about
a second of real time which is fast enough for me.  Note my comments
in the definition of ksh function _cd below.  I ran into inexplicable
runaway recursion (intermittently!) using the unalias approach.
Fortunately there is a published way to unalias by adding escaping
the alias with \.

Any suggestions for how to do this in ksh are welcome.  Likewise for
improved perl code.
---
Mark S. Evans                 Tandem Telecommunications Systems Inc.
Phone: 214-516-6201           850 E. Central Parkway
Fax:   214-516-6801           Plano, TX 75074
Mail:  mse@ttsi.lonestar.org



.kshrc definitions:

PWDSZ=25     # maximum prompt length
export PS1="`//blast/usr/local/bin/prunepwd $PWDSZ`\> "
alias cd=_cd
function _pwd {
	PS1="`//blast/usr/local/bin/prunepwd $PWDSZ`\> "
}
function _cd {
	# Ran into apparent Apollo (SR10.3) ksh bug here - unaliasing cd
	# would intermittently fail to prevent recursion.  Using
	# backslash in the alias name revokes the alias.
	# unalias cd     # don't do this on Apollo
	\cd $*           # backslash prevents recursion on Apollo SR10.3
	# alias cd=_cd   # don't do this on Apollo
	PS1="`//blast/usr/local/bin/prunepwd $PWDSZ`\> "
}


The perl script follows.  Perl is available via anonymous ftp from
any site that archives gnu stuff.  If you haven't tried it, you're
missing out on a great tool.

------------------------ snip from here to top --------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  prunepwd
# Wrapped by root@blast on Thu Apr 25 07:05:20 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'prunepwd' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'prunepwd'\"
else
echo shar: Extracting \"'prunepwd'\" \(2128 characters\)
sed "s/^X//" >'prunepwd' <<'END_OF_FILE'
X#!/usr/bin/perl
X##
X## prunepwd.pl - Prune a `pwd` string 
X## 
X## prunepwd prunes the current working directory path to a size that
X## is reasonable for a prompt.  The size limit is specified by
X## optional command line argument.  The default is 25.
X## 
X## If the path is a descendent of the home directory path, the leading
X## home directory path is replaced with ``~''.  Otherwise, a leading
X## //node_name (ala Apollo) is replaced with ``node_name:''.
X## Directories are trimmed from the beginning of the path (following
X## the node name) until the path length (including node name) is less
X## than the limit.  The last directory in the path is never pruned,
X## even if its length exceeds the limit.  The set of pruned
X## directories is replaced by ``...''.
X## 
X## Examples:
X## 
X## //blast/usr/abc/def/ghi/jkl/mno/pqr/stu/vwx      (before)
X## blast:/.../pqr/stu/vwx                           (after)
X## 
X## //blast/user/mse/learn/perl/chapter1             (before)
X## ~/learn/perl/chapter1                            (after)
X##
X$pwdsz = shift || 25;		# limit for pwd string
chop($cwd=`pwd`);
X$home=$ENV{'HOME'};
if ($cwd eq "//"){
X    print $cwd;
X    exit ();
X}
if (index ($cwd, $home) == 0) {
X    $node = "";
X    $cwd = "~" . substr ($cwd, length ($home));
X} else {
X    if ($cwd =~ m|^//|) {
X	## Apollo style path (//node/path/...)
X        ($node, $cwd) = ($cwd =~ m|//([^/]*)(.*)|o);
X	$node .= ":";
X    } else {
X        ## Unix style path (/path/...)
X        $node = "";
X    }
X}
X$len = length ($node) + length ($cwd);
if ($len > $pwdsz) {
X    @path = split (/\//, $cwd);
X    ##
X    ## always leave the final component of the path even if its
X    ## length is greater than the limit.
X    ##
X    if ($#path > 1) {
X        ##
X        ## Find number of leading components in path to skip
X        ##
X        for ($skip = 0; $len > $pwdsz && $skip < ($#path); $skip++) {
X	    $len -= (length ($path[$skip]) + 1);
X	    if ($skip == 0) {
X	        $len += 3;	# length of "..."
X	    }
X	}
X        $path[$skip-1] = "...";
X	if ($skip > 1) {
X	    splice (@path, 0, $skip-1 );
X	}
X    }
X    $cwd =  join ("/", @path);
X}
print $node, $cwd;
X
END_OF_FILE
if test 2128 -ne `wc -c <'prunepwd'`; then
    echo shar: \"'prunepwd'\" unpacked with wrong size!
fi
chmod +x 'prunepwd'
# end of 'prunepwd'
fi
echo shar: End of shell archive.
exit 0
-- 
Mark S. Evans                 Tandem Telecommunications Systems Inc.
Phone: 214-516-6201           850 E. Central Parkway
Fax:   214-516-6801           Plano, TX 75074
Mail:  mse@ttsi.lonestar.org

dave@aspect.UUCP (Dave Corcoran) (05/09/91)

In article <1991Apr25.122017.3868@ttsi.lonestar.org>, root@ttsi.lonestar.org (System) writes:
> A recent spate of articles (in comp.unix.shell) about pwd style 

Which I missed so forgive me if this has been proposed.

> A really long path is shortened by successively pruning leading path 
> components until the length is less than a user-specified size.
> Pruned components are replaced with "..." as in

> Any suggestions for how to do this in ksh are welcome.  Likewise for
> improved perl code.

Although this will not limit of the prompt to a specified size it is terse.

PS1='${PWD#$HOME/}'

You could substitute $DIR for $HOME and then set DIR to the
leading path you want trimmed.
-- 
David Corcoran		      -@@
uunet!aspect!dave	        ~
Having the right to do something is not the same as being right in doing it.
					--  C.K. Chesterson