aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2016-08-20 12:29:24 +1200
committerTom Ryder <tom@sanctum.geek.nz>2016-08-20 12:43:48 +1200
commit416fc33ff1e9e034cf2bb4a58bb177f46606afd5 (patch)
treee067bc1c8c7af4bb7267b0b691b8b1a7fe832bb7
parentRemove option term spec from bd() (diff)
downloaddotfiles-416fc33ff1e9e034cf2bb4a58bb177f46606afd5.tar.gz
dotfiles-416fc33ff1e9e034cf2bb4a58bb177f46606afd5.zip
Port ud() to POSIX sh
-rw-r--r--README.markdown2
-rw-r--r--bash/bashrc.d/ud.bash50
-rw-r--r--sh/shrc.d/ud.sh42
3 files changed, 43 insertions, 51 deletions
diff --git a/README.markdown b/README.markdown
index 3bf1e604..6e6f2bbb 100644
--- a/README.markdown
+++ b/README.markdown
@@ -187,6 +187,7 @@ in `sh/shrc.d` to be loaded by any POSIX interactive shell. Those include:
preserved; I hate ending up `root`-owned files in my home directory.
* `tmux()` changes the default command for `tmux(1)` to `attach-session -d`
if a session exists, or creates a new session if one doesn't.
+* `ud()` changes into an indexed ancestor of a directory.
* `vim()` defines three functions to always use `vim(1)` as my `ex(1)`,
`vi(1)` and `view(1)` implementation if it's available.
@@ -211,7 +212,6 @@ There are a few other little tricks defined for other shells, mostly in
* `readv()` prints names and values from `read` calls to `stderr`.
* `readz()` is an alias for `read -d '' -r`.
* `sd()` changes into a sibling of the current directory.
-* `ud()` changes into an indexed ancestor of a directory.
* `vared()` allows interactively editing a variable with Readline, emulating
a Zsh function I like by the same name.
* `vr()` tries to change to the root directory of a source control
diff --git a/bash/bashrc.d/ud.bash b/bash/bashrc.d/ud.bash
deleted file mode 100644
index e23de1fa..00000000
--- a/bash/bashrc.d/ud.bash
+++ /dev/null
@@ -1,50 +0,0 @@
-# Shortcut to step up the directory tree with an arbitrary number of steps,
-# like cd .., cd ../.., etc
-ud() {
-
- # For completeness' sake, we'll pass any options to cd
- local arg
- local -a opts
- for arg ; do
- case $arg in
- --)
- shift
- break
- ;;
- -*)
- shift
- opts[${#opts[@]}]=$arg
- ;;
- *)
- break
- ;;
- esac
- done
-
- # Check and save optional first argument, number of steps upward; default
- # to 1 if absent
- local -i steps
- steps=${1:-1}
- if ! ((steps > 0)) ; then
- printf 'bash: %s: Invalid step count %s\n' "$FUNCNAME" "$1" >&2
- return 2
- fi
-
- # Check and save optional second argument, target directory; default to
- # $PWD (typical usage case)
- local dirname
- dirname=${2:-"$PWD"}
- if [[ ! -e $dirname ]] ; then
- printf 'bash: %s: Target directory %s does not exist\n' "$FUNCNAME" "$2" >&2
- return 1
- fi
-
- # Append /.. to the target the specified number of times
- local -i i
- for (( i = 0 ; i < steps ; i++ )) ; do
- dirname=${dirname%/}/..
- done
-
- # Try to change into it
- cd "${opts[@]}" -- "$dirname"
-}
diff --git a/sh/shrc.d/ud.sh b/sh/shrc.d/ud.sh
new file mode 100644
index 00000000..0dfd858c
--- /dev/null
+++ b/sh/shrc.d/ud.sh
@@ -0,0 +1,42 @@
+# Shortcut to step up the directory tree with an arbitrary number of steps,
+# like cd .., cd ../.., etc
+ud() {
+
+ # Change the positional parameters from the number of steps given to a
+ # "../../.." string
+ set -- "$(
+
+ # Check first argument, number of steps upward, default to 1
+ # "0" is weird, but valid; "-1" however makes no sense at all
+ steps=${1:-1}
+ if [ "$steps" -lt 0 ] ; then
+ printf >&2 'ud(): Invalid step count\n'
+ exit 2
+ fi
+
+ # Check second argument, target directory, default to $PWD
+ dirname=${2:-"$PWD"}
+
+ # Append /.. to the target the specified number of times
+ i=0
+ while [ "$i" -lt "$steps" ] ; do
+ dirname=${dirname%/}/..
+ i=$((i+1))
+ done
+
+ # Check we have a target after all that
+ if [ -z "$dirname" ] ; then
+ printf >&2 'ud(): Destination construction failed\n'
+ exit 1
+ fi
+
+ # Print the target
+ printf '%s\n' "$dirname"
+
+ # If the subshell failed, return from the function with the same exit
+ # value
+ )" || return
+
+ # Try to change into the determined directory
+ command cd -- "$@"
+}