aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2016-08-23 15:09:05 +1200
committerTom Ryder <tom@sanctum.geek.nz>2016-08-23 15:09:05 +1200
commit626141db6ec398396de81fdedf0ae7b6d237c9c6 (patch)
treeecd0783b4e3deb7d6c0f5ab179f27eab80789aff
parentMerge branch 'master' into freebsd (diff)
parentMerge branch 'openbsd' (diff)
downloaddotfiles-626141db6ec398396de81fdedf0ae7b6d237c9c6.tar.gz
dotfiles-626141db6ec398396de81fdedf0ae7b6d237c9c6.zip
Merge branch 'master' into freebsd
-rw-r--r--Makefile4
-rw-r--r--README.markdown31
-rw-r--r--bash/bash_completion.d/_ssh_config_hosts.bash21
-rw-r--r--bash/bash_completion.d/sftp.bash4
-rw-r--r--bash/bash_completion.d/ssh-copy-id.bash4
-rw-r--r--bash/bash_completion.d/ssh.bash26
-rw-r--r--bash/bashrc12
-rw-r--r--bash/bashrc.d/prompt.bash7
-rwxr-xr-xbin/apf68
-rwxr-xr-xbin/rfcf2
-rwxr-xr-xbin/urlh2
-rwxr-xr-xbin/urlmt2
-rwxr-xr-xbin/xgo14
-rw-r--r--gnupg/sks-keyservers.net/crl.pem31
-rw-r--r--pdksh/pdkshrc.d/prompt.pdksh55
-rw-r--r--sh/profile.d/keychain.sh2
-rw-r--r--sh/shrc5
-rw-r--r--sh/shrc.d/bd.sh11
-rw-r--r--sh/shrc.d/cd.sh76
-rw-r--r--sh/shrc.d/ksh.sh4
-rw-r--r--sh/shrc.d/pd.sh12
-rw-r--r--sh/shrc.d/prompt.sh3
-rw-r--r--sh/shrc.d/rd.sh63
-rw-r--r--sh/shrc.d/sd.sh18
-rw-r--r--sh/shrc.d/ud.sh26
-rw-r--r--tmux/tmux.conf.m429
26 files changed, 287 insertions, 245 deletions
diff --git a/Makefile b/Makefile
index 0c57d423..95d62f21 100644
--- a/Makefile
+++ b/Makefile
@@ -153,7 +153,7 @@ install-bash-completion : install-bash
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 \
- [ -x "$$name" ] && \
+ [ -x "$$name" ] || continue ; \
install -m 0755 -- "$$name" "$(HOME)"/.local/bin ; \
done
@@ -183,7 +183,7 @@ install-finger :
install-games : games/acq games/kvlt games/zs check-games install-games-man
install -m 0755 -d -- "$(HOME)"/.local/games
for name in games/* ; do \
- [ -x "$$name" ] && \
+ [ -x "$$name" ] || continue ; \
install -m 0755 -- "$$name" "$(HOME)"/.local/games ; \
done
diff --git a/README.markdown b/README.markdown
index 1790afb2..b1948e4b 100644
--- a/README.markdown
+++ b/README.markdown
@@ -15,11 +15,10 @@ Installation
$ make -n install
$ make install
-For the default target, you'll need `bash(1)`, `git(1)`, `install(1)`,
-`make(1)`, `m4(1)`, and `tic(1)`. You'll need to have a recent enough version
-of Git to support
-[submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) for the Vim
-installation to work; it's required for the plugin setup.
+For the default `all` target, you'll need `git(1)`, `install(1)`, `make(1)`,
+and `m4(1)`. This target includes the Bash files, but you don't need `bash` to
+actually install them, and the rest of the shell configuration should work
+without it.
The installation `Makefile` will overwrite things standing in the way of its
installed files without backing them up, so read the output of `make -n
@@ -129,17 +128,20 @@ defaults for interactive behavior.
A terminal session with my prompt looks something like this:
- tom@conan:~/.dotfiles(master+!)$ git status
+ ~$ ssh remote
+ tom@remote:~$ cd .dotfiles
+ tom@remote:~/.dotfiles(master+!)$ git status
M README.markdown
M bash/bashrc.d/prompt.bash
A init
- tom@conan:~/.dotfiles(master+!)$ foobar
+ tom@remote:~/.dotfiles(master+!)$ foobar
foobar: command not found
- tom@conan:~/.dotfiles(master+!)<127>$ sleep 5 &
+ tom@remote:~/.dotfiles(master+!)<127>$ sleep 5 &
[1] 28937
- tom@conan:~/.dotfiles(master+!){1}$
+ tom@remote:~/.dotfiles(master+!){1}$
-It expands based on context to include these elements in this order:
+The username and hostname are skipped if not connected via SSH. The right side
+of the prompt expands based on context to include these elements in this order:
* Whether in a Git repository if applicable, and punctuation to show
repository status including reference to upstreams at a glance. Subversion
@@ -165,8 +167,6 @@ in `sh/shrc.d` to be loaded by any POSIX interactive shell. Those include:
* `bc()` silences startup messages from GNU `bc(1)`.
* `bd()` changes into a named ancestor of the current directory.
* `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,
@@ -190,6 +190,9 @@ in `sh/shrc.d` to be loaded by any POSIX interactive shell. Those include:
* `pd()` changes to the argument's parent directory.
* `pwgen()` generates just one decent password with `pwgen(1)`.
* `rcsdiff()` forces a unified format for `rcsdiff(1)`.
+* `rd()` replaces the first instance of its first argument with its second
+ argument in `$PWD`, emulating a feature of the Zsh `cd` builtin that I
+ like.
* `scp()` tries to detect forgotten hostnames in `scp(1)` command calls.
* `scr()` creates a temporary directory and changes into it.
* `sd()` changes into a sibling of the current directory.
@@ -380,8 +383,8 @@ Installed by the `install-bin` target:
* `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.
-* `br(1)` launches $BROWSER, or a more suitable application for an URL if it
- knows of one.
+* `br(1)` launches `$BROWSER`, or a more suitable application for an URL if
+ it knows of one.
* `ca(1)` prints a count of its given arguments.
* `cf(1)` prints a count of entries in a given directory.
* `clrd(1)` sets up a per-line file read, clearing the screen first.
diff --git a/bash/bash_completion.d/_ssh_config_hosts.bash b/bash/bash_completion.d/_ssh_config_hosts.bash
new file mode 100644
index 00000000..02e9af06
--- /dev/null
+++ b/bash/bash_completion.d/_ssh_config_hosts.bash
@@ -0,0 +1,21 @@
+# Complete ssh_config(5) hostnames
+_ssh_config_hosts() {
+
+ # Read hostnames from existent config files, no asterisks
+ local -a hosts
+ local config option value
+ for config in "$HOME"/.ssh/config /etc/ssh/ssh_config ; do
+ [[ -e $config ]] || continue
+ while read -r option value _ ; do
+ [[ $option == Host ]] || continue
+ [[ $value != *'*'* ]] || continue
+ hosts[${#hosts[@]}]=$value
+ done < "$config"
+ done
+
+ # Generate completion reply
+ for host in "${hosts[@]}" ; do
+ [[ $host == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
+ COMPREPLY[${#COMPREPLY[@]}]=$host
+ done
+}
diff --git a/bash/bash_completion.d/sftp.bash b/bash/bash_completion.d/sftp.bash
new file mode 100644
index 00000000..5d52c739
--- /dev/null
+++ b/bash/bash_completion.d/sftp.bash
@@ -0,0 +1,4 @@
+# Completion for sftp(1) with ssh_config(5) hostnames
+declare -F _ssh_config_hosts >/dev/null ||
+ source "$HOME"/.bash_completion.d/_ssh_config_hosts.bash
+complete -F _ssh_config_hosts -o default sftp
diff --git a/bash/bash_completion.d/ssh-copy-id.bash b/bash/bash_completion.d/ssh-copy-id.bash
new file mode 100644
index 00000000..daf52751
--- /dev/null
+++ b/bash/bash_completion.d/ssh-copy-id.bash
@@ -0,0 +1,4 @@
+# Completion for ssh-copy-id(1) with ssh_config(5) hostnames
+declare -F _ssh_config_hosts >/dev/null ||
+ source "$HOME"/.bash_completion.d/_ssh_config_hosts.bash
+complete -F _ssh_config_hosts -o default ssh-copy-id
diff --git a/bash/bash_completion.d/ssh.bash b/bash/bash_completion.d/ssh.bash
index bbb9b246..03745eaa 100644
--- a/bash/bash_completion.d/ssh.bash
+++ b/bash/bash_completion.d/ssh.bash
@@ -1,22 +1,4 @@
-# Completion for ssh/sftp/ssh-copy-id with config hostnames
-_ssh() {
-
- # Read hostnames from existent config files, no asterisks
- local -a hosts
- local config option value
- for config in "$HOME"/.ssh/config /etc/ssh/ssh_config ; do
- [[ -e $config ]] || continue
- while read -r option value _ ; do
- [[ $option == Host ]] || continue
- [[ $value != *'*'* ]] || continue
- hosts[${#hosts[@]}]=$value
- done < "$config"
- done
-
- # Generate completion reply
- for host in "${hosts[@]}" ; do
- [[ $host == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
- COMPREPLY[${#COMPREPLY[@]}]=$host
- done
-}
-complete -F _ssh -o default ssh sftp ssh-copy-id
+# Completion for ssh(1) with ssh_config(5) hostnames
+declare -F _ssh_config_hosts >/dev/null ||
+ source "$HOME"/.bash_completion.d/_ssh_config_hosts.bash
+complete -F _ssh_config_hosts -o default ssh
diff --git a/bash/bashrc b/bash/bashrc
index d6b2adca..d2562749 100644
--- a/bash/bashrc
+++ b/bash/bashrc
@@ -1,3 +1,9 @@
+# Make sure the shell is interactive
+case $- in
+ *i*) ;;
+ *) return ;;
+esac
+
# Ensure we're using at least version 2.05. Weird arithmetic syntax needed here
# due to leading zeroes and trailing letters in some 2.x version numbers (e.g.
# 2.05a).
@@ -6,12 +12,6 @@
((10#${BASH_VERSINFO[1]%%[![:digit:]]*} < 5)) &&
return
-# Make sure the shell is interactive
-case $- in
- *i*) ;;
- *) return ;;
-esac
-
# Don't do anything if running a restricted shell
shopt -q restricted_shell && return
diff --git a/bash/bashrc.d/prompt.bash b/bash/bashrc.d/prompt.bash
index e61b69d5..2559d9d8 100644
--- a/bash/bashrc.d/prompt.bash
+++ b/bash/bashrc.d/prompt.bash
@@ -15,8 +15,11 @@ prompt() {
# If Bash 4.0 is available, trim very long paths in prompt
((BASH_VERSINFO[0] >= 4)) && PROMPT_DIRTRIM=4
- # Basic prompt shape
- PS1='\u@\h:\w'
+ # Basic prompt shape depends on whether we're in SSH or not
+ PS1=
+ [[ -n $SSH_CONNECTION ]] &&
+ PS1=$PS1'\u@\h:'
+ PS1=$PS1'\w'
# Add sub-commands; VCS, job, and return status checks
PS1=$PS1'$(prompt vcs)$(prompt job)$(prompt ret)'
diff --git a/bin/apf b/bin/apf
index 17a30be9..39bc0720 100755
--- a/bin/apf
+++ b/bin/apf
@@ -12,43 +12,51 @@ 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" "$$"
+# If there were arguments given on the command line, we need to be careful and
+# prepend our ones first
+if [ "$#" -gt 0 ] ; then
+
+ # Iterate through any remaining arguments
+ 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
+ if [ -n "$argf" ] ; then
+
+ # Reset the positional parameters
+ set --
+
+ # Put our file arguments in first before we continue with the loop
+ if [ -e "$argf" ] ; then
+ while IFS= read -r farg ; do
+ case $farg in
+ '#'*) continue ;;
+ *[![:space:]]*) ;;
+ *) continue ;;
+ esac
+ set -- "$@" "$farg"
+ done < "$argf"
+ fi
+
+ # Unset the argfile so we don't repeat this bit
+ unset -v argf
fi
- }
- for sig in EXIT HUP INT TERM ; do
- # shellcheck disable=SC2064
- trap "cleanup $sig" "$sig"
- done
- td=$(mktd "$self") || exit
- # Write the arguments in reverse to a temporary file
- revf=$td/revf
- sed '1!G;$!{h;d}' "$argf" > "$revf" || exit
+ # Stack the original invocation argument back onto the positional
+ # parameters
+ set -- "$@" "$carg"
+ done
- # 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
+# If there weren't, we can just read the file and slap them in
+elif [ -e "$argf" ] ; then
+ while IFS= read -r farg ; do
+ case $farg in
'#'*) continue ;;
*[![:space:]]*) ;;
*) continue ;;
esac
- set -- "$arg" "$@"
- done < "$revf"
-
- # We can remove the temporary stuff now, which allows us to exec safely
- cleanup ''
+ set -- "$@" "$farg"
+ done < "$argf"
fi
# Run the command with the changed arguments
diff --git a/bin/rfcf b/bin/rfcf
index 72c076a9..633eaace 100755
--- a/bin/rfcf
+++ b/bin/rfcf
@@ -9,4 +9,4 @@ fi
rn=$1
# Retrieve the RFC with curl(1)
-curl https://tools.ietf.org/rfc/rfc"$rn".txt
+curl -fsSL https://tools.ietf.org/rfc/rfc"$rn".txt
diff --git a/bin/urlh b/bin/urlh
index 6a768a9f..8e9463e7 100755
--- a/bin/urlh
+++ b/bin/urlh
@@ -9,7 +9,7 @@ fi
url=$1 header=$2
# Run cURL header request
-curl -I -- "$url" |
+curl -fIsSL -- "$url" |
# Unfold the headers
unf |
diff --git a/bin/urlmt b/bin/urlmt
index 7332663e..b209f26a 100755
--- a/bin/urlmt
+++ b/bin/urlmt
@@ -5,5 +5,5 @@ urlh "$1" Content-Type |
# Use last line only, remove any charset suffix
sed '
$!d
-s/; .*//
+s/;.*//
'
diff --git a/bin/xgo b/bin/xgo
index e808027c..8329c511 100755
--- a/bin/xgo
+++ b/bin/xgo
@@ -15,6 +15,12 @@ for url ; do (
*[/.]youtube.com/watch*)
mpv -- "$url" && exit
;;
+ https://github.com/*/blob/*)
+ url=$(printf '%s\n' "$url" | sed 's_/blob/_/raw/_')
+ ;;
+ *://imgur.com/*)
+ url=$(printf '%s\n' "$url" | sed 's_imgur\.com_i.imgur.com_;s/$/.jpg/')
+ ;;
esac
# Get the MIME type data
@@ -22,10 +28,18 @@ for url ; do (
# If the MIME type is an image, load it in feh(1)
case $mt in
+ audio/*|video/*)
+ mpv --force-window -- "$url" && exit
+ ;;
image/gif) ;;
image/*)
curl -- "$url" | feh - && exit
;;
+ text/plain)
+ # shellcheck disable=SC2016
+ urxvt -e sh -c 'curl -- "$1" | view -' \
+ _ "$url" && exit
+ ;;
esac
# Otherwise, just pass it to br(1)
diff --git a/gnupg/sks-keyservers.net/crl.pem b/gnupg/sks-keyservers.net/crl.pem
index 43b2560b..ce8cd7a8 100644
--- a/gnupg/sks-keyservers.net/crl.pem
+++ b/gnupg/sks-keyservers.net/crl.pem
@@ -1,8 +1,8 @@
-----BEGIN X509 CRL-----
-MIIEczCCAlsCAQEwDQYJKoZIhvcNAQELBQAwXDELMAkGA1UEBhMCTk8xDTALBgNV
+MIIEhzCCAm8CAQEwDQYJKoZIhvcNAQELBQAwXDELMAkGA1UEBhMCTk8xDTALBgNV
BAgMBE9zbG8xHjAcBgNVBAoMFXNrcy1rZXlzZXJ2ZXJzLm5ldCBDQTEeMBwGA1UE
-AwwVc2tzLWtleXNlcnZlcnMubmV0IENBFw0xNDEwMTAxNjM5MTdaFw0xNTA0MDgx
-NjM5MTdaMIIBuDASAgEBFw0xMjEwMDkwMTAyMDVaMBICAQIXDTEyMTAwOTAxMDIw
+AwwVc2tzLWtleXNlcnZlcnMubmV0IENBFw0xNjA4MDgxOTMwMjdaFw0xNzAyMDQx
+OTMwMjdaMIIBzDASAgEBFw0xMjEwMDkwMTAyMDVaMBICAQIXDTEyMTAwOTAxMDIw
NVowEgIBAxcNMTQwNTAxMTEyMDU2WjASAgEEFw0xMjEwMDkwMTAyMDVaMBICAQgX
DTE0MDUwNjE4MjQzMVowEgIBDBcNMTQwNjI4MTI0NTU2WjASAgERFw0xNDA0MjYx
MjU4MjdaMBICARMXDTEzMTExMzE5MzczM1owEgIBFBcNMTQwNDI5MTczNDA0WjAS
@@ -11,16 +11,17 @@ NDI5MTczNDA0WjASAgEjFw0xMzExMTMxOTM3MzNaMBICASQXDTE0MDUwNzIwMTIy
OFowEgIBKBcNMTQwNDI5MjAwNjAyWjASAgEpFw0xNDA0MjYxNDI0MjRaMBICASsX
DTE0MDUwMzE0NDgwNlowEgIBLRcNMTQwNDMwMDgxNTU4WjASAgEuFw0xNDA0MzAw
ODE2MTdaMBICAS8XDTE0MDQyNjEzMDIxNlowEgIBMxcNMTQwNDI5MTczNjIwWjAS
-AgE0Fw0xNDA1MTIxODQwNThaoA8wDTALBgNVHRQEBAICEBowDQYJKoZIhvcNAQEL
-BQADggIBAAZLkVRNqj9nL6f2Cv/AlDe0pMx2ZLNyIN3/KXSByUoIH4NMSDuPQqec
-ceUq+W5Vrh8EDUC9MbUMA1MSv/DWdG/422to8/iDnC/F423JLfOVwQABR5F37mxF
-MH+6aL9QgEezqHjnMg2MKRukB29TXR9rj3Q2HOhn+MH45Cfw7HDpCA+zaCUAHz1d
-74pyp38hfMT5s3Xm2M2ibtOoHmQYbx4rYra+dwPce41QppF2XnfV++6gxUv5F41U
-t7aouAt1ZsrIdcP+7crh4KbeTUIR3eEO/tHs74HVjhMtdsn1rTM668Dl3eg6rcv7
-CCNMgXbotNUekuWlf8YFM01BOyHUaWrMfpS/1WkKqVR/0BzMuSoPAHehoq5SGm1B
-RkVl9/acH07nvmziQQEnyJDZKaJplnIZ+vgNW07cW8eaeafVXTF8fkornyCVDE92
-YGxLQiUu2lQ4qcbb9OH1ki0LnUvCVo8SbzH913VqcvE6EHhoHyaHtBqswBwP5NZd
-ybC2bxOYhmICVnK8ee/1Yz9dnjtJsMhB3qtW3vkJ6yn7bjRLH01U8wvhJDo8Cjhe
-dyZnT3JE9lzPYb3JqkYIn1YnolUF/zhoVTcUQVSn81u44yx5yrPbsvjIsiSWt4Pd
-Q7y++Yy2Sgh9uApIF/1xqsu+dZnOR/rMQdQXwM4bmXn/6itZ/22l
+AgE0Fw0xNDA1MTIxODQwNThaMBICAWsXDTE1MTEyNTE5MjkyNlqgDzANMAsGA1Ud
+FAQEAgIQJzANBgkqhkiG9w0BAQsFAAOCAgEAKbyM6U6B+RleyuF4O1t/G7SVhvHl
+Yc6bqeV4zNj6B2j9Qw9YtO14USsxVw7RKZPhNvzSJhgBxxRtAOks0tVuGOkjN57V
+qMc9Hiwd/d5WQOkDvaJv44yT5tUq3NhaV8c8bQzeogjXW4h5I0+YsLT84phAnwXK
+Gj95A50vmjXZX7zUbS0TT6GVMjI0RBUIoRu5Ueax4gyX9WOKu0RQ4gZONzlYvbMk
+exX+VWD9JWaA3pWKsxyUrRnDR1e7tUsnDXsh3i5krQinEQ1JYf3/lpGWMOygJV40
+9L0PhZB7cX4xDV2Vg0kBfKU7gr/C0uEF9fZJut8tqwe2LKj54dYa3ktX9Jbjq53F
+WZthON6mMJxtTtjAdWyhQbbM+zy7hOE3cc4aivm9ZAXl30UNBWlPQsJRk3hTScMd
+ye+A9RDRmG68qsoIWbTn/W5PBdiQ+MIxzO8fYwzs8yywQ1/VHHvbS1q0YC1PNono
+6ayc9vHbghGc/RK67BTa1Oj9fqOVgy4XVxzPPzl4JAc4b6ELASS3owzuwUE8CrxP
+drmYWn5ZII+w+0DNn9H5lPasxR5RQ/qPW7T5a8xpuNz+Uj/X4Baedl2DU4wzSP1m
+nvntH0EgqgVXKFpxUT94CSRSiSOReElUZ17j7v28d8IhHCW3rou/JFxMgTIqmIg4
+jyCyTTMl3V9xWCw=
-----END X509 CRL-----
diff --git a/pdksh/pdkshrc.d/prompt.pdksh b/pdksh/pdkshrc.d/prompt.pdksh
index f9dfa584..05e3eced 100644
--- a/pdksh/pdkshrc.d/prompt.pdksh
+++ b/pdksh/pdkshrc.d/prompt.pdksh
@@ -15,13 +15,19 @@ prompt() {
# Turn complex, colored PS1 and debugging PS4 prompts on
on)
- # Set up prompt, including optional PROMPT_PREFIX and PROMPT_SUFFIX
- # variables
- PS1='\u@\h:\w'
- PS1=$PS1'$(prompt vcs)'
- PS1=$PS1'$(prompt job)'
- PS1='${PROMPT_PREFIX}'$PS1
- PS1=$PS1'${PROMPT_SUFFIX}'
+ # Basic prompt shape depends on whether we're in SSH or not
+ PS1=
+ [[ -n $SSH_CONNECTION ]] &&
+ PS1=$PS1'\u@\h:'
+ PS1=$PS1'\w'
+
+ # Add sub-commands; VCS, job, and return status checks
+ PS1=$PS1'$(prompt vcs)$(prompt job)'
+
+ # Add prefix and suffix
+ PS1='${PROMPT_PREFIX}'$PS1'${PROMPT_SUFFIX}'
+
+ # Add terminating "$" or "#" sign
PS1=$PS1'\$'
# Count available colors
@@ -79,10 +85,10 @@ prompt() {
# Git prompt function
git)
- # Bail if we have no git(1)
- if ! hash git 2>/dev/null ; then
- return 1
- fi
+ # Bail if we're not in a work tree--or, implicitly, if we don't
+ # have git(1).
+ [[ $(git rev-parse --is-inside-work-tree 2>/dev/null) = true ]] ||
+ return
# Attempt to determine git branch, bail if we can't
typeset branch
@@ -102,12 +108,14 @@ prompt() {
typeset state
# Upstream HEAD has commits after local HEAD; we're "behind"
- (($(git rev-list --count 'HEAD..@{u}' 2>/dev/null) > 0)) &&
- state=${state}\<
+ typeset -i behind
+ behind=$(git rev-list --count 'HEAD..@{u}' 2>/dev/null)
+ ((behind)) && state=${state}'<'
# Local HEAD has commits after upstream HEAD; we're "ahead"
- (($(git rev-list --count '@{u}..HEAD' 2>/dev/null) > 0)) &&
- state=${state}\>
+ typeset -i ahead
+ ahead=$(git rev-list --count '@{u}..HEAD' 2>/dev/null)
+ ((ahead)) && state=${state}'>'
# Tracked files are modified
git diff-files --quiet ||
@@ -115,19 +123,20 @@ prompt() {
# Changes are staged
git diff-index --cached --quiet HEAD ||
- state=${state}\+
+ state=${state}'+'
# There are some untracked and unignored files
[[ -n $(git ls-files --others --exclude-standard) ]] &&
- state=${state}\?
+ state=${state}'?'
# There are stashed changes
git rev-parse --quiet --verify refs/stash >/dev/null &&
- state=${state}\^
+ state=${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"
+ printf '(%s%s%s)' \
+ "${PROMPT_VCS:+git:}" "${branch:-unknown}" "$state"
;;
# Revert to simple inexpensive prompts
@@ -142,9 +151,7 @@ prompt() {
vcs)
typeset vcs
for vcs in "${PROMPT_VCS[@]:-git}" ; do
- if prompt "$vcs" ; then
- return
- fi
+ prompt "$vcs" && return
done
;;
@@ -152,9 +159,7 @@ prompt() {
job)
typeset -i jobc
jobc=$(jobs -p | sed -n '$=')
- if ((jobc > 0)) ; then
- printf '{%u}' "$jobc"
- fi
+ ((jobc)) && printf '{%u}' "$jobc"
;;
# Print error
diff --git a/sh/profile.d/keychain.sh b/sh/profile.d/keychain.sh
index 66c23d32..542bd02e 100644
--- a/sh/profile.d/keychain.sh
+++ b/sh/profile.d/keychain.sh
@@ -1,5 +1,5 @@
# ssh-askpass setup
-[ -n "${SSH_ASKPASS:="$(command -v ssh-askpass 2>&1)"}" ] &&
+[ -n "${SSH_ASKPASS:="$(command -v ssh-askpass 2>/dev/null)"}" ] &&
export SSH_ASKPASS
# keychain setup
diff --git a/sh/shrc b/sh/shrc
index deb55cc2..9e201ef1 100644
--- a/sh/shrc
+++ b/sh/shrc
@@ -4,6 +4,11 @@ case $- in
*) return ;;
esac
+# Basic PS1 for POSIX shell; if we're using something more advanced, something
+# in ~/.shrc.d should overrule this. Does every POSIX shell support these? dash
+# does, at least.
+PS1=$(printf '%s@%s$ ' "$(whoami)" "$(hostname -s)")
+
# 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
diff --git a/sh/shrc.d/bd.sh b/sh/shrc.d/bd.sh
index a5344ae7..14d65c3b 100644
--- a/sh/shrc.d/bd.sh
+++ b/sh/shrc.d/bd.sh
@@ -1,18 +1,21 @@
# Move back up the directory tree to the first directory matching the name
bd() {
+ # Check argument count
+ if [ "$#" -gt 1 ] ; then
+ printf >&2 'bd(): Too many arguments'
+ return 2
+ fi
+
# Set positional parameters to an option terminator and what will hopefully
# end up being a target directory
set -- "$(
- # Check there's no more than one argument
- [ "$#" -le 1 ] || exit 1
-
# The requested pattern is the first argument, defaulting to just the
# parent directory
req=${1:-..}
- # Strip trailing slashes if a trailing slash isn't the whole pattern
+ # Strip trailing slashes if a trailing slash is not the whole pattern
[ "$req" = / ] || req=${req%/}
# What to do now depends on the request
diff --git a/sh/shrc.d/cd.sh b/sh/shrc.d/cd.sh
deleted file mode 100644
index 7bfacd6d..00000000
--- a/sh/shrc.d/cd.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-# 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; otherwise,
- # we won't be changing any parameters
- 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 ;;
- -*) opts=1 ; shift ;;
- esac
- done
-
- # Shift off -- if it's the first argument
- [ "$1" = -- ] && shift
-
- # Print an explanatory error if there were options and then two
- # arguments
- if [ "$#" -eq 2 ] && [ -n "$opts" ] ; then
- printf >&2 'cd(): Can'\''t combine options and substitution\n'
- fi
-
- # Check we have no options and two non-null arguments
- [ -z "$opts" ] || return
- [ "$#" -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 that a substitution resulted in an actual change and that
- # we ended up with a non-null target, or print an error to stderr
- if [ "$cur" = "$curtc" ] || [ -z "$new" ]; then
- printf >&2 'cd(): Substitution failed\n'
- exit 1
- fi
-
- # Print the target
- printf '%s\n' "$new"
- )"
-
- # If the subshell printed nothing, return with failure
- [ -n "$2" ] || return
- fi
-
- # Execute the cd command as normal
- command cd "$@"
-}
diff --git a/sh/shrc.d/ksh.sh b/sh/shrc.d/ksh.sh
index b12f13c8..046cd6c4 100644
--- a/sh/shrc.d/ksh.sh
+++ b/sh/shrc.d/ksh.sh
@@ -4,7 +4,7 @@
# does it the other way around.
case $KSH_VERSION in
*'PD KSH '*|*'MIRBSD KSH '*)
- [ -f "${KSH_ENV:-"$HOME"/.pdkshrc}" ] || return
- . "${KSH_ENV:-"$HOME"/.pdkshrc}"
+ [ -f "${KSH_ENV:="$HOME"/.pdkshrc}" ] || return
+ . "$KSH_ENV"
;;
esac
diff --git a/sh/shrc.d/pd.sh b/sh/shrc.d/pd.sh
index c022b1e8..de4ea23b 100644
--- a/sh/shrc.d/pd.sh
+++ b/sh/shrc.d/pd.sh
@@ -4,16 +4,16 @@
# argument, this just shifts up a directory, i.e. `cd ..`
pd() {
+ # Check argument count
+ if [ "$#" -gt 1 ] ; then
+ printf >&2 'pd(): Too many arguments\n'
+ return 2
+ fi
+
# Change the positional parameters from the target to its containing
# directory
set -- "$(
- # Check argument count
- if [ "$#" -gt 1 ] ; then
- printf >&2 'pd(): Too many arguments\n'
- exit 2
- fi
-
# Figure out target dirname
dirname=${1:-..}
dirname=${dirname%/}
diff --git a/sh/shrc.d/prompt.sh b/sh/shrc.d/prompt.sh
deleted file mode 100644
index ef3009ae..00000000
--- a/sh/shrc.d/prompt.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-# Basic PS1 for POSIX shell
-# Does every POSIX shell support these? dash does, at least.
-PS1=$(printf '%s@%s$ ' "$(id -nu)" "$(hostname -s)")
diff --git a/sh/shrc.d/rd.sh b/sh/shrc.d/rd.sh
new file mode 100644
index 00000000..9fd99a55
--- /dev/null
+++ b/sh/shrc.d/rd.sh
@@ -0,0 +1,63 @@
+#
+# Replace the first instance of the first argument string with the second
+# argument string in $PWD, and make that the target of the cd builtin. This is
+# to emulate a feature of the `cd` builtin in Zsh that I like, but that I think
+# should be a separate command rather than overloading `cd`.
+#
+# $ pwd
+# /usr/local/bin
+# $ rd local
+# $ pwd
+# /usr/bin
+# $ rd usr opt
+# $ pwd
+# /opt/bin
+#
+rd() {
+
+ # Check argument count
+ case $# in
+ 1|2) ;;
+ *)
+ printf >&2 \
+ 'rd(): Need a string and optionally a replacement\n'
+ return 2
+ ;;
+ esac
+
+ # Set the positional parameters to an option terminator and what will
+ # hopefully end up being the substituted directory name
+ set -- "$(
+
+ # Current path: e.g. /foo/ayy/bar/ayy
+ cur=$PWD
+ # Pattern to replace: e.g. ayy
+ pat=$1
+ # Text with which to replace pattern: e.g. lmao
+ # This can be a null string or unset, in order to *remove* the pattern
+ rep=$2
+
+ # /foo/
+ curtc=${cur%%"$pat"*}
+ # /bar/ayy
+ curlc=${cur#*"$pat"}
+ # /foo/lmao/bar/ayy
+ new=${curtc}${rep}${curlc}
+
+ # Check that a substitution resulted in an actual change and that we
+ # ended up with a non-null target, or print an error to stderr
+ if [ "$cur" = "$curtc" ] || [ -z "$new" ] ; then
+ printf >&2 'rd(): Substitution failed\n'
+ exit 1
+ fi
+
+ # Print the target
+ printf '%s\n' "$new"
+ )"
+
+ # If the subshell printed nothing, return with failure
+ [ -n "$1" ] || return
+
+ # Try to change into the determined directory
+ command cd -- "$@"
+}
diff --git a/sh/shrc.d/sd.sh b/sh/shrc.d/sd.sh
index 80ae7c12..66612f4c 100644
--- a/sh/shrc.d/sd.sh
+++ b/sh/shrc.d/sd.sh
@@ -1,6 +1,6 @@
#
-# sd -- sibling/switch directory -- Shortcut to switch to another directory
-# with the same parent, i.e. a sibling of the current directory.
+# Shortcut to switch to another directory with the same parent, i.e. a sibling
+# of the current directory.
#
# $ pwd
# /home/you
@@ -34,14 +34,16 @@
#
sd() {
+ # Check argument count
+ if [ "$#" -gt 1 ] ; then
+ printf >&2 'sd(): Too many arguments\n'
+ return 2
+ fi
+
+ # Change positional parameters to what will hopefully be a completed
+ # substitution
set -- "$(
- # Check argument count
- if [ "$#" -gt 1 ] ; then
- printf >&2 'sd(): Too many arguments\n'
- exit 1
- fi
-
# Set the positional parameters to either the requested directory, or
# all siblings of the current directory if no request
spec=$1
diff --git a/sh/shrc.d/ud.sh b/sh/shrc.d/ud.sh
index 259f3167..44a3a81d 100644
--- a/sh/shrc.d/ud.sh
+++ b/sh/shrc.d/ud.sh
@@ -2,23 +2,27 @@
# like cd .., cd ../.., etc
ud() {
+ # Check argument count
+ if [ "$#" -gt 1 ] ; then
+ printf >&2 'ud(): Too many arguments\n'
+ return 2
+ fi
+
+ # Check first argument, number of steps upward, default to 1.
+ # "0" is weird, but valid; "-1" however makes no sense at all
+ if [ "${1:-1}" -lt 0 ] ; then
+ printf >&2 'ud(): Invalid step count\n'
+ return 2
+ fi
+
# Change the positional parameters from the number of steps given to a
# "../../.." string
set -- "$(
- # Check first argument, number of steps upward, default to 1
- # "0" is weird, but valid; "-1" however makes no sense at all
- steps=${1:-1}
- if [ "$steps" -lt 0 ] ; then
- printf >&2 'ud(): Invalid step count\n'
- exit 2
- fi
-
- # Check second argument, target directory, default to $PWD
+ # Append /.. to the target (default PWD) the specified number of times
dirname=${2:-"$PWD"}
-
- # Append /.. to the target the specified number of times
i=0
+ steps=${1:-1}
while [ "$i" -lt "$steps" ] ; do
dirname=${dirname%/}/..
i=$((i+1))
diff --git a/tmux/tmux.conf.m4 b/tmux/tmux.conf.m4
index f7fc1e8e..a4af9f8e 100644
--- a/tmux/tmux.conf.m4
+++ b/tmux/tmux.conf.m4
@@ -1,23 +1,22 @@
-# My tmux session is no-display land because I attach to it with all sorts of
-# terminal clients, including PuTTY, so I don't always have X forwarding
-# available and therefore it's not appropriate to set the display
+# Strip out a lot of machine and X11 dependent crap from the initial
+# environment
+set-environment -gru COLORFGBG
+set-environment -gru COLORTERM
set-environment -gru DISPLAY
+set-environment -gru SSH_CLIENT
+set-environment -gru SSH_CONNECTION
+set-environment -gru SSH_TTY
+set-environment -gru WINDOWID
-# Force the browser to be Lynx in case we inherited a non-null DISPLAY
-set-environment -g BROWSER 'lynx'
-
-# The only environment variables I want tmux to update for me are SSH_CLIENT,
-# SSH_CONNECTION, and SSH_TTY, all of which are occasionally useful
-set-option -g update-environment 'SSH_CLIENT SSH_CONNECTION SSH_TTY'
+# Otherwise, use the environment we had when we started; don't touch it during
+# a session unless I specifically ask
+set-option -g update-environment ''
# Setting this makes each new pane a non-login shell, which suits me better
set-option -g default-command "$SHELL"
-# All of my terminals are 256 colors, so use the appropriate termcap/terminfo,
-# and unset COLORFGBG and COLORTERM to stop programs getting confused
+# Expect a 256-color terminal
set-option -g default-terminal 'screen-256color'
-set-environment -gru COLORFGBG
-set-environment -gru COLORTERM
# Change the prefix to ^A rather than the default of ^B, because I'm a godless
# GNU Screen refugee, and also I like using ^B in my shell and in Vim more
@@ -74,8 +73,8 @@ bind-key s choose-session
# Session title on the left side of the status bar
set-option -g status-left '[#S] '
-# Hostname and the current date on the right side of the status bar
-set-option -g status-right ' [#H] #(date +"%F %T")'
+# Username, hostname, and the current date on the right side of the status bar
+set-option -g status-right ' [#(whoami)@#H] #(date +"%F %T")'
# Update the status bar every second
set-option -g status-interval 1