diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2016-08-23 14:28:18 +1200 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2016-08-23 14:28:18 +1200 |
commit | 1e94aa430c0eefce9396e993272309788c6a21d0 (patch) | |
tree | 7445e71f88a44f2df461a66cd88cd5f5ee14b405 /sh/shrc.d/rd.sh | |
parent | Correct stderr redirection for keychain(1) check (diff) | |
download | dotfiles-1e94aa430c0eefce9396e993272309788c6a21d0.tar.gz dotfiles-1e94aa430c0eefce9396e993272309788c6a21d0.zip |
Fix up ?d() functions
Count arguments in right places; return 2 on usage errors where
possible; minimise subshell activity; move directory replacement
functionality to its own function `rd()` rather than overloading `cd`.
Diffstat (limited to 'sh/shrc.d/rd.sh')
-rw-r--r-- | sh/shrc.d/rd.sh | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/sh/shrc.d/rd.sh b/sh/shrc.d/rd.sh new file mode 100644 index 00000000..9fd99a55 --- /dev/null +++ b/sh/shrc.d/rd.sh @@ -0,0 +1,63 @@ +# +# Replace the first instance of the first argument string with the second +# argument string in $PWD, and make that the target of the cd builtin. This is +# to emulate a feature of the `cd` builtin in Zsh that I like, but that I think +# should be a separate command rather than overloading `cd`. +# +# $ pwd +# /usr/local/bin +# $ rd local +# $ pwd +# /usr/bin +# $ rd usr opt +# $ pwd +# /opt/bin +# +rd() { + + # Check argument count + case $# in + 1|2) ;; + *) + printf >&2 \ + 'rd(): Need a string and optionally a replacement\n' + return 2 + ;; + esac + + # Set the positional parameters to an option terminator and what will + # hopefully end up being the substituted directory name + set -- "$( + + # Current path: e.g. /foo/ayy/bar/ayy + cur=$PWD + # Pattern to replace: e.g. ayy + pat=$1 + # Text with which to replace pattern: e.g. lmao + # This can be a null string or unset, in order to *remove* the pattern + rep=$2 + + # /foo/ + curtc=${cur%%"$pat"*} + # /bar/ayy + curlc=${cur#*"$pat"} + # /foo/lmao/bar/ayy + new=${curtc}${rep}${curlc} + + # Check that a substitution resulted in an actual change and that we + # ended up with a non-null target, or print an error to stderr + if [ "$cur" = "$curtc" ] || [ -z "$new" ] ; then + printf >&2 'rd(): Substitution failed\n' + exit 1 + fi + + # Print the target + printf '%s\n' "$new" + )" + + # If the subshell printed nothing, return with failure + [ -n "$1" ] || return + + # Try to change into the determined directory + command cd -- "$@" +} |