aboutsummaryrefslogtreecommitdiff
path: root/sh
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2017-05-27 22:52:40 +1200
committerTom Ryder <tom@sanctum.geek.nz>2017-05-27 22:52:40 +1200
commitcbbec36d4403dbed6d61232e86b5d4995c8da1fe (patch)
tree9d72ab0bc7b93adb29559624975d519606621f87 /sh
parent1302b279bf2b1b2ae76ea8251a32e480d64f2f7a (diff)
downloaddotfiles-cbbec36d4403dbed6d61232e86b5d4995c8da1fe.tar.gz
More error-resistant sd()
Diffstat (limited to 'sh')
-rw-r--r--sh/shrc.d/hgrep.sh6
-rw-r--r--sh/shrc.d/pmd.sh2
-rw-r--r--sh/shrc.d/sd.sh86
3 files changed, 62 insertions, 32 deletions
diff --git a/sh/shrc.d/hgrep.sh b/sh/shrc.d/hgrep.sh
index 1c4c3ec5..fe297ab3 100644
--- a/sh/shrc.d/hgrep.sh
+++ b/sh/shrc.d/hgrep.sh
@@ -6,11 +6,11 @@
hgrep() {
if [ "$#" -eq 0 ] ; then
printf >&2 'hgrep(): Need a pattern\n'
- exit 2
+ return 2
fi
- if ! [ -n "$HISTFILE" ] ; then
+ if [ -z "$HISTFILE" ] ; then
printf >&2 'hgrep(): No HISTFILE\n'
- exit 2
+ return 2
fi
grep "$@" "$HISTFILE"
}
diff --git a/sh/shrc.d/pmd.sh b/sh/shrc.d/pmd.sh
index c96a50bd..4b0cd5bd 100644
--- a/sh/shrc.d/pmd.sh
+++ b/sh/shrc.d/pmd.sh
@@ -1,6 +1,6 @@
# Print the marked directory
pmd() {
- if ! [ -n "$PMD" ] ; then
+ if [ -z "$PMD" ] ; then
printf >&2 'pmd(): Mark not set\n'
return 1
fi
diff --git a/sh/shrc.d/sd.sh b/sh/shrc.d/sd.sh
index af82b67e..8b12c170 100644
--- a/sh/shrc.d/sd.sh
+++ b/sh/shrc.d/sd.sh
@@ -41,45 +41,75 @@ sd() {
# Read sole optional argument
case $1 in
- # If blank, get a full list of directories at this level; include
- # dotfiles, but not the . and .. entries, using glob tricks to avoid
- # Bash ruining things with `dotglob`
+ # Slashes aren't allowed
+ */*)
+ printf >&2 'bd(): Illegal slash\n'
+ return 2
+ ;;
+
+ # If blank, we try to find if there's just one sibling, and change to
+ # that if so
'')
+ # First a special case: root dir
+ case $PWD in
+ *[!/]*) ;;
+ *)
+ printf >&2 'sd(): No siblings\n'
+ return 1
+ ;;
+ esac
+
+ # Get a full list of directories at this level; include dotfiles,
+ # but not the . and .. entries, using glob tricks to avoid Bash
+ # ruining things with `dotglob`
set -- ../[!.]*/
[ -e "$1" ] || shift
set -- ../.[!.]*/ "$@"
[ -e "$1" ] || shift
set -- ../..?*/ "$@"
[ -e "$1" ] || shift
- ;;
- # If not, get that directory, and the current one; shift it off if it
- # doesn't exist
- *)
- set -- ../"${1%/}"/ ../"${PWD##*/}"/
- [ -e "$1" ] || shift
- ;;
- esac
+ # Check the number of matches
+ case $# in
- # We should now have two parameters: the current directory and the matched
- # sibling
- case $# in
- 2) ;;
- 0|1)
- printf >&2 'sd(): No match\n'
- return 1
- ;;
- *)
- printf >&2 'sd(): Multiple matches\n'
- return 1
+ # One match? Must be $PWD, so no siblings--throw in 0 just in
+ # case, but that Shouldn't Happen (TM)
+ 0|1)
+ printf >&2 'sd(): No siblings\n'
+ return 1
+ ;;
+
+ # Two matches; hopefully just one sibling, but which is it?
+ 2)
+
+ # Push PWD onto the stack, strip trailing slashes
+ set -- "$1" "$2" "$PWD"
+ while : ; do
+ case $3 in
+ */) set -- "$1" "$2" "${3%/}" ;;
+ *) break ;;
+ esac
+ done
+
+ # Pick whichever of our two parameters doesn't look like
+ # PWD as our sole parameter
+ case $1 in
+ ../"${3##*/}"/) set -- "$2" ;;
+ *) set -- "$1" ;;
+ esac
+ ;;
+
+ # Anything else? Multiple siblings--user will need to specify
+ *)
+ printf >&2 'sd(): Multiple siblings\n'
+ return 1
+ ;;
+ esac
;;
- esac
- # Find which of these two is not the current directory and set that as our
- # sole parameter
- case $1 in
- ../"${PWD##*/}"/) set -- "$2" ;;
- *) set -- "$1" ;;
+ # If not, simply set our target to that directory, and let `cd` do the
+ # complaining if it doesn't exist
+ *) set -- ../"$1" ;;
esac
# Try and change into the first parameter