diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2016-08-23 15:09:05 +1200 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2016-08-23 15:09:05 +1200 |
commit | 626141db6ec398396de81fdedf0ae7b6d237c9c6 (patch) | |
tree | ecd0783b4e3deb7d6c0f5ab179f27eab80789aff | |
parent | Merge branch 'master' into freebsd (diff) | |
parent | Merge branch 'openbsd' (diff) | |
download | dotfiles-626141db6ec398396de81fdedf0ae7b6d237c9c6.tar.gz dotfiles-626141db6ec398396de81fdedf0ae7b6d237c9c6.zip |
Merge branch 'master' into freebsd
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | README.markdown | 31 | ||||
-rw-r--r-- | bash/bash_completion.d/_ssh_config_hosts.bash | 21 | ||||
-rw-r--r-- | bash/bash_completion.d/sftp.bash | 4 | ||||
-rw-r--r-- | bash/bash_completion.d/ssh-copy-id.bash | 4 | ||||
-rw-r--r-- | bash/bash_completion.d/ssh.bash | 26 | ||||
-rw-r--r-- | bash/bashrc | 12 | ||||
-rw-r--r-- | bash/bashrc.d/prompt.bash | 7 | ||||
-rwxr-xr-x | bin/apf | 68 | ||||
-rwxr-xr-x | bin/rfcf | 2 | ||||
-rwxr-xr-x | bin/urlh | 2 | ||||
-rwxr-xr-x | bin/urlmt | 2 | ||||
-rwxr-xr-x | bin/xgo | 14 | ||||
-rw-r--r-- | gnupg/sks-keyservers.net/crl.pem | 31 | ||||
-rw-r--r-- | pdksh/pdkshrc.d/prompt.pdksh | 55 | ||||
-rw-r--r-- | sh/profile.d/keychain.sh | 2 | ||||
-rw-r--r-- | sh/shrc | 5 | ||||
-rw-r--r-- | sh/shrc.d/bd.sh | 11 | ||||
-rw-r--r-- | sh/shrc.d/cd.sh | 76 | ||||
-rw-r--r-- | sh/shrc.d/ksh.sh | 4 | ||||
-rw-r--r-- | sh/shrc.d/pd.sh | 12 | ||||
-rw-r--r-- | sh/shrc.d/prompt.sh | 3 | ||||
-rw-r--r-- | sh/shrc.d/rd.sh | 63 | ||||
-rw-r--r-- | sh/shrc.d/sd.sh | 18 | ||||
-rw-r--r-- | sh/shrc.d/ud.sh | 26 | ||||
-rw-r--r-- | tmux/tmux.conf.m4 | 29 |
26 files changed, 287 insertions, 245 deletions
@@ -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)' @@ -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 @@ -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 @@ -9,7 +9,7 @@ fi url=$1 header=$2 # Run cURL header request -curl -I -- "$url" | +curl -fIsSL -- "$url" | # Unfold the headers unf | @@ -5,5 +5,5 @@ urlh "$1" Content-Type | # Use last line only, remove any charset suffix sed ' $!d -s/; .*// +s/;.*// ' @@ -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 @@ -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 |