From 8547a2e1ea9135381e1538401ef4da60fb379d99 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Tue, 23 May 2017 21:53:10 +1200 Subject: Remove mysql() function Clumsy interaction too close to default behaviour anyway --- sh/shrc.d/mysql.sh | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 sh/shrc.d/mysql.sh (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/mysql.sh b/sh/shrc.d/mysql.sh deleted file mode 100644 index abb496d2..00000000 --- a/sh/shrc.d/mysql.sh +++ /dev/null @@ -1,25 +0,0 @@ -# If a file ~/.mysql/$1.cnf exists, call mysql(1) using that file, discarding -# the rest of the arguments. Otherwise just run MySQL with given args. Use -# restrictive permissions on these files. Doesn't allow filenames beginning -# with hyphens. -# -# Examples: -# -# [client] -# host=dbhost.example.com -# user=foo -# password=SsJ2pICe226jM -# -# [mysql] -# database=bar -# -mysql() { - case $1 in - -*) ;; - *) - [ -f "$HOME/.mysql/$1".cnf ] && - set -- --defaults-extra-file="$HOME/.mysql/$1".cnf - ;; - esac - command mysql "$@" -} -- cgit v1.2.3 From 4b780b8415db74508729991e5a2014bc7a54ff17 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Wed, 24 May 2017 22:06:49 +1200 Subject: Correct gt() error output --- sh/shrc.d/gt.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/gt.sh b/sh/shrc.d/gt.sh index d18a4ab8..c90af073 100644 --- a/sh/shrc.d/gt.sh +++ b/sh/shrc.d/gt.sh @@ -4,7 +4,7 @@ gt() { # Check argument count if [ "$#" -gt 1 ] ; then - printf >&2 'gd(): Too many arguments\n' + printf >&2 'gt(): Too many arguments\n' return 2 fi -- cgit v1.2.3 From b4b144c3f8aa98a26b9a59c204ec0d5b4619ef72 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 25 May 2017 18:21:23 +1200 Subject: Shorter/saner implementation for bd() Avoids subshell mess and consequent trailing-space workaround --- sh/shrc.d/bd.sh | 85 ++++++++++++++++++++------------------------------------- 1 file changed, 29 insertions(+), 56 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/bd.sh b/sh/shrc.d/bd.sh index bf64a9aa..02da6773 100644 --- a/sh/shrc.d/bd.sh +++ b/sh/shrc.d/bd.sh @@ -3,68 +3,41 @@ bd() { # Check argument count if [ "$#" -gt 1 ] ; then - printf >&2 'bd(): Too many arguments' + printf >&2 'bd(): Too many arguments\n' return 2 fi - # Set positional parameters to an option terminator and what will hopefully - # end up being a target directory - set -- "$( + # Look at argument given + case $1 in - # The requested pattern is the first argument, defaulting to just the - # parent directory - req=${1:-..} + # If it has a leading slash or is . or .., don't touch the arguments + /*|.|..) ;; - # Strip trailing slashes if a trailing slash is not the whole pattern - [ "$req" = / ] || req=${req%/} + # Otherwise, we'll try to find a matching ancestor and then shift the + # initial request off the argument list + *) - # What to do now depends on the request - case $req in + # Push the current directory onto the stack + set -- "$1" "$PWD" - # Just go straight to the root or dot directories if asked - (/|.|..) - dirname=$req - ;; - - # Anything with a leading / needs to anchor to the start of the - # path. A strange request though. Why not just use cd? - (/*) - dirname=$req - case $PWD in - ("$dirname"/*) ;; - (*) dirname='' ;; + # Keep chopping at the current directory until it's empty or it + # matches the request + while [ -n "$2" ] ; do + set -- "$1" "${2%/*}" + case $2 in + (*/"$1") break ;; esac - ;; - - # In all other cases, iterate through the PWD to find a match, or - # whittle the target down to an empty string trying - (*) - dirname=$PWD - while [ -n "$dirname" ] ; do - dirname=${dirname%/*} - case $dirname in - (*/"$req") break ;; - esac - done - ;; - esac - - # Check we have a target after all that - if [ -z "$dirname" ] ; then - printf >&2 'bd(): Directory name not in path\n' - exit 1 - fi - - # Print the target with trailing slash to work around newline stripping - printf '%s/' "${dirname%/}" - )" - - # Remove trailing slash - set -- "${1%/}" - - # If the subshell printed nothing, return with failure - [ -n "$1" ] || return - - # Try to change into the determined directory - command cd -- "$@" + done + + # If the first argument ended up empty, we have no match + if [ -z "$2" ] ; then + printf >&2 'bd(): No match\n' + return 1 + fi + shift + ;; + esac + + # We have a match; try and change into it + command cd -- "$1" } -- cgit v1.2.3 From e199448d724746af892a67608c88fb2ddc075c72 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Thu, 25 May 2017 18:31:36 +1200 Subject: Even terser/nicer bd() --- sh/shrc.d/bd.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/bd.sh b/sh/shrc.d/bd.sh index 02da6773..5b2c3d59 100644 --- a/sh/shrc.d/bd.sh +++ b/sh/shrc.d/bd.sh @@ -22,18 +22,18 @@ bd() { # Keep chopping at the current directory until it's empty or it # matches the request - while [ -n "$2" ] ; do - set -- "$1" "${2%/*}" + while set -- "$1" "${2%/*}" ; do case $2 in - (*/"$1") break ;; + */"$1") break ;; + */*) ;; + *) + printf >&2 'bd(): No match\n' + return 1 + ;; esac done # If the first argument ended up empty, we have no match - if [ -z "$2" ] ; then - printf >&2 'bd(): No match\n' - return 1 - fi shift ;; esac -- cgit v1.2.3 From 9ed69d70d9201817c7f36c7f210ce163e84eb54b Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 26 May 2017 00:39:02 +1200 Subject: Reimplement sd() without subshell --- sh/shrc.d/bd.sh | 6 ++--- sh/shrc.d/sd.sh | 80 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 44 insertions(+), 42 deletions(-) (limited to 'sh/shrc.d') 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" } -- cgit v1.2.3 From cd114eec94fd07e831ef6c70b7732408d0a59e90 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 26 May 2017 17:48:49 +1200 Subject: Correct default behaviour for bd() with no args --- sh/shrc.d/bd.sh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/bd.sh b/sh/shrc.d/bd.sh index 2dc21173..7901e115 100644 --- a/sh/shrc.d/bd.sh +++ b/sh/shrc.d/bd.sh @@ -1,14 +1,17 @@ # Move back up the directory tree to the first directory matching the name bd() { - # Check argument count - if [ "$#" -gt 1 ] ; then - printf >&2 'bd(): Too many arguments\n' - return 2 - fi + # Check argument count; default to ".." + case $# in + 0) set -- .. ;; + 1) ;; + *) + printf >&2 'bd(): Too many arguments\n' + return 2 + esac # Look at argument given; default to going up one level - case ${1:-..} in + case $1 in # If it has a leading slash or is . or .., don't touch the arguments /*|.|..) ;; -- cgit v1.2.3 From 520f9e174aa0569a95469a7d2b746582bdf0c18c Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 26 May 2017 20:23:54 +1200 Subject: More bd() improvements Including rigorous trailing-slash handling --- sh/shrc.d/bd.sh | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/bd.sh b/sh/shrc.d/bd.sh index 7901e115..9b877faf 100644 --- a/sh/shrc.d/bd.sh +++ b/sh/shrc.d/bd.sh @@ -1,31 +1,48 @@ # Move back up the directory tree to the first directory matching the name bd() { - # Check argument count; default to ".." - case $# in - 0) set -- .. ;; - 1) ;; - *) - printf >&2 'bd(): Too many arguments\n' - return 2 - esac + # Check arguments; default to ".." + if [ "$#" -gt 1 ] ; then + printf >&2 'bd(): Too many arguments\n' + return 2 + fi + set -- "${1:-..}" # 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 - /*|.|..) ;; + # If it's slash, dot, or dot-dot, we'll just go there, like `cd` would + /|.|..) ;; + + # Anything else with a slash anywhere is an error + */*) + printf >&2 'bd(): Illegal slash\n' + return 2 + ;; # Otherwise, we'll try to find a matching ancestor and then shift the # initial request off the argument list *) # 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 - while set -- "$1" "${2%/*}" ; do + while : ; do + + # Make certain there are no trailing slashes to foul us up + while : ; do + case $2 in + */) set -- "$1" "${2%/}" ;; + *) break ;; + esac + done + + # Strip a path element + set -- "$1" "${2%/*}" + + # Check whether we're arrived case $2 in */"$1") break ;; */*) ;; -- cgit v1.2.3 From 2d0fefe4cde7831c7e49641df217ee0354751a63 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 26 May 2017 20:24:13 +1200 Subject: Reimplement ud() More fault-tolerant and no subshell or temporary vars --- sh/shrc.d/ud.sh | 62 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 32 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/ud.sh b/sh/shrc.d/ud.sh index 79f4b5e7..a3997702 100644 --- a/sh/shrc.d/ud.sh +++ b/sh/shrc.d/ud.sh @@ -2,48 +2,46 @@ # like cd .., cd ../.., etc ud() { - # Check argument count - if [ "$#" -gt 1 ] ; then + # Check arguments; default to 1 and $PWD + if [ "$#" -gt 2 ] ; then printf >&2 'ud(): Too many arguments\n' return 2 fi + set -- "${1:-1}" "${2:-"$PWD"}" + set -- "$1" "$2" - # Check first argument, number of steps upward, default to 1. - # "0" is weird, but valid; "-1" however makes no sense at all - if [ "${1:-1}" -lt 0 ] ; then + # Check first argument, number of steps upward. "0" is weird, but valid; + # "-1" however makes no sense at all + if [ "$1" -lt 0 ] ; then printf >&2 'ud(): Invalid step count\n' return 2 fi - # Change the positional parameters from the number of steps given to a - # "../../.." string - set -- "$( - - # Append /.. to the target (default PWD) the specified number of times - dirname=${2:-"$PWD"} - i=0 - steps=${1:-1} - while [ "$i" -lt "$steps" ] ; do - dirname=${dirname%/}/.. - i=$((i+1)) + # Check second argument, starting path, for relativity and anchor it if + # need be + case $2 in + /*) ;; + *) set -- "$1" "$PWD"/"$2" ;; + esac + + # Chop an element off the target the specified number of times + while [ "$1" -gt 0 ] ; do + + # Make certain there are no trailing slashes to foul us up + while : ; do + case $2 in + */) set -- "$1" "${2%/}" ;; + *) break ;; + esac done - # Check we have a target after all that - if [ -z "$dirname" ] ; then - printf >&2 'ud(): Destination construction failed\n' - exit 1 - fi + # Strip a path element + set -- "$(($1-1))" "${2%/*}" + done - # Print the target with trailing slash to work around newline stripping - printf '%s/' "${dirname%/}" - )" + # Shift off the count, which should now be zero + shift - # Remove trailing slash - set -- "${1%/}" - - # If the subshell printed nothing, return with failure - [ -n "$1" ] || return - - # Try to change into the determined directory - command cd -- "$@" + # Try to change into the determined directory, or the root if blank + command cd -- "${1:-/}" } -- cgit v1.2.3 From 62f7ea87871b861a079a64ef0e278370865498e4 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 26 May 2017 20:34:16 +1200 Subject: Still tinkering with ?d.sh scripts --- sh/shrc.d/pd.sh | 49 ++++++++++++++++++++----------------------------- sh/shrc.d/rd.sh | 2 -- sh/shrc.d/sd.sh | 2 -- 3 files changed, 20 insertions(+), 33 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/pd.sh b/sh/shrc.d/pd.sh index ce43837b..e3a6daaa 100644 --- a/sh/shrc.d/pd.sh +++ b/sh/shrc.d/pd.sh @@ -2,39 +2,30 @@ # 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 ..` +# +# Note this is equivalent to `ud 1`. pd() { - # Check argument count + # Check arguments; default to $PWD if [ "$#" -gt 1 ] ; then printf >&2 'pd(): Too many arguments\n' return 2 fi - - # Change the positional parameters from the target to its containing - # directory - set -- "$( - - # 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 with trailing slash to work around newline stripping - printf '%s/' "${dirname%/}" - )" - - # Remove trailing slash - set -- "${1%/}" - - # If the subshell printed nothing, return with failure - [ -n "$1" ] || return - - # Try to change into the determined directory - command cd -- "$@" + set -- "${1:-"$PWD"}" + + # Make certain there are no trailing slashes to foul us up, and anchor path + # if relative + while : ; do + case $1 in + */) set -- "${1%/}" ;; + /*) break ;; + *) set -- "$PWD"/"$1" ;; + esac + done + + # Strip a path element + set -- "${1%/*}" + + # Try to change into the determined directory, or root if empty + command cd -- "${1:-/}" } diff --git a/sh/shrc.d/rd.sh b/sh/shrc.d/rd.sh index 3b699c0d..c4c1c063 100644 --- a/sh/shrc.d/rd.sh +++ b/sh/shrc.d/rd.sh @@ -1,4 +1,3 @@ -# # 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 @@ -12,7 +11,6 @@ # $ rd usr opt # $ pwd # /opt/bin -# rd() { # Check argument count diff --git a/sh/shrc.d/sd.sh b/sh/shrc.d/sd.sh index 561a77f4..af82b67e 100644 --- a/sh/shrc.d/sd.sh +++ b/sh/shrc.d/sd.sh @@ -1,4 +1,3 @@ -# # Shortcut to switch to another directory with the same parent, i.e. a sibling # of the current directory. # @@ -31,7 +30,6 @@ # /tmp/tmp.ZSunna5Eup/a # # Seems to work for symbolic links. -# sd() { # Check argument count -- cgit v1.2.3 From df7182774a97fd330f0ce6358ae4c2454b121f9e Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 26 May 2017 20:45:23 +1200 Subject: Remove hare-brained no-op line --- sh/shrc.d/ud.sh | 1 - 1 file changed, 1 deletion(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/ud.sh b/sh/shrc.d/ud.sh index a3997702..06234569 100644 --- a/sh/shrc.d/ud.sh +++ b/sh/shrc.d/ud.sh @@ -8,7 +8,6 @@ ud() { return 2 fi set -- "${1:-1}" "${2:-"$PWD"}" - set -- "$1" "$2" # Check first argument, number of steps upward. "0" is weird, but valid; # "-1" however makes no sense at all -- cgit v1.2.3 From 0eca7eafffbd667b7e5f4d2423adb54ea5582165 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 26 May 2017 20:45:37 +1200 Subject: Tidy/golf gt() down a bit --- sh/shrc.d/gt.sh | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/gt.sh b/sh/shrc.d/gt.sh index c90af073..95ab4c2f 100644 --- a/sh/shrc.d/gt.sh +++ b/sh/shrc.d/gt.sh @@ -3,26 +3,24 @@ gt() { # Check argument count - if [ "$#" -gt 1 ] ; then - printf >&2 'gt(): Too many arguments\n' + if [ "$#" -ne 1 ] ; then + printf >&2 'gt(): Need one argument\n' return 2 fi - # Strip trailing slash - set -- "${1%/}" - - # If target doesn't have a leading slash, add PWD prefix - case $1 in - /*) ;; - *) set -- "${PWD%/}"/"$1" - esac + # Make certain there are no trailing slashes to foul us up, and anchor path + # if relative + while : ; do + case $1 in + */) set -- "${1%/}" ;; + /*) break ;; + *) set -- "$PWD"/"$1" ;; + esac + done # If target isn't a directory, chop to its parent [ -d "$1" ] || set -- "${1%/*}" - # If target is now empty, go to the root - [ -n "$1" ] || set -- / - - # Try to change into the determined directory - command cd -- "$@" + # Try to change into the determined directory, or root if empty + command cd -- "${1:-/}" } -- cgit v1.2.3 From 1bca0a6205c0c22bc0e23c642f47da18d5164766 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Fri, 26 May 2017 20:46:48 +1200 Subject: Remove ad() It has no real advantages over and isn't as clever as just cd /a*/b*/c* --- sh/shrc.d/ad.sh | 80 --------------------------------------------------------- 1 file changed, 80 deletions(-) delete mode 100644 sh/shrc.d/ad.sh (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/ad.sh b/sh/shrc.d/ad.sh deleted file mode 100644 index 55866683..00000000 --- a/sh/shrc.d/ad.sh +++ /dev/null @@ -1,80 +0,0 @@ -# Find an abbreviated path -ad() { - - # Check argument count - if [ "$#" -ne 1 ] ; then - printf >&2 'ad(): Need just one argument\n' - return 2 - fi - - # Change the positional parameters from the abbreviated request - # to any matched directory - set -- "$( - - # Clean up and anchor the request - req=${1%/}/ - case $req in - (/*) ;; - (*) req=${PWD%/}/${req#/} ;; - esac - - # Start building the target directory; go through the request piece by - # piece until it is used up - dir= - while [ -n "$req" ] ; do - - # Chop the next front bit off the request and add it to the dir - dir=${dir%/}/${req%%/*} - req=${req#*/} - - # If that exists, all is well and we can keep iterating - [ -d "$dir" ] && continue - - # Set the positional parameters to a glob expansion of the - # abbreviated directory given - set -- "$dir"* - - # Iterate through the positional parameters filtering out - # directories; we need to run right through the whole list to check - # that we have at most one match - entd= - for ent ; do - [ -d "$ent" ] || continue - - # If we already found a match and have found another one, bail - # out - if [ -n "$entd" ] ; then - printf >&2 'ad(): More than one matching dir for %s*:\n' \ - "$dir" - printf >&2 '%s\n' "$@" - exit 1 - fi - - # Otherwise, this can be our first one - entd=$ent - done - - # If we found no match, bail out - if [ -z "$entd" ] ; then - printf >&2 'ad(): No matching dirs: %s*\n' "$dir" - exit 1 - fi - - # All is well, tack on what we have found and keep going - dir=$entd - - done - - # Print the target with trailing slash to work around newline stripping - printf '%s/' "${dir%/}" - )" - - # Remove trailing slash - set -- "${1%/}" - - # If the subshell printed nothing, return with failure - [ -n "$1" ] || return - - # Try to change into the determined directory - command cd -- "$@" -} -- cgit v1.2.3 From 1a672fccf7d8c9b41e02d86c1f7f39a5d025aaf6 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 27 May 2017 21:17:34 +1200 Subject: More refinements to bd() --- sh/shrc.d/bd.sh | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/bd.sh b/sh/shrc.d/bd.sh index 9b877faf..1b253e3d 100644 --- a/sh/shrc.d/bd.sh +++ b/sh/shrc.d/bd.sh @@ -20,44 +20,27 @@ bd() { return 2 ;; - # Otherwise, we'll try to find a matching ancestor and then shift the - # initial request off the argument list + # Otherwise, add and keep chopping at the current directory until it's + # empty or it matches the request, then shift the request off *) - - # Push the current directory onto the stack set -- "$1" "$PWD" - - # Keep chopping at the current directory until it's empty or it - # matches the request while : ; do - - # Make certain there are no trailing slashes to foul us up - while : ; do - case $2 in - */) set -- "$1" "${2%/}" ;; - *) break ;; - esac - done - - # Strip a path element - set -- "$1" "${2%/*}" - - # Check whether we're arrived case $2 in - */"$1") break ;; - */*) ;; - *) - printf >&2 'bd(): No match\n' - return 1 - ;; + */"$1"|'') break ;; + */) set -- "$1" "${2%/}" ;; + *) set -- "$1" "${2%/*}" ;; esac done - - # If the first argument ended up empty, we have no match shift ;; esac + # If we have nothing to change into, there's an error + if [ -z "$1" ] ; then + printf >&2 'bd(): No match\n' + return 1 + fi + # We have a match; try and change into it command cd -- "$1" } -- cgit v1.2.3 From 05eac418f012b9d92f1955cab3d19a5cb9aef760 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 27 May 2017 21:24:17 +1200 Subject: Add safety to bd() Handle case if PWD does not start with a slash--a big "Shouldn't Happen", but easy enough to be worth handling, since it would loop infinitely otherwise --- sh/shrc.d/bd.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/bd.sh b/sh/shrc.d/bd.sh index 1b253e3d..29bde513 100644 --- a/sh/shrc.d/bd.sh +++ b/sh/shrc.d/bd.sh @@ -28,7 +28,8 @@ bd() { case $2 in */"$1"|'') break ;; */) set -- "$1" "${2%/}" ;; - *) set -- "$1" "${2%/*}" ;; + */*) set -- "$1" "${2%/*}" ;; + *) set -- "$1" '' ;; esac done shift -- cgit v1.2.3 From 5db5287e727a2c73278bd33b9728a3cef1a741eb Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 27 May 2017 21:33:02 +1200 Subject: Use -z rather than !-n --- sh/shrc.d/gd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/gd.sh b/sh/shrc.d/gd.sh index fa5776f2..9f6a43e7 100644 --- a/sh/shrc.d/gd.sh +++ b/sh/shrc.d/gd.sh @@ -8,7 +8,7 @@ gd() { fi # Complain if mark not actually set yet - if ! [ -n "$PMD" ] ; then + if [ -z "$PMD" ] ; then printf >&2 'gd(): Mark not set\n' return 1 fi -- cgit v1.2.3 From 1302b279bf2b1b2ae76ea8251a32e480d64f2f7a Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 27 May 2017 21:33:09 +1200 Subject: Remove redundant `|| return` from gd() It will do that implicitly anyway --- sh/shrc.d/gd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/gd.sh b/sh/shrc.d/gd.sh index 9f6a43e7..10135d01 100644 --- a/sh/shrc.d/gd.sh +++ b/sh/shrc.d/gd.sh @@ -14,5 +14,5 @@ gd() { fi # Go to the marked directory - cd -- "$PMD" || return + cd -- "$PMD" } -- cgit v1.2.3 From cbbec36d4403dbed6d61232e86b5d4995c8da1fe Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 27 May 2017 22:52:40 +1200 Subject: More error-resistant sd() --- sh/shrc.d/hgrep.sh | 6 ++-- sh/shrc.d/pmd.sh | 2 +- sh/shrc.d/sd.sh | 86 ++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 62 insertions(+), 32 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/hgrep.sh b/sh/shrc.d/hgrep.sh index 1c4c3ec5..fe297ab3 100644 --- a/sh/shrc.d/hgrep.sh +++ b/sh/shrc.d/hgrep.sh @@ -6,11 +6,11 @@ hgrep() { if [ "$#" -eq 0 ] ; then printf >&2 'hgrep(): Need a pattern\n' - exit 2 + return 2 fi - if ! [ -n "$HISTFILE" ] ; then + if [ -z "$HISTFILE" ] ; then printf >&2 'hgrep(): No HISTFILE\n' - exit 2 + return 2 fi grep "$@" "$HISTFILE" } diff --git a/sh/shrc.d/pmd.sh b/sh/shrc.d/pmd.sh index c96a50bd..4b0cd5bd 100644 --- a/sh/shrc.d/pmd.sh +++ b/sh/shrc.d/pmd.sh @@ -1,6 +1,6 @@ # Print the marked directory pmd() { - if ! [ -n "$PMD" ] ; then + if [ -z "$PMD" ] ; then printf >&2 'pmd(): Mark not set\n' return 1 fi diff --git a/sh/shrc.d/sd.sh b/sh/shrc.d/sd.sh index af82b67e..8b12c170 100644 --- a/sh/shrc.d/sd.sh +++ b/sh/shrc.d/sd.sh @@ -41,45 +41,75 @@ sd() { # Read sole optional argument case $1 in - # 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` + # Slashes aren't allowed + */*) + printf >&2 'bd(): Illegal slash\n' + return 2 + ;; + + # If blank, we try to find if there's just one sibling, and change to + # that if so '') + # First a special case: root dir + case $PWD in + *[!/]*) ;; + *) + printf >&2 'sd(): No siblings\n' + return 1 + ;; + esac + + # 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 - ;; - # If not, get that directory, and the current one; shift it off if it - # doesn't exist - *) - set -- ../"${1%/}"/ ../"${PWD##*/}"/ - [ -e "$1" ] || shift - ;; - esac + # Check the number of matches + case $# in - # 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 + # One match? Must be $PWD, so no siblings--throw in 0 just in + # case, but that Shouldn't Happen (TM) + 0|1) + printf >&2 'sd(): No siblings\n' + return 1 + ;; + + # Two matches; hopefully just one sibling, but which is it? + 2) + + # Push PWD onto the stack, strip trailing slashes + set -- "$1" "$2" "$PWD" + while : ; do + case $3 in + */) set -- "$1" "$2" "${3%/}" ;; + *) break ;; + esac + done + + # Pick whichever of our two parameters doesn't look like + # PWD as our sole parameter + case $1 in + ../"${3##*/}"/) set -- "$2" ;; + *) set -- "$1" ;; + esac + ;; + + # Anything else? Multiple siblings--user will need to specify + *) + printf >&2 'sd(): Multiple siblings\n' + return 1 + ;; + esac ;; - esac - # 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" ;; + # If not, simply set our target to that directory, and let `cd` do the + # complaining if it doesn't exist + *) set -- ../"$1" ;; esac # Try and change into the first parameter -- cgit v1.2.3 From ee2a3a4d87665fb8b79363b1f78250908ec78b94 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 27 May 2017 22:53:36 +1200 Subject: Revert "Remove redundant `|| return` from gd()" This reverts commit 1302b279bf2b1b2ae76ea8251a32e480d64f2f7a. This was added because of Shellcheck being fussy --- sh/shrc.d/gd.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/gd.sh b/sh/shrc.d/gd.sh index 10135d01..9f6a43e7 100644 --- a/sh/shrc.d/gd.sh +++ b/sh/shrc.d/gd.sh @@ -14,5 +14,5 @@ gd() { fi # Go to the marked directory - cd -- "$PMD" + cd -- "$PMD" || return } -- cgit v1.2.3 From 5f714e85e2d97bf820b86db924eb00f459d731eb Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 27 May 2017 23:51:52 +1200 Subject: Simplify rd() a lot Including removing the pesky subshell --- sh/shrc.d/rd.sh | 45 ++++++++++----------------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) (limited to 'sh/shrc.d') diff --git a/sh/shrc.d/rd.sh b/sh/shrc.d/rd.sh index c4c1c063..9633713a 100644 --- a/sh/shrc.d/rd.sh +++ b/sh/shrc.d/rd.sh @@ -23,42 +23,17 @@ rd() { ;; 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 + # Check there's something to substitute, and do it + case $PWD in + *"$1"*) + set -- "${PWD%%"$1"*}""$2""${PWD#*"$1"}" + ;; + *) printf >&2 'rd(): Substitution failed\n' - exit 1 - fi - - # Print the target with trailing slash to work around newline stripping - printf '%s/' "${new%/}" - )" - - # Remove trailing slash - set -- "${1%/}" - - # If the subshell printed nothing, return with failure - [ -n "$1" ] || return + return 1 + ;; + esac # Try to change into the determined directory - command cd -- "$@" + command cd -- "$1" } -- cgit v1.2.3