by popular request, add

• dirs, pushd, popd like ports/shells/csh (Berkeley C shell)
• precmd, chpwd like ports/shells/zsh (Z shell)
and implement keeping ${DIRSTACK[0]} up to date via chpwd()
instead of doing it on entry of pushd and dirs (so that it
can be used directly)

this is slow compared to earlier, but people seem to want it
This commit is contained in:
tg 2007-09-24 20:30:04 +00:00
parent 491a420607
commit f632120cc2
1 changed files with 192 additions and 4 deletions

View File

@ -1,7 +1,36 @@
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.20 2007/09/24 20:30:04 tg Exp $
#-
# Copyright (c) 2007
# Thorsten Glaser <tg@mirbsd.de>
#
# Provided that these terms and disclaimer and all copyright notices
# are retained or reproduced in an accompanying document, permission
# is granted to deal in this work without restriction, including un-
# limited rights to use, publicly perform, distribute, sell, modify,
# merge, give away, or sublicence.
#
# Advertising materials mentioning features or use of this work must
# display the following acknowledgement:
# This product includes material provided by Thorsten Glaser.
#
# This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
# the utmost extent permitted by applicable law, neither express nor
# implied; without malicious intent or gross negligence. In no event
# may a licensor, author or contributor be held liable for indirect,
# direct, other damage, loss, or other issues arising in any way out
# of dealing in the work, even if advised of the possibility of such
# damage or existence of a defect, except proven that it results out
# of said person's immediate fault when using the work as intended.
#-
# sample mksh initialisation file for interactive shells
: ${EDITOR:=/bin/ed} ${TERM:=vt100} ${HOSTNAME:=$(ulimit -c 0;hostname -s 2>&-)}
[[ $HOSTNAME = @(localhost|*([ ])) ]] && HOSTNAME=$(ulimit -c 0;hostname 2>&-)
: ${HOSTNAME:=nil}; PS1='#'; [[ "$(ulimit -c 0; id -u 2>&-)" -eq 0 ]] || PS1='$'
PS1='$(((e = $?)) && print $e\|)${USER:=$(ulimit -c 0; id -un 2>&- || \
function precmd {
:
}
PS1='$(e=$?; precmd; ((e)) && print $e\|)${USER:=$(ulimit -c 0; id -un 2>&- || \
print nobody)}@${HOSTNAME%%.*}:$(typeset pfx=~ wd=${PWD:-?}
typeset -i n=${COLUMNS:-80}/3; let n="n < 7 ? 7 : n"
[[ ${wd#$pfx} = $wd || $pfx = ?(/) ]] || wd=\~${wd#$pfx}
@ -26,6 +55,167 @@ whence -p hd >&- || function hd {
-e '" |" "%_p"' -e '"|\n"' "$@"
}
# Berkeley C shell compatible dirs, popd, and pushd functions
# Z shell compatible chpwd() hook, used to update DIRSTACK[0]
set -A DIRSTACK
function chpwd {
typeset d thome
d=$(readlink -nf .)
thome=$(readlink -nf ~/.)
DIRSTACK[0]=$d
[[ ${d##$thome} = $d ]] || DIRSTACK[0]=\~${d##$thome}
:
}
chpwd .
function cd {
builtin cd "$@"
chpwd "$@"
}
function cd_csh {
typeset d t=$1
[[ $t = ~* ]] && t=$HOME${t#~}
if ! d=$(builtin cd "$t" 2>&1); then
print -u2 "${1}: ${d##*$t - }."
return 1
fi
cd "$t"
}
function dirs {
typeset d
typeset -i isnoglob=0 fl=0 fv=0 fn=0 cpos=0
[[ $(set +o) == *-o\ noglob* ]] && isnoglob=1
set -o noglob
while getopts ":lvn" d; do
case $d {
(l) fl=1 ;;
(v) fv=1 ;;
(n) fn=1 ;;
(*) print -u2 'Usage: dirs [-lvn].'
return 1 ;;
}
done
shift $((OPTIND - 1))
if (( $# > 0 )); then
print -u2 'Usage: dirs [-lvn].'
return 1
fi
if (( fv )); then
fv=0
while (( fv < ${#DIRSTACK[*]} )); do
d=${DIRSTACK[fv]}
if [[ $fl$d = 1~* ]]; then
d=$HOME${d#~}
fi
print -r -- "$fv $d"
let fv++
done
else
fv=0
while (( fv < ${#DIRSTACK[*]} )); do
d=${DIRSTACK[fv]}
if [[ $fl$d = 1~* ]]; then
d=$HOME${d#~}
fi
if (( fn && (cpos += ${#d} + 1) >= 79 && ${#d} < 80 )); then
print
(( cpos = ${#d} + 1 ))
fi
print -nr -- "$d "
let fv++
done
print
fi
(( isnoglob )) || set +o noglob
return 0
}
function popd {
typeset d fa=""
typeset -i isnoglob=0 n=1
[[ $(set +o) == *-o\ noglob* ]] && isnoglob=1
set -o noglob
while getopts ":0123456789lvn" d; do
case $d {
(l|v|n) fa="$fa -$d" ;;
(+*) n=2
break ;;
(*) print -u2 'Usage: popd [-lvn] [+<n>].'
return 1 ;;
}
done
shift $((OPTIND - n))
n=0
if (( $# > 1 )); then
print -u2 popd: Too many arguments.
return 1
elif [[ $1 = ++([0-9]) && $1 != +0 ]]; then
if (( (n = ${1#+}) >= ${#DIRSTACK[*]} )); then
print -u2 popd: Directory stack not that deep.
return 1
fi
elif [[ -n $1 ]]; then
print -u2 popd: Bad directory.
return 1
fi
if (( ${#DIRSTACK[*]} < 2 )); then
print -u2 popd: Directory stack empty.
return 1
fi
unset DIRSTACK[n]
set -A DIRSTACK -- "${DIRSTACK[@]}"
cd_csh "${DIRSTACK[0]}" || return 1
(( isnoglob )) || set +o noglob
dirs $fa
}
function pushd {
typeset d fa=""
typeset -i isnoglob=0 n=1
[[ $(set +o) == *-o\ noglob* ]] && isnoglob=1
set -o noglob
while getopts ":0123456789lvn" d; do
case $d {
(l|v|n) fa="$fa -$d" ;;
(+*) n=2
break ;;
(*) print -u2 'Usage: pushd [-lvn] [<dir>|+<n>].'
return 1 ;;
}
done
shift $((OPTIND - n))
if (( $# == 0 )); then
if (( ${#DIRSTACK[*]} < 2 )); then
print -u2 pushd: No other directory.
return 1
fi
d=${DIRSTACK[1]}
DIRSTACK[1]=${DIRSTACK[0]}
cd_csh "$d" || return 1
elif (( $# > 1 )); then
print -u2 pushd: Too many arguments.
return 1
elif [[ $1 = ++([0-9]) && $1 != +0 ]]; then
if (( (n = ${1#+}) >= ${#DIRSTACK[*]} )); then
print -u2 pushd: Directory stack not that deep.
return 1
fi
while (( n-- )); do
d=${DIRSTACK[0]}
unset DIRSTACK[0]
set -A DIRSTACK -- "${DIRSTACK[@]}" "$d"
done
cd_csh "${DIRSTACK[0]}" || return 1
else
set -A DIRSTACK -- placeholder "${DIRSTACK[@]}"
cd_csh "$1" || return 1
fi
(( isnoglob )) || set +o noglob
dirs $fa
}
# strip comments (and leading/trailing whitespace if IFS is set) from
# any file(s) given as argument, or stdin if none, and spew to stdout
function Lstripcom {
@ -35,6 +225,4 @@ function Lstripcom {
done; }
}
# place customisations between this line and the “: RCSID” line below
: $MirOS: src/bin/mksh/dot.mkshrc,v 1.19 2007/09/03 09:25:05 tg Rel $
: place customsations above this line!