diff options
-rw-r--r-- | README.markdown | 2 | ||||
-rw-r--r-- | bash/bashrc.d/pd.bash | 53 | ||||
-rw-r--r-- | sh/shrc.d/pd.sh | 37 |
3 files changed, 38 insertions, 54 deletions
diff --git a/README.markdown b/README.markdown index b3f2396b..9bbf12d9 100644 --- a/README.markdown +++ b/README.markdown @@ -180,6 +180,7 @@ in `sh/shrc.d` to be loaded by any POSIX interactive shell. Those include: * `mkcd()` creates a directory and changes into it. * `mysql()` allows shortcuts to MySQL configuration files stored in `~/.mysql`. +* `pd()` changes to the argument's parent directory. * `pwgen()` generates just one decent password with `pwgen(1)`. * `rcsdiff()` forces a unified format for `rcsdiff(1)`. * `scp()` tries to detect forgotten hostnames in `scp(1)` command calls. @@ -206,7 +207,6 @@ There are a few other little tricks defined for other shells, mostly in It's dependent on information written by the `ls.sh` script in `~/.profile.d`. * `path()` manages the contents of `PATH` conveniently. -* `pd()` changes to the argument's parent directory. * `prompt()` sets up my interactive prompt. * `pushd()` adds a default destination of `$HOME` to the `pushd` builtin. * `readv()` prints names and values from `read` calls to `stderr`. diff --git a/bash/bashrc.d/pd.bash b/bash/bashrc.d/pd.bash deleted file mode 100644 index 47a317e0..00000000 --- a/bash/bashrc.d/pd.bash +++ /dev/null @@ -1,53 +0,0 @@ -# Attempt to change into the argument's parent directory; preserve any options -# and pass them to cd. This is intended for use when you've got a file path in -# a variable, or in history, or in Alt+., and want to quickly move to its -# containing directory. In the absence of an argument, this just shifts up a -# directory, i.e. `cd ..` -pd() { - - # 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 - - # Determine target directory - local target - case $# in - 0) - target=.. - ;; - 1) - target=$1 - target=${target%/} - target=${target%/*} - ;; - *) - printf 'bash: %s: too many arguments\n' \ - "$FUNCNAME" >&2 - return 2 - ;; - esac - - # If we have a target directory, try to change into it - if [[ -n $target ]] ; then - builtin cd "${opts[@]}" -- "$target" - else - printf 'bash: %s: error calculating parent directory\n' \ - "$FUNCNAME" >&2 - return 2 - fi -} diff --git a/sh/shrc.d/pd.sh b/sh/shrc.d/pd.sh new file mode 100644 index 00000000..c022b1e8 --- /dev/null +++ b/sh/shrc.d/pd.sh @@ -0,0 +1,37 @@ +# Attempt to change into the argument's parent directory; This is intended for +# use when you've got a file path in a variable, or in history, or in Alt+., +# and want to quickly move to its containing directory. In the absence of an +# argument, this just shifts up a directory, i.e. `cd ..` +pd() { + + # Change the positional parameters from the target to its containing + # directory + set -- "$( + + # Check argument count + if [ "$#" -gt 1 ] ; then + printf >&2 'pd(): Too many arguments\n' + exit 2 + fi + + # Figure out target dirname + dirname=${1:-..} + dirname=${dirname%/} + dirname=${dirname%/*} + + # Check we have a target after 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 printed nothing, return with failure + [ -n "$1" ] || return + + # Try to change into the determined directory + command cd -- "$@" +} |