aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2018-12-14 13:14:00 +1300
committerTom Ryder <tom@sanctum.geek.nz>2018-12-14 13:14:00 +1300
commite0ff7ac01d6439d826ff9ef6f134a7638ade714f (patch)
tree781004065fefcbfd8e543a61de3d168383e71bde
parent131368cd38f99c591e027003aec6fa23bbd834ef (diff)
parenta3074a46668edb11542505ae9c46e2814b047bbe (diff)
downloaddotfiles-e0ff7ac01d6439d826ff9ef6f134a7638ade714f.tar.gz
dotfiles-e0ff7ac01d6439d826ff9ef6f134a7638ade714f.zip
Merge branch 'release/v3.2.0'v3.2.0
* release/v3.2.0: Bump VERSION Refactor some conditionals Factor out zsh ENV hack into one file Refactor "path list" not to require a subshell Correct completion for deep pass(1) directories Move filetype.vim helper funcs into autoload Fix a local var name in openssl(1ssl) completion Correct a variable ref in openssl(1ssl) completion Disable shellcheck rules for missed definition Add filenames treatment to mex(1df) completion Remove unneeded declaration Refactor some completions to avoid loops Remove unneeded stdout redirect Remove unneeded semicolon from sh "for VAR ; do" Substitute bad `continue` for `return` Add actual completion matching to git completion Apply much simpler completion to Git
-rw-r--r--VERSION4
-rw-r--r--bash/bash_completion.d/_ssh_config_hosts.bash43
-rw-r--r--bash/bash_completion.d/git.bash41
-rw-r--r--bash/bash_completion.d/gpg.bash13
-rw-r--r--bash/bash_completion.d/make.bash2
-rw-r--r--bash/bash_completion.d/man.bash1
-rw-r--r--bash/bash_completion.d/mex.bash2
-rw-r--r--bash/bash_completion.d/openssl.bash29
-rw-r--r--bash/bash_completion.d/pass.bash2
-rw-r--r--bash/bash_completion.d/path.bash2
-rw-r--r--bash/bashrc2
-rw-r--r--bash/bashrc.d/keep.bash2
-rw-r--r--bash/bashrc.d/vared.bash2
-rw-r--r--bin/ap.sh2
-rw-r--r--bin/apf.sh2
-rw-r--r--bin/d2u.sh2
-rw-r--r--bin/eds.sh4
-rw-r--r--bin/fnp.sh2
-rw-r--r--bin/loc.sh2
-rw-r--r--bin/mex.sh2
-rw-r--r--bin/mkcp.sh2
-rw-r--r--bin/mked.sh2
-rw-r--r--bin/mkmv.sh2
-rw-r--r--bin/mkvi.sh2
-rw-r--r--bin/pp.sh2
-rw-r--r--bin/sqs.sh2
-rw-r--r--bin/stbl.sh2
-rw-r--r--bin/stex.sh2
-rw-r--r--bin/stws.sh2
-rw-r--r--bin/sue.sh2
-rw-r--r--bin/u2d.sh2
-rw-r--r--bin/xgo.sh2
-rw-r--r--check/bash.sh2
-rw-r--r--check/ksh.sh2
-rw-r--r--check/sh.sh2
-rw-r--r--check/xinit.sh2
-rw-r--r--check/zsh.sh2
-rw-r--r--ksh/kshrc.d/keep.ksh2
-rw-r--r--readline/inputrc6
-rw-r--r--sh/profile12
-rw-r--r--sh/profile.d/downloads.sh6
-rw-r--r--sh/profile.d/options.sh7
-rw-r--r--sh/profile.d/welcome.sh10
-rw-r--r--sh/shinit9
-rw-r--r--sh/shrc4
-rw-r--r--sh/shrc.d/bc.sh3
-rw-r--r--sh/shrc.d/ed.sh6
-rw-r--r--sh/shrc.d/grep.sh20
-rw-r--r--sh/shrc.d/gt.sh4
-rw-r--r--sh/shrc.d/ls.sh36
-rw-r--r--sh/shrc.d/mkcd.sh3
-rw-r--r--sh/shrc.d/path.sh33
-rw-r--r--sh/shrc.d/tree.sh2
-rw-r--r--sh/shrc.d/vr.sh11
-rw-r--r--vim/autoload/filetype.vim76
-rw-r--r--vim/filetype.vim81
-rw-r--r--zsh/profile.d/zsh.sh25
-rw-r--r--zsh/zshrc.d/keep.zsh2
58 files changed, 314 insertions, 239 deletions
diff --git a/VERSION b/VERSION
index 63c62745..2a431fea 100644
--- a/VERSION
+++ b/VERSION
@@ -1,2 +1,2 @@
-tejr dotfiles v3.1.0
-Wed Dec 5 22:40:16 UTC 2018
+tejr dotfiles v3.2.0
+Fri Dec 14 00:14:00 UTC 2018
diff --git a/bash/bash_completion.d/_ssh_config_hosts.bash b/bash/bash_completion.d/_ssh_config_hosts.bash
index 3f937a2a..0959f52b 100644
--- a/bash/bash_completion.d/_ssh_config_hosts.bash
+++ b/bash/bash_completion.d/_ssh_config_hosts.bash
@@ -1,31 +1,26 @@
# Complete ssh_config(5) hostnames
_ssh_config_hosts() {
- # Iterate through words from a subshell
- local ci comp
- while read -r comp ; do
- COMPREPLY[ci++]=$comp
- done < <(
+ # Iterate through SSH client config paths
+ local config
+ for config in "$HOME"/.ssh/config /etc/ssh/ssh_config ; do
+ [[ -e $config ]] || continue
- # Iterate through SSH client config paths
- for config in "$HOME"/.ssh/config /etc/ssh/ssh_config ; do
- [[ -e $config ]] || continue
+ # Read 'Host' options and their first value from file
+ local option value ci
+ while read -r option value _ ; do
+ [[ $option == Host ]] || continue
- # Read 'Host' options and their first value from file
- while read -r option value _ ; do
- [[ $option == Host ]] || continue
+ # Check host value
+ case $value in
+ # No empties
+ '') ;;
+ # No wildcards
+ *'*'*) ;;
+ # Found a match; print it
+ "$2"*) COMPREPLY[ci++]=$value ;;
+ esac
- # Check host value
- case $value in
- # No empties
- ('') ;;
- # No wildcards
- (*'*'*) ;;
- # Found a match; print it
- ("$2"*) printf '%s\n' "$value" ;;
- esac
-
- done < "$config"
- done
- )
+ done < "$config"
+ done
}
diff --git a/bash/bash_completion.d/git.bash b/bash/bash_completion.d/git.bash
new file mode 100644
index 00000000..c3a4d49c
--- /dev/null
+++ b/bash/bash_completion.d/git.bash
@@ -0,0 +1,41 @@
+# Complete Git with branch names or tag names if specific keys are used, but
+# fall back on filenames otherwise; it's too complicated to be worth trying to
+# do it all contextually
+
+# Requires Bash >=4.0 for COMP_KEY
+((BASH_VERSINFO[0] >= 4)) || return
+
+# Define and set helper function
+_git() {
+
+ # What completion to do
+ case $COMP_KEY in
+
+ # Complete with branch names if C-x,B is pressed
+ 98)
+ local ci
+ while read -r _ ref ; do
+ branch=${ref#refs/heads/}
+ case $branch in
+ "$2"*) COMPREPLY[ci++]=$branch ;;
+ esac
+ done < <(git show-ref --heads)
+ ;;
+
+ # Complete with tag names if C-x,T is pressed
+ 116)
+ local ci
+ while read -r _ ref ; do
+ tag=${ref#refs/tags/}
+ case $tag in
+ "$2"*) COMPREPLY[ci++]=$tag ;;
+ esac
+ done < <(git show-ref --tags)
+ ;;
+
+ # Do no completion, so we fall back on filenames
+ *) return 1 ;;
+
+ esac
+}
+complete -F _git -o bashdefault -o default git
diff --git a/bash/bash_completion.d/gpg.bash b/bash/bash_completion.d/gpg.bash
index c6f92676..5a055352 100644
--- a/bash/bash_completion.d/gpg.bash
+++ b/bash/bash_completion.d/gpg.bash
@@ -13,14 +13,9 @@ _gpg() {
# Generate completion reply from gpg(1) options
local ci comp
while read -r comp ; do
- COMPREPLY[ci++]=$comp
- done < <(
- gpg --dump-options 2>/dev/null |
- while read -r option ; do
- case $option in
- ("$2"*) printf '%s\n' "$option" ;;
- esac
- done
- )
+ case $comp in
+ "$2"*) COMPREPLY[ci++]=$comp ;;
+ esac
+ done < <(gpg --dump-options 2>/dev/null)
}
complete -F _gpg -o bashdefault -o default gpg
diff --git a/bash/bash_completion.d/make.bash b/bash/bash_completion.d/make.bash
index 7f8b8125..909c52fb 100644
--- a/bash/bash_completion.d/make.bash
+++ b/bash/bash_completion.d/make.bash
@@ -34,11 +34,11 @@ _make() {
esac
# Break the target up with space delimiters
- declare -a targets
IFS=' ' read -a targets -r \
< <(printf '%s\n' "${line%%:*}")
# Short-circuit if there are no targets
+ # shellcheck disable=SC2154
((${#targets[@]})) || exit
# Make matches behave correctly
diff --git a/bash/bash_completion.d/man.bash b/bash/bash_completion.d/man.bash
index 50ab852e..714fa493 100644
--- a/bash/bash_completion.d/man.bash
+++ b/bash/bash_completion.d/man.bash
@@ -56,7 +56,6 @@ _man() {
fi
# Add pages from each manual directory
- local pages pi
for mp in "${manpaths[@]}" ; do
[[ -n $mp ]] || continue
diff --git a/bash/bash_completion.d/mex.bash b/bash/bash_completion.d/mex.bash
index b1e0e1a7..d9604b2c 100644
--- a/bash/bash_completion.d/mex.bash
+++ b/bash/bash_completion.d/mex.bash
@@ -51,4 +51,4 @@ _mex() {
done
)
}
-complete -F _mex mex
+complete -F _mex -o filenames mex
diff --git a/bash/bash_completion.d/openssl.bash b/bash/bash_completion.d/openssl.bash
index 1cb4bd07..1e2a9c58 100644
--- a/bash/bash_completion.d/openssl.bash
+++ b/bash/bash_completion.d/openssl.bash
@@ -8,25 +8,18 @@ _openssl() {
((COMP_CWORD == 1)) || return
# Iterate through completions produced by subshell
- local ci comp
- while read -r comp ; do
- COMPREPLY[ci++]=$comp
+ local -a subcmds
+ local ci subcmd
+ while read -a subcmds -r ; do
+ for subcmd in "${subcmds[@]}" ; do
+ case $subcmd in
+ "$2"*) COMPREPLY[ci++]=$subcmd ;;
+ esac
+ done
done < <(
-
- # Run each of the command-listing commands; read each line into an
- # array of subcommands (they are printed as a table)
- for list in commands digest-commands cipher-commands ; do
- openssl list -"$list"
- done | {
- declare -a subcmds
- while read -a subcmds -r ; do
- for subcmd in "${subcmds[@]}" ; do
- case $subcmd in
- ("$2"*) printf '%s\n' "$subcmd" ;;
- esac
- done
- done
- }
+ openssl list -commands \
+ -cipher-commands \
+ -digest-commands
)
}
complete -F _openssl -o bashdefault -o default openssl
diff --git a/bash/bash_completion.d/pass.bash b/bash/bash_completion.d/pass.bash
index 5a6e0b6c..760e774e 100644
--- a/bash/bash_completion.d/pass.bash
+++ b/bash/bash_completion.d/pass.bash
@@ -30,7 +30,7 @@ _pass() {
# Try to iterate into subdirs, use depth search with ** if available
if shopt -s globstar 2>/dev/null ; then
- for entry in "$pass_dir"/"$2"**/*.gpg ; do
+ for entry in "$pass_dir"/"$2"*/**/*.gpg ; do
entries[ei++]=$entry
done
else
diff --git a/bash/bash_completion.d/path.bash b/bash/bash_completion.d/path.bash
index 9234f132..c3bb7b80 100644
--- a/bash/bash_completion.d/path.bash
+++ b/bash/bash_completion.d/path.bash
@@ -62,11 +62,11 @@ _path() {
fi
# Break PATH into parts
- declare -a paths
IFS=: read -a paths -d '' -r \
< <(printf '%s\0' "$PATH")
# Print shell-quoted matching parts, null-terminated
+ # shellcheck disable=SC2154
for path in "${paths[@]}" ; do
case $path in
("$2"*) printf '%q\0' "$path" ;;
diff --git a/bash/bashrc b/bash/bashrc
index a05526f2..0400e41d 100644
--- a/bash/bashrc
+++ b/bash/bashrc
@@ -6,7 +6,7 @@ esac
# Don't do anything if restricted, not even sourcing the ENV file
# Testing $- for "r" doesn't work
-! shopt -q restricted_shell >/dev/null 2>&1 || return
+! shopt -q restricted_shell 2>/dev/null || return
# Clear away all aliases; we do this here rather than in the $ENV file shared
# between POSIX shells, because ksh relies on aliases to implement certain
diff --git a/bash/bashrc.d/keep.bash b/bash/bashrc.d/keep.bash
index 48196aeb..191dac4b 100644
--- a/bash/bashrc.d/keep.bash
+++ b/bash/bashrc.d/keep.bash
@@ -83,7 +83,7 @@ EOF
# Iterate through the NAMEs given
local name
- for name ; do
+ for name do
# Check NAMEs for validity
case $name in
diff --git a/bash/bashrc.d/vared.bash b/bash/bashrc.d/vared.bash
index e024f48a..491e5bff 100644
--- a/bash/bashrc.d/vared.bash
+++ b/bash/bashrc.d/vared.bash
@@ -24,7 +24,7 @@ vared() {
return 2
fi
local name
- for name ; do
+ for name do
IFS= read -e -i "${!name}" -p "${prompt:-"$name"=}" -r -- "${name?}"
done
}
diff --git a/bin/ap.sh b/bin/ap.sh
index 1d6376cc..2b13dfde 100644
--- a/bin/ap.sh
+++ b/bin/ap.sh
@@ -10,7 +10,7 @@ shift
# Iterate through the remaining args; it's legal for there to be none, but in
# that case the user may as well just have invoked the command directly
-for arg ; do
+for arg do
# If this is the first iteration, clear the params away (we grabbed them in
# the for statement)
diff --git a/bin/apf.sh b/bin/apf.sh
index 5e40e9b8..e11145ff 100644
--- a/bin/apf.sh
+++ b/bin/apf.sh
@@ -16,7 +16,7 @@ shift 2
if [ "$#" -gt 0 ] ; then
# Iterate through any remaining arguments
- for carg ; do
+ for carg do
# If this is the first command argument, then before we add it, we'll
# add all the ones from the file first if it exists
diff --git a/bin/d2u.sh b/bin/d2u.sh
index 892c446b..eceb11de 100644
--- a/bin/d2u.sh
+++ b/bin/d2u.sh
@@ -10,7 +10,7 @@ fi
r=$(printf '\r')
# Iterate over arguments and apply the same ed(1) script to each of them
-for fn ; do
+for fn do
# Note the heredoc WORD is intentionally unquoted because we want to expand
# $r within it to get a literal carriage return; the escape characters
diff --git a/bin/eds.sh b/bin/eds.sh
index c85069c6..c692cb30 100644
--- a/bin/eds.sh
+++ b/bin/eds.sh
@@ -21,7 +21,7 @@ case :$PATH: in
esac
# Prepend the path to each of the names given if they don't look like options
-for arg ; do
+for arg do
[ -n "$reset" ] || set -- && reset=1
case $arg in
--)
@@ -44,7 +44,7 @@ done
"${VISUAL:-"${EDITOR:-ed}"}" "$@"
# Make any created scripts executable if they now appear to be files
-for script ; do
+for script do
[ -f "$script" ] || continue
chmod +x -- "$script"
done
diff --git a/bin/fnp.sh b/bin/fnp.sh
index ec68e51f..bc0c7e21 100644
--- a/bin/fnp.sh
+++ b/bin/fnp.sh
@@ -4,7 +4,7 @@
[ "$#" -gt 0 ] || set -- -
# Iterate through arguments
-for arg ; do
+for arg do
# We'll print the filename "-stdin-" rather than - just to be slightly more
# explicit
diff --git a/bin/loc.sh b/bin/loc.sh
index 995c6932..214e87da 100644
--- a/bin/loc.sh
+++ b/bin/loc.sh
@@ -7,7 +7,7 @@ if [ "$#" -eq 0 ] ; then
fi
# Iterate through each search term and run an appropriate find(1) command
-for pat ; do
+for pat do
# Skip dotfiles, dotdirs, and symbolic links; print anything that matches
# the term as a substring (and stop iterating through it)
diff --git a/bin/mex.sh b/bin/mex.sh
index cf4e07e7..e79f8f2f 100644
--- a/bin/mex.sh
+++ b/bin/mex.sh
@@ -9,7 +9,7 @@ if [ "$#" -eq 0 ] ; then
fi
# Iterate through the given names
-for name ; do
+for name do
# Clear the found variable
found=
diff --git a/bin/mkcp.sh b/bin/mkcp.sh
index 10308263..3acf12f0 100644
--- a/bin/mkcp.sh
+++ b/bin/mkcp.sh
@@ -7,7 +7,7 @@ if [ "$#" -lt 2 ] ; then
fi
# Get the last argument (the directory to create)
-for dir ; do : ; done
+for dir do : ; done
# Create it, or bail
mkdir -p -- "$dir" || exit
diff --git a/bin/mked.sh b/bin/mked.sh
index 4e280205..93e21573 100644
--- a/bin/mked.sh
+++ b/bin/mked.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Create paths to all files before invoking editor
-for file ; do
+for file do
mkdir -p -- "${file%/*}" || exit
done
exec "$EDITOR" "$@"
diff --git a/bin/mkmv.sh b/bin/mkmv.sh
index 53b5aa8f..832c205e 100644
--- a/bin/mkmv.sh
+++ b/bin/mkmv.sh
@@ -7,7 +7,7 @@ if [ "$#" -lt 2 ] ; then
fi
# Get the last argument (the directory to create)
-for dir ; do : ; done
+for dir do : ; done
# Create it, or bail
mkdir -p -- "$dir" || exit
diff --git a/bin/mkvi.sh b/bin/mkvi.sh
index 244b89f8..c5974383 100644
--- a/bin/mkvi.sh
+++ b/bin/mkvi.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Create paths to all files before invoking editor
-for file ; do
+for file do
mkdir -p -- "${file%/*}" || exit
done
exec "$VISUAL" "$@"
diff --git a/bin/pp.sh b/bin/pp.sh
index b472a012..e9c25571 100644
--- a/bin/pp.sh
+++ b/bin/pp.sh
@@ -1,5 +1,5 @@
# Print the full path to each argument; path need not exist
-for arg ; do
+for arg do
case $arg in
/*) path=$arg ;;
*) path=$PWD/$arg ;;
diff --git a/bin/sqs.sh b/bin/sqs.sh
index 28435059..447a6563 100644
--- a/bin/sqs.sh
+++ b/bin/sqs.sh
@@ -8,7 +8,7 @@ if [ "$#" -eq 0 ] ; then
fi
# Iterate through the given files
-for sn ; do
+for sn do
# Strip trailing slash if any and then query string
sn=${sn%/}
diff --git a/bin/stbl.sh b/bin/stbl.sh
index 23d77703..2f6702b1 100644
--- a/bin/stbl.sh
+++ b/bin/stbl.sh
@@ -7,7 +7,7 @@ if [ "$#" -eq 0 ] ; then
fi
# Iterate over arguments and apply the same ed(1) script to each of them
-for fn ; do
+for fn do
ed -s -- "$fn" <<'EOF' || ex=1
$g/^ *$/d
w
diff --git a/bin/stex.sh b/bin/stex.sh
index 14d2cabf..b27d9cf8 100644
--- a/bin/stex.sh
+++ b/bin/stex.sh
@@ -13,7 +13,7 @@ ext=$1
shift
# Iterate through the given files (remaining args)
-for sn ; do
+for sn do
# Strip trailing slash if any and then extension
sn=${sn%/}
diff --git a/bin/stws.sh b/bin/stws.sh
index ce2c14d0..59a8652a 100644
--- a/bin/stws.sh
+++ b/bin/stws.sh
@@ -7,7 +7,7 @@ if [ "$#" -eq 0 ] ; then
fi
# Iterate over arguments and apply the same ed(1) script to each of them
-for fn ; do
+for fn do
ed -s -- "$fn" <<'EOF' || ex=1
g/ *$/ s/ *$//
w
diff --git a/bin/sue.sh b/bin/sue.sh
index 654c041f..34343e4a 100644
--- a/bin/sue.sh
+++ b/bin/sue.sh
@@ -4,7 +4,7 @@
user=
# Iterate over the given files
-for file ; do
+for file do
# Get the file's owner, or bail
file_owner=$(stat -c %U -- "$file") || exit
diff --git a/bin/u2d.sh b/bin/u2d.sh
index 31030341..cdbe9a33 100644
--- a/bin/u2d.sh
+++ b/bin/u2d.sh
@@ -10,7 +10,7 @@ fi
r=$(printf '\r')
# Iterate over arguments and apply the same ed(1) script to each of them
-for fn ; do
+for fn do
# Note the heredoc WORD is intentionally unquoted because we want to expand
# $r within it to get a literal carriage return; the escape characters
diff --git a/bin/xgo.sh b/bin/xgo.sh
index 3fb11fde..e627f9c6 100644
--- a/bin/xgo.sh
+++ b/bin/xgo.sh
@@ -7,7 +7,7 @@ if [ "$#" -eq 0 ] ; then
fi
# Iterate over the URL arguments
-for url ; do (
+for url do (
# Look for patterns in the URL that suggest transformations
case $url in
diff --git a/check/bash.sh b/check/bash.sh
index 1f9e1b38..510f2af0 100644
--- a/check/bash.sh
+++ b/check/bash.sh
@@ -5,7 +5,7 @@ set \
bash/bash_profile \
bash/bashrc \
bash/bashrc.d/*.bash
-for bash ; do
+for bash do
bash -n -- "$bash" || exit
done
printf 'GNU Bash dotfiles parsed successfully.\n'
diff --git a/check/ksh.sh b/check/ksh.sh
index f4bade82..cf83bc1f 100644
--- a/check/ksh.sh
+++ b/check/ksh.sh
@@ -1,7 +1,7 @@
set \
ksh/kshrc \
ksh/kshrc.d/*.ksh
-for ksh ; do
+for ksh do
ksh -n -- "$ksh" || exit
done
sh -n -- ksh/shrc.d/ksh.sh || exit
diff --git a/check/sh.sh b/check/sh.sh
index 92910c11..e0162f47 100644
--- a/check/sh.sh
+++ b/check/sh.sh
@@ -4,7 +4,7 @@ set \
sh/shinit \
sh/shrc \
sh/shrc.d/*.sh
-for sh ; do
+for sh do
sh -n -- "$sh" || exit
done
printf 'POSIX shell dotfiles parsed successfully.\n'
diff --git a/check/xinit.sh b/check/xinit.sh
index fa235c9d..ae03b8c2 100644
--- a/check/xinit.sh
+++ b/check/xinit.sh
@@ -1,7 +1,7 @@
set \
X/xinitrc \
X/xinitrc.d/*.sh
-for xinit ; do
+for xinit do
sh -n -- "$xinit" || exit
done
printf 'Xinit startup scripts parsed successfully.\n'
diff --git a/check/zsh.sh b/check/zsh.sh
index ce209584..0170e586 100644
--- a/check/zsh.sh
+++ b/check/zsh.sh
@@ -2,7 +2,7 @@ set \
zsh/zprofile \
zsh/zshrc.d/*.zsh \
zsh/zshrc
-for zsh ; do
+for zsh do
zsh -n -- "$zsh" || exit
done
sh -n zsh/profile.d/zsh.sh || exit
diff --git a/ksh/kshrc.d/keep.ksh b/ksh/kshrc.d/keep.ksh
index f6593c3d..629b2fe6 100644
--- a/ksh/kshrc.d/keep.ksh
+++ b/ksh/kshrc.d/keep.ksh
@@ -94,7 +94,7 @@ EOF
# Iterate through the NAMEs given
typeset name
- for name ; do
+ for name do
# Check NAMEs for validity
case $name in
diff --git a/readline/inputrc b/readline/inputrc
index c11d8fe7..857952cd 100644
--- a/readline/inputrc
+++ b/readline/inputrc
@@ -62,6 +62,12 @@ $if Bash
# Alt+A cycles through completion options
"\ea": menu-complete
+ # Special completion keys for git(1)
+ ## Branches
+ "\C-xb": complete
+ ## Tags
+ "\C-xt": complete
+
# Ctrl-Alt-L to clear screen; more ksh-like
"\e\C-l": clear-screen
diff --git a/sh/profile b/sh/profile
index 68e803ca..7f16cb32 100644
--- a/sh/profile
+++ b/sh/profile
@@ -1,5 +1,7 @@
# Add ~/.local/bin to PATH if it exists
-[ -d "$HOME"/.local/bin ] && PATH=$HOME/.local/bin:$PATH
+if [ -d "$HOME"/.local/bin ] ; then
+ PATH=$HOME/.local/bin:$PATH
+fi
# Load all supplementary scripts in ~/.profile.d
for sh in "$HOME"/.profile.d/*.sh ; do
@@ -13,11 +15,3 @@ if [ -f "$HOME"/.shinit ] ; then
ENV=$HOME/.shinit
export ENV
fi
-
-# If ENV_FORCE is set and we're interactive, source ENV explicitly
-# At the moment this is just for zsh-as-ksh/sh
-if [ -n "$ENV_FORCE" ] ; then
- case $- in *i*)
- [ -f "$ENV" ] && . "$ENV" ;;
- esac
-fi
diff --git a/sh/profile.d/downloads.sh b/sh/profile.d/downloads.sh
index 865cb859..1a89bc3f 100644
--- a/sh/profile.d/downloads.sh
+++ b/sh/profile.d/downloads.sh
@@ -8,7 +8,7 @@ esac
[ -z "$TMUX" ] || return
# Not if ~/.hushlogin exists
-[ -e "$HOME"/.hushlogin ] && return
+! [ -e "$HOME"/.hushlogin ] || return
# Not if ~/.downloads doesn't
[ -f "$HOME"/.downloads ] || return
@@ -27,5 +27,7 @@ esac
printf 'You have %u unsorted files in %s.\n' "$#" "$dir"
lc=$((lc+1))
done < "$HOME"/.downloads
- [ "$((lc > 0))" -eq 1 ] && printf '\n'
+ if [ "$lc" -gt 0 ] ; then
+ printf '\n'
+ fi
)
diff --git a/sh/profile.d/options.sh b/sh/profile.d/options.sh
index 73f62243..58376fb3 100644
--- a/sh/profile.d/options.sh
+++ b/sh/profile.d/options.sh
@@ -22,9 +22,10 @@ options() {
# Iterate through remaining arguments (desired options), creating files to
# show they're available if found in the help output
- for opt ; do
- command -p grep -q -- '[^[:alnum:]]--'"$opt"'[^[:alnum:]]' help &&
- touch -- "$opt"
+ for opt do
+ command -p grep -q -- \
+ '[^[:alnum:]]--'"$opt"'[^[:alnum:]]' help || continue
+ touch -- "$opt"
done
}
diff --git a/sh/profile.d/welcome.sh b/sh/profile.d/welcome.sh
index ede7a05f..cdd41edb 100644
--- a/sh/profile.d/welcome.sh
+++ b/sh/profile.d/welcome.sh
@@ -20,8 +20,10 @@ esac
# Show a fortune
if welcome fortune ; then
- [ -d "$HOME"/.local/share/games/fortunes ] &&
- : "${FORTUNE_PATH:="$HOME"/.local/share/games/fortunes}"
+ if ! [ -n "$FORTUNE_PATH"] &&
+ [ -d "$HOME"/.local/share/games/fortunes ] ; then
+ FORTUNE_PATH=$HOME/.local/share/games/fortunes
+ fi
fortune -s "$FORTUNE_PATH"
printf '\n'
fi
@@ -34,7 +36,9 @@ esac
# Run verse(1) if we haven't seen it already today
if welcome verse ; then
- [ -f "$HOME"/.verse ] && read -r last <"$HOME"/.verse
+ if [ -f "$HOME"/.verse ] ; then
+ read -r last <"$HOME"/.verse
+ fi
now=$(date +%Y%m%d)
if [ "$now" -gt "${last:-0}" ] ; then
verse
diff --git a/sh/shinit b/sh/shinit
index fe770a70..fb72cd14 100644
--- a/sh/shinit
+++ b/sh/shinit
@@ -1,4 +1,7 @@
-# If the shell is interactive, source ~/.shrc
-case $- in *i*)
- [ -f "$HOME"/.shrc ] && . "$HOME"/.shrc ;;
+# If the shell is interactive, and ~/.shrc exists, source it
+case $- in
+ *i*)
+ if [ -f "$HOME"/.shrc ] ; then
+ . "$HOME"/.shrc
+ fi
esac
diff --git a/sh/shrc b/sh/shrc
index 6359dbc3..808e944d 100644
--- a/sh/shrc
+++ b/sh/shrc
@@ -22,5 +22,7 @@ done
unset -v sh
# If ENV_EXT was set and exists, source that too, then clean it away
-[ -e "$ENV_EXT" ] && . "$ENV_EXT"
+if [ -e "$ENV_EXT" ] ; then
+ . "$ENV_EXT"
+fi
unset -v ENV_EXT
diff --git a/sh/shrc.d/bc.sh b/sh/shrc.d/bc.sh
index aee88e09..591b4359 100644
--- a/sh/shrc.d/bc.sh
+++ b/sh/shrc.d/bc.sh
@@ -6,8 +6,9 @@
bc() {
# Add --quiet to stop the annoying welcome banner
- [ -e "$HOME"/.cache/sh/opt/bc/quiet ] &&
+ if [ -e "$HOME"/.cache/sh/opt/bc/quiet ] ; then
set -- --quiet "$@"
+ fi
# Run bc(1) with the concluded arguments
command bc "$@"
diff --git a/sh/shrc.d/ed.sh b/sh/shrc.d/ed.sh
index e6b6eee8..dc8433f6 100644
--- a/sh/shrc.d/ed.sh
+++ b/sh/shrc.d/ed.sh
@@ -12,16 +12,18 @@ ed() {
fi
# Add --verbose to explain errors
- [ -e "$HOME"/.cache/sh/opt/ed/verbose ] &&
+ if [ -e "$HOME"/.cache/sh/opt/ed/verbose ] ; then
set -- --verbose "$@"
+ fi
# Add an asterisk prompt (POSIX feature)
set -- -p\* "$@"
# Run in rlwrap(1) if available
set -- ed "$@"
- command -v rlwrap >/dev/null 2>&1 &&
+ if command -v rlwrap >/dev/null 2>&1 ; then
set -- rlwrap --history-filename=/dev/null "$@"
+ fi
# Run determined command
command "$@"
diff --git a/sh/shrc.d/grep.sh b/sh/shrc.d/grep.sh
index 43797ef5..997babc9 100644
--- a/sh/shrc.d/grep.sh
+++ b/sh/shrc.d/grep.sh
@@ -9,37 +9,43 @@ unset -v GREP_OPTIONS
grep() {
# Add --binary-files=without-match to gracefully skip binary files
- [ -e "$HOME"/.cache/sh/opt/grep/binary-files ] &&
+ if [ -e "$HOME"/.cache/sh/opt/grep/binary-files ] ; then
set -- --binary-files=without-match "$@"
+ fi
# Add --color=auto if the terminal has at least 8 colors
- [ -e "$HOME"/.cache/sh/opt/grep/color ] &&
- [ "$({ tput colors||tput Co||echo 0; } 2>/dev/null)" -ge 8 ] &&
+ if [ -e "$HOME"/.cache/sh/opt/grep/color ] &&
+ [ "$({ tput colors||tput Co||echo 0; } 2>/dev/null)" -ge 8 ] ; then
set -- --color=auto "$@"
+ fi
# Add --devices=skip to gracefully skip devices
- [ -e "$HOME"/.cache/sh/opt/grep/devices ] &&
+ if [ -e "$HOME"/.cache/sh/opt/grep/devices ] ; then
set -- --devices=skip "$@"
+ fi
# Add --directories=skip to gracefully skip directories
- [ -e "$HOME"/.cache/sh/opt/grep/directories ] &&
+ if [ -e "$HOME"/.cache/sh/opt/grep/directories ] ; then
set -- --directories=skip "$@"
+ fi
# Add --exclude to ignore .gitignore and .gitmodules files
- [ -e "$HOME"/.cache/sh/opt/grep/exclude ] &&
+ if [ -e "$HOME"/.cache/sh/opt/grep/exclude ] ; then
set -- \
--exclude=.gitignore \
--exclude=.gitmodules \
"$@"
+ fi
# Add --exclude-dir to ignore version control dot-directories
- [ -e "$HOME"/.cache/sh/opt/grep/exclude-dir ] &&
+ if [ -e "$HOME"/.cache/sh/opt/grep/exclude-dir ] ; then
set -- \
--exclude-dir=.cvs \
--exclude-dir=.git \
--exclude-dir=.hg \
--exclude-dir=.svn \
"$@"
+ fi
# Run grep(1) with the concluded arguments
command grep "$@"
diff --git a/sh/shrc.d/gt.sh b/sh/shrc.d/gt.sh
index 95ab4c2f..7a52571d 100644
--- a/sh/shrc.d/gt.sh
+++ b/sh/shrc.d/gt.sh
@@ -19,7 +19,9 @@ gt() {
done
# If target isn't a directory, chop to its parent
- [ -d "$1" ] || set -- "${1%/*}"
+ if ! [ -d "$1" ] ; then
+ set -- "${1%/*}"
+ fi
# Try to change into the determined directory, or root if empty
command cd -- "${1:-/}"
diff --git a/sh/shrc.d/ls.sh b/sh/shrc.d/ls.sh
index 7e843cc7..1083dfca 100644
--- a/sh/shrc.d/ls.sh
+++ b/sh/shrc.d/ls.sh
@@ -12,26 +12,30 @@ unset -v LS_OPTIONS LS_COLORS
# Define function proper
ls() {
- # -F to show trailing indicators of the filetype
- # -q to replace control chars with '?'
+ # POSIX options:
+ ## -F to show trailing indicators of the filetype
+ ## -q to replace control chars with '?'
set -- -Fq "$@"
-
- # If output is to a terminal, add -x to format entries across, not down
- [ -t 1 ] && set -- -x "$@"
-
- # Add --block-size=K to always show the filesize in kibibytes
- [ -e "$HOME"/.cache/sh/opt/ls/block-size ] &&
+ ## -x to format entries across, not down, if output looks like a terminal
+ if [ -t 1 ] ; then
+ set -- -x "$@"
+ fi
+
+ # GNU options:
+ ## Add --block-size=K to always show the filesize in kibibytes
+ if [ -e "$HOME"/.cache/sh/opt/ls/block-size ] ; then
set -- --block-size=1024 "$@"
-
- # Add --color if the terminal has at least 8 colors
- [ -e "$HOME"/.cache/sh/opt/ls/color ] &&
- [ "$({ tput colors||tput Co||echo 0; } 2>/dev/null)" -ge 8 ] &&
+ fi
+ ## Add --color if the terminal has at least 8 colors
+ if [ -e "$HOME"/.cache/sh/opt/ls/color ] &&
+ [ "$(exec 2>/dev/null;tput colors||tput Co||echo 0)" -ge 8 ] ; then
set -- --color=auto "$@"
-
- # Add --time-style='+%Y-%m-%d %H:%M:%S' to show the date in my preferred
- # (fixed) format
- [ -e "$HOME"/.cache/sh/opt/ls/time-style ] &&
+ fi
+ ## Add --time-style='+%Y-%m-%d %H:%M:%S' to show the date in my preferred
+ ## (fixed) format
+ if [ -e "$HOME"/.cache/sh/opt/ls/time-style ] ; then
set -- --time-style='+%Y-%m-%d %H:%M:%S' "$@"
+ fi
# If the operating system is FreeBSD, there are some specific options we
# can add that might mean different things to e.g. GNU ls(1)
diff --git a/sh/shrc.d/mkcd.sh b/sh/shrc.d/mkcd.sh
index c59a8c54..cd882b51 100644
--- a/sh/shrc.d/mkcd.sh
+++ b/sh/shrc.d/mkcd.sh
@@ -1,4 +1,5 @@
# Create a directory and change into it
mkcd() {
- mkdir -p -- "$1" && command cd -- "$1"
+ command -p mkdir -p -- "$1" || return
+ command cd -- "$1"
}
diff --git a/sh/shrc.d/path.sh b/sh/shrc.d/path.sh
index b6b1820f..a854e148 100644
--- a/sh/shrc.d/path.sh
+++ b/sh/shrc.d/path.sh
@@ -5,15 +5,16 @@ path() {
case $1 in
# List current directories in PATH
- list|'') (
- path=$PATH:
- while [ -n "$path" ] ; do
- dir=${path%%:*}
- path=${path#*:}
- [ -n "$dir" ] || continue
- printf '%s\n' "$dir"
+ list|'')
+ set -- "$PATH":
+ while [ -n "$1" ] ; do
+ case $1 in
+ :*) ;;
+ *) printf '%s\n' "${1%%:*}" ;;
+ esac
+ set -- "${1#*:}"
done
- ) ;;
+ ;;
# Helper function checks directory argument makes sense
_argcheck)
@@ -33,7 +34,9 @@ path() {
# Add a directory at the start of $PATH
insert)
- [ "$#" -eq 2 ] || set -- "$1" "$PWD"
+ if ! [ "$#" -eq 2 ] ; then
+ set -- "$1" "$PWD"
+ fi
path _argcheck "$@" || return
if path check "$2" ; then
printf >&2 'path(): %s: %s already in PATH\n' "$@"
@@ -44,7 +47,9 @@ path() {
# Add a directory to the end of $PATH
append)
- [ "$#" -eq 2 ] || set -- "$1" "$PWD"
+ if ! [ "$#" -eq 2 ] ; then
+ set -- "$1" "$PWD"
+ fi
path _argcheck "$@" || return
if path check "$2" ; then
printf >&2 'path(): %s: %s already in PATH\n' "$@"
@@ -55,7 +60,9 @@ path() {
# Remove a directory from $PATH
remove)
- [ "$#" -eq 2 ] || set -- "$1" "$PWD"
+ if ! [ "$#" -eq 2 ] ; then
+ set -- "$1" "$PWD"
+ fi
path _argcheck "$@" || return
if ! path check "$2" ; then
printf >&2 'path(): %s: %s not in PATH\n' "$@"
@@ -107,7 +114,9 @@ path() {
# Check whether a directory is in PATH
check)
path _argcheck "$@" || return
- [ "$#" -eq 2 ] || set -- "$1" "$PWD"
+ if ! [ "$#" -eq 2 ] ; then
+ set -- "$1" "$PWD"
+ fi
case :$PATH: in
*:"$2":*) return 0 ;;
esac
diff --git a/sh/shrc.d/tree.sh b/sh/shrc.d/tree.sh
index d462f3e1..a7e5bef3 100644
--- a/sh/shrc.d/tree.sh
+++ b/sh/shrc.d/tree.sh
@@ -22,7 +22,7 @@ tree() {
[ -t 1 ] || exit
# Not if output terminal doesn't have at least 8 colors
- [ "$({ tput colors||tput Co||echo 0; } 2>/dev/null)" -ge 8 ]
+ [ "$(exec 2>/dev/null;tput colors||tput Co||echo 0)" -ge 8 ]
) ; then
set -- -C "$@"
diff --git a/sh/shrc.d/vr.sh b/sh/shrc.d/vr.sh
index 8b35357c..c7057ec2 100644
--- a/sh/shrc.d/vr.sh
+++ b/sh/shrc.d/vr.sh
@@ -11,9 +11,14 @@ vr() {
exit 2
fi
- # Get path from first argument, strip trailing slash
+ # Get path from first argument
path=${1:-"$PWD"}
- [ "$path" = / ] || path=${path%/}
+
+ # Strip a trailing slash
+ case $path in
+ (/) ;;
+ (*) path=${path%/} ;;
+ esac
# Step into the directory
cd -- "$path" || exit
@@ -34,7 +39,7 @@ vr() {
# that is the root (bad)
while svn info >/dev/null 2>&1 ; do
root=$PWD
- [ "$root" = / ] && break
+ ! [ "$root" = / ] || break
cd .. || exit
done
if [ -n "$root" ] ; then
diff --git a/vim/autoload/filetype.vim b/vim/autoload/filetype.vim
new file mode 100644
index 00000000..d1e4e3d7
--- /dev/null
+++ b/vim/autoload/filetype.vim
@@ -0,0 +1,76 @@
+" Helper function to run the 'filetypedetect' group on a file with its
+" extension stripped off
+function! filetype#StripRepeat() abort
+
+ " Check we have the fnameescape() function
+ if !exists('*fnameescape')
+ return
+ endif
+
+ " Expand the match result
+ let l:fn = expand('<afile>')
+
+ " Strip leading and trailing #hashes#
+ if l:fn =~# '^#\+.*#\+$'
+ let l:fn = substitute(l:fn, '^#\+\(.\+\)#\+$', '\1', '')
+
+ " Strip trailing tilde~
+ elseif l:fn =~# '\~$'
+ let l:fn = substitute(l:fn, '\~$', '', '')
+
+ " Strip generic .extension
+ else
+ let l:fn = expand('<afile>:r')
+ endif
+
+ " Re-run the group if there's anything left
+ if strlen(l:fn)
+ execute 'doautocmd filetypedetect BufRead ' . fnameescape(l:fn)
+ endif
+
+endfunction
+
+" Helper function to run the 'filetypedetect' group on a file in a temporary
+" sudoedit(8) directory, modifying it with an attempt to reverse the temporary
+" filename change
+function! filetype#SudoRepeat() abort
+
+ " Check we have the fnameescape() function
+ if !exists('*fnameescape')
+ return
+ endif
+
+ " Expand the match result
+ let l:fn = expand('<afile>')
+
+ " myfileXXQGS16A.conf: strip eight chars before final period
+ if l:fn =~# '/[^./]\+\w\{8}\.[^./]\+$'
+ let l:fr = expand('<afile>:r')
+ let l:fe = expand('<afile>:e')
+ let l:fn = strpart(l:fr, -8, strlen(l:fr)) . '.' . l:fe
+
+ " myfile.XXQGS16A: strip extension
+ elseif l:fn =~# '/[^./]\+\.\w\{8}$'
+ let l:fn = expand('<afile>:r')
+
+ " Unrecognised pattern; return, don't repeat
+ else
+ return
+ endif
+
+ " Re-run the group if there's anything left
+ if strlen(l:fn)
+ execute 'doautocmd filetypedetect BufRead ' . fnameescape(l:fn)
+ endif
+
+endfunction
+
+" Check whether the first line was changed and looks like a shebang, and if
+" so, re-run filetype detection
+function! filetype#CheckShebang() abort
+ if line('''[') == 1 && getline(1) =~# '^#!'
+ doautocmd filetypedetect BufRead
+ endif
+endfunction
+
+
diff --git a/vim/filetype.vim b/vim/filetype.vim
index cc0de4e4..3ac816d4 100644
--- a/vim/filetype.vim
+++ b/vim/filetype.vim
@@ -10,81 +10,6 @@ if !has('autocmd') || &compatible
finish
endif
-" Helper function to run the 'filetypedetect' group on a file with its
-" extension stripped off
-function! s:StripRepeat()
-
- " Check we have the fnameescape() function
- if !exists('*fnameescape')
- return
- endif
-
- " Expand the match result
- let l:fn = expand('<afile>')
-
- " Strip leading and trailing #hashes#
- if l:fn =~# '^#\+.*#\+$'
- let l:fn = substitute(l:fn, '^#\+\(.\+\)#\+$', '\1', '')
-
- " Strip trailing tilde~
- elseif l:fn =~# '\~$'
- let l:fn = substitute(l:fn, '\~$', '', '')
-
- " Strip generic .extension
- else
- let l:fn = expand('<afile>:r')
- endif
-
- " Re-run the group if there's anything left
- if strlen(l:fn)
- execute 'doautocmd filetypedetect BufRead ' . fnameescape(l:fn)
- endif
-
-endfunction
-
-" Helper function to run the 'filetypedetect' group on a file in a temporary
-" sudoedit(8) directory, modifying it with an attempt to reverse the temporary
-" filename change
-function! s:SudoRepeat()
-
- " Check we have the fnameescape() function
- if !exists('*fnameescape')
- return
- endif
-
- " Expand the match result
- let l:fn = expand('<afile>')
-
- " myfileXXQGS16A.conf: strip eight chars before final period
- if l:fn =~# '/[^./]\+\w\{8}\.[^./]\+$'
- let l:fr = expand('<afile>:r')
- let l:fe = expand('<afile>:e')
- let l:fn = strpart(l:fr, -8, strlen(l:fr)) . '.' . l:fe
-
- " myfile.XXQGS16A: strip extension
- elseif l:fn =~# '/[^./]\+\.\w\{8}$'
- let l:fn = expand('<afile>:r')
-
- " Unrecognised pattern; return, don't repeat
- else
- return
- endif
-
- " Re-run the group if there's anything left
- if strlen(l:fn)
- execute 'doautocmd filetypedetect BufRead ' . fnameescape(l:fn)
- endif
-
-endfunction
-
-" Check whether the first line was changed and looks like a shebang, and if
-" so, re-run filetype detection
-function! s:CheckShebang()
- if line('''[') == 1 && getline(1) =~# '^#!'
- doautocmd filetypedetect BufRead
- endif
-endfunction
-
" Use our own filetype detection rules
augroup filetypedetect
autocmd!
@@ -97,7 +22,7 @@ augroup filetypedetect
\,?*~
\,?*.{bak,example,in,new,old,orig,sample,test}
\,?*.dpkg-{bak,dist,new,old}
- \ call s:StripRepeat()
+ \ call filetype#StripRepeat()
" Stuff Tom cares about enough and edits often enough to type based on
" filename patterns follows.
@@ -534,7 +459,7 @@ augroup filetypedetect
\ /var/tmp/?*????????.*
\,/var/tmp/?*.????????
\ if !did_filetype()
- \| call s:SudoRepeat()
+ \| call filetype#SudoRepeat()
\|endif
" Generic text, config, and log files, if no type assigned yet
@@ -568,6 +493,6 @@ augroup filetypedetect
" On leaving insert mode, check whether the first line was changed and looks
" like a shebang format, and if so, re-run filetype detection
- autocmd InsertLeave * call s:CheckShebang()
+ autocmd InsertLeave * call filetype#CheckShebang()
augroup END
diff --git a/zsh/profile.d/zsh.sh b/zsh/profile.d/zsh.sh
index 47de6d4d..37ec8014 100644
--- a/zsh/profile.d/zsh.sh
+++ b/zsh/profile.d/zsh.sh
@@ -5,24 +5,33 @@
# ~/.profile is read. This seems to have been fixed in Zsh commit ID fde365e,
# which was followed by release 5.3.0.
-# Is this zsh masquerading as sh/ksh?
+# This hack is only applicable to interactive zsh invoked as sh/ksh, when ENV
+# exists, so check each of those:
+## Interactive?
+case $- in
+ *i*) ;;
+ *) return ;;
+esac
+## zsh?
[ -n "$ZSH_VERSION" ] || return
+## Invoked as sh or ksh?
case $ZSH_NAME in
sh|ksh) ;;
*) return ;;
esac
+## ENV exists?
+[ -e "$ENV" ] || return
# Iterate through the zsh version number to see if it's at least 5.3.0; if not,
-# we'll have ~/.profile force sourcing $ENV
-if ! (
+# we'll source $ENV ourselves, since ~/.profile probably didn't do it
+if (
zvs=$ZSH_VERSION
for fv in 5 3 0 ; do
zv=${zvs%%[!0-9]*}
- [ "$((zv > fv))" -eq 1 ] && exit 0
- [ "$((zv < fv))" -eq 1 ] && exit 1
- zvs=${zvs#*.}
- [ -n "$zvs" ] || exit 0
+ ! [ "$zv" -gt "$fv" ] || exit 1
+ ! [ "$zv" -lt "$fv" ] || exit 0
+ zvs=${ZSH_VERSION#*.}
done
) ; then
- ENV_FORCE=1
+ . "$ENV"
fi
diff --git a/zsh/zshrc.d/keep.zsh b/zsh/zshrc.d/keep.zsh
index 59696301..c47748cd 100644
--- a/zsh/zshrc.d/keep.zsh
+++ b/zsh/zshrc.d/keep.zsh
@@ -83,7 +83,7 @@ EOF
# Iterate through the NAMEs given
local name
- for name ; do
+ for name do
# Check NAMEs for validity
case $name in