aboutsummaryrefslogtreecommitdiff
path: root/sh
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2017-06-02 22:09:38 +1200
committerTom Ryder <tom@sanctum.geek.nz>2017-06-02 22:09:38 +1200
commite1e02dae1d6cfe6c34d1f0641349fab6eadca19c (patch)
treef11de1d64997ef90579fef04018e66350e3dfb73 /sh
parenta3ddf9e5799a4727625c0676d6e32c055640b9c5 (diff)
parent54e85f42174610a0aaf29a4912c22bb8d7a4f742 (diff)
downloaddotfiles-e1e02dae1d6cfe6c34d1f0641349fab6eadca19c.tar.gz
Merge branch 'master' into port/bsd/freebsd
Diffstat (limited to 'sh')
-rw-r--r--sh/profile.d/downloads.sh28
-rw-r--r--sh/shrc.d/ad.sh80
-rw-r--r--sh/shrc.d/bd.sh99
-rw-r--r--sh/shrc.d/gd.sh2
-rw-r--r--sh/shrc.d/gt.sh28
-rw-r--r--sh/shrc.d/hgrep.sh6
-rw-r--r--sh/shrc.d/mysql.sh25
-rw-r--r--sh/shrc.d/pd.sh49
-rw-r--r--sh/shrc.d/pmd.sh2
-rw-r--r--sh/shrc.d/rd.sh47
-rw-r--r--sh/shrc.d/sd.sh110
-rw-r--r--sh/shrc.d/ud.sh61
12 files changed, 213 insertions, 324 deletions
diff --git a/sh/profile.d/downloads.sh b/sh/profile.d/downloads.sh
new file mode 100644
index 00000000..fb8dd64a
--- /dev/null
+++ b/sh/profile.d/downloads.sh
@@ -0,0 +1,28 @@
+# Only if shell is interactive
+case $- in
+ *i*) ;;
+ *) return ;;
+esac
+
+# Only if not in a tmux window
+[ -z "$TMUX" ] || return
+
+# Not if ~/.hushlogin exists
+[ -e "$HOME"/.hushlogin ] && return
+
+# Not if ~/.downloads doesn't
+[ -f "$HOME"/.downloads ] || return
+
+# Count files in each directory, report if greater than zero
+(
+ while IFS= read -r dir ; do
+ case $dir in
+ '#'*) continue ;;
+ esac
+ [ -d "$dir" ] || continue
+ set -- "$dir"/*
+ [ -e "$1" ] || shift
+ [ "$#" -gt 0 ] || continue
+ printf '\nYou have %u unsorted files in %s.\n\n' "$#" "$dir"
+ done < "$HOME"/.downloads
+)
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 -- "$@"
-}
diff --git a/sh/shrc.d/bd.sh b/sh/shrc.d/bd.sh
index bf64a9aa..29bde513 100644
--- a/sh/shrc.d/bd.sh
+++ b/sh/shrc.d/bd.sh
@@ -1,70 +1,47 @@
# Move back up the directory tree to the first directory matching the name
bd() {
- # Check argument count
+ # Check arguments; default to ".."
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 -- "$(
-
- # The requested pattern is the first argument, defaulting to just the
- # parent directory
- req=${1:-..}
-
- # Strip trailing slashes if a trailing slash is not the whole pattern
- [ "$req" = / ] || req=${req%/}
-
- # What to do now depends on the request
- case $req in
-
- # 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='' ;;
+ set -- "${1:-..}"
+
+ # Look at argument given; default to going up one level
+ case $1 in
+
+ # 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, add and keep chopping at the current directory until it's
+ # empty or it matches the request, then shift the request off
+ *)
+ set -- "$1" "$PWD"
+ while : ; do
+ case $2 in
+ */"$1"|'') break ;;
+ */) set -- "$1" "${2%/}" ;;
+ */*) set -- "$1" "${2%/*}" ;;
+ *) set -- "$1" '' ;;
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
+ done
+ 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
- # Try to change into the determined directory
- command cd -- "$@"
+ # We have a match; try and change into it
+ command cd -- "$1"
}
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
diff --git a/sh/shrc.d/gt.sh b/sh/shrc.d/gt.sh
index d18a4ab8..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 'gd(): 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:-/}"
}
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/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 "$@"
-}
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/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/rd.sh b/sh/shrc.d/rd.sh
index 3b699c0d..9633713a 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
@@ -25,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"
}
diff --git a/sh/shrc.d/sd.sh b/sh/shrc.d/sd.sh
index 4d63b7d6..8b12c170 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
@@ -40,48 +38,80 @@ sd() {
return 2
fi
- # Change positional parameters to what will hopefully be a completed
- # substitution
- set -- "$(
+ # Read sole optional argument
+ case $1 in
+
+ # 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
+
+ # Check the number of matches
+ case $# in
+
+ # 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
+ ;;
- # 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
+ # Two matches; hopefully just one sibling, but which is it?
+ 2)
- # 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
+ # Push PWD onto the stack, strip trailing slashes
+ set -- "$1" "$2" "$PWD"
+ while : ; do
+ case $3 in
+ */) set -- "$1" "$2" "${3%/}" ;;
+ *) break ;;
+ esac
+ done
- # Print the target with trailing slash to work around newline stripping
- printf '%s/' "${1%/}"
- )"
+ # Pick whichever of our two parameters doesn't look like
+ # PWD as our sole parameter
+ case $1 in
+ ../"${3##*/}"/) set -- "$2" ;;
+ *) set -- "$1" ;;
+ esac
+ ;;
- # Remove trailing slash
- set -- "${1%/}"
+ # Anything else? Multiple siblings--user will need to specify
+ *)
+ printf >&2 'sd(): Multiple siblings\n'
+ return 1
+ ;;
+ esac
+ ;;
- # If the subshell printed nothing, return with failure
- [ -n "$1" ] || return
+ # If not, simply set our target to that directory, and let `cd` do the
+ # complaining if it doesn't exist
+ *) set -- ../"$1" ;;
+ esac
- # Try to change into the determined directory
- command cd -- "$@"
+ # Try and change into the first parameter
+ command cd -- "$1"
}
diff --git a/sh/shrc.d/ud.sh b/sh/shrc.d/ud.sh
index 79f4b5e7..06234569 100644
--- a/sh/shrc.d/ud.sh
+++ b/sh/shrc.d/ud.sh
@@ -2,48 +2,45 @@
# 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"}"
- # 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:-/}"
}