mksh/dot.mkshrc
tg 2cfc3e5c3d mksh R40 Release Candidate 1
Testsuite:
• add new need-pass: {yes|no} attribute, default yes
• exit with 1 if a need-pass test failed unexpectedly
  idea by Kacper Kornet <draenog@pld-linux.org>
• mark utf8bom-2 as need-pass: no
Infrstructure:
• add housekeeping function for making a tty raw
• switch functions with unused results to void
• struct op: u.charflag contains last char of ;; in TPAT
• var.c:arraysearch is now a global function
Language:
• add ;& (fall through) and ;| (examine next) delimiters
  in addition to ;; (end case) as zsh extensions, because
  POSIX standardised on ;& already
• add -A (read into array), -N (read exactly n bytes),
  -n (read up to n bytes), -t (timeout) flags for read
  from ksh93
• allow read -N -1 or -n -1 to slurp the entire input
• add -a (read into array the input characters) extension
  specific to mksh to read, idea by David Korn
• add -e (exit with error if PWD was not set correctly
  after a physical cd) to cd builtin, mandated by next
  POSIX, and change error codes accordingly
Rewrites:
• full rewrite of read builtin and its manpage section
• add regression tetss for most of the new functionality
• duplicate hexdump demo tests for use of read -a
• use read -raN-1 in dot.mkshrc to get NUL safe base64,
  DJB cdb hash and Jenkins one-at-a-time hash functions
2011-05-29 02:18:57 +00:00

389 lines
9.3 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# $Id$
# $MirOS: src/bin/mksh/dot.mkshrc,v 1.60 2011/05/29 02:18:49 tg Exp $
#-
# Copyright (c) 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011
# Thorsten Glaser <tg@mirbsd.org>
#
# 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.
#
# 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.
#-
# ${ENV:-~/.mkshrc}: 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}; if (( USER_ID )); then PS1='$'; else PS1='#'; fi
function precmd {
typeset e=$?
(( e )) && print -n "$e|"
}
PS1='
$(precmd)${USER:=$(ulimit -c 0;id -un 2>&-||print \?)}@${HOSTNAME%%.*}:$(
typeset d=${PWD:-?} n p=~; [[ $p = ?(*/) ]] || d=${d/#$p/~}
(( (${%d}>0 ? ${%d}: ${#d}) > (n = (COLUMNS/3<7 ? 7: COLUMNS/3)) )) && {
d=${d:(-n)}; p=...; } || p=; print -nr -- "$p$d") '"$PS1 "
: ${MKSH:=$(whence -p mksh)}; export EDITOR HOSTNAME MKSH TERM USER
alias ls=ls
unalias ls
alias l='ls -F'
alias la='l -a'
alias ll='l -l'
alias lo='l -alo'
whence -p rot13 >&- || alias rot13='tr \
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \
nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
whence -p hd >&- || function hd {
hexdump -e '"%08.8_ax " 8/1 "%02X " " - " 8/1 "%02X "' \
-e '" |" "%_p"' -e '"|\n"' "$@"
}
# Berkeley C shell compatible dirs, popd, and pushd functions
# Z shell compatible chpwd() hook, used to update DIRSTACK[0]
DIRSTACKBASE=$(realpath ~/. 2>&- || print -nr -- "$HOME")
set -A DIRSTACK
function chpwd {
DIRSTACK[0]=$(realpath . 2>&- || print -r -- "$PWD")
[[ $DIRSTACKBASE = ?(*/) ]] || \
DIRSTACK[0]=${DIRSTACK[0]/#$DIRSTACKBASE/~}
:
}
chpwd .
function cd {
builtin cd "$@"
chpwd "$@"
}
function cd_csh {
typeset d t=${1/#~/$DIRSTACKBASE}
if ! d=$(builtin cd "$t" 2>&1); then
print -u2 "${1}: ${d##*$t - }."
return 1
fi
cd "$t"
}
function dirs {
typeset d dwidth
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]}
(( fl )) && d=${d/#~/$DIRSTACKBASE}
print -r -- "$fv $d"
let fv++
done
else
fv=0
while (( fv < ${#DIRSTACK[*]} )); do
d=${DIRSTACK[fv]}
(( fl )) && d=${d/#~/$DIRSTACKBASE}
(( dwidth = (${%d} > 0 ? ${%d} : ${#d}) ))
if (( fn && (cpos += dwidth + 1) >= 79 && \
dwidth < 80 )); then
print
(( cpos = dwidth + 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
}
# pager (not control character safe)
function smores {
typeset dummy line llen curlin=0
cat "$@" | while IFS= read -r line; do
llen=${%line}
(( llen == -1 )) && llen=${#line}
(( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
if (( (curlin += llen) >= LINES )); then
print -n -- '\033[7m--more--\033[0m'
read -u1 dummy
[[ $dummy = [Qq]* ]] && return 0
curlin=$llen
fi
print -r -- "$line"
done
}
# base64 encoder and decoder, RFC compliant, NUL safe
function Lb64decode {
[[ -o utf8-mode ]]; typeset u=$?
set +U
typeset c s="$*" t=
[[ -n $s ]] || { s=$(cat;print x); s=${s%x}; }
typeset -i i=0 n=${#s} p=0 v x
typeset -i16 o
while (( i < n )); do
c=${s:(i++):1}
case $c {
(=) break ;;
([A-Z]) (( v = 1#$c - 65 )) ;;
([a-z]) (( v = 1#$c - 71 )) ;;
([0-9]) (( v = 1#$c + 4 )) ;;
(+) v=62 ;;
(/) v=63 ;;
(*) continue ;;
}
(( x = (x << 6) | v ))
case $((p++)) {
(0) continue ;;
(1) (( o = (x >> 4) & 255 )) ;;
(2) (( o = (x >> 2) & 255 )) ;;
(3) (( o = x & 255 ))
p=0
;;
}
t=$t\\x${o#16#}
done
print -n $t
(( u )) || set -U
}
set -A Lb64encode_code -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
function Lb64encode {
[[ -o utf8-mode ]]; typeset u=$?
set +U
typeset c s t
if (( $# )); then
read -raN-1 s <<<"$*"
unset s[${#s[*]}-1]
else
read -raN-1 s
fi
typeset -i i=0 n=${#s[*]} j v
while (( i < n )); do
(( v = s[i++] << 16 ))
(( j = i < n ? s[i++] : 0 ))
(( v |= j << 8 ))
(( j = i < n ? s[i++] : 0 ))
(( v |= j ))
t=$t${Lb64encode_code[v >> 18]}${Lb64encode_code[v >> 12 & 63]}
c=${Lb64encode_code[v >> 6 & 63]}
if (( i <= n )); then
t=$t$c${Lb64encode_code[v & 63]}
elif (( i == n + 1 )); then
t=$t$c=
else
t=$t==
fi
if (( ${#t} == 76 || i >= n )); then
print $t
t=
fi
done
(( u )) || set -U
}
# DJB cdb hash (not via stdio, for speed)
typeset -Z11 -Uui16 Lcdbhash_result
function Lcdbhash_add {
[[ -o utf8-mode ]]; typeset u=$?
set +U
typeset s
if (( $# )); then
read -raN-1 s <<<"$*"
unset s[${#s[*]}-1]
else
read -raN-1 s
fi
typeset -i i=0 n=${#s[*]}
while (( i < n )); do
((# Lcdbhash_result = (Lcdbhash_result * 33) ^ s[i++] ))
done
(( u )) || set -U
}
function Lcdbhash {
Lcdbhash_result=5381
Lcdbhash_add "$@"
print ${Lcdbhash_result#16#}
}
# Jenkins one-at-a-time hash (not via stdio, for speed)
typeset -Z11 -Uui16 Loaathash_result
function Loaathash_add {
[[ -o utf8-mode ]]; typeset u=$?
set +U
typeset s
if (( $# )); then
read -raN-1 s <<<"$*"
unset s[${#s[*]}-1]
else
read -raN-1 s
fi
typeset -i i=0 n=${#s[*]}
while (( i < n )); do
((# Loaathash_result = (Loaathash_result + s[i++]) *
1025 ))
((# Loaathash_result ^= Loaathash_result >> 6 ))
done
(( u )) || set -U
}
function Loaathash_do {
Loaathash_add "$@"
((# Loaathash_result += Loaathash_result << 3 ))
((# Loaathash_result = (Loaathash_result ^
(Loaathash_result >> 11)) * 32769 ))
print ${Loaathash_result#16#}
}
function Loaathash {
Loaathash_result=0
Loaathash_do "$@"
}
function Loaathash1 {
Loaathash_result=0x100
Loaathash_do "$@"
}
# 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 {
cat "$@" | { set -o noglob; while read _line; do
_line=${_line%%#*}
[[ -n $_line ]] && print -r -- $_line
done; }
}
: place customisations below this line
for p in ~/.etc/bin ~/bin; do
[[ -d $p/. ]] || continue
[[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
done
export SHELL=$MKSH MANWIDTH=80 LESSHISTFILE=-
alias cls='print -n \\033c'
#unset LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_IDENTIFICATION LC_MONETARY \
# LC_NAME LC_NUMERIC LC_TELEPHONE LC_TIME
#p=en_GB.UTF-8
#set -U
#export LANG=C LC_CTYPE=$p LC_MEASUREMENT=$p LC_MESSAGES=$p LC_PAPER=$p
unset p
: place customisations above this line