aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2016-08-19 23:22:51 +1200
committerTom Ryder <tom@sanctum.geek.nz>2016-08-19 23:22:51 +1200
commit6daae9a75afa12f929be810a52ad21139233adfa (patch)
tree409f8935029dca341ee4809581d375bd3a42cae4
parentMerge branch 'master' into freebsd (diff)
parentUpdate documentation for br(1) and xgo(1) (diff)
downloaddotfiles-6daae9a75afa12f929be810a52ad21139233adfa.tar.gz
dotfiles-6daae9a75afa12f929be810a52ad21139233adfa.zip
Merge branch 'master' into freebsd
-rw-r--r--.gitignore3
-rw-r--r--ISSUES.markdown24
-rw-r--r--Makefile160
-rw-r--r--README.markdown110
-rw-r--r--bash/bash_completion.d/man.bash4
-rw-r--r--bash/bash_profile16
-rw-r--r--bash/bashrc38
-rw-r--r--bash/bashrc.d/cd.bash32
-rw-r--r--bash/bashrc.d/grep.bash33
-rw-r--r--bash/bashrc.d/keychain.bash4
-rw-r--r--bash/bashrc.d/lhn.bash7
-rw-r--r--bash/bashrc.d/ls.bash20
-rw-r--r--bash/bashrc.d/prompt.bash14
-rw-r--r--bash/bashrc.d/scp.bash10
-rw-r--r--bash/bashrc.d/scr.bash12
-rw-r--r--bash/bashrc.d/vim.bash15
-rwxr-xr-xbin/apf80
-rwxr-xr-xbin/dmp11
-rwxr-xr-xbin/edda63
-rwxr-xr-xbin/eds86
-rwxr-xr-xbin/fgscr2
-rwxr-xr-xbin/han22
-rwxr-xr-xbin/plmu2
-rw-r--r--[-rwxr-xr-x]bin/rfct.awk (renamed from bin/rfct)2
-rw-r--r--[-rwxr-xr-x]bin/rndi.awk (renamed from bin/rndi)1
-rwxr-xr-xbin/rndl6
-rwxr-xr-xbin/shb2
-rw-r--r--[-rwxr-xr-x]bin/slsf.awk (renamed from bin/slsf)1
-rwxr-xr-xbin/stws2
-rwxr-xr-xbin/td6
-rwxr-xr-xbin/tlcs3
-rwxr-xr-xbin/try5
-rwxr-xr-xbin/urlc7
-rwxr-xr-xbin/urlh2
-rwxr-xr-xbin/urlmt8
-rwxr-xr-xbin/xgo14
-rwxr-xr-x[-rw-r--r--]bin/xgoc0
-rwxr-xr-xcheck/bash (renamed from test/bash)0
-rwxr-xr-xcheck/bin (renamed from test/bin)2
-rwxr-xr-xcheck/games (renamed from test/games)2
-rwxr-xr-xcheck/man (renamed from test/man)7
-rwxr-xr-xcheck/pdksh (renamed from test/pdksh)0
-rwxr-xr-xcheck/sh (renamed from test/sh)2
-rwxr-xr-xcheck/urxvt (renamed from test/urxvt)0
-rw-r--r--dircolors/dircolors117
-rw-r--r--games/kvlt.sed6
-rwxr-xr-xgames/rndn82
-rw-r--r--git/gitconfig.m45
-rw-r--r--man/man1/apf.174
-rw-r--r--man/man1/br.112
-rw-r--r--man/man1/dmp.114
-rw-r--r--man/man1/edda.110
-rw-r--r--man/man1/unf.12
-rw-r--r--man/man1/xgo.18
-rw-r--r--man/man7/dotfiles.7.header1
-rw-r--r--pdksh/pdkshrc5
-rw-r--r--pdksh/pdkshrc.d/diff.pdksh4
-rw-r--r--pdksh/pdkshrc.d/ed.pdksh26
-rw-r--r--pdksh/pdkshrc.d/gdb.pdksh4
-rw-r--r--pdksh/pdkshrc.d/gpg.pdksh10
-rw-r--r--pdksh/pdkshrc.d/keychain.pdksh4
-rw-r--r--pdksh/pdkshrc.d/mkcd.pdksh4
-rw-r--r--pdksh/pdkshrc.d/prompt.pdksh7
-rw-r--r--pdksh/pdkshrc.d/pwgen.pdksh8
-rw-r--r--pdksh/pdkshrc.d/rcsdiff.pdksh4
-rw-r--r--pdksh/pdkshrc.d/scp.pdksh9
-rw-r--r--pdksh/pdkshrc.d/sudo.pdksh7
-rw-r--r--pdksh/pdkshrc.d/tmux.pdksh19
-rw-r--r--sh/profile13
-rw-r--r--sh/profile.d/editor.sh7
-rw-r--r--sh/profile.d/env.sh10
-rw-r--r--sh/profile.d/grep.sh30
-rw-r--r--sh/profile.d/ls.sh34
-rw-r--r--sh/profile.d/pager.sh2
-rw-r--r--sh/profile.d/visual.sh3
-rw-r--r--sh/shrc12
-rw-r--r--sh/shrc.d/bc.sh (renamed from bash/bashrc.d/bc.bash)0
-rw-r--r--sh/shrc.d/cd.sh72
-rw-r--r--sh/shrc.d/diff.sh (renamed from bash/bashrc.d/diff.bash)0
-rw-r--r--sh/shrc.d/ed.sh (renamed from bash/bashrc.d/ed.bash)4
-rw-r--r--sh/shrc.d/env.sh8
-rw-r--r--sh/shrc.d/gdb.sh (renamed from bash/bashrc.d/gdb.bash)0
-rw-r--r--sh/shrc.d/gpg.sh (renamed from bash/bashrc.d/gpg.bash)0
-rw-r--r--sh/shrc.d/grep.sh35
-rw-r--r--sh/shrc.d/hgrep.sh (renamed from bash/bashrc.d/hgrep.bash)8
-rw-r--r--sh/shrc.d/keychain.sh3
-rw-r--r--sh/shrc.d/ksh.sh10
-rw-r--r--sh/shrc.d/ls.sh15
-rw-r--r--sh/shrc.d/mkcd.sh (renamed from bash/bashrc.d/mkcd.bash)0
-rw-r--r--sh/shrc.d/mysql.sh (renamed from bash/bashrc.d/mysql.bash)6
-rw-r--r--sh/shrc.d/pwgen.sh (renamed from bash/bashrc.d/pwgen.bash)0
-rw-r--r--sh/shrc.d/rcsdiff.sh (renamed from bash/bashrc.d/rcsdiff.bash)0
-rw-r--r--sh/shrc.d/scp.sh14
-rw-r--r--sh/shrc.d/scr.sh (renamed from pdksh/pdkshrc.d/scr.pdksh)7
-rw-r--r--sh/shrc.d/sudo.sh (renamed from bash/bashrc.d/sudo.bash)4
-rw-r--r--sh/shrc.d/tmux.sh (renamed from bash/bashrc.d/tmux.bash)2
-rw-r--r--sh/shrc.d/vim.sh (renamed from pdksh/pdkshrc.d/vim.pdksh)4
m---------vim/bundle/abolish0
m---------vim/bundle/targets0
-rw-r--r--vim/vimrc2
-rw-r--r--zsh/zprofile6
-rw-r--r--zsh/zshrc12
102 files changed, 728 insertions, 877 deletions
diff --git a/.gitignore b/.gitignore
index 45f195cf..7b4a8107 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,7 @@
+bin/rfct
+bin/rndi
bin/sd2u
+bin/slsf
bin/su2d
bin/unf
games/acq
diff --git a/ISSUES.markdown b/ISSUES.markdown
index a94cf846..68c6c482 100644
--- a/ISSUES.markdown
+++ b/ISSUES.markdown
@@ -8,22 +8,14 @@ Known issues
* man(1) completion doesn't work on OpenBSD as manpath(1) isn't a thing on
that system; need to find some way of finding which manual directories
should be searched at runtime, if there is one.
-* mktemp(1) is not POSIX, though it's commonly available; where a temporary
- file is unavoidable, it might be nice to abstract this with a wrapper
- script that uses mktemp(1) if it can, but otherwise uses mkdir(1) with a
- randomised name in "${TMPDIR:-/tmp}". Is mktemp(1) on every *BSD?
- - Mostly fixed now with mktd(1), still using mktemp(1) in a few places
-* Where practical, the remaining Bash scripts in bin need to be reimplemented
- as POSIX sh
- - Mostly done now:
-
- [tom@conan:~/.dotfiles/bin](git:master)$ grep bash *
- apf:#!/usr/bin/env bash
- edda:#!/usr/bin/env bash
- eds:#!/usr/bin/env bash
- han:#!/usr/bin/env bash
- jfcd:#!/usr/bin/env bash
-
* OpenBSD doesn't have a `pandoc` package at all. It would be nice to find
some way of converting the README.markdown into a palatable troff format
with some more readily available (and preferably less heavyweight) tool.
+* At least one of the completion scripts (pass.bash) hangs on empty
+ completions (i.e. nothing matches the search term) in Bash 4.4rc1; the last
+ thing bash -x shows is an "exit 1" hang
+* The checks gscr(1) makes to determine where it is are a bit naive (don't
+ work with bare repos) and could probably be improved with some appropriate
+ git-reflog(1) cals
+* The \xFF syntax for regex as used in rfct(1) is not POSIX. Need to decide
+ if it's well-supported enough to keep it anyway.
diff --git a/Makefile b/Makefile
index 8e724663..5d8369c9 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,6 @@
install-bin \
install-bin-man \
install-curl \
- install-dircolors \
install-dotfiles-man \
install-dunst \
install-finger \
@@ -42,12 +41,12 @@
install-wyrd \
install-x \
install-zsh \
- test \
- test-bash \
- test-bin \
- test-games \
- test-sh \
- test-urxvt \
+ check \
+ check-bash \
+ check-bin \
+ check-games \
+ check-sh \
+ check-urxvt \
lint \
lint-bash \
lint-bin \
@@ -55,16 +54,28 @@
lint-sh \
lint-urxvt
+.SUFFIXES: .awk .sed
+
NAME := Tom Ryder
EMAIL := tom@sanctum.geek.nz
KEY := 0xC14286EA77BB8872
SENDMAIL := /usr/bin/msmtp
-all : bin/sd2u bin/su2d bin/unf git/gitconfig gnupg/gpg.conf
+all : bin/rfct \
+ bin/rndi \
+ bin/sd2u \
+ bin/slsf \
+ bin/su2d \
+ bin/unf \
+ git/gitconfig \
+ gnupg/gpg.conf
clean distclean :
rm -f \
+ bin/rfct \
+ bin/rndi \
bin/sd2u \
+ bin/slsf \
bin/su2d \
bin/unf \
games/acq \
@@ -76,30 +87,6 @@ clean distclean :
mutt/muttrc \
tmux/tmux.conf
-bin/sd2u : bin/sd2u.sed
- bin/shb bin/sd2u.sed sed -f > "$@"
- chmod +x "$@"
-
-bin/su2d : bin/su2d.sed
- bin/shb bin/su2d.sed sed -f > "$@"
- chmod +x "$@"
-
-bin/unf : bin/unf.sed
- bin/shb bin/unf.sed sed -f > "$@"
- chmod +x "$@"
-
-games/acq : games/acq.sed
- bin/shb games/acq.sed sed -f > "$@"
- chmod +x "$@"
-
-games/kvlt : games/kvlt.sed
- bin/shb games/kvlt.sed sed -f > "$@"
- chmod +x "$@"
-
-games/zs : games/zs.sed
- bin/shb games/zs.sed sed -f > "$@"
- chmod +x "$@"
-
git/gitconfig : git/gitconfig.m4
m4 \
-D DOTFILES_NAME="$(NAME)" \
@@ -127,11 +114,18 @@ tmux/tmux.conf : tmux/tmux.conf.m4
m4 -D TMUX_COLOR="$(TMUX_COLOR)" \
tmux/tmux.conf.m4 > tmux/tmux.conf
+.awk :
+ bin/shb "$<" awk -f > "$@"
+ chmod +x "$@"
+
+.sed :
+ bin/shb "$<" sed -f > "$@"
+ chmod +x "$@"
+
install : install-bash \
install-bash-completion \
install-bin \
install-curl \
- install-dircolors \
install-git \
install-gnupg \
install-readline \
@@ -144,7 +138,7 @@ install-abook :
"$(HOME)"/.abook
install -pm 0644 -- abook/abookrc "$(HOME)"/.abook
-install-bash : test-bash
+install-bash : check-bash install-sh
install -m 0755 -d -- \
"$(HOME)"/.config \
"$(HOME)"/.bashrc.d \
@@ -160,13 +154,11 @@ install-bash-completion : install-bash
install -pm 0644 -- bash/bash_completion "$(HOME)"/.config/bash_completion
install -pm 0644 -- bash/bash_completion.d/* "$(HOME)"/.bash_completion.d
-install-bin : bin/sd2u bin/su2d bin/unf test-bin install-bin-man
+install-bin : bin/sd2u bin/su2d bin/unf check-bin install-bin-man
install -m 0755 -d -- "$(HOME)"/.local/bin
for name in bin/* ; do \
- case $$name in \
- *.sed) ;; \
- *) install -m 0755 -- "$$name" "$(HOME)"/.local/bin ;; \
- esac \
+ [ -x "$$name" ] || continue ; \
+ install -m 0755 -- "$$name" "$(HOME)"/.local/bin ; \
done
install-bin-man :
@@ -179,9 +171,6 @@ install-bin-man :
install-curl :
install -pm 0644 -- curl/curlrc "$(HOME)"/.curlrc
-install-dircolors :
- install -pm 0644 -- dircolors/dircolors "$(HOME)"/.dircolors
-
install-dotfiles-man : man/man7/dotfiles.7
install -m 0755 -d -- "$(HOME)"/.local/share/man/man7
install -pm 0644 -- man/man7/*.7 "$(HOME)"/.local/share/man/man7
@@ -195,13 +184,11 @@ install-finger :
install -pm 0644 -- finger/project "$(HOME)"/.project
install -pm 0644 -- finger/pgpkey "$(HOME)"/.pgpkey
-install-games : games/acq games/kvlt games/zs test-games install-games-man
+install-games : games/acq games/kvlt games/zs check-games install-games-man
install -m 0755 -d -- "$(HOME)"/.local/games
- for game in games/* ; do \
- case $$game in \
- *.sed) ;; \
- *) install -m 0755 -- "$$game" "$(HOME)"/.local/games ;; \
- esac \
+ for name in games/* ; do \
+ [ -x "$$name" ] || continue ; \
+ install -m 0755 -- "$$name" "$(HOME)"/.local/games ; \
done
install-games-man :
@@ -229,12 +216,6 @@ install-i3 : install-x
install -m 0755 -d -- "$(HOME)"/.i3
install -pm 0644 -- i3/* "$(HOME)"/.i3
-install-pdksh : test-pdksh install-sh
- install -m 0755 -d -- \
- "$(HOME)"/.pdkshrc.d
- install -pm 0644 -- pdksh/pdkshrc "$(HOME)"/.pdkshrc
- install -pm 0644 -- pdksh/pdkshrc.d/* "$(HOME)"/.pdkshrc.d
-
install-maildir :
install -m 0755 -d -- \
"$(HOME)"/Mail/inbox/cur \
@@ -264,6 +245,12 @@ install-newsbeuter :
install-mysql :
install -pm 0644 -- mysql/my.cnf "$(HOME)"/.my.cnf
+install-pdksh : check-pdksh install-sh
+ install -m 0755 -d -- \
+ "$(HOME)"/.pdkshrc.d
+ install -pm 0644 -- pdksh/pdkshrc "$(HOME)"/.pdkshrc
+ install -pm 0644 -- pdksh/pdkshrc.d/* "$(HOME)"/.pdkshrc.d
+
install-perlcritic :
install -pm 0644 -- perlcritic/perlcriticrc "$(HOME)"/.perlcriticrc
@@ -276,10 +263,14 @@ install-psql :
install-readline :
install -pm 0644 -- readline/inputrc "$(HOME)"/.inputrc
-install-sh : test-sh
- install -m 0755 -d -- "$(HOME)"/.profile.d
+install-sh : check-sh
+ install -m 0755 -d -- \
+ "$(HOME)"/.profile.d \
+ "$(HOME)"/.shrc.d
install -pm 0644 -- sh/profile "$(HOME)"/.profile
install -pm 0644 -- sh/profile.d/* "$(HOME)"/.profile.d
+ install -pm 0644 -- sh/shrc "$(HOME)"/.shrc
+ install -pm 0644 -- sh/shrc.d/* "$(HOME)"/.shrc.d
install-subversion :
install -m 0755 -d -- "$(HOME)"/.subversion
@@ -294,7 +285,7 @@ install-terminfo :
install-tmux : tmux/tmux.conf
install -pm 0644 -- tmux/tmux.conf "$(HOME)"/.tmux.conf
-install-urxvt : test-urxvt
+install-urxvt : check-urxvt
install -m 0755 -d -- "$(HOME)"/.urxvt/ext
install -m 0755 -- urxvt/ext/* "$(HOME)"/.urxvt/ext
@@ -312,24 +303,11 @@ install-gvim-config :
install -pm 0644 -- vim/gvimrc "$(HOME)"/.gvimrc
install-vim-plugins : install-vim-config
- install -m 0755 -d -- "$(HOME)"/.vim/bundle
- find vim/bundle -name .git -prune -o \
- \( -type d -print \) | \
- while IFS= read -r dir ; do \
- install -m 0755 -d -- \
- "$$dir" "$(HOME)"/.vim/"$${dir#vim/}" ; \
- done
- find vim/bundle -name .git -prune -o \
- \( -type f ! -name '.git*' -print \) | \
- while IFS= read -r file ; do \
- install -pm 0644 -- \
- "$$file" "$(HOME)"/.vim/"$${file#vim/}" ; \
- done
- for dir in vim/after/* ; do \
- install -m 0755 -d -- "$(HOME)"/.vim/after/"$${dir##*/}" ; \
- install -pm 0644 -- "$$dir"/* \
- "$(HOME)"/.vim/after/"$${dir##*/}" ; \
- done
+ find vim/after vim/bundle -name .git -prune -o \
+ -type d -exec sh -c 'install -m 0755 -d -- \
+ "$(HOME)"/.vim/"$${1#vim/}"' _ {} \; -o \
+ -type f -exec sh -c 'install -m 0644 -- \
+ "$$1" "$(HOME)"/.vim/"$${1#vim/}"' _ {} \;
install-vim-pathogen : install-vim-plugins
install -m 0755 -d -- "$(HOME)"/.vim/autoload
@@ -350,32 +328,32 @@ install-x :
install -pm 0644 -- X/Xresources "$(HOME)"/.Xresources
install -pm 0644 -- X/Xresources.d/* "$(HOME)"/.Xresources.d
-install-zsh :
+install-zsh : install-sh
install -pm 0644 -- zsh/zprofile "$(HOME)"/.zprofile
install -pm 0644 -- zsh/zshrc "$(HOME)"/.zshrc
-test : test-bash test-bin test-games test-man test-sh test-urxvt
+check : check-bash check-bin check-games check-man check-sh check-urxvt
-test-bash :
- test/bash
+check-bash :
+ check/bash
-test-bin :
- test/bin
+check-bin :
+ check/bin
-test-games :
- test/games
+check-games :
+ check/games
-test-pdksh :
- test/pdksh
+check-pdksh :
+ check/pdksh
-test-man :
- test/man
+check-man :
+ check/man
-test-sh :
- test/sh
+check-sh :
+ check/sh
-test-urxvt :
- test/urxvt
+check-urxvt :
+ check/urxvt
lint : lint-bash lint-bin lint-games lint-sh lint-urxvt
diff --git a/README.markdown b/README.markdown
index 191371f4..47197122 100644
--- a/README.markdown
+++ b/README.markdown
@@ -47,8 +47,6 @@ Configuration is included for:
shells
* [cURL](https://curl.haxx.se/) -- Command-line tool for transferring data with
URL syntax
-* [`dircolors(1)`](https://www.gnu.org/software/coreutils/manual/html_node/dircolors-invocation.html)
- -- Color GNU `ls(1)` output
* [Dunst](http://knopwob.org/dunst/) -- A lightweight X11 notification daemon
that works with `libnotify`
* `finger(1)` -- User information lookup program
@@ -83,7 +81,7 @@ Configuration is included for:
frontend for [Remind](https://www.roaringpenguin.com/products/remind)
* [X11](https://www.x.org/wiki/) -- Windowing system with network transparency
for Unix
-* [Zsh](http://www.zsh.org/) -- Bourne-style shell designed for interactive
+* [Zsh](https://www.zsh.org/) -- Bourne-style shell designed for interactive
use
The configurations for Bash, GnuPG, Mutt, tmux, and Vim are the most expansive
@@ -133,21 +131,22 @@ defaults for interactive behavior.
A terminal session with my prompt looks something like this:
- [tom@conan:~/.dotfiles](git:master+!)$ git status
+ tom@conan:~/.dotfiles(master+!)$ git status
M README.markdown
M bash/bashrc.d/prompt.bash
A init
- [tom@conan:~/.dotfiles](git:master+!)$ foobar
+ tom@conan:~/.dotfiles(master+!)$ foobar
foobar: command not found
- [tom@conan:~/.dotfiles](git:master+!)<127>$ sleep 5 &
+ tom@conan:~/.dotfiles(master+!)<127>$ sleep 5 &
[1] 28937
- [tom@conan:~/.dotfiles](git:master+!){1}$
+ tom@conan:~/.dotfiles(master+!){1}$
It expands based on context to include these elements in this order:
* Whether in a Git repository if applicable, and punctuation to show whether
there are local modifications at a glance; Subversion support can also be
- enabled (I need it at work)
+ enabled (I need it at work), in which case a `git:` or `svn:` prefix is
+ added appropriately
* The number of running background jobs, if non-zero
* The exit status of the last command, if non-zero
@@ -160,6 +159,65 @@ common terminals using both `termcap(5)` and `terminfo(5)`, including \*BSD
systems. It's also designed to degrade gracefully for eight-color and no-color
terminals.
+#### Functions
+
+If a function can be written in POSIX `sh` without too much hackery, I put it
+in `sh/shrc.d` to be loaded by any POSIX interactive shell. Those include:
+
+* `bc()` silences startup messages from GNU `bc(1)`.
+* `diff()` forces the unified format for `diff(1)`.
+* `cd()` wraps the `cd` builtin to allow for a second parameter for string
+ substitution, emulating a Zsh function I like.
+* `ed()` tries to get verbose error messages, a prompt, and a Readline
+ environment for `ed(1)`.
+* `env()` sorts the output of `env(1)` if it was invoked with no arguments,
+ because the various shells have different ways of listing exported
+ variables.
+* `gdb()` silences startup messages from `gdb(1)`.
+* `gpg()` quietens `gpg(1)` down for most commands.
+* `hgrep()` allows searching `$HISTFILE`.
+* `keychain()` updates `$GPG_TTY` if set for `keychain(1)`.
+* `mkcd()` creates a directory and changes into it.
+* `mysql()` allows shortcuts to MySQL configuration files stored in
+ `~/.mysql`.
+* `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.
+* `scr()` creates a temporary directory and changes into it.
+* `sudo()` forces `-H` for `sudo(8)` calls so that `$HOME` is never
+ 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.
+* `vim()` defines three functions to always use `vim(1)` as my `ex(1)`,
+ `vi(1)` and `view(1)` implementation if it's available.
+
+There are a few other little tricks defined for other shells, mostly in
+`bash/bashrc.d`:
+
+* `bd()` changes into a named ancestor of the current directory.
+* `fnl()` runs a command and saves its output and error into temporary files,
+ defining variables with the filenames in them.
+* `grep()` tries to apply color and other options good for interactive use,
+ depending on the capabilities of the system `grep(1)`. It's dependent on
+ information written by the `grep.sh` script in `~/.profile.d`.
+* `keep()` stores ad-hoc shell functions and variables.
+* `lhn()` gets the history number of the last command.
+* `ls()` tries to apply color to `ls(1)` for interactive use if available.
+ 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`.
+* `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
+ repository.
+
#### Completion
I find the `bash-completion` package a bit too heavy for my tastes, and turn it
@@ -182,28 +240,6 @@ files for things I really do get tired of typing repeatedly:
I also add completions for my own scripts and functions where useful.
-#### Functions
-
-There are a few other little tricks in `bash/bashrc.d`, including:
-
-* `bd()` changes into a named ancestor of the current directory.
-* `fnl()` runs a command and save its output and error into temporary files.
-* `hgrep()` searches `$HISTFILE`.
-* `keep()` stores ad-hoc shell functions and variables.
-* `mkcd()` creates a directory and changes into it.
-* `path()` manages the contents of `PATH` conveniently.
-* `pd()` changes to the argument's parent directory.
-* `readv()` prints names and values from `read` calls to `stderr`.
-* `readz()` is an alias for `read -d '' -r`.
-* `scr()` creates a temporary directory and changes into it.
-* `sd()` changes into a sibling of the current directory.
-* `ud()` changes into an indexed ancestor of a directory.
-
-I also wrap a few command calls with functions to stop me from doing silly
-things that the commands themselves don't catch. My favourite is the one that
-stops me from calling `scp(1)` with no colon in either argument. I also do
-things like give default arguments to `pwgen(1)`.
-
#### pdksh
The pdksh configuration files and functions are not nearly as featureful as the
@@ -211,6 +247,11 @@ Bash ones. They're tested on OpenBSD and FreeBSD pdksh implementations, but the
former is the primary system for which I'm maintaining them, and there are some
feature differences.
+#### Zsh
+
+These are experimental; I do not like Zsh much at the moment. The files started
+as a joke (`exec bash`).
+
### GnuPG
The configuration for GnuPG is intended to follow [RiseUp's OpenPGP best
@@ -339,7 +380,7 @@ Installed by the `install-bin` target:
for unfolding HTTP headers, but it should work for most RFC 822
formats.
* `apf(1)` prepends arguments to a command with ones read from a file,
- intended as a framework for shell functions.
+ intended as a framework for shell wrappers or functions.
* `ax(1)` evaluates an awk expression given on the command line; this is
intended as a quick way to test how Awk would interpret a given expression.
* `bel(1)` prints a terminal bell character.
@@ -422,9 +463,10 @@ your `/etc/manpath` configuration, depending on your system.
Testing
-------
-You can test that both sets of shell scripts are syntactically correct with
-`make test-bash`, `make test-sh`, or `make test` for everything including the
-scripts in `bin` and `games`.
+You can check that both sets of shell scripts are syntactically correct with
+`make check-bash`, `make check-sh`, or `make check` for everything including
+the scripts in `bin` and `games`. There's no proper test suite for the actual
+functionality (yet).
If you have [ShellCheck](https://www.shellcheck.net/) and/or
[Perl::Critic](http://perlcritic.com/), there's a `lint` target for the shell
diff --git a/bash/bash_completion.d/man.bash b/bash/bash_completion.d/man.bash
index f1762a01..d2499c0a 100644
--- a/bash/bash_completion.d/man.bash
+++ b/bash/bash_completion.d/man.bash
@@ -35,8 +35,8 @@ _man() {
# Iterate through the manual page paths and add every manual page we find
for manpath in "${manpaths[@]}" ; do
- [[ $manpath ]] || continue
- if [[ $section ]] ; then
+ [[ -n $manpath ]] || continue
+ if [[ -n $section ]] ; then
for page in "$manpath"/"$subdir"/"$word"*."$section"?(.[glx]z|.bz2|.lzma|.Z) ; do
pages[${#pages[@]}]=$page
done
diff --git a/bash/bash_profile b/bash/bash_profile
index ee735720..db1d9bc8 100644
--- a/bash/bash_profile
+++ b/bash/bash_profile
@@ -14,16 +14,12 @@ elif ((BASH_VERSINFO[0] == 2)) &&
fi
# Load any supplementary scripts
-if [[ -d $HOME/.bash_profile.d ]] ; then
- for bash_profile in "$HOME"/.bash_profile.d/*.bash ; do
- if [[ -e $bash_profile ]] ; then
- source "$bash_profile"
- fi
- done
- unset -v bash_profile
-fi
+for sh in "$HOME"/.bash_profile.d/*.bash ; do
+ [[ -e $sh ]] && source "$sh"
+done
+unset -v sh
-# Source interactive Bash config if it exists
-if [[ -e $HOME/.bashrc ]] ; then
+# If ~/.bashrc exists, source that too; the test for interactivity is in there
+if [[ -f $HOME/.bashrc ]] ; then
source "$HOME"/.bashrc
fi
diff --git a/bash/bashrc b/bash/bashrc
index b551819d..7defd85d 100644
--- a/bash/bashrc
+++ b/bash/bashrc
@@ -8,21 +8,22 @@ elif ((BASH_VERSINFO[0] == 2)) &&
return
fi
-# Don't do anything if not running interactively
-if [[ $- != *i* ]] ; then
- return
-fi
+# Make sure the shell is interactive
+case $- in
+ *i*) ;;
+ *) return ;;
+esac
# Don't do anything if running a restricted shell
if shopt -q restricted_shell ; then
return
fi
-# Keep around sixteen million lines of history in file
-HISTFILESIZE=$((1 << 24))
+# Keep around four thousand lines of history in file
+HISTFILESIZE=$((1 << 12))
-# Keep around four thousand lines of history in memory
-HISTSIZE=$((1 << 12))
+# Keep around one thousand lines of history in memory
+HISTSIZE=$((1 << 10))
# Ignore duplicate commands and whitespace in history
HISTCONTROL=ignoreboth
@@ -101,20 +102,15 @@ fi
# If COMP_WORDBREAKS has a value, strip all colons from it; this allows
# completing filenames correctly, since an unquoted colon is not a syntactic
# character: <http://tiswww.case.edu/php/chet/bash/FAQ> (E13)
-if [[ $COMP_WORDBREAKS ]] ; then
+if [[ -n $COMP_WORDBREAKS ]] ; then
COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
fi
-# Load any supplementary scripts
-for bashrc in "$HOME"/.bashrc.d/*.bash ; do
- [[ -e $bashrc ]] || continue
- source "$bashrc"
-done
-unset -v bashrc
-
-# Load any completion files
-for bashcmp in "$HOME"/.bash_completion.d/*.bash ; do
- [[ -e $bashcmp ]] || continue
- source "$bashcmp"
+# Load POSIX shell functions, Bash-specific scripts, and Bash completion files,
+# in that order
+for sh in "$ENV" \
+ "$HOME"/.bashrc.d/*.bash \
+ "$HOME"/.bash_completion.d/*.bash ; do
+ [[ -e $sh ]] && source "$sh"
done
-unset -v bashcmp
+unset -v sh
diff --git a/bash/bashrc.d/cd.bash b/bash/bashrc.d/cd.bash
deleted file mode 100644
index 04de96d5..00000000
--- a/bash/bashrc.d/cd.bash
+++ /dev/null
@@ -1,32 +0,0 @@
-# If given two arguments to cd, replace the first with the second in $PWD,
-# emulating a Zsh function that I often find useful; preserves options too
-cd() {
- local arg
- local -a opts
- for arg ; do
- case $arg in
- --)
- shift
- break
- ;;
- -*)
- shift
- opts[${#opts[@]}]=$arg
- ;;
- *)
- break
- ;;
- esac
- done
- if (($# == 2)) ; then
- if [[ $PWD == *"$1"* ]] ; then
- builtin cd "${opts[@]}" -- "${PWD/"$1"/"$2"}"
- else
- printf 'bash: %s: could not replace substring\n' \
- "$FUNCNAME" >&2
- return 2
- fi
- else
- builtin cd "${opts[@]}" -- "$@"
- fi
-}
diff --git a/bash/bashrc.d/grep.bash b/bash/bashrc.d/grep.bash
deleted file mode 100644
index 11eeb5b0..00000000
--- a/bash/bashrc.d/grep.bash
+++ /dev/null
@@ -1,33 +0,0 @@
-# Store whether we have colors in a variable
-declare -i colors
-colors=$( {
- tput Co || tput colors
-} 2>/dev/null )
-
-# Store grep(1)'s --help output in a variable
-grep_help=$(grep --help 2>/dev/null)
-
-# Use GREPOPTS to add some useful options to grep(1) calls if applicable; we
-# use a function wrapper to do this, rather than GREP_OPTIONS as we don't want
-# to change grep(1)'s actual behaviour inside scripts
-declare -a GREPOPTS
-if [[ -n $GREP_COLORS ]] && ((colors >= 8)) ; then
- GREPOPTS[${#GREPOPTS[@]}]='--color=auto'
-fi
-if [[ $grep_help == *--binary-files* ]] ; then
- GREPOPTS[${#GREPOPTS[@]}]='--binary-files=without-match'
-fi
-if [[ $grep_help == *--exclude* ]] ; then
- GREPOPTS[${#GREPOPTS[@]}]='--exclude={.gitignore,.gitmodules}'
-fi
-if [[ $grep_help == *--exclude-dir* ]] ; then
- GREPOPTS[${#GREPOPTS[@]}]='--exclude-dir={.cvs,.git,.hg,.svn}'
-fi
-
-# Done, unset helper vars
-unset -v grep_help colors
-
-# Define function proper
-grep() {
- command grep "${GREPOPTS[@]}" "$@"
-}
diff --git a/bash/bashrc.d/keychain.bash b/bash/bashrc.d/keychain.bash
deleted file mode 100644
index 40fe5d71..00000000
--- a/bash/bashrc.d/keychain.bash
+++ /dev/null
@@ -1,4 +0,0 @@
-# If GPG_TTY is set, update it
-if [[ -n $GPG_TTY ]] ; then
- GPG_TTY=$(tty)
-fi
diff --git a/bash/bashrc.d/lhn.bash b/bash/bashrc.d/lhn.bash
new file mode 100644
index 00000000..89c6f5da
--- /dev/null
+++ b/bash/bashrc.d/lhn.bash
@@ -0,0 +1,7 @@
+# Print the history number of the last command
+lhn () {
+ local last
+ last=$(fc -l -1) || return
+ [[ -n $last ]] || return
+ printf '%u\n' "${last%%[^0-9]*}"
+}
diff --git a/bash/bashrc.d/ls.bash b/bash/bashrc.d/ls.bash
deleted file mode 100644
index 4b647163..00000000
--- a/bash/bashrc.d/ls.bash
+++ /dev/null
@@ -1,20 +0,0 @@
-# Store whether we have colors in a variable
-declare -i colors
-colors=$( {
- tput Co || tput colors
-} 2>/dev/null )
-
-# Use LSOPTS to add some useful options to ls(1) calls if applicable; we use a
-# function wrapper to do this
-declare -a LSOPTS
-if [[ -n $LS_COLORS ]] && ((colors >= 8)) ; then
- LSOPTS[${#LSOPTS[@]}]='--color=auto'
-fi
-
-# Done, unset helper var
-unset -v colors
-
-# Define function proper
-ls() {
- command ls "${LSOPTS[@]}" "$@"
-}
diff --git a/bash/bashrc.d/prompt.bash b/bash/bashrc.d/prompt.bash
index b5ac74b1..081cff69 100644
--- a/bash/bashrc.d/prompt.bash
+++ b/bash/bashrc.d/prompt.bash
@@ -24,7 +24,7 @@ prompt() {
fi
# Basic prompt shape
- PS1='[\u@\h:\w]'
+ PS1='\u@\h:\w'
# Add sub-commands; VCS, job, and return status checks
PS1=$PS1'$(prompt vcs)$(prompt job)$(prompt ret)'
@@ -104,6 +104,13 @@ prompt() {
return 1
fi
+ # Bail if we're not in a work tree
+ local iswt
+ iswt=$(git rev-parse --is-inside-work-tree 2>/dev/null)
+ if [[ $iswt != true ]] ; then
+ return 1
+ fi
+
# Attempt to determine git branch, bail if we can't
local branch
branch=$( {
@@ -130,8 +137,9 @@ prompt() {
state=${state}^
fi
- # Print the status in brackets with a git: prefix
- printf '(git:%s%s)' "${branch:-unknown}" "$state"
+ # Print the status in brackets; add a git: prefix only if there
+ # might be another VCS prompt (because PROMPT_VCS is set)
+ printf '(%s%s%s)' "${PROMPT_VCS:+git:}" "${branch:-unknown}" "$state"
;;
# Subversion prompt function
diff --git a/bash/bashrc.d/scp.bash b/bash/bashrc.d/scp.bash
deleted file mode 100644
index cd2f8521..00000000
--- a/bash/bashrc.d/scp.bash
+++ /dev/null
@@ -1,10 +0,0 @@
-# Wrap scp(1) to check for missing colons
-scp() {
- # shellcheck disable=SC2048
- if (($# >= 2)) && [[ $* != *:* ]] ; then
- printf 'bash: %s: Missing colon, probably an error\n' \
- "$FUNCNAME" >&2
- return 2
- fi
- command scp "$@"
-}
diff --git a/bash/bashrc.d/scr.bash b/bash/bashrc.d/scr.bash
deleted file mode 100644
index bf2990fd..00000000
--- a/bash/bashrc.d/scr.bash
+++ /dev/null
@@ -1,12 +0,0 @@
-# Create a temporary directory and change into it, to stop me putting stray
-# files into $HOME, and making the system do cleanup for me. Single optional
-# argument is the string to use for naming the directory; defaults to "scr".
-scr() {
- if (($# <= 1)) ; then
- pushd -- "$(mktd "${1:-"$FUNCNAME"}")"
- else
- printf 'bash: %s: too many arguments\n' \
- "$FUNCNAME" >&2
- return 2
- fi
-}
diff --git a/bash/bashrc.d/vim.bash b/bash/bashrc.d/vim.bash
deleted file mode 100644
index 37fc1871..00000000
--- a/bash/bashrc.d/vim.bash
+++ /dev/null
@@ -1,15 +0,0 @@
-# If Vim exists on the system, use it instead of ex, vi, and view
-if ! hash vim 2>/dev/null ; then
- return
-fi
-
-# Define functions proper
-ex() {
- vim -e "$@"
-}
-vi() {
- vim "$@"
-}
-view() {
- vim -R "$@"
-}
diff --git a/bin/apf b/bin/apf
index 06f7aa6b..956142fe 100755
--- a/bin/apf
+++ b/bin/apf
@@ -1,43 +1,55 @@
-#!/usr/bin/env bash
-# Prepend arguments from a file to a command call
+#!/bin/sh
+# Prepend arguments from a file to the given arguments for a command
self=apf
-# Require at least two arguments, give usage otherwise
-if (($# < 2)) ; then
- printf '%s: usage: %s ARGFILE COMMAND [ARGS...]\n' \
- "$self" "$self" >&2
+# Require at least two arguments
+if [ "$#" -lt 2 ] ; then
+ printf >&2 '%s: Need an arguments file and a command\n' "$self"
exit 2
fi
# First argument is the file containing the null-delimited arguments
-argfile=$1
-shift
-
-# Check the arguments file makes sense
-if [[ ! -e $argfile ]] ; then
- printf '%s: %s: No such file or directory\n' \
- "$self" "$argfile"
- exit 1
-elif [[ -d $argfile ]] ; then
- printf '%s: %s: Is a directory\n' \
- "$self" "$argfile"
- exit 1
-elif [[ ! -r $argfile ]] ; then
- printf '%s: %s: Permission denied\n' \
- "$self" "$argfile"
- exit 1
-fi
+argf=$1 cmd=$2
+shift 2
+
+# If the file exists, we'll read it. If it doesn't, this is not an error (think
+# personal config files like ~/.vimrc)
+if [ -f "$argf" ] ; then
+
+ # Create a temporary directory with name in $td, and handle POSIX-ish traps to
+ # remove it when the script exits.
+ td=
+ cleanup() {
+ [ -n "$td" ] && rm -fr -- "$td"
+ if [ "$1" != EXIT ] ; then
+ trap - "$1"
+ kill "-$1" "$$"
+ fi
+ }
+ for sig in EXIT HUP INT TERM ; do
+ # shellcheck disable=SC2064
+ trap "cleanup $sig" "$sig"
+ done
+ td=$(mktd "$self") || exit
-# Read all the null-delimited arguments from the file
-declare -a args
-while IFS= read -rd '' arg ; do
- args[${#args[@]}]=$arg
-done < "$argfile"
+ # Write the arguments in reverse to a temporary file
+ revf=$td/revf
+ sed '1!G;$!{h;d}' "$argf" > "$revf" || exit
-# Next argument is the command to run
-cmd=$1
-shift
+ # Stack up all the arguments from the file. Skip blank lines and comments.
+ # An empty file is also fine.
+ while IFS= read -r arg ; do
+ case $arg in
+ '#'*) continue ;;
+ *[![:space:]]*) ;;
+ *) continue ;;
+ esac
+ set -- "$arg" "$@"
+ done < "$revf"
+
+ # We can remove the temporary stuff now, which allows us to exec safely
+ cleanup
+fi
-# Run the command with the retrieved arguments first, then the rest of the
-# command line as passed to the function
-command "$cmd" "${args[@]}" "$@"
+# Run the command with the changed arguments
+exec "$cmd" "$@"
diff --git a/bin/dmp b/bin/dmp
index 9ef58f67..d25082dd 100755
--- a/bin/dmp
+++ b/bin/dmp
@@ -1,11 +1,15 @@
#!/bin/sh
+# Sole optional argument is the password timeout (defaults to 10 seconds)
+timeout_sec=${1:-10}
+
# Get the password store directory, bail if we can't
pwsd=${PASSWORD_STORE_DIR:-$HOME/.password-store}
pwsd=${pwsd%/}
[ -n "$pwsd" ] || exit
# Get the password; get all the names from find(1)
+# shellcheck disable=SC2016
pw=$(
cd -- "$pwsd" || exit
# Get all the names from find(1)
@@ -13,10 +17,7 @@ pw=$(
# Sort them
sort |
# Strip the leading directory and the trailing .gpg
- sed '
-s_^\./__
-s_\.gpg$__
- ' |
+ sed 's_^\./__;s_\.gpg$__' |
# Use dmenu(1) to prompt the user to select one
dmenu
) || exit
@@ -25,4 +26,4 @@ s_\.gpg$__
[ -n "$pw" ] || exit
# Pump the password into the clipboard xsel(2); allow 10 seconds
-pass show "$pw" | xsel -ibt 10000
+pass show "$pw" | xsel -ibt "$((timeout_sec * 1000))"
diff --git a/bin/edda b/bin/edda
index 0f242c58..7bc1642b 100755
--- a/bin/edda
+++ b/bin/edda
@@ -1,50 +1,33 @@
-#!/usr/bin/env bash
+#!/bin/sh
# Run ed(1) over multiple files, duplicating stdin.
-self=edda
-
-# Define usage function
-usage() {
- printf 'USAGE: %s [OPTS] [--] FILE1 [FILE2...]\n' "$self"
-}
# Need at least one file
-if ! (($#)) ; then
- usage >&2
- exit 1
+if [ "$#" -eq 0 ] ; then
+ printf >&2 'edda: Need at least one file\n'
+ exit 2
fi
-# Need ed(1) -- some systems daring to call themselves UNIX-like don't have it
-# installed by default. What's POSIX, precious?
-hash ed || exit
-
-# Parse options out, give help if necessary
-declare -a opts
-for arg ; do
- case $arg in
- --help|-h|-\?)
- usage
- exit
- ;;
- --)
- shift
- break
- ;;
- -*)
- shift
- opts[${#opts[@]}]=$arg
- ;;
- esac
-done
-
-# Duplicate stdin into a file, which we'll remove on exit
-stdin=$(mktemp -t "$self".XXXXXX) || exit
+# Create a temporary directory with name in $td, and handle POSIX-ish traps to
+# remove it when the script exits.
+td=
cleanup() {
- rm -f -- "$stdin"
+ [ -n "$td" ] && rm -fr -- "$td"
+ if [ "$1" != EXIT ] ; then
+ trap - "$1"
+ kill "-$1" "$$"
+ fi
}
-trap cleanup EXIT
-cat > "$stdin"
+for sig in EXIT HUP INT TERM ; do
+ # shellcheck disable=SC2064
+ trap "cleanup $sig" "$sig"
+done
+td=$(mktd "$self") || exit
+
+# Duplicate stdin into a file
+script=$td/script
+cat >"$script" || exit
-# Run ed(1) over each file with the options and stdin given
+# Run ed(1) over each file with the stdin given
for file ; do
- ed "${opts[@]}" -- "$file" < "$stdin"
+ ed -- "$file" <"$script"
done
diff --git a/bin/eds b/bin/eds
index 06686810..3d0fceed 100755
--- a/bin/eds
+++ b/bin/eds
@@ -1,64 +1,52 @@
-#!/usr/bin/env bash
+#!/bin/sh
# Create and edit executable scripts in a directory EDSPATH (defaults to ~/.local/bin)
-self=eds
-# Define a function to show usage
-usage() {
- printf 'USAGE: %s [EDITOR_OPTS] [--] FILE1 [FILE2...]\n' \
- "$self"
-}
+# Need at least one script name
+if [ "$#" -eq 0 ] ; then
+ printf >&2 'eds: Need at least one script name\n'
+ exit 2
+fi
+
+# Create the script directory if it doesn't exist yet
+ep=${EDSPATH:-$HOME/.local/bin}
+if ! [ -d "$ep" ] ; then
+ mkdir -p -- "$ep" || exit
+fi
-# Process options, including detecting requests for help
-declare -a opts
+# Warn if that's not in $PATH
+case :$PATH: in
+ *:"$ep":*) ;;
+ *)
+ printf >&2 'eds: warning: %s not in PATH\n' "$ep"
+ ;;
+esac
+
+# Prepend the path to each of the names given if they don't look like options
for arg ; do
+ [ -n "$reset" ] || set -- && reset=1
case $arg in
- --help|-h|-\?)
- usage
- exit 0
- ;;
--)
- shift
- break
+ optend=1
+ set -- "$@" "$arg"
+ continue
;;
-*)
- shift
- opts[${#opts[@]}]=$arg
- ;;
- *)
- break
+ if [ -z "$optend" ] ; then
+ set -- "$@" "$arg"
+ continue
+ fi
;;
esac
+ optend=1
+ set -- "$@" "$ep"/"$arg"
done
-# If no arguments left, spit usage as an error and bail
-if ! (($#)) ; then
- usage >&2
- exit 1
-fi
-
-# Create the script directory if it doesn't exist yet
-edspath=${EDSPATH:-$HOME/.local/bin}
-if [[ ! -d $edspath ]] ; then
- mkdir -p -- "$edspath" || exit
-fi
-
-# Create a new array with the script directory prepended to the given names
-declare -a files
-files=("${@/#/$edspath/}")
-
-# Collect the names of any scripts that don't exist yet so we can make them
-# executable after we're done editing
-declare -a creations
-for file in "${files[@]}" ; do
- [[ -e $file ]] && continue
- creations[${#creations[@]}]=$file
-done
-
-# Run the editor; if EDITOR isn't set, use vi(1)
-"${EDITOR:-vi}" "${opts[@]}" -- "${files[@]}"
+# Run the editor over the arguments
+echo "${VISUAL:-"${EDITOR:-ed}"}" "$@"
+exit
# Make any created scripts executable if they now appear to be files
-for creation in "${creations[@]}" ; do
- [[ -f $creation ]] || continue
- chmod +x -- "$creation"
+for script ; do
+ [ -f "$script" ] || continue
+ chmod +x -- "$script"
done
diff --git a/bin/fgscr b/bin/fgscr
index 510fd7cc..9e80cd09 100755
--- a/bin/fgscr
+++ b/bin/fgscr
@@ -2,7 +2,7 @@
# Find all the Git repositories in a directory and scrub them all
# Check we have gscr(1) first
-command -v gscr >/dev/null || exit
+command -v gscr >/dev/null 2>&1 || exit
# Look for any dir named .git in the given (default current) dir and run
# gscr(1) on it
diff --git a/bin/han b/bin/han
index 7c495d2b..0f081890 100755
--- a/bin/han
+++ b/bin/han
@@ -3,31 +3,31 @@
self=han
# Give up completely if no BASH_VERSINFO (<2.0)
-if ! [ -n "$BASH_VERSINFO" ] ; then
- exit
-fi
+[ -n "$BASH_VERSINFO" ] || exit
# Figure out the options with which we can call help; Bash >=4.0 has an -m
-# option which prints the help output in a man-page like format.
+# option which prints the help output in a man-page like format
declare -a helpopts
if ((BASH_VERSINFO[0] >= 4)) ; then
helpopts=(-m)
fi
-# Create a temporary file and set up a trap to get rid of it.
-tmpdir=$(mktemp -dt "$self".XXXXXX) || exit
+# Create a temporary directory with name in $td, and a trap to remove it when
+# the script exits
+td=
cleanup() {
- rm -fr -- "$tmpdir"
+ [[ -n "$td" ]] && rm -fr -- "$td"
}
trap cleanup EXIT
+td=$(mktd "$self") || exit
# If we have exactly one argument and a call to the help builtin with that
-# argument succeeds, display its output with `pager -s`.
+# argument succeeds, display its output with `pager -s`
if (($# == 1)) &&
- help "${helpopts[@]}" "$1" >"$tmpdir"/"$1".help 2>/dev/null ; then
- (cd -- "$tmpdir" && pager -s -- "$1".help)
+ help "${helpopts[@]}" "$1" >"$td"/"$1".help 2>/dev/null ; then
+ (cd -- "$td" && "$PAGER" -s -- "$1".help)
-# Otherwise, just pass all the arguments to man(1).
+# Otherwise, just pass all the arguments to man(1)
else
man "$@"
fi
diff --git a/bin/plmu b/bin/plmu
index b753a59a..cf9b7eae 100755
--- a/bin/plmu
+++ b/bin/plmu
@@ -6,7 +6,7 @@ ef=$HOME/.plenv/non-cpanm-modules
# Check that exceptions file is sorted
if ! sort -c -- "$ef" ; then
- printf '%s not sorted\n' "$ef" >&2
+ printf >&2 '%s not sorted\n' "$ef"
exit 1
fi
diff --git a/bin/rfct b/bin/rfct.awk
index dff7a4e2..53e948b2 100755..100644
--- a/bin/rfct
+++ b/bin/rfct.awk
@@ -1,4 +1,4 @@
-#!/usr/bin/awk -f
+# Format an RFC in text format for terminal reading
# A record is a paragraph
BEGIN {
diff --git a/bin/rndi b/bin/rndi.awk
index bf78951c..337498cb 100755..100644
--- a/bin/rndi
+++ b/bin/rndi.awk
@@ -1,4 +1,3 @@
-#!/usr/bin/awk -f
# Get a low-quality random number between two integers. Depending on the awk
# implementation, if you don't provide a third argument (a seed), you might get
# very predictable random numbers based on the current epoch second.
diff --git a/bin/rndl b/bin/rndl
index 2ac3bf47..7d5cb6b7 100755
--- a/bin/rndl
+++ b/bin/rndl
@@ -1,5 +1,6 @@
#!/bin/sh
# Print a random line from input
+self=rndl
# If there are no arguments, we're checking stdin; this is more complicated
# than checking file arguments because we have to count the lines in order to
@@ -7,7 +8,8 @@
# file if we don't want to read all of the input into memory (!)
if [ "$#" -eq 0 ] ; then
- # Try to create the temporary directory with mktd(1) safely
+ # Create a temporary directory with name in $td, and handle POSIX-ish traps to
+ # remove it when the script exits.
td=
cleanup() {
[ -n "$td" ] && rm -fr -- "$td"
@@ -20,7 +22,7 @@ if [ "$#" -eq 0 ] ; then
# shellcheck disable=SC2064
trap "cleanup $sig" "$sig"
done
- td=$(mktd rndl) || exit
+ td=$(mktd "$self") || exit
# We'll operate on stdin in the temp directory; write the script's stdin to
# it with cat(1)
diff --git a/bin/shb b/bin/shb
index 743e5b75..49894b0f 100755
--- a/bin/shb
+++ b/bin/shb
@@ -14,7 +14,7 @@ scr=$1 intn=$2
shift 2
# Try and find the path to the interpreter command, bail out if we can't
-if ! intp=$(command -v "$intn") ; then
+if ! intp=$(command -v "$intn" 2>/dev/null) ; then
printf >&2 '%s: %s: command not found\n' "$self" "$intn"
exit 1
fi
diff --git a/bin/slsf b/bin/slsf.awk
index 6824ec13..9d12225d 100755..100644
--- a/bin/slsf
+++ b/bin/slsf.awk
@@ -1,4 +1,3 @@
-#!/usr/bin/awk -f
# Print the first non-glob "Host" name from each line of ssh_config(5) files
# Manage the processing flag (starts set in each file)
diff --git a/bin/stws b/bin/stws
index f48ef76f..2ceae935 100755
--- a/bin/stws
+++ b/bin/stws
@@ -3,7 +3,7 @@
# Check arguments
if [ "$#" -eq 0 ] ; then
- printf >&2 'tstf: Need a filename\n'
+ printf >&2 'stws: Need a filename\n'
exit 2
fi
diff --git a/bin/td b/bin/td
index e6cbfd93..90df92d9 100755
--- a/bin/td
+++ b/bin/td
@@ -12,7 +12,7 @@ file=${1:-"${TODO_NAME:-todo}"}
cd -- "$dir" || exit
# If the current directory isn't a Git repository, try to create one
-if ! command -v isgr >/dev/null ; then
+if ! command -v isgr >/dev/null 2>&1 ; then
printf >&2 'isgr: command not found\n'
exit 1
fi
@@ -21,8 +21,8 @@ isgr || git init || exit
# If the to-do file doesn't exist yet, create it
[ -e "$file" ] || touch -- "$file" || exit
-# Launch $VISUAL (or $EDITOR (or vi(1))) to edit the appropriate to-do file
-"${VISUAL:-"${EDITOR:-vi}"}" "$file"
+# Launch an appropriate editor to edit that file
+"${VISUAL:-"${EDITOR:-ed}"}" "$file"
# Add the file to the changeset
git add -- "$file"
diff --git a/bin/tlcs b/bin/tlcs
index dcd76c7d..30068303 100755
--- a/bin/tlcs
+++ b/bin/tlcs
@@ -67,7 +67,8 @@ if [ "$((color_count >= 8))" -eq 1 ] ; then
fi
fi
-# Temporary directory for the FIFOs
+# Create a temporary directory with name in $td, and handle POSIX-ish traps to
+# remove it when the script exits.
td=
cleanup() {
[ -n "$td" ] && rm -fr -- "$td"
diff --git a/bin/try b/bin/try
index f0ba317d..7d6d57a8 100755
--- a/bin/try
+++ b/bin/try
@@ -26,7 +26,8 @@ if [ "$#" -eq 0 ] ; then
exit 2
fi
-# Create a buffer file for the error output, and clean up the file when we exit
+# Create a temporary directory with name in $td, and handle POSIX-ish traps to
+# remove it when the script exits.
td=
cleanup() {
[ -n "$td" ] && rm -fr -- "$td"
@@ -40,9 +41,9 @@ for sig in EXIT HUP INT TERM ; do
trap "cleanup $sig" "$sig"
done
td=$(mktd "$self") || exit
-errbuff=$td/errbuff
# Open a filehandle to the error buffer, just to save on file operations
+errbuff=$td/errbuff
exec 3>"$errbuff"
# Keep trying the command, writing error output to the buffer file, and exit
diff --git a/bin/urlc b/bin/urlc
index 63f075bf..e306d48f 100755
--- a/bin/urlc
+++ b/bin/urlc
@@ -5,8 +5,8 @@ self=urlc
# cURL request timeout
tm=${URLCHECK_TIMEOUT:-8}
-# Create buffer files for the headers and body content, to be cleaned up on
-# exit
+# Create a temporary directory with name in $td, and handle POSIX-ish traps to
+# remove it when the script exits.
td=
cleanup() {
[ -n "$td" ] && rm -fr -- "$td"
@@ -20,6 +20,9 @@ for sig in EXIT HUP INT TERM ; do
trap "cleanup $sig" "$sig"
done
td=$(mktd "$self") || exit
+
+# Create buffer files for the headers and body content, to be cleaned up on
+# exit
list=$td/list head=$td/head body=$td/body
# Iterate through input; ignore leading/trailing whitespace
diff --git a/bin/urlh b/bin/urlh
index 2c547ad0..6a768a9f 100755
--- a/bin/urlh
+++ b/bin/urlh
@@ -12,7 +12,7 @@ url=$1 header=$2
curl -I -- "$url" |
# Unfold the headers
-unf |
+unf |
# Change the line endings to UNIX format
sd2u |
diff --git a/bin/urlmt b/bin/urlmt
index 465ff588..7332663e 100755
--- a/bin/urlmt
+++ b/bin/urlmt
@@ -1,3 +1,9 @@
#!/bin/sh
# Get the MIME type for a given URL
-urlh "$1" Content-Type | sed 's/; .*//'
+urlh "$1" Content-Type |
+
+# Use last line only, remove any charset suffix
+sed '
+$!d
+s/; .*//
+'
diff --git a/bin/xgo b/bin/xgo
index 56bbb0f9..e808027c 100755
--- a/bin/xgo
+++ b/bin/xgo
@@ -11,23 +11,23 @@ for url ; do (
# If it's a YouTube video without a given start time, load it in mpv(1)
case $url in
- *youtube.com/watch*[?\&]t=) ;;
- *youtube.com/watch*)
- mpv -- "$url" && continue
+ *[/.]youtube.com/watch*[?\&]t=) ;;
+ *[/.]youtube.com/watch*)
+ mpv -- "$url" && exit
;;
esac
+ # Get the MIME type data
+ mt=$(urlmt "$url")
+
# If the MIME type is an image, load it in feh(1)
case $mt in
image/gif) ;;
image/*)
- curl -- "$url" | feh - && continue
+ curl -- "$url" | feh - && exit
;;
esac
- # Get the MIME type data
- mt=$(urlmt "$url")
-
# Otherwise, just pass it to br(1)
br "$url"
) & done
diff --git a/bin/xgoc b/bin/xgoc
index 9e4b0929..9e4b0929 100644..100755
--- a/bin/xgoc
+++ b/bin/xgoc
diff --git a/test/bash b/check/bash
index f203c2c1..f203c2c1 100755
--- a/test/bash
+++ b/check/bash
diff --git a/test/bin b/check/bin
index a4d5e452..2fc4e767 100755
--- a/test/bin
+++ b/check/bin
@@ -1,6 +1,6 @@
#!/bin/sh
for bin in bin/* ; do
- [ -f "$bin" ] || continue
+ [ -x "$bin" ] || continue
hb=$(sed 1q "$bin") || exit
case $hb in
*bash)
diff --git a/test/games b/check/games
index 3afe6414..d3b5feac 100755
--- a/test/games
+++ b/check/games
@@ -1,6 +1,6 @@
#!/bin/sh
for game in games/* ; do
- [ -f "$game" ] || continue
+ [ -x "$game" ] || continue
hb=$(sed 1q "$game") || exit
case $hb in
*bash)
diff --git a/test/man b/check/man
index 4b5a7831..802f5b3c 100755
--- a/test/man
+++ b/check/man
@@ -35,15 +35,18 @@ comm -13 "$td"/bin "$td"/man > "$td"/nobin
# Emit the content of both, if any
ex=0
if [ -s "$td"/noman ] ; then
- printf >&2 '%s\n' 'No manual pages found for:'
+ printf >&2 'No manual pages found for:\n'
cat >&2 -- "$td"/noman
ex=1
fi
if [ -s "$td"/nobin ] ; then
- printf >&2 '%s\n' 'Stray manual page for:'
+ printf >&2 'Stray manual page for:\n'
cat >&2 -- "$td"/nobin
ex=1
fi
# Exit appropriately
+if [ "$ex" -eq 0 ] ; then
+ printf 'All scripts have manual pages.\n'
+fi
exit "$ex"
diff --git a/test/pdksh b/check/pdksh
index fd1d55b7..fd1d55b7 100755
--- a/test/pdksh
+++ b/check/pdksh
diff --git a/test/sh b/check/sh
index 47e41c77..ec3ba339 100755
--- a/test/sh
+++ b/check/sh
@@ -1,5 +1,5 @@
#!/bin/sh
-for sh in sh/* sh/profile.d/* ; do
+for sh in sh/* sh/profile.d/* sh/shrc.d/* ; do
[ -f "$sh" ] || continue
sh -n "$sh" || exit
done
diff --git a/test/urxvt b/check/urxvt
index d27d6660..d27d6660 100755
--- a/test/urxvt
+++ b/check/urxvt
diff --git a/dircolors/dircolors b/dircolors/dircolors
deleted file mode 100644
index 2b583feb..00000000
--- a/dircolors/dircolors
+++ /dev/null
@@ -1,117 +0,0 @@
-TERM ansi
-TERM linux
-TERM putty
-TERM putty-256color
-TERM rxvt
-TERM rxvt-256color
-TERM rxvt-unicode
-TERM rxvt-unicode-256color
-TERM screen
-TERM screen-256color
-TERM xterm
-TERM xterm-256color
-DIR 01;34
-LINK 01;36
-FIFO 40;33
-SOCK 01;35
-DOOR 01;35
-BLK 40;33;01
-CHR 40;33;01
-ORPHAN 40;31;01
-EXEC 01;32
-.tar 01;31
-.tgz 01;31
-.arj 01;31
-.taz 01;31
-.lzh 01;31
-.lzma 01;31
-.tlz 01;31
-.txz 01;31
-.zip 01;31
-.z 01;31
-.Z 01;31
-.dz 01;31
-.gz 01;31
-.lz 01;31
-.xz 01;31
-.bz2 01;31
-.bz 01;31
-.tbz 01;31
-.tbz2 01;31
-.tz 01;31
-.deb 01;31
-.rpm 01;31
-.jar 01;31
-.war 01;31
-.ear 01;31
-.sar 01;31
-.rar 01;31
-.ace 01;31
-.zoo 01;31
-.cpio 01;31
-.7z 01;31
-.rz 01;31
-.jpg 01;35
-.jpeg 01;35
-.gif 01;35
-.bmp 01;35
-.pbm 01;35
-.pgm 01;35
-.ppm 01;35
-.tga 01;35
-.xbm 01;35
-.xpm 01;35
-.tif 01;35
-.tiff 01;35
-.png 01;35
-.svg 01;35
-.svgz 01;35
-.mng 01;35
-.pcx 01;35
-.mov 01;35
-.mpg 01;35
-.mpeg 01;35
-.m2v 01;35
-.mkv 01;35
-.webm 01;35
-.ogm 01;35
-.mp4 01;35
-.m4v 01;35
-.mp4v 01;35
-.vob 01;35
-.qt 01;35
-.nuv 01;35
-.wmv 01;35
-.asf 01;35
-.rm 01;35
-.rmvb 01;35
-.flc 01;35
-.avi 01;35
-.fli 01;35
-.flv 01;35
-.gl 01;35
-.dl 01;35
-.xcf 01;35
-.xwd 01;35
-.yuv 01;35
-.cgm 01;35
-.emf 01;35
-.axv 01;35
-.anx 01;35
-.ogv 01;35
-.ogx 01;35
-.aac 00;36
-.au 00;36
-.flac 00;36
-.mid 00;36
-.midi 00;36
-.mka 00;36
-.mp3 00;36
-.mpc 00;36
-.ogg 00;36
-.ra 00;36
-.wav 00;36
-.axa 00;36
-.oga 00;36
-.spx 00;36
-.xspf 00;36
diff --git a/games/kvlt.sed b/games/kvlt.sed
index 1cb06b5a..f90eab2f 100644
--- a/games/kvlt.sed
+++ b/games/kvlt.sed
@@ -8,6 +8,9 @@ y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
s/^/~/
s/$/~/
+# All numbers become 666
+s,[0-9][0-9]*,666,g
+
# Various words for KVLT
s,\([^A-Z]\)ASSOCIATION\([^A-Z]\),\1KVLT\2,g
s,\([^A-Z]\)BUSINESS\([^A-Z]\),\1KVLT\2,g
@@ -66,9 +69,6 @@ s,\([^A-Z]\)AND\([^A-Z]\),\1VND\2,g
# TRUE -> TRV
s,\([^A-Z]\)TRUE\([^A-Z]\),\1TRV\2,g
-# All numbers become 666
-s,[0-9][0-9]*,666,g
-
# Remove the padding established above
s/^~//
s/~$//
diff --git a/games/rndn b/games/rndn
index b4faed65..3abf730a 100755
--- a/games/rndn
+++ b/games/rndn
@@ -1,59 +1,43 @@
-#!/usr/bin/env bash
-
+#!/bin/sh
# Esoteric random number generator
-# <http://dilbert.com/strip/2001-10-25>
-self=rndn
-
-# Define usage function
-usage() {
- printf 'USAGE: %s [-h | -s SEED]\n' "$self"
-}
-# Parse options
-while getopts 'hs:' opt ; do
- case $opt in
+# Single optional argument is a random seed, otherwise use rnds(1)
+s=${1:-"$(rnds)"}
- # -h for help
- h)
- usage
- exit 0
- ;;
-
- # -s to set seed manually
- s)
- seed=$OPTARG
- ;;
-
- # Unknown option, print usage and fail
- \?)
- usage >&2
- exit 2
- ;;
- esac
-done
-shift "$((OPTIND-1))"
+# Validate s
+case $s in
+ *[!0-9]*)
+ printf >&2 'rndn: Seed must be non-negative integer\n'
+ exit 2
+ ;;
+esac
-# If no seed given, get one from Bash's $RANDOM
-: "${seed:=$((RANDOM ** 2))}"
-
-# Truncate the seed
-seed=${seed:0:32}
-
-# Check seed meets algorithm conditions
-if [[ $seed == *[^0-9]* ]] || ((seed < 0)) ; then
- printf >&2 '%s: error: seed must be non-negative integer\n' "$self"
- exit 2
-fi
+# Helper functions
+t() {
+ printf %u "$1" | cut -c -"$2"
+}
+l() {
+ printf %u "$1" | wc -c
+}
+c() {
+ printf %u "$1" | cut -c "$2"
+}
-# Apply algorithm
-for ((seed += 10, i = 0; i < ${#seed}; i++)) ; do
- ((sum += ${seed:i:1}))
+# Apply algorithm; you are not expected to understand this
+s=$(t "$((s + 10))" 32) i=1 t=0
+while [ "$i" -le "$(l "$s")" ] ; do
+ d=$(c "$s" "$i")
+ t=$((t + d)) i=$((i + 1))
done
-for ((red = seed - sum; ${#red} > 1; red = redn)) ; do
- for ((j = 0, redn = 0; j < ${#red}; j++)) ; do
- ((redn += ${red:j:1}))
+p=$((s - t))
+while [ "$(l "$p")" -gt 1 ] ; do
+ j=1 q=0
+ while [ "$j" -le "$(l "$p")" ] ; do
+ d=$(c "$p" "$j")
+ q=$((q + d)) j=$((j + 1))
done
+ p=$q
done
# Print result
-printf '%u\n' "$red"
+printf '%u\n' "$p"
diff --git a/git/gitconfig.m4 b/git/gitconfig.m4
index 616fdad8..73bdae98 100644
--- a/git/gitconfig.m4
+++ b/git/gitconfig.m4
@@ -1,5 +1,7 @@
[advice]
statusHints = false
+ detachedHead = false
+ pushUpdateRejected = false
[alias]
others = ls-files --others --exclude-standard
@@ -24,6 +26,9 @@
[merge]
ff = false
+[pull]
+ ff = only
+
[push]
default = current
diff --git a/man/man1/apf.1 b/man/man1/apf.1
index 67b3b25a..7cb2ab28 100644
--- a/man/man1/apf.1
+++ b/man/man1/apf.1
@@ -7,30 +7,34 @@
foorc
foo --bar baz
.SH DESCRIPTION
-Add null-delimited arguments read from a file to a command's arguments before
-running it. This is intended as a way of implementing *rc files for interactive
-shell calls to programs that don't support such files, without having to use
-broken environment variables (e.g. GREP_OPTIONS); this enables you to, for
-example, use arguments with shell metacharacters and spaces in them that you do
-not want expanded.
-
+Add newline-delimited arguments read from a file to a command's arguments
+(before any given ones) before running it. This is intended as a quick way of
+implementing *rc files for interactive shell calls to programs that don't
+support such files, without having to use broken environment variables like GNU
+grep(1)'s GREP_OPTIONS.
+.P
+This enables you to use arguments with shell metacharacters and spaces in them
+that you do not want expanded. The only exception is that you cannot have
+newlines in any of the arguments. This was done to keep POSIX sh(1)
+compatibility.
+.P
For example, given this simple program in our $PATH, printargs:
-
- $ cat ~/.local/bin/printargs
+.P
+ $ cat /usr/bin/printargs
#!/bin/sh
- printf '%s\n' "$@"
-
+ printf '%s\\n' "$@"
+.P
Which just prints its arguments:
-
+.P
$ printargs a b c
a
b
c
-
+.P
We could do this:
-
- $ printf '%s\0' -f --flag --option '? foo bar *' > "$HOME"/.printargsrc
-
+.P
+ $ printf '%s\\n' -f --flag --option '? foo bar *' > "$HOME"/.printargsrc
+.P
$ apf "$HOME"/.printargsrc printargs a b c
-f
--flag
@@ -39,27 +43,23 @@ We could do this:
a
b
c
-
-We could then make a permanent wrapper function with:
-
+.P
+We could then make a permanent wrapper script in two line:
+.P
+ $ cat >~/.local/bin/printargs
+ #!/bin/sh
+ exec apf "$HOME"/.printargsrc /usr/bin/printargs
+ ^D
+ $ chmod +x ~/.local/bin/printargs
+.P
+Or just a shell function, if it's needed interactively:
+.P
$ printargs() { apf "$HOME"/.printargsrc printargs "$@" ; }
-
- $ printargs a b c
- -f
- --flag
- --option
- ? foo bar *
- a
- b
- c
-
- $ printf '%s\n' !-2:q >> "$HOME"/.bashrc
-
-This means you can edit the options in the *rc file, and don't have to redefine
-a wrapper function.
-
-If you actually want those options to *always* be added, regardless of whether
-you're in an interactive shell, you really should make an actual wrapper
-script.
+.P
+It's not considered an error if the file doesn't exist or is empty. If it's a
+directory or otherwise not byte-readable, an error will be printed to stderr,
+but execution of the called program will continue anyway. Blank lines or lines
+beginning with # are also ignored. Both leading and trailing whitespace is
+preserved.
.SH AUTHOR
Tom Ryder <tom@sanctum.geek.nz>
diff --git a/man/man1/br.1 b/man/man1/br.1
index ad841750..5f6de5f7 100644
--- a/man/man1/br.1
+++ b/man/man1/br.1
@@ -12,14 +12,12 @@ BROWSER=firefox
.B br
.SH DESCRIPTION
.B br
-run with no arguments just execs the program in the $BROWSER environment
-variable. If given a single URL, it tries to get its MIME type from a HEAD
-request and matches on the URL and/or the MIME type to see if any more suitable
-programs could open it. Otherwise, it falls back on $BROWSER.
+just execs the program in the $BROWSER environment variable with the given
+arguments. That's it.
.P
-At the time of writing, it tries to load image types with feh(1), and YouTube
-URLs without a start time with mpv(1).
+It was written to have a clean way to launch $BROWSER from ~/.xbindkeysrc. It
+has no other reason to exist.
.SH SEE ALSO
-brxs(1), urlh(1), urlmt(1), feh(1), mpv(1)
+xgo(1), xgoc(1)
.SH AUTHOR
Tom Ryder <tom@sanctum.geek.nz>
diff --git a/man/man1/dmp.1 b/man/man1/dmp.1
index 2d9111d6..e9b5dc4f 100644
--- a/man/man1/dmp.1
+++ b/man/man1/dmp.1
@@ -1,15 +1,19 @@
-.TH DMP 1 "May 2014" "Manual page for dmp"
+.TH DMP 1 "August 2016" "Manual page for dmp"
.SH NAME
.B dmp
\- pick a pass(1) password with dmenu(1)
.SH SYNOPSIS
.B dmp
+.br
+.B dmp 25
.SH DESCRIPTION
.B dmp
-applies dmenu(1) to pick a password entry
-from a pass(1) store and put it into the X
-CLIPBOARD for up to 10 seconds.
+applies dmenu(1) to pick a password entry from a pass(1) store and put it into
+the X CLIPBOARD for up to 10 seconds.
+.P
+An optional timeout in seconds can be applied, after which xsel(1) will remove
+the password from the clipboard. This timeout defaults to 10 seconds.
.SH SEE ALSO
-dmenu(1), pass(1)
+dmenu(1), pass(1), xsel(1)
.SH AUTHOR
Tom Ryder <tom@sanctum.geek.nz>
diff --git a/man/man1/edda.1 b/man/man1/edda.1
index 21e6b163..3123c0ce 100644
--- a/man/man1/edda.1
+++ b/man/man1/edda.1
@@ -1,14 +1,14 @@
-.TH EDDA 1 "June 2015" "Manual page for edda"
+.TH EDDA 1 "August 2016" "Manual page for edda"
.SH NAME
.B edda
\- run ed(1) over multiple files
.SH SYNOPSIS
-.B edda [OPTS] [--] FILE1 [FILE2...]
+.B edda FILE1 [FILE2...]
.SH DESCRIPTION
-Duplicate any data on stdin into a temporary file, and run ed(1) with any given
-options over each of the files given as the remaining arguments. Example:
+Duplicate any data on stdin into a temporary file, and run ed(1) options over
+each of the files given as the remaining arguments. Example:
.P
- $ edda -s /etc/app.d/*.conf <<EOF
+ $ edda /etc/app.d/*.conf <<EOF
,s/foo/bar/g
w
EOF
diff --git a/man/man1/unf.1 b/man/man1/unf.1
index 709e7d2b..57d4548f 100644
--- a/man/man1/unf.1
+++ b/man/man1/unf.1
@@ -13,7 +13,7 @@ FILE
FILE1 FILE2...
.br
curl -I http://www.example.net/ |
-.B
+.B
unf
.SH DESCRIPTION
Joins lines with leading spaces in the output to the previous line,
diff --git a/man/man1/xgo.1 b/man/man1/xgo.1
index 13cbdd37..5eec6517 100644
--- a/man/man1/xgo.1
+++ b/man/man1/xgo.1
@@ -6,8 +6,12 @@
.B xgo
.SH DESCRIPTION
.B xgo
-examines each of its arguments and opens an appropriate program to view it,
-falling back on $BROWSER.
+examines each of its arguments, including making an HTTP HEAD request to try
+and get its MIME type, and then opens an appropriate program to view it,
+falling back on $BROWSER. The choices of application are very opinionated.
+.SH FUTURE
+There could probably be a MIME-type and/or URL-pattern to program configuration
+file, rather than hard-coding it.
.SH SEE ALSO
br(1), xgoc(1)
.SH AUTHOR
diff --git a/man/man7/dotfiles.7.header b/man/man7/dotfiles.7.header
index 2731f7dc..b059b0fd 100644
--- a/man/man7/dotfiles.7.header
+++ b/man/man7/dotfiles.7.header
@@ -1,4 +1,3 @@
% DOTFILES(7)
% Tom Ryder
% June 2016
-
diff --git a/pdksh/pdkshrc b/pdksh/pdkshrc
index 46dbba2c..48799c2e 100644
--- a/pdksh/pdkshrc
+++ b/pdksh/pdkshrc
@@ -4,11 +4,10 @@ set -o emacs
# Save history
HISTFILE=$HOME/.pdksh_history
-HISTSIZE=$((1 << 12))
+HISTSIZE=$((1 << 10))
# Load any supplementary scripts
for pdkshrc in "$HOME"/.pdkshrc.d/*.pdksh ; do
- [[ -e $pdkshrc ]] || continue
- . "$pdkshrc"
+ [[ -e $pdkshrc ]] && . "$pdkshrc"
done
unset -v pdkshrc
diff --git a/pdksh/pdkshrc.d/diff.pdksh b/pdksh/pdkshrc.d/diff.pdksh
deleted file mode 100644
index 2c752c8d..00000000
--- a/pdksh/pdkshrc.d/diff.pdksh
+++ /dev/null
@@ -1,4 +0,0 @@
-# Use a unified format for diff(1) by default
-diff() {
- command diff -u "$@"
-}
diff --git a/pdksh/pdkshrc.d/ed.pdksh b/pdksh/pdkshrc.d/ed.pdksh
deleted file mode 100644
index f64f6dc6..00000000
--- a/pdksh/pdkshrc.d/ed.pdksh
+++ /dev/null
@@ -1,26 +0,0 @@
-# Add a colon prompt to ed when a command is expected rather than text; makes
-# it feel a lot more like using ex. Only do this when stdin is a terminal,
-# however. Also try and use -v for more verbose error output, and rlwrap(1) if
-# it's available.
-ed() {
-
- # We're only adding options if input is from a terminal
- if [[ -t 0 ]] ; then
-
- # Colon prompt (POSIX)
- set -- -p : "$@"
-
- # Verbose if availble (not POSIX)
- if ed -sv - </dev/null >&0 2>&0 ; then
- set -- -v "$@"
- fi
- fi
-
- # Execute the ed(1) call, in a wrapper if appropriate and with the
- # concluded options
- if [[ -t 0 ]] && command -v rlwrap >/dev/null ; then
- command rlwrap ed "$@"
- else
- command ed "$@"
- fi
-}
diff --git a/pdksh/pdkshrc.d/gdb.pdksh b/pdksh/pdkshrc.d/gdb.pdksh
deleted file mode 100644
index ec9d4137..00000000
--- a/pdksh/pdkshrc.d/gdb.pdksh
+++ /dev/null
@@ -1,4 +0,0 @@
-# Don't print the GDB copyright message on every invocation
-gdb() {
- command gdb -q "$@"
-}
diff --git a/pdksh/pdkshrc.d/gpg.pdksh b/pdksh/pdkshrc.d/gpg.pdksh
deleted file mode 100644
index 62d123ea..00000000
--- a/pdksh/pdkshrc.d/gpg.pdksh
+++ /dev/null
@@ -1,10 +0,0 @@
-# Wrapper around gpg(1) to stop ``--batch'' breaking things
-gpg() {
- # shellcheck disable=SC2048
- case $* in
- *--ed*|*--gen-k*|*--sign-k*)
- set -- --no-batch "$@"
- ;;
- esac
- command gpg "$@"
-}
diff --git a/pdksh/pdkshrc.d/keychain.pdksh b/pdksh/pdkshrc.d/keychain.pdksh
deleted file mode 100644
index 40fe5d71..00000000
--- a/pdksh/pdkshrc.d/keychain.pdksh
+++ /dev/null
@@ -1,4 +0,0 @@
-# If GPG_TTY is set, update it
-if [[ -n $GPG_TTY ]] ; then
- GPG_TTY=$(tty)
-fi
diff --git a/pdksh/pdkshrc.d/mkcd.pdksh b/pdksh/pdkshrc.d/mkcd.pdksh
deleted file mode 100644
index 6342d4a6..00000000
--- a/pdksh/pdkshrc.d/mkcd.pdksh
+++ /dev/null
@@ -1,4 +0,0 @@
-# Create a directory and change into it
-mkcd() {
- mkdir -p -- "$1" && builtin cd -- "$1"
-}
diff --git a/pdksh/pdkshrc.d/prompt.pdksh b/pdksh/pdkshrc.d/prompt.pdksh
index c3db782b..71e952a0 100644
--- a/pdksh/pdkshrc.d/prompt.pdksh
+++ b/pdksh/pdkshrc.d/prompt.pdksh
@@ -17,7 +17,7 @@ prompt() {
on)
# Set up prompt, including optional PROMPT_PREFIX and PROMPT_SUFFIX
# variables
- PS1='[\u@\h:\w]'
+ PS1='\u@\h:\w'
PS1=$PS1'$(prompt vcs)'
PS1=$PS1'$(prompt job)'
PS1='${PROMPT_PREFIX}'$PS1
@@ -111,8 +111,9 @@ prompt() {
state=${state}^
fi
- # Print the status in brackets with a git: prefix
- printf '(git:%s%s)' "${branch:-unknown}" "$state"
+ # Print the status in brackets; add a git: prefix only if there
+ # might be another VCS prompt (because PROMPT_VCS is set)
+ printf '(%s%s%s)' "${PROMPT_VCS:+git:}" "${branch:-unknown}" "$state"
;;
# Revert to simple inexpensive prompts
diff --git a/pdksh/pdkshrc.d/pwgen.pdksh b/pdksh/pdkshrc.d/pwgen.pdksh
deleted file mode 100644
index 7ba056e5..00000000
--- a/pdksh/pdkshrc.d/pwgen.pdksh
+++ /dev/null
@@ -1,8 +0,0 @@
-# Set some defaults for pwgen(1), because its defaults are to give me a long
-# list of relatively short passwords, when I generally want only one good one
-pwgen() {
- if ! (($#)) ; then
- set -- --secure -- "${PWGEN_LENGTH:-15}" "${PWGEN_COUNT:-1}"
- fi
- command pwgen "$@"
-}
diff --git a/pdksh/pdkshrc.d/rcsdiff.pdksh b/pdksh/pdkshrc.d/rcsdiff.pdksh
deleted file mode 100644
index 18b1d324..00000000
--- a/pdksh/pdkshrc.d/rcsdiff.pdksh
+++ /dev/null
@@ -1,4 +0,0 @@
-# Use a unified format for rcsdiff(1) by default
-rcsdiff() {
- command rcsdiff -u "$@"
-}
diff --git a/pdksh/pdkshrc.d/scp.pdksh b/pdksh/pdkshrc.d/scp.pdksh
deleted file mode 100644
index c3565f21..00000000
--- a/pdksh/pdkshrc.d/scp.pdksh
+++ /dev/null
@@ -1,9 +0,0 @@
-# Wrap scp(1) to check for missing colons
-scp() {
- # shellcheck disable=SC2048
- if (($# >= 2)) && [[ $* != *:* ]] ; then
- printf 'ksh: scp: Missing colon, probably an error\n' >&2
- return 2
- fi
- command scp "$@"
-}
diff --git a/pdksh/pdkshrc.d/sudo.pdksh b/pdksh/pdkshrc.d/sudo.pdksh
deleted file mode 100644
index d6d91d12..00000000
--- a/pdksh/pdkshrc.d/sudo.pdksh
+++ /dev/null
@@ -1,7 +0,0 @@
-# Add the -H parameter to sudo(8) calls, always use the target user's $HOME
-sudo() {
- if [[ $1 != -v ]] ; then
- set -- -H "$@"
- fi
- command sudo "$@"
-}
diff --git a/pdksh/pdkshrc.d/tmux.pdksh b/pdksh/pdkshrc.d/tmux.pdksh
deleted file mode 100644
index f0d0e36a..00000000
--- a/pdksh/pdkshrc.d/tmux.pdksh
+++ /dev/null
@@ -1,19 +0,0 @@
-# Attach to existing tmux session rather than create a new one if possible
-tmux() {
-
- # If given any arguments, just use them as they are
- if (($#)) ; then
- :
-
- # If a session exists, just attach to it
- elif command tmux has-session 2>/dev/null ; then
- set -- attach-session -d
-
- # Create a new session with an appropriate name
- else
- set -- new-session -s "${TMUX_SESSION:-default}"
- fi
-
- # Execute with concluded arguments
- command tmux "$@"
-}
diff --git a/sh/profile b/sh/profile
index e9e974e0..5dfe0ef3 100644
--- a/sh/profile
+++ b/sh/profile
@@ -4,8 +4,13 @@ if [ -d "$HOME"/.local/bin ] ; then
fi
# Load all supplementary scripts in ~/.profile.d
-for profile in "$HOME"/.profile.d/*.sh ; do
- [ -e "$profile" ] || continue
- . "$profile"
+for sh in "$HOME"/.profile.d/*.sh ; do
+ [ -e "$sh" ] && . "$sh"
done
-unset -v profile
+unset -v sh
+
+# If ENV is unset after running those scripts and ~/.shrc exists, set it as ENV
+if [ -z "$ENV" ] && [ -f "$HOME"/.shrc ] ; then
+ ENV=$HOME/.shrc
+ export ENV
+fi
diff --git a/sh/profile.d/editor.sh b/sh/profile.d/editor.sh
index 7ed9e262..ee0da70b 100644
--- a/sh/profile.d/editor.sh
+++ b/sh/profile.d/editor.sh
@@ -1,4 +1,3 @@
-# Set editor
-EDITOR=vi
-VISUAL=$EDITOR
-export EDITOR VISUAL
+# Set command-line editor
+EDITOR=ed
+export EDITOR
diff --git a/sh/profile.d/env.sh b/sh/profile.d/env.sh
deleted file mode 100644
index f1b83919..00000000
--- a/sh/profile.d/env.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-# If we're running some kind of ksh, export ENV to find a suitable startup
-# file. Bash differs considerably from this behaviour; it uses ENV as its
-# startup file when it's invoked as sh(1), and uses .bashrc or --rcfile as its
-# interactive startup file, so it doesn't need to be specified here.
-case $KSH_VERSION in
- *'PD KSH '*) ENV=$HOME/.pdkshrc ;;
-esac
-if [ -n "$ENV" ] ; then
- export ENV
-fi
diff --git a/sh/profile.d/grep.sh b/sh/profile.d/grep.sh
index 87c9a6cc..892351ca 100644
--- a/sh/profile.d/grep.sh
+++ b/sh/profile.d/grep.sh
@@ -1,13 +1,21 @@
-# Store grep(1)'s --help output in a variable
-grep_help=$(grep --help 2>/dev/null)
+# Test that we have metadata about what options this system's grep(1) supports,
+# and try to create it if not
+(
+ # Create a directory to hold metadata about grep
+ gcd=$HOME/.cache/grep
+ if ! [ -d "$gcd" ] ; then
+ mkdir -p -- "$gcd" || exit
+ fi
-# Set and export GREP_COLORS if available and appropriate
-case $grep_help in
- *--color*)
- GREP_COLORS='ms=01;31:mc=01;31:sl=:cx=:fn=35:ln=32:bn=32:se=36'
- export GREP_COLORS
- ;;
-esac
+ # Write grep(1)'s --help output to a file, even if it's empty
+ if ! [ -f "$gcd"/help ] ; then
+ grep --help </dev/null >"$gcd"/help 2>/dev/null || exit
-# We're done parsing grep(1)'s --help output now
-unset -v grep_help
+ # Iterate through some useful options and create files to show they're
+ # available
+ for opt in binary-files color exclude exclude-dir ; do
+ grep -q -- --"$opt" "$gcd"/help || continue
+ touch -- "$gcd"/"$opt" || exit
+ done
+ fi
+)
diff --git a/sh/profile.d/ls.sh b/sh/profile.d/ls.sh
index a3cc84b7..0c3754e9 100644
--- a/sh/profile.d/ls.sh
+++ b/sh/profile.d/ls.sh
@@ -1,18 +1,20 @@
-# Store ls(1)'s --help output in a variable
-ls_help=$(ls --help 2>/dev/null)
+# Test that we have metadata about what options this system's ls(1) supports,
+# and try to create it if not
+(
+ # Create a directory to hold metadata about ls(1)
+ lcd=$HOME/.cache/ls
+ if ! [ -d "$lcd" ] ; then
+ mkdir -p -- "$lcd" || exit
+ fi
-# Run dircolors(1) to export LS_COLORS if available and appropriate
-case $ls_help in
- *--color*)
- if command -v dircolors >/dev/null 2>&1 ; then
- if [ -r "$HOME"/.dircolors ] ; then
- eval "$(dircolors --sh -- "$HOME"/.dircolors)"
- else
- eval "$(dircolors --sh)"
- fi
- fi
- ;;
-esac
+ # Write ls(1)'s --help output to a file, even if it's empty
+ if ! [ -f "$lcd"/help ] ; then
+ ls --help >"$lcd"/help 2>/dev/null || exit
-# We're done parsing ls(1)'s --help output now
-unset -v ls_help
+ # Iterate through some useful options and create files to show they're
+ # available
+ if grep -q -- --color "$lcd"/help ; then
+ touch -- "$lcd"/color || exit
+ fi
+ fi
+)
diff --git a/sh/profile.d/pager.sh b/sh/profile.d/pager.sh
index 2cbcb26d..f0c4fab4 100644
--- a/sh/profile.d/pager.sh
+++ b/sh/profile.d/pager.sh
@@ -1,6 +1,6 @@
# If we don't have less(1), we'll just use whatever pager the application or
# system deems fit
-command less >/dev/null 2>&1 || return
+command -v less >/dev/null 2>&1 || return
# Use less(1) as my PAGER
PAGER=less
diff --git a/sh/profile.d/visual.sh b/sh/profile.d/visual.sh
new file mode 100644
index 00000000..95eb1d5d
--- /dev/null
+++ b/sh/profile.d/visual.sh
@@ -0,0 +1,3 @@
+# Set visual editor
+VISUAL=vi
+export VISUAL
diff --git a/sh/shrc b/sh/shrc
new file mode 100644
index 00000000..deb55cc2
--- /dev/null
+++ b/sh/shrc
@@ -0,0 +1,12 @@
+# Make sure the shell is interactive
+case $- in
+ *i*) ;;
+ *) return ;;
+esac
+
+# Load all the POSIX-compatible functions from ~/.shrc.d; more advanced shells
+# like bash will have their own functions
+for sh in "$HOME"/.shrc.d/*.sh ; do
+ [ -e "$sh" ] && . "$sh"
+done
+unset -v sh
diff --git a/bash/bashrc.d/bc.bash b/sh/shrc.d/bc.sh
index 643678ac..643678ac 100644
--- a/bash/bashrc.d/bc.bash
+++ b/sh/shrc.d/bc.sh
diff --git a/sh/shrc.d/cd.sh b/sh/shrc.d/cd.sh
new file mode 100644
index 00000000..dd98a422
--- /dev/null
+++ b/sh/shrc.d/cd.sh
@@ -0,0 +1,72 @@
+# If given two arguments, replace the first instance of the first argument with
+# the second argument in $PWD, and make that the target of cd(). This POSIX
+# version cannot handle options, but it can handle an option terminator (--),
+# so e.g. `cd -- -foo -bar` should work.
+cd() {
+
+ # First check to see if we can perform the substitution at all
+ if (
+
+ # If we have any options, we can't do it, because POSIX shell doesn't
+ # let us (cleanly) save the list of options for use later in the script
+ for arg ; do
+ case $arg in
+ --) break ;;
+ -*) return 1 ;;
+ esac
+ done
+
+ # Shift off -- if it's the first argument
+ [ "$1" = -- ] && shift
+
+ # Check we have two non-null arguments
+ [ "$#" -eq 2 ] || return
+ [ -n "$1" ] || return
+ [ -n "$2" ] || return
+
+ ) ; then
+
+ # Set the positional parameters to an option terminator and what will
+ # hopefully end up being the substituted directory name
+ set -- -- "$(
+
+ # If the first of the existing positional arguments is --, shift it
+ # off
+ [ "$1" = -- ] && shift
+
+ # 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
+ rep=$2
+
+ # /foo/
+ curtc=${cur%%"$pat"*}
+ # /bar/ayy
+ curlc=${cur#*"$pat"}
+ # /foo/lmao/bar/ayy
+ new=${curtc}${rep}${curlc}
+
+ # Check pattern was actually in $PWD; this indirectly checks that
+ # $PWD and $pat are both actually set, too; it's valid for $rep to
+ # be empty, though
+ [ "$cur" != "$curtc" ] || exit
+
+ # Check we ended up with something to change into
+ [ -n "$new" ] || exit
+
+ # Print the replaced result
+ printf '%s\n' "$new"
+ )"
+
+ # Check we have a second argument
+ if [ -z "$2" ] ; then
+ printf >&2 'cd(): Substitution failed\n'
+ return 1
+ fi
+ fi
+
+ # Execute the cd command as normal
+ command cd "$@"
+}
diff --git a/bash/bashrc.d/diff.bash b/sh/shrc.d/diff.sh
index 2c752c8d..2c752c8d 100644
--- a/bash/bashrc.d/diff.bash
+++ b/sh/shrc.d/diff.sh
diff --git a/bash/bashrc.d/ed.bash b/sh/shrc.d/ed.sh
index b87894df..4638d2cb 100644
--- a/bash/bashrc.d/ed.bash
+++ b/sh/shrc.d/ed.sh
@@ -5,7 +5,7 @@
ed() {
# We're only adding options if input is from a terminal
- if [[ -t 0 ]] ; then
+ if [ -t 0 ] ; then
# Colon prompt (POSIX)
set -- -p : "$@"
@@ -18,7 +18,7 @@ ed() {
# Execute the ed(1) call, in a wrapper if appropriate and with the
# concluded options
- if [[ -t 0 ]] && hash rlwrap 2>/dev/null ; then
+ if [ -t 0 ] && command -v rlwrap >/dev/null 2>&1 ; then
command rlwrap ed "$@"
else
command ed "$@"
diff --git a/sh/shrc.d/env.sh b/sh/shrc.d/env.sh
new file mode 100644
index 00000000..4fa980f2
--- /dev/null
+++ b/sh/shrc.d/env.sh
@@ -0,0 +1,8 @@
+# Sort the output of env(1) for me
+env() {
+ if [ "$#" -eq 0 ] ; then
+ command env | sort
+ else
+ command env "$@"
+ fi
+}
diff --git a/bash/bashrc.d/gdb.bash b/sh/shrc.d/gdb.sh
index ec9d4137..ec9d4137 100644
--- a/bash/bashrc.d/gdb.bash
+++ b/sh/shrc.d/gdb.sh
diff --git a/bash/bashrc.d/gpg.bash b/sh/shrc.d/gpg.sh
index 62d123ea..62d123ea 100644
--- a/bash/bashrc.d/gpg.bash
+++ b/sh/shrc.d/gpg.sh
diff --git a/sh/shrc.d/grep.sh b/sh/shrc.d/grep.sh
new file mode 100644
index 00000000..df2101aa
--- /dev/null
+++ b/sh/shrc.d/grep.sh
@@ -0,0 +1,35 @@
+# Our ~/.profile should already have made a directory with the supported
+# options for us; if not, we won't be wrapping grep(1) with a function at all
+[ -d "$HOME"/.cache/grep ] || return
+
+# Define function proper
+grep() {
+
+ # Add --color if the terminal has at least 8 colors
+ [ -e "$HOME"/.cache/grep/color ] &&
+ [ "$({ tput colors || tput Co ; } 2>/dev/null)" -ge 8 ] &&
+ set -- --color=auto "$@"
+
+ # Add --binary-files=without-match to gracefully skip binary files
+ [ -e "$HOME"/.cache/grep/binary-files ] &&
+ set -- --binary-files=without-match "$@"
+
+ # Add --exclude to ignore .gitignore and .gitmodules files
+ [ -e "$HOME"/.cache/grep/exclude ] &&
+ set -- \
+ --exclude=.gitignore \
+ --exclude=.gitmodules \
+ "$@"
+
+ # Add --exclude-dir to ignore version control dot-directories
+ [ -e "$HOME"/.cache/grep/exclude-dir ] &&
+ set -- \
+ --exclude-dir=.cvs \
+ --exclude-dir=.git \
+ --exclude-dir=.hg \
+ --exclude-dir=.svn \
+ "$@"
+
+ # Run grep(1) with the concluded arguments
+ command grep "$@"
+}
diff --git a/bash/bashrc.d/hgrep.bash b/sh/shrc.d/hgrep.sh
index 2f7f8d54..1c4c3ec5 100644
--- a/bash/bashrc.d/hgrep.bash
+++ b/sh/shrc.d/hgrep.sh
@@ -4,12 +4,12 @@
# $ history | grep PATTERN
#
hgrep() {
- if ! (($#)) ; then
- printf >&2 '%s: Need a pattern\n' "$FUNCNAME"
+ if [ "$#" -eq 0 ] ; then
+ printf >&2 'hgrep(): Need a pattern\n'
exit 2
fi
- if ! [[ -n $HISTFILE ]] ; then
- printf >&2 '%s: No HISTFILE\n' "$FUNCNAME"
+ if ! [ -n "$HISTFILE" ] ; then
+ printf >&2 'hgrep(): No HISTFILE\n'
exit 2
fi
grep "$@" "$HISTFILE"
diff --git a/sh/shrc.d/keychain.sh b/sh/shrc.d/keychain.sh
new file mode 100644
index 00000000..82f83473
--- /dev/null
+++ b/sh/shrc.d/keychain.sh
@@ -0,0 +1,3 @@
+# If GPG_TTY is set, update it
+[ -n "$GPG_TTY" ] || return
+GPG_TTY=$(tty)
diff --git a/sh/shrc.d/ksh.sh b/sh/shrc.d/ksh.sh
new file mode 100644
index 00000000..b12f13c8
--- /dev/null
+++ b/sh/shrc.d/ksh.sh
@@ -0,0 +1,10 @@
+# If we're running some kind of ksh, we'll need to source its specific
+# configuration if it was defined or if we can find it. Bash and Zsh invoke
+# their own rc files first, which I've written to then look for ~/.shrc; ksh
+# does it the other way around.
+case $KSH_VERSION in
+ *'PD KSH '*|*'MIRBSD KSH '*)
+ [ -f "${KSH_ENV:-"$HOME"/.pdkshrc}" ] || return
+ . "${KSH_ENV:-"$HOME"/.pdkshrc}"
+ ;;
+esac
diff --git a/sh/shrc.d/ls.sh b/sh/shrc.d/ls.sh
new file mode 100644
index 00000000..eec25eb7
--- /dev/null
+++ b/sh/shrc.d/ls.sh
@@ -0,0 +1,15 @@
+# Our ~/.profile should already have made a directory with the supported
+# options for us; if not, we won't be wrapping ls(1) with a function at all
+[ -d "$HOME"/.cache/ls ] || return
+
+# Define function proper
+ls() {
+
+ # Add --color if the terminal has at least 8 colors
+ [ -e "$HOME"/.cache/ls/color ] &&
+ [ "$({ tput colors || tput Co ; } 2>/dev/null)" -ge 8 ] &&
+ set -- --color=auto "$@"
+
+ # Run ls(1) with the concluded arguments
+ command ls "$@"
+}
diff --git a/bash/bashrc.d/mkcd.bash b/sh/shrc.d/mkcd.sh
index 6342d4a6..6342d4a6 100644
--- a/bash/bashrc.d/mkcd.bash
+++ b/sh/shrc.d/mkcd.sh
diff --git a/bash/bashrc.d/mysql.bash b/sh/shrc.d/mysql.sh
index 0d5ddb86..d37c3ead 100644
--- a/bash/bashrc.d/mysql.bash
+++ b/sh/shrc.d/mysql.sh
@@ -11,11 +11,9 @@
# database=bar
#
mysql() {
- local config
- config=$HOME/.mysql/$1.cnf
- if [[ -r $config ]] ; then
+ if [ -f "$HOME/.mysql/$1".cnf ] ; then
shift
- set -- --defaults-extra-file="$config" "$@"
+ set -- --defaults-extra-file="$HOME/.mysql/$1".cnf "$@"
fi
command mysql "$@"
}
diff --git a/bash/bashrc.d/pwgen.bash b/sh/shrc.d/pwgen.sh
index 7ba056e5..7ba056e5 100644
--- a/bash/bashrc.d/pwgen.bash
+++ b/sh/shrc.d/pwgen.sh
diff --git a/bash/bashrc.d/rcsdiff.bash b/sh/shrc.d/rcsdiff.sh
index 18b1d324..18b1d324 100644
--- a/bash/bashrc.d/rcsdiff.bash
+++ b/sh/shrc.d/rcsdiff.sh
diff --git a/sh/shrc.d/scp.sh b/sh/shrc.d/scp.sh
new file mode 100644
index 00000000..cc46b229
--- /dev/null
+++ b/sh/shrc.d/scp.sh
@@ -0,0 +1,14 @@
+# Wrap scp(1) to check for missing colons
+scp() {
+ # shellcheck disable=SC2048
+ if [ "$#" -ge 2 ] ; then
+ case $* in
+ *:*) ;;
+ *)
+ printf >&2 'scp(): Missing colon, probably an error\n'
+ return 2
+ ;;
+ esac
+ fi
+ command scp "$@"
+}
diff --git a/pdksh/pdkshrc.d/scr.pdksh b/sh/shrc.d/scr.sh
index 01bd20cb..255b9322 100644
--- a/pdksh/pdkshrc.d/scr.pdksh
+++ b/sh/shrc.d/scr.sh
@@ -2,10 +2,5 @@
# files into $HOME, and making the system do cleanup for me. Single optional
# argument is the string to use for naming the directory; defaults to "scr".
scr() {
- if (($# <= 1)) ; then
- cd -- "$(mktd "${1:-scr}")"
- else
- printf 'ksh: scr: too many arguments\n' >&2
- return 2
- fi
+ cd -- "$(mktd "${1:-scr}")"
}
diff --git a/bash/bashrc.d/sudo.bash b/sh/shrc.d/sudo.sh
index d6d91d12..a5883168 100644
--- a/bash/bashrc.d/sudo.bash
+++ b/sh/shrc.d/sudo.sh
@@ -1,7 +1,5 @@
# Add the -H parameter to sudo(8) calls, always use the target user's $HOME
sudo() {
- if [[ $1 != -v ]] ; then
- set -- -H "$@"
- fi
+ [ "$1" != -v ] && set -- -H "$@"
command sudo "$@"
}
diff --git a/bash/bashrc.d/tmux.bash b/sh/shrc.d/tmux.sh
index f0d0e36a..bd954be8 100644
--- a/bash/bashrc.d/tmux.bash
+++ b/sh/shrc.d/tmux.sh
@@ -2,7 +2,7 @@
tmux() {
# If given any arguments, just use them as they are
- if (($#)) ; then
+ if [ "$#" -gt 0 ] ; then
:
# If a session exists, just attach to it
diff --git a/pdksh/pdkshrc.d/vim.pdksh b/sh/shrc.d/vim.sh
index 37fc1871..e9174082 100644
--- a/pdksh/pdkshrc.d/vim.pdksh
+++ b/sh/shrc.d/vim.sh
@@ -1,7 +1,5 @@
# If Vim exists on the system, use it instead of ex, vi, and view
-if ! hash vim 2>/dev/null ; then
- return
-fi
+command -v vim >/dev/null 2>&1 || return
# Define functions proper
ex() {
diff --git a/vim/bundle/abolish b/vim/bundle/abolish
-Subproject e6a170cda8ee542ec5f1384c9643d4330ee6b18
+Subproject 125908e01dd69294743c7e22d3028855158aa44
diff --git a/vim/bundle/targets b/vim/bundle/targets
-Subproject 5c2ae9dbe358b2b78bd887e09ff8d10294b2b23
+Subproject 81dd6d1c3c36622f8df6ee7c67ec3707838df75
diff --git a/vim/vimrc b/vim/vimrc
index 5e496e26..ab7acf30 100644
--- a/vim/vimrc
+++ b/vim/vimrc
@@ -69,7 +69,7 @@ if has('syntax')
" Use my custom color scheme if possible, otherwise I'm happy with whatever
" the default is, and it usually cares about my background
set background=dark
- silent! colorscheme juvenile
+ silent! colorscheme sahara
endif
" Command-line based features
diff --git a/zsh/zprofile b/zsh/zprofile
index b61ca248..95214ef6 100644
--- a/zsh/zprofile
+++ b/zsh/zprofile
@@ -1 +1,5 @@
-exec bash -l
+# Zsh doesn't source ~/.profile by default, even when this file is absent.
+# <https://sanctum.geek.nz/images/identifying-heresy.jpg>
+if [[ -e $HOME/.profile ]] ; then
+ source "$HOME"/.profile
+fi
diff --git a/zsh/zshrc b/zsh/zshrc
index a2a3d4ca..014ac3fd 100644
--- a/zsh/zshrc
+++ b/zsh/zshrc
@@ -1 +1,11 @@
-exec bash
+# Emacs keybindings even if EDITOR is vi(1)
+bindkey -e
+
+# History settings
+setopt histignorealldups sharehistory
+HISTFILE=$HOME/.zsh_history
+SAVEHIST=$((1 << 12))
+HISTSIZE=$((1 << 10))
+
+# Load POSIX shell functions
+source "$ENV"