aboutsummaryrefslogtreecommitdiff
path: root/sh
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2016-08-19 12:48:35 +1200
committerTom Ryder <tom@sanctum.geek.nz>2016-08-19 12:48:35 +1200
commit3d8cf05dfc685e799aa5e20319e8e33288e74e04 (patch)
tree28668e9ba83860c7a30cea5a2c5b80533121ae39 /sh
parentFlag issue fixed (diff)
downloaddotfiles-3d8cf05dfc685e799aa5e20319e8e33288e74e04.tar.gz
dotfiles-3d8cf05dfc685e799aa5e20319e8e33288e74e04.zip
Change cd() into POSIX shell script
Diffstat (limited to 'sh')
-rw-r--r--sh/shrc.d/cd.sh72
1 files changed, 72 insertions, 0 deletions
diff --git a/sh/shrc.d/cd.sh b/sh/shrc.d/cd.sh
new file mode 100644
index 00000000..dd98a422
--- /dev/null
+++ b/sh/shrc.d/cd.sh
@@ -0,0 +1,72 @@
+# If given two arguments, replace the first instance of the first argument with
+# the second argument in $PWD, and make that the target of cd(). This POSIX
+# version cannot handle options, but it can handle an option terminator (--),
+# so e.g. `cd -- -foo -bar` should work.
+cd() {
+
+ # First check to see if we can perform the substitution at all
+ if (
+
+ # If we have any options, we can't do it, because POSIX shell doesn't
+ # let us (cleanly) save the list of options for use later in the script
+ for arg ; do
+ case $arg in
+ --) break ;;
+ -*) return 1 ;;
+ esac
+ done
+
+ # Shift off -- if it's the first argument
+ [ "$1" = -- ] && shift
+
+ # Check we have two non-null arguments
+ [ "$#" -eq 2 ] || return
+ [ -n "$1" ] || return
+ [ -n "$2" ] || return
+
+ ) ; then
+
+ # Set the positional parameters to an option terminator and what will
+ # hopefully end up being the substituted directory name
+ set -- -- "$(
+
+ # If the first of the existing positional arguments is --, shift it
+ # off
+ [ "$1" = -- ] && shift
+
+ # 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
+ rep=$2
+
+ # /foo/
+ curtc=${cur%%"$pat"*}
+ # /bar/ayy
+ curlc=${cur#*"$pat"}
+ # /foo/lmao/bar/ayy
+ new=${curtc}${rep}${curlc}
+
+ # Check pattern was actually in $PWD; this indirectly checks that
+ # $PWD and $pat are both actually set, too; it's valid for $rep to
+ # be empty, though
+ [ "$cur" != "$curtc" ] || exit
+
+ # Check we ended up with something to change into
+ [ -n "$new" ] || exit
+
+ # Print the replaced result
+ printf '%s\n' "$new"
+ )"
+
+ # Check we have a second argument
+ if [ -z "$2" ] ; then
+ printf >&2 'cd(): Substitution failed\n'
+ return 1
+ fi
+ fi
+
+ # Execute the cd command as normal
+ command cd "$@"
+}