aboutsummaryrefslogtreecommitdiff
path: root/sh
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2017-05-26 00:39:02 +1200
committerTom Ryder <tom@sanctum.geek.nz>2017-05-26 00:39:02 +1200
commit9ed69d70d9201817c7f36c7f210ce163e84eb54b (patch)
treead2a9838bdb36e5492858d19d2d056534f109a3d /sh
parente199448d724746af892a67608c88fb2ddc075c72 (diff)
downloaddotfiles-9ed69d70d9201817c7f36c7f210ce163e84eb54b.tar.gz
Reimplement sd() without subshell
Diffstat (limited to 'sh')
-rw-r--r--sh/shrc.d/bd.sh6
-rw-r--r--sh/shrc.d/sd.sh80
2 files changed, 44 insertions, 42 deletions
diff --git a/sh/shrc.d/bd.sh b/sh/shrc.d/bd.sh
index 5b2c3d59..2dc21173 100644
--- a/sh/shrc.d/bd.sh
+++ b/sh/shrc.d/bd.sh
@@ -7,8 +7,8 @@ bd() {
return 2
fi
- # Look at argument given
- case $1 in
+ # Look at argument given; default to going up one level
+ case ${1:-..} in
# If it has a leading slash or is . or .., don't touch the arguments
/*|.|..) ;;
@@ -18,7 +18,7 @@ bd() {
*)
# Push the current directory onto the stack
- set -- "$1" "$PWD"
+ set -- "${1%/}" "$PWD"
# Keep chopping at the current directory until it's empty or it
# matches the request
diff --git a/sh/shrc.d/sd.sh b/sh/shrc.d/sd.sh
index 4d63b7d6..561a77f4 100644
--- a/sh/shrc.d/sd.sh
+++ b/sh/shrc.d/sd.sh
@@ -40,48 +40,50 @@ sd() {
return 2
fi
- # Change positional parameters to what will hopefully be a completed
- # substitution
- set -- "$(
+ # Read sole optional argument
+ case $1 in
- # Set the positional parameters to either the requested directory, or
- # all siblings of the current directory if no request
- spec=$1
- set --
- if [ -n "$spec" ] ; then
- set -- "$@" ../"$spec"
- else
- for sib in ../.* ../* ; do
- case ${sib#../} in
- (.|..|"${PWD##*/}") continue ;;
- esac
- set -- "$@" "$sib"
- done
- fi
+ # 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`
+ '')
+ set -- ../[!.]*/
+ [ -e "$1" ] || shift
+ set -- ../.[!.]*/ "$@"
+ [ -e "$1" ] || shift
+ set -- ../..?*/ "$@"
+ [ -e "$1" ] || shift
+ ;;
- # We should have exactly one sibling
- case $# in
- (1) ;;
- (0)
- printf >&2 'sd(): No siblings\n'
- exit 1
- ;;
- (*)
- printf >&2 'sd(): More than one sibling\n'
- exit 1
- ;;
- esac
+ # If not, get that directory, and the current one; shift it off if it
+ # doesn't exist
+ *)
+ set -- ../"${1%/}"/ ../"${PWD##*/}"/
+ [ -e "$1" ] || shift
+ ;;
+ esac
- # Print the target with trailing slash to work around newline stripping
- printf '%s/' "${1%/}"
- )"
+ # 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
+ ;;
+ esac
- # Remove trailing slash
- set -- "${1%/}"
+ # 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" ;;
+ esac
- # If the subshell printed nothing, return with failure
- [ -n "$1" ] || return
-
- # Try to change into the determined directory
- command cd -- "$@"
+ # Try and change into the first parameter
+ command cd -- "$1"
}