├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── bashrc ├── bashrc.d ├── .hostname-vanity │ ├── adora │ ├── biers │ ├── catra │ ├── gentoo │ ├── iroh │ ├── nameless │ ├── rpi │ ├── spike │ ├── viper │ └── zoe ├── 000-misc.sh ├── 050-hostname-vanity.sh ├── aliases.sh ├── debian.sh ├── gentoo-nspawn.sh ├── history.sh ├── path.sh └── prompt.sh ├── bin ├── go-mod-env ├── loldebian ├── normalize-ssh-known-hosts ├── random-password.sh ├── resize-active-terminal.sh ├── sort-gitconfig ├── ssh-copy-id-super-unsafe └── ssh-super-unsafe ├── cwiid-wminput-sideways ├── git-config ├── git-config.d ├── common ├── tianon └── tianon-debian ├── inputrc ├── install.sh ├── ssh-config.d ├── 000-common ├── 010-local ├── github └── zzz-sockets ├── tmux.conf ├── vim-pack-tianon └── start │ └── tianon ├── vim-tianon ├── after │ └── ftplugin │ │ ├── gitcommit.vim │ │ ├── markdown.vim │ │ └── yaml.vim └── plugin ├── vimrc.d ├── 000-defaults.vim ├── alternate-dockerfile-names.vim ├── ctrl-c.vim ├── sort-words.vim ├── theme.vim └── tianon-defaults.vim └── yt-dlp.conf /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Files I never want to accidentally commit. 3 | # 4 | # Use ".git/info/exclude" if there are more files you want to add to this list that only make sense for your local usage! 5 | # 6 | # Having them here makes Git remind me to keep them secret+safe and forces me to jump through extra hoops to actually commit them: 7 | # 8 | # $ git add ssh-config.d/foo 9 | # The following paths are ignored by one of your .gitignore files: 10 | # The following paths are ignored by one of your .gitignore files: 11 | # ssh-config.d/foo 12 | # Use -f if you really want to add them. 13 | # 14 | 15 | git-config.d/personal** 16 | ssh-config.d/* 17 | 18 | bin/_youtube-dl 19 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vim-pack-tianon/start/jellybeans"] 2 | path = vim-pack-tianon/start/jellybeans 3 | url = https://github.com/nanotech/jellybeans.vim.git 4 | [submodule "vim-pack-tianon/start/vim-afterimage"] 5 | path = vim-pack-tianon/start/vim-afterimage 6 | url = https://github.com/tpope/vim-afterimage.git 7 | [submodule "vim-pack-tianon/start/vim-eunuch"] 8 | path = vim-pack-tianon/start/vim-eunuch 9 | url = https://github.com/tpope/vim-eunuch.git 10 | [submodule "vim-pack-tianon/start/vim-sensible"] 11 | path = vim-pack-tianon/start/vim-sensible 12 | url = https://github.com/tpope/vim-sensible.git 13 | [submodule "vim-pack-tianon/start/vim-vividchalk"] 14 | path = vim-pack-tianon/start/vim-vividchalk 15 | url = https://github.com/tpope/vim-vividchalk.git 16 | [submodule "vim-pack-tianon/start/mojo.vim"] 17 | path = vim-pack-tianon/start/mojo.vim 18 | url = https://github.com/yko/mojo.vim.git 19 | [submodule "vim-pack-tianon/start/jenkinsfile"] 20 | path = vim-pack-tianon/start/jenkinsfile 21 | url = https://github.com/martinda/Jenkinsfile-vim-syntax.git 22 | [submodule "vim-pack-tianon/start/nginx.vim"] 23 | path = vim-pack-tianon/start/nginx.vim 24 | url = https://github.com/chr4/nginx.vim.git 25 | [submodule "vim-pack-tianon/start/vim-perl"] 26 | path = vim-pack-tianon/start/vim-perl 27 | url = https://github.com/vim-perl/vim-perl.git 28 | [submodule "vim-pack-tianon/start/vim-ps1"] 29 | path = vim-pack-tianon/start/vim-ps1 30 | url = https://github.com/PProvost/vim-ps1.git 31 | [submodule "vim-pack-tianon/start/vim-docker"] 32 | path = vim-pack-tianon/start/vim-docker 33 | url = https://github.com/tianon/vim-docker.git 34 | [submodule "vim-pack-tianon/start/vim-jq"] 35 | path = vim-pack-tianon/start/vim-jq 36 | url = https://github.com/bfrg/vim-jq.git 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Tianon Gravi 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dotfiles 2 | 3 | Usage: 4 | 5 | ```console 6 | $ git clone --recurse-submodules https://github.com/tianon/home.git ~/somewhere/useful/and/permanent # (you don't want to have to move this after install) 7 | $ ~/somewhere/useful/and/permanent/install.sh 8 | $ # profit 9 | ``` 10 | 11 | If you ever `git pull`, be sure to update submodules too (`git submodule update`). 12 | 13 | If there are new features added to `install.sh`, it is intended to be idempotent, so feel free to run it again and it should ensure that all functionality is installed and enabled. 14 | 15 | (You'll probably also want to create `git-config.d/personal` and include `user.name` and `user.email` in it, if they don't already exist in your `~/.gitconfig`!) 16 | -------------------------------------------------------------------------------- /bashrc: -------------------------------------------------------------------------------- 1 | # extra bashrc goodies 2 | # to be sourced at the end of ~/.bashrc 3 | 4 | # do some fancy footwork to set $HOME if it isn't 5 | homeDir=~ 6 | : "${HOME:=$homeDir}" 7 | export HOME 8 | unset homeDir 9 | 10 | dotfilesDir="$(readlink -f "$BASH_SOURCE")" 11 | dotfilesDir="$(dirname "$dotfilesDir")" 12 | 13 | export PATH="$PATH:$HOME/bin:$dotfilesDir/bin" 14 | 15 | for dotfileSource in "$dotfilesDir"/bashrc.d/*.sh; do 16 | if [ -r "$dotfileSource" ]; then 17 | source "$dotfileSource" 18 | fi 19 | done 20 | unset dotfileSource 21 | 22 | unset dotfilesDir 23 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/adora: -------------------------------------------------------------------------------- 1 | 2 | Hey Adora 3 | ~Catra 4 | 5 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/biers: -------------------------------------------------------------------------------- 1 | 2 | 3 | Aaron Doral: The Hybrid objects. 4 | D'Anna Biers: She doesn't get a vote. Jump the ship. 5 | 6 | 7 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/catra: -------------------------------------------------------------------------------- 1 | 2 | "I won't be controlled. I am not a piece of their machine. I am not a weapon." 3 | -Adora 4 | 5 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/gentoo: -------------------------------------------------------------------------------- 1 | 2 | Gentoo is for Ricers. 3 | 4 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/iroh: -------------------------------------------------------------------------------- 1 | 2 | If you look for the light, you can often find it 3 | 4 | ... but if you look for the dark, 5 | that is all you will ever see. 6 | 7 | - Uncle Iroh 8 | 9 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/nameless: -------------------------------------------------------------------------------- 1 | 2 | 3 | King of Qin: 4 | 5 | I have just come to a realization! This scroll by Broken Sword contains no 6 | secrets of his swordsmanship. What this reveals is his highest ideal. 7 | 8 | In the first state, man and sword become one and each other. Here, even a 9 | blade of grass can be used as a lethal weapon. 10 | 11 | In the next stage, the sword resides not in the hand but in the heart. Even 12 | without a weapon, the warrior can slay his enemy from a hundred paces. 13 | 14 | But the ultimate ideal is when the sword disappears altogether. The warrior 15 | embraces all around him. 16 | 17 | The desire to kill no longer exists. Only peace remains. 18 | 19 | 20 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/rpi: -------------------------------------------------------------------------------- 1 | 2 | 3 | Cherry Jam: Raspberry, watch out! 4 | 5 | - Strawberry Shortcake's Berry Bitty Adventures 6 | 7 | 8 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/spike: -------------------------------------------------------------------------------- 1 | 2 | "We like to talk big, vampires do. 3 | 'I'm going to destroy the world.' 4 | That's just tough-guy talk. 5 | Strutting around with your friends over a pint of blood. 6 | The truth is, I like this world. 7 | You've got... dog racing, Manchester united. 8 | And you've got people. 9 | Billions of people walking around like Happy Meals with legs. 10 | It's all right here. 11 | 12 | But then someone comes along with a vision. 13 | With a real... passion for destruction. 14 | Angel could pull it off. 15 | Good-bye, Piccadilly. Farewell, Leicester-bloody-Square." 16 | 17 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/viper: -------------------------------------------------------------------------------- 1 | 2 | 3 | Adama: What do you hear? 4 | Starbuck: Nothing but the rain. 5 | Adama: Grab your gun and bring in the cat. 6 | Starbuck: Boom, boom, boom! 7 | 8 | 9 | -------------------------------------------------------------------------------- /bashrc.d/.hostname-vanity/zoe: -------------------------------------------------------------------------------- 1 | 2 | 3 | Lacy [to Zoe]: Do you realize you're six feet tall and weigh a ton? 4 | 5 | 6 | -------------------------------------------------------------------------------- /bashrc.d/000-misc.sh: -------------------------------------------------------------------------------- 1 | # normalize TERM to xterm-256color for known-supported terminals 2 | case "${COLORTERM:-}" in 3 | gnome-terminal | mate-terminal | xfce4-terminal) 4 | export TERM='xterm-256color' 5 | ;; 6 | esac 7 | 8 | # keep GOPATH out of ~/go 9 | : "${GOPATH:=$HOME/.cache/go}" 10 | export GOPATH 11 | 12 | # make "docker-compose build" actually use "docker build" under the covers 13 | export COMPOSE_DOCKER_CLI_BUILD=1 14 | # https://github.com/docker/compose/releases/tag/1.25.0 15 | # https://github.com/docker/compose/commit/cacbcccc0c68bfcd33f4707bd388b1441523c521 + https://github.com/docker/compose/commit/5add9192ac52a5c72ecc1495aa68cbfeb5a8e863 16 | # https://www.docker.com/blog/faster-builds-in-compose-thanks-to-buildkit-support/ 17 | -------------------------------------------------------------------------------- /bashrc.d/050-hostname-vanity.sh: -------------------------------------------------------------------------------- 1 | shortHostname="$(exec 2>/dev/null; hostname --short || hostname -s || hostname || :)" 2 | case "$shortHostname" in 3 | *-gentoo) shortHostname='gentoo' ;; 4 | rpi[0-9]*) shortHostname='rpi' ;; 5 | esac 6 | thisDir="$(dirname "$BASH_SOURCE")" 7 | if [ -r "$thisDir/.hostname-vanity/$shortHostname" ]; then 8 | cat "$thisDir/.hostname-vanity/$shortHostname" 9 | fi 10 | unset shortHostname thisDir 11 | -------------------------------------------------------------------------------- /bashrc.d/aliases.sh: -------------------------------------------------------------------------------- 1 | alias updog='docker run -it --rm -e TERM' 2 | alias docker-follow='docker attach --no-stdin --sig-proxy=false' 3 | 4 | # 💕 for Clint (https://salsa.debian.org/debian/debianutils/-/commit/3a8dd10b4502f7bae8fc6973c13ce23fc9da7efb) 5 | alias which='command -v' 6 | 7 | # from http://git.661346.n2.nabble.com/git-grep-to-operate-across-who-repository-and-not-just-CWD-tp6071541p6074384.html 8 | cdup-git() { 9 | local eh 10 | eh="$(git rev-parse --is-inside-work-tree)" || return 11 | case "$eh" in 12 | true) 13 | eh="$(git rev-parse --show-toplevel)" 14 | test -z "$eh" || cd "$eh" 15 | ;; 16 | false) 17 | eh="$(git rev-parse --git-dir)" || return 18 | cd "$eh" || return 19 | eh="$(git rev-parse --is-bare-repository)" || return 20 | test "$eh" = 'true' || cd .. 21 | ;; 22 | esac 23 | } 24 | 25 | unset-docker() { 26 | local var 27 | for var in "${!DOCKER_@}"; do 28 | unset "$var" 29 | done 30 | } 31 | -------------------------------------------------------------------------------- /bashrc.d/debian.sh: -------------------------------------------------------------------------------- 1 | uid="$(id -un 2>/dev/null || :)" 2 | if [ "$uid" = 'tianon' ]; then 3 | : "${DEBFULLNAME:=Tianon Gravi}" 4 | : "${DEBEMAIL:=tianon@debian.org}" 5 | export DEBFULLNAME DEBEMAIL 6 | fi 7 | unset uid 8 | 9 | export DEBOOTSTRAP_MIRROR='http://deb.debian.org/debian' 10 | export UBUNTUTOOLS_DEBIAN_MIRROR="$DEBOOTSTRAP_MIRROR" 11 | 12 | # quilt is much amaze: https://wiki.debian.org/UsingQuilt#Using_quilt_with_Debian_source_packages 13 | export QUILT_PATCHES=debian/patches 14 | export QUILT_REFRESH_ARGS='-p ab --no-timestamps --no-index' 15 | -------------------------------------------------------------------------------- /bashrc.d/gentoo-nspawn.sh: -------------------------------------------------------------------------------- 1 | if [ -f /etc/systemd/nspawn/gentoo.nspawn ]; then 2 | #alias gentoo='sudo machinectl shell --quiet --setenv DISPLAY="$DISPLAY" tianon@gentoo' 3 | gentoo() { 4 | if [ -t 1 ]; then 5 | local tty='--tty --send-sighup' 6 | else 7 | if systemd-run --help 2>&1 | grep -q -- '--pipe'; then 8 | local tty='--pipe' 9 | else 10 | echo >&2 'warning: systemd-run does not appear to support "--pipe"; results might be odd' 11 | local tty='--tty' 12 | fi 13 | fi 14 | if [ "$#" -eq 0 ]; then 15 | set -- /usr/bin/env bash --login -i 16 | fi 17 | sudo systemd-run \ 18 | --machine gentoo \ 19 | --uid tianon \ 20 | --property WorkingDirectory=/home/tianon \ 21 | --quiet --wait $tty \ 22 | --setenv DISPLAY="$DISPLAY" \ 23 | "$@" 24 | } 25 | fi 26 | -------------------------------------------------------------------------------- /bashrc.d/history.sh: -------------------------------------------------------------------------------- 1 | # don't put duplicate lines or lines starting with space in the history. 2 | # See bash(1) for more options 3 | HISTCONTROL=ignoreboth 4 | 5 | # append to the history file, don't overwrite it 6 | shopt -s histappend 7 | # http://askubuntu.com/a/67306 8 | PROMPT_COMMAND="history -a; ${PROMPT_COMMAND:-}" 9 | 10 | # for setting history length see HISTSIZE and HISTFILESIZE in bash(1) 11 | HISTSIZE=400000000 12 | HISTFILESIZE=$(( HISTSIZE * 2 )) 13 | -------------------------------------------------------------------------------- /bashrc.d/path.sh: -------------------------------------------------------------------------------- 1 | # https://github.com/tianon/debian-bin 2 | for debianBinDir in \ 3 | "$HOME/docker/debian-bin" \ 4 | "$HOME/git/debian-bin" \ 5 | ; do 6 | if [ -d "$debianBinDir" ]; then 7 | export PATH="$PATH:$debianBinDir/generic:$debianBinDir/docker-sbuild" 8 | break 9 | fi 10 | done 11 | unset debianBinDir 12 | 13 | # https://github.com/tianon/docker-bin 14 | dockerBinDir="$HOME/docker/bin" 15 | if [ -d "$dockerBinDir" ]; then 16 | export PATH="$PATH:$dockerBinDir:$dockerBinDir/sbuild" 17 | # https://github.com/tianon/docker-museum 18 | if [ -r "$dockerBinDir/smart/.bashrc" ]; then 19 | source "$dockerBinDir/smart/.bashrc" 20 | fi 21 | fi 22 | unset dockerBinDir 23 | -------------------------------------------------------------------------------- /bashrc.d/prompt.sh: -------------------------------------------------------------------------------- 1 | # this sets up my custom prompt (PS1 + PS0), including my custom titlebar string (in known-supported terminals) 2 | 3 | _tianon_history_1() { 4 | history 1 | sed -r 's/^[ ]*[0-9]+[ ]+//' 5 | } 6 | _tianon_titlebar_cmd() { 7 | _tianon_history_1 | awk -v len=50 ' 8 | { 9 | if (length($0) > len) 10 | print substr($0, 1, len-3) "..."; 11 | else 12 | print; 13 | } 14 | ' 15 | } 16 | if ! command -v __git_ps1 > /dev/null; then 17 | if [ -s /usr/share/git/git-prompt.sh ]; then 18 | # Gentoo is fun: https://bugs.gentoo.org/477920 + https://bugs.gentoo.org/507480 19 | source /usr/share/git/git-prompt.sh 20 | fi 21 | fi 22 | export GIT_PS1_SHOWDIRTYSTATE=1 23 | export GIT_PS1_SHOWSTASHSTATE=1 24 | export GIT_PS1_SHOWUNTRACKEDFILES=1 25 | export GIT_PS1_SHOWUPSTREAM=1 26 | _tianon_prompt_extra() { 27 | local extraBits= 28 | 29 | if [ "${#DIRSTACK[@]}" -gt 1 ]; then 30 | extraBits+="${extraBits:+; }pushd:${#DIRSTACK[@]}" 31 | fi 32 | 33 | if [ -n "${WSL_DISTRO_NAME:-}" ]; then 34 | extraBits+="${extraBits:+; }wsl:$WSL_DISTRO_NAME" 35 | fi 36 | 37 | # https://github.com/docker/cli/blob/fb261fdd0cb890ef05b113d482faf5f8480dc959/cli/command/cli.go#L412-L432 38 | # (DOCKER_HOST has higher precedence than DOCKER_CONTEXT) 39 | if [ -n "${DOCKER_HOST:-}" ]; then 40 | extraBits+="${extraBits:+; }$DOCKER_HOST" 41 | elif [ -n "${DOCKER_CONTEXT:-}" ]; then 42 | extraBits+="${extraBits:+; }docker:$DOCKER_CONTEXT" 43 | fi 44 | 45 | if [ -n "${BASHBREW_ARCH:-}" ]; then 46 | extraBits+="${extraBits:+; }bashbrew:$BASHBREW_ARCH" 47 | fi 48 | 49 | # see above for where we try a little harder to ensure __git_ps1 is set (but ignore errors here in case it doesn't or it fails) 50 | local gitBits; gitBits="$(__git_ps1 '%s' 2>/dev/null || :)" 51 | if [ -n "$gitBits" ]; then 52 | extraBits+="${extraBits:+; }$gitBits" 53 | fi 54 | 55 | if [ -n "$extraBits" ]; then 56 | printf ' (%s) ' "$extraBits" 57 | fi 58 | } 59 | 60 | # set a fancy prompt (non-color, unless we know we "want" color) 61 | color= 62 | case "${TERM:-}" in 63 | xterm-color | *-256color | vt220) color=1 ;; 64 | *) 65 | if command -v tput > /dev/null && tput setaf 1 &> /dev/null; then 66 | color=1 67 | fi 68 | ;; 69 | esac 70 | declare -A colors=( 71 | [reset]='' 72 | [date]='' # HH:MM:SS 73 | [recap]='' # ... $ command ... 74 | [user]='' # tianon@... 75 | [host]='' # ...@xyz 76 | [colon]='' # : 77 | [path]='' # ~/docker/... 78 | [extra]='' # (master=) 79 | ) 80 | # these two have to be separate because they're used from a function (after "colors" is unset) 81 | _tianon_dollar_color= # $ 82 | _tianon_dollar_color_failed= # $ (when the previous command failed) 83 | if [ -n "$color" ]; then 84 | colors=( 85 | [reset]='\e[m' 86 | 87 | [date]='\e[1;30m' #'\e[37m' # HH:MM:SS 88 | [recap]='\e[0;30m' # ... $ command ... 89 | [user]='\e[0;32m' # tianon@... 90 | [host]='\e[1;32m' # ...@xyz 91 | [colon]='\e[1;30m' # : 92 | [path]='\e[1;34m' # ~/docker/... 93 | [extra]='\e[0;32m' # (master=) 94 | 95 | [non_tianon_user]='\e[4;93m' # steam@..., root@..., etc 96 | ) 97 | _tianon_dollar_color='\e[0;31m' # $ 98 | _tianon_dollar_color_failed='\e[1;33m' # $ (when the previous command failed) 99 | numColors="$(tput colors 2>/dev/null || :)" 100 | case "${numColors:-8}" in 101 | 256) 102 | colors[date]='\e[0;38;5;56m' 103 | colors[recap]='\e[0;38;5;237m' 104 | colors[user]='\e[0;38;5;23m' 105 | colors[host]='\e[1;38;5;46m' 106 | colors[colon]='\e[0;38;5;166m' 107 | colors[path]='\e[0;38;5;26m' 108 | colors[extra]='\e[0;38;5;100m' 109 | colors[non_tianon_user]='\e[4;38;5;15m' 110 | _tianon_dollar_color='\e[0;38;5;201m' 111 | _tianon_dollar_color_failed='\e[1;38;5;220m' 112 | ;; 113 | esac 114 | unset numColors 115 | fi 116 | 117 | # TODO make "tianon" here customizable 118 | user="$(id -un 2>/dev/null || :)" 119 | if [ "$user" != 'tianon' ] && [ -n "${colors[non_tianon_user]:-}" ]; then 120 | # if I'm not "tianon" make it more obvious 121 | colors[user]="${colors[non_tianon_user]}" 122 | fi 123 | unset user 124 | 125 | _tianon_prompt_dollar_color() { 126 | if [ "$1" = '0' ]; then 127 | echo -e "$_tianon_dollar_color" 128 | else 129 | # if the previous command failed, change the prompt color 130 | echo -e "$_tianon_dollar_color_failed" 131 | fi 132 | } 133 | 134 | # "$?" in PS1 is silly, and each subshell clobbers the previous $? value, so we have to propagate that exit code through _every_ subshell for all subshells to get it 135 | # more succinctly, 136 | # PS1='$(echo $?) $(echo $?) $ ' 137 | # would lead to a prompt of 138 | # '1 0 $ ' 139 | # (following a command whose exit code was 1) 140 | # PS1='$(_tianon_ps1 echo $?) $(_tianon_ps1 echo $?) $ ' 141 | # would lead to a prompt of 142 | # '1 1 $ ' 143 | # (which is what we would expect and intend instead) 144 | _tianon_ps1() { 145 | local ret="$?" 146 | "$@" || : 147 | return "$ret" 148 | } 149 | 150 | dateFormat='%H:%M:%S' 151 | 152 | PS1= 153 | PS1+='\['${colors[date]}'\]\D{'"$dateFormat"'}\['${colors[recap]}'\] ... \$ $(_tianon_ps1 _tianon_history_1)\['${colors[reset]}'\]'$'\n' 154 | PS1+='\['${colors[user]}'\]\u@\['${colors[host]}'\]\h\['${colors[colon]}'\]:\['${colors[path]}'\]\w\['${colors[extra]}'\]$(_tianon_ps1 _tianon_prompt_extra)\[$(_tianon_ps1 _tianon_prompt_dollar_color "$?")\]\$\['${colors[reset]}'\] ' 155 | 156 | # PS0: http://stromberg.dnsalias.org/~strombrg/PS0-prompt/ 157 | PS0=${colors[date]}'\D{'"$dateFormat"'}'${colors[recap]}' ... \$ $(_tianon_history_1)'${colors[reset]}$'\n' 158 | 159 | if [ -z "${colors[date]:-}" ]; then 160 | # if we have no date colors, add more whitespace to visually compensate 161 | PS1='\n'"$PS1" 162 | PS0+='\n' 163 | fi 164 | 165 | unset color colors dateFormat 166 | 167 | # if this is an xterm set the title to user@host:dir 168 | case "${TERM:-}" in 169 | xterm* | rxvt*) 170 | titlebarBits='\e]0;[\h] $(_tianon_ps1 _tianon_titlebar_cmd) {\u, \w}\a' 171 | PS0+="$titlebarBits" 172 | PS1+="\[$titlebarBits\]" 173 | unset titlebarBits 174 | ;; 175 | esac 176 | -------------------------------------------------------------------------------- /bin/go-mod-env: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # GOTOOLCHAIN: https://go.dev/doc/toolchain 5 | : "${CGO_ENABLED=0}" "${GOTOOLCHAIN=local}" 6 | export CGO_ENABLED GOTOOLCHAIN 7 | 8 | self="$(basename "$0")" 9 | user="$(id -u)" 10 | user+=":$(id -g)" 11 | args=( 12 | --interactive --rm --init 13 | --mount "type=bind,src=$PWD,dst=/wd" 14 | --workdir /wd 15 | --user "$user" 16 | --env HOME=/tmp 17 | #--mount "type=volume,src=$self-home,dst=/tmp" 18 | 19 | # "go mod" cache is stored in /go/pkg/mod/cache 20 | --env GOPATH=/go 21 | --mount "type=volume,src=$self-gopath,dst=/go" 22 | --env GOCACHE=/go/.cache 23 | 24 | # https://proxy.golang.org/ 25 | --env GOPROXY='https://proxy.golang.org' 26 | 27 | --env CGO_ENABLED 28 | --env GO386 29 | --env GOAMD64 30 | --env GOARCH 31 | --env GOARM 32 | --env GOCOVERDIR # https://go.dev/doc/build-cover 33 | --env GOFLAGS 34 | --env GOOS 35 | --env GOTOOLCHAIN 36 | ) 37 | 38 | if [ -t 0 ] && [ -t 1 ]; then 39 | args+=( --tty --env TERM ) 40 | fi 41 | 42 | exec docker run "${args[@]}" "${GOLANG_IMAGE:-golang}" "$@" 43 | -------------------------------------------------------------------------------- /bin/loldebian: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | set -x 5 | sudo apt update 6 | sudo apt full-upgrade --purge --auto-remove 7 | -------------------------------------------------------------------------------- /bin/normalize-ssh-known-hosts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | src="$HOME/.ssh/known_hosts" 5 | src="$(readlink -f "$src")" 6 | tmp="$src.normalized" 7 | 8 | gawk ' 9 | { 10 | split($1, splitHosts, ","); 11 | for (i in splitHosts) { 12 | host = splitHosts[i]; 13 | hosts[$2 " " $3][host] = 1; 14 | } 15 | } 16 | function host_compare_bracket(host) { 17 | if (host ~ /^\[?[0-9]/) { 18 | return 3; 19 | } else if (host ~ /^\[/) { 20 | return 2; 21 | } else { 22 | return 1; 23 | } 24 | } 25 | function host_compare(host1, host2) { 26 | host1bracket = host_compare_bracket(host1); 27 | host2bracket = host_compare_bracket(host2); 28 | if (host1bracket == host2bracket) { 29 | if (host1 < host2) { 30 | return -1; 31 | } else if (host1 == host2) { 32 | return 0; 33 | } else { 34 | return 1; 35 | } 36 | } 37 | return host1bracket - host2bracket; 38 | } 39 | function host_sort(i1, v1, i2, v2) { 40 | indexes = host_compare(i1, i2); 41 | if (indexes != 0) { 42 | return indexes; 43 | } 44 | return host_compare(v1, v2); 45 | } 46 | END { 47 | PROCINFO["sorted_in"] = "host_sort"; 48 | for (key in hosts) { 49 | lineHosts = ""; 50 | for (host in hosts[key]) { 51 | lineHosts = (lineHosts ? lineHosts "," : "") host; 52 | } 53 | lines[lineHosts] = key; 54 | } 55 | for (lineHosts in lines) { 56 | print lineHosts, lines[lineHosts]; 57 | } 58 | } 59 | ' "$src" > "$tmp" 60 | [ -s "$tmp" ] # basic sanity check 61 | mv "$tmp" "$src" 62 | -------------------------------------------------------------------------------- /bin/random-password.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # $ sudo apt install 'wamerican.*' 'wbritish.*' 5 | # $ cat /usr/share/dict/* | sort -u | wc -l 6 | # 663022 7 | # 664557 8 | # 667133 9 | # (three different machines -- average ~665000) 10 | 11 | # > Math.pow(665000, 4) * Math.pow(16, 40) 12 | # 2.8581557253970005e+71 13 | # > Math.log2(Math.pow(665000, 4) * Math.pow(16, 40)) 14 | # 237.37197926020255 15 | 16 | IFS=$'\n' 17 | randomWords=( $(cat /usr/share/dict/* | shuf -n4) ) 18 | unset IFS 19 | 20 | randomHash="$(head -c1M /dev/urandom | sha1sum | cut -d' ' -f1)" 21 | 22 | echo "${randomWords[@]}" "$randomHash" 23 | -------------------------------------------------------------------------------- /bin/resize-active-terminal.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | win="$(xdotool getactivewindow)" 5 | 6 | class="$(xprop -id "$win" | awk '/^WM_CLASS/ { split($3, a, "\""); print a[2] }')" 7 | case "$class" in 8 | Terminal|gnome-terminal|xfce4-terminal) 9 | ;; 10 | *) 11 | echo >&2 "error: refusing to resize window of class: $class" 12 | exit 1 13 | ;; 14 | esac 15 | 16 | exec xdotool windowsize --usehints "$win" "${1:-80}" "${2:-24}" 17 | -------------------------------------------------------------------------------- /bin/sort-gitconfig: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # inspired by https://blog.wizardsoftheweb.pro/sort-git-config/ 5 | # adpated to handle "[include(If)]" sections (which are position/order dependent), comments, and more syntax edge cases :D 6 | 7 | # TODO add getopt so this can still take "-w" and handle multiple files 8 | 9 | file="$1"; shift 10 | 11 | write= 12 | if [ "$file" = '-w' ]; then 13 | file="$1"; shift 14 | write=1 15 | exec > "$file.sorted" 16 | fi 17 | 18 | gawk ' 19 | BEGIN { 20 | section = "" 21 | sort = 0 22 | line = "" 23 | comment = 0 24 | } 25 | 26 | function parseline() { 27 | gsub(/^[[:space:]]+|[[:space:]]+$/, "", line) 28 | if (line) { 29 | # "[include(If)]" sections are position/order dependent (so we add an extra "sort" column to ensure they stay in the correct order and everything "pivot sorts" around them) 30 | if (section ~ /^\[include/) { sort++ } 31 | 32 | if (match(line, /^\[[^\]]+\]/, m)) { 33 | section = m[0] 34 | line = substr(line, length(section) + 1) 35 | gsub(/^[[:space:]]+/, "", line) 36 | 37 | # https://github.com/tianon/home/issues/1 38 | gsub(/ /, "|", section) 39 | } 40 | 41 | if (line) { 42 | # normalize comment character and make sure they stay "in order" 43 | if (match(line, /^[;#]/, m)) { 44 | line = "#" sprintf("%03d", comment) substr(line, length(m[0]) + 1) 45 | comment++ 46 | } 47 | 48 | printf "sort%03d\t%s\t%s\n", sort, section, line 49 | } 50 | } 51 | line = "" 52 | } 53 | 54 | { 55 | # handle line continuations (but only for non-comment lines) 56 | line = line $0 57 | if (line !~ /^[[:space:]]*[;#]/ && line ~ /\\$/) { 58 | gsub(/\\$/, "", line) 59 | next 60 | } 61 | parseline() 62 | } 63 | 64 | END { 65 | # line continuation at EOF????????? MONSTER. 66 | parseline() 67 | } 68 | ' "$file" | LC_ALL=C sort -u | gawk -F '\t' ' 69 | BEGIN { 70 | section = "" 71 | printed = 0 72 | } 73 | 74 | $2 != section { 75 | section = $2 76 | if (printed) { 77 | printf "\n" 78 | } 79 | 80 | # https://github.com/tianon/home/issues/1 81 | printSection = section 82 | gsub(/[|]/, " ", printSection) 83 | 84 | printf "%s\n", printSection 85 | } 86 | 87 | { 88 | printed = 1 89 | if (match($3, /^#[0-9]{3}/, m)) { 90 | # remove comment ordering numbers 91 | $3 = "#" substr($3, length(m[0]) + 1) 92 | } 93 | for (i = 3; i <= NF; i++) { 94 | if (section || i > 3) { 95 | printf "\t" 96 | } 97 | printf "%s", $i 98 | } 99 | printf "\n" 100 | } 101 | ' 102 | 103 | if [ -n "$write" ]; then 104 | exec >&- 105 | mv -f "$file.sorted" "$file" 106 | fi 107 | -------------------------------------------------------------------------------- /bin/ssh-copy-id-super-unsafe: -------------------------------------------------------------------------------- 1 | ssh-super-unsafe -------------------------------------------------------------------------------- /bin/ssh-super-unsafe: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | self="${0:-ssh}" 5 | self="$(basename "$self")" 6 | 7 | self="${self%-super-unsafe}" 8 | 9 | set -x 10 | exec "$self" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$@" 11 | -------------------------------------------------------------------------------- /cwiid-wminput-sideways: -------------------------------------------------------------------------------- 1 | # see also /etc/cwiid/wminput/buttons 2 | 3 | Plugin.led.Led4 = 1 4 | Plugin.led.Battery = 1 5 | 6 | Wiimote.A = KEY_A 7 | Wiimote.B = KEY_B 8 | Wiimote.Up = KEY_LEFT 9 | Wiimote.Down = KEY_RIGHT 10 | Wiimote.Left = KEY_DOWN 11 | Wiimote.Right = KEY_UP 12 | Wiimote.Minus = KEY_KPMINUS 13 | Wiimote.Plus = KEY_KPPLUS 14 | Wiimote.Home = KEY_H 15 | Wiimote.1 = KEY_1 16 | Wiimote.2 = KEY_2 17 | 18 | #Nunchuk.C = BTN_LEFT 19 | #Nunchuk.Z = BTN_RIGHT 20 | 21 | #Classic.Up = KEY_UP 22 | #Classic.Down = KEY_DOWN 23 | #Classic.Left = KEY_LEFT 24 | #Classic.Right = KEY_RIGHT 25 | #Classic.Minus = KEY_BACK 26 | #Classic.Plus = KEY_FORWARD 27 | #Classic.Home = KEY_HOME 28 | #Classic.A = BTN_LEFT 29 | #Classic.B = BTN_RIGHT 30 | #Classic.X = 31 | #Classic.Y = 32 | #Classic.ZL = 33 | #Classic.ZR = 34 | #Classic.L = 35 | #Classic.R = 36 | -------------------------------------------------------------------------------- /git-config: -------------------------------------------------------------------------------- 1 | # vim:set ft=gitconfig: 2 | # TODO if only there were a generic way to "git-config.d" that doesn't involve generated files ;.; 3 | # ("path = git-config.d/*" or somesuch) 4 | 5 | [include] 6 | path = git-config.d/common 7 | path = git-config.d/personal 8 | -------------------------------------------------------------------------------- /git-config.d/common: -------------------------------------------------------------------------------- 1 | # vim:set ft=gitconfig: 2 | 3 | [branch] 4 | autoSetupMerge = true 5 | autoSetupRebase = always 6 | 7 | [color "grep"] 8 | # to match standard grep colors 9 | filename = magenta 10 | linenumber = green 11 | 12 | [color "status"] 13 | header = yellow 14 | 15 | [core] 16 | editor = vim 17 | pager = less --quit-if-one-screen --no-init 18 | 19 | [diff] 20 | colorMoved = dimmed_zebra 21 | renameLimit = 0 22 | renames = copies 23 | 24 | [init] 25 | defaultBranch = main 26 | 27 | [push] 28 | default = upstream 29 | 30 | [rebase] 31 | autoStash = true 32 | missingCommitsCheck = warn 33 | 34 | [tag] 35 | sort = creatordate 36 | -------------------------------------------------------------------------------- /git-config.d/tianon: -------------------------------------------------------------------------------- 1 | # vim:set ft=gitconfig: 2 | # For my usage, I symlink this file as "personal" (see "git-config" one level up). 3 | # I chose to structure it this way so that users don't clone my ~/home, install it, and then accidentally start commiting with their user.name + user.email set as me. :D 4 | # (But I still wanted my files to be available for other people to see *how* I choose to use this.) 5 | 6 | [pull] 7 | ff = only 8 | 9 | [user] 10 | email = admwiggin@gmail.com 11 | name = Tianon Gravi 12 | 13 | [includeIf "gitdir:~/git/debian/**"] 14 | path = tianon-debian 15 | 16 | [includeIf "gitdir:~/debian/**"] 17 | path = tianon-debian 18 | -------------------------------------------------------------------------------- /git-config.d/tianon-debian: -------------------------------------------------------------------------------- 1 | # vim:set ft=gitconfig: 2 | 3 | [user] 4 | email = tianon@debian.org 5 | -------------------------------------------------------------------------------- /inputrc: -------------------------------------------------------------------------------- 1 | # mappings for "page up" and "page down" to step through history 2 | "\e[5~": history-search-backward 3 | "\e[6~": history-search-forward 4 | 5 | # mappings for Ctrl-left-arrow and Ctrl-right-arrow for word moving 6 | "\e[5C": forward-word 7 | "\e[5D": backward-word 8 | "\e[1;5C": forward-word 9 | "\e[1;5D": backward-word 10 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | thisDir="$(dirname "$(readlink -f "$BASH_SOURCE")")" 5 | 6 | if [ -e "$HOME/.bashrc" ]; then 7 | sed -ri 's!^(HIST[A-Z]*SIZE=)!#\1!' "$HOME/.bashrc" 8 | fi 9 | 10 | declare -A files=( 11 | ["$HOME/.bashrc"]="source '$thisDir/bashrc'" 12 | ["$HOME/.gitconfig"]=$'[include]\n\t'"path = $thisDir/git-config" 13 | ["$HOME/.inputrc"]="\$include $thisDir/inputrc" 14 | ["$HOME/.ssh/config"]="Include $thisDir/ssh-config.d/*" # TODO this should only be done if the permissions on "ssh-config.d" are such that it will actually work (SSH is very picky and if permissions are bad this will make "ssh" literally fail to do *anything* which is not ideal) 15 | ["$HOME/.tmux.conf"]="source-file '$thisDir/tmux.conf'" 16 | ) 17 | 18 | # Debian includes a default ~/.profile that loads bashrc, but Alpine doesn't, so if ~/.profile doesn't exist or doesn't mention bashrc, let's adjust it too 19 | if [ ! -e "$HOME/.profile" ] || ! grep -q bashrc "$HOME/.profile"; then 20 | files["$HOME/.profile"]='[ -z "$BASH_VERSION" ] || . "$HOME/.bashrc"' 21 | fi 22 | 23 | if [ ! -d "$HOME/.ssh" ]; then 24 | mkdir "$HOME/.ssh" 25 | chmod 700 "$HOME/.ssh" 26 | fi 27 | if [ ! -d "$HOME/.ssh/sockets" ]; then 28 | mkdir "$HOME/.ssh/sockets" 29 | fi 30 | 31 | for f in "${!files[@]}"; do 32 | if [ ! -e "$f" ] || ! grep -q "$thisDir" "$f"; then 33 | line="${files[$f]}" 34 | printf "updating %q -- %s\n" "$f" "${line//$'\n'/\\n}" 35 | if [ -s "$f" ]; then 36 | echo >> "$f" 37 | fi 38 | echo "${files[$f]}" >> "$f" 39 | fi 40 | done 41 | 42 | for d in "$HOME/.vim/pack" "$HOME/.config/nvim/pack"; do 43 | if [ ! -d "$d/tianon" ]; then 44 | mkdir -pv "$d" 45 | ln -svfT "$thisDir/vim-pack-tianon" "$d/tianon" 46 | fi 47 | done 48 | -------------------------------------------------------------------------------- /ssh-config.d/000-common: -------------------------------------------------------------------------------- 1 | HashKnownHosts no 2 | ExitOnForwardFailure yes 3 | UpdateHostKeys ask 4 | 5 | # seconds between pings 6 | ServerAliveInterval 30 7 | # pings before disconnect 8 | ServerAliveCountMax 10 9 | # 30 * 10 == 300 seconds before disconnect 10 | 11 | # vim:set ft=sshconfig: 12 | -------------------------------------------------------------------------------- /ssh-config.d/010-local: -------------------------------------------------------------------------------- 1 | # allow for per-host ~/.ssh/config.d when this clone of https://github.com/tianon/home is auto-synchronized between machines 2 | Include ~/.ssh/config.d/* 3 | 4 | # vim:set ft=sshconfig: 5 | -------------------------------------------------------------------------------- /ssh-config.d/github: -------------------------------------------------------------------------------- 1 | Host github.com gist.github.com 2 | User git 3 | 4 | # vim:set ft=sshconfig: 5 | -------------------------------------------------------------------------------- /ssh-config.d/zzz-sockets: -------------------------------------------------------------------------------- 1 | Match all 2 | # use sockets if they're available 3 | ControlPath ~/.ssh/sockets/%r@%h-%p 4 | # and if they're not, make it so 5 | ControlPersist 15m 6 | ControlMaster auto 7 | 8 | # vim:set ft=sshconfig: 9 | -------------------------------------------------------------------------------- /tmux.conf: -------------------------------------------------------------------------------- 1 | # partly from paultag: http://public.pault.ag/stuff/.tmux.conf 2 | 3 | set -g set-titles on 4 | set -g set-titles-string '#T - tmux<#I:#W>' 5 | 6 | unbind C-b 7 | set -g prefix ^A 8 | bind a send-prefix 9 | 10 | # last active window 11 | bind-key C-a last-window 12 | 13 | # Less ugly key for the copy mode 14 | bind-key Escape copy-mode -u 15 | 16 | # Start window numbering at 1 17 | set -g base-index 1 18 | # Like base-index, but set the starting index for pane numbers. 19 | set-window-option -g pane-base-index 1 20 | 21 | # No delay in command sequences 22 | set -s escape-time 0 23 | 24 | # Rather than constraining window size to the maximum size of any client 25 | # connected to the *session*, constrain window size to the maximum size of any 26 | # client connected to *that window*. Much more reasonable. 27 | setw -g aggressive-resize on 28 | 29 | set -g status on 30 | set -g status-interval 1 31 | 32 | #### COLOUR (Solarized 256) 33 | # default statusbar colors 34 | set-option -g status-style fg=colour136,bg=colour235 35 | # default window title colors 36 | set-window-option -g window-status-style fg=colour244 37 | # active window title colors 38 | set-window-option -g window-status-current-style fg=colour166 39 | # pane border 40 | set-option -g pane-border-style fg=colour235 41 | set-option -g pane-active-border-style fg=colour240 42 | # message text 43 | set-option -g message-style fg=colour166,bg=colour235 44 | # pane number display 45 | set-option -g display-panes-active-colour colour33 #blue 46 | set-option -g display-panes-colour colour166 #orange 47 | # clock 48 | set-window-option -g clock-mode-colour colour64 #green (lolignored) 49 | 50 | set -g status-left '#[fg=colour70,bold]%H:%M:%S#[default] ' 51 | set -g status-left-length 42 52 | set -g status-right ' #[fg=colour161,bold]♥#[default] #[fg=colour32,bold]#H#[default]' 53 | set -g status-right-length 52 54 | 55 | # Instruct tmux to treat top-bit-set characters in the status-left and 56 | # status-right strings as UTF-8; notably, this is important for wide 57 | # characters. This option defaults to off. 58 | #set -g status-utf8 on 59 | 60 | set-window-option -g window-status-format '#I:#W#F' 61 | set-window-option -g window-status-current-format '#I:#W#F' 62 | 63 | # Monitor for activity in the window. Windows with activity are 64 | # highlighted in the status line. 65 | #set-window-option -g monitor-activity on 66 | 67 | # We like bash 68 | set -g default-command bash 69 | 70 | # If on, ring the terminal bell when an activity, content or silence alert occurs. 71 | #set -g bell-on-alert on 72 | # listen for activity on all windows 73 | set -g bell-action any 74 | 75 | # Set the maximum number of lines held in window history. 76 | # This setting applies only to new windows - existing window 77 | # histories are not resized and retain the limit at the point 78 | # they were created. 79 | set -g history-limit 100000 80 | 81 | set -g default-terminal 'screen-256color' 82 | -------------------------------------------------------------------------------- /vim-pack-tianon/start/tianon: -------------------------------------------------------------------------------- 1 | ../../vim-tianon -------------------------------------------------------------------------------- /vim-tianon/after/ftplugin/gitcommit.vim: -------------------------------------------------------------------------------- 1 | " gitcommit-specific defaults 2 | setlocal spell 3 | 4 | " https://unix.stackexchange.com/a/138212 5 | setlocal wrap formatoptions-=t 6 | -------------------------------------------------------------------------------- /vim-tianon/after/ftplugin/markdown.vim: -------------------------------------------------------------------------------- 1 | " Markdown-specific defaults 2 | setlocal spell linebreak 3 | -------------------------------------------------------------------------------- /vim-tianon/after/ftplugin/yaml.vim: -------------------------------------------------------------------------------- 1 | " YAML-specific defaults 2 | setlocal autoindent sw=2 ts=2 expandtab 3 | -------------------------------------------------------------------------------- /vim-tianon/plugin: -------------------------------------------------------------------------------- 1 | ../vimrc.d -------------------------------------------------------------------------------- /vimrc.d/000-defaults.vim: -------------------------------------------------------------------------------- 1 | " These settings are inspired by / taken from the "defaults.vim" file shipped 2 | " with Vim upstream (which is the default Vim loads in the absense of a 3 | " "~/.vimrc" file). 4 | " 5 | " See "/usr/share/vim/vim81/defaults.vim" or https://github.com/vim/vim/blob/8e1986e3896cc8c2a05fc6291a39ebb275e1cebf/runtime/defaults.vim 6 | 7 | " Use Vim settings, rather than Vi settings (much better!). 8 | " This must be first, because it changes other options as a side effect. 9 | set nocompatible 10 | 11 | " see also https://github.com/tpope/vim-sensible 12 | " (which should be cloned inside ~/.vim/pack/tianon/start/vim-sensible) 13 | 14 | " display incomplete commands 15 | set showcmd 16 | 17 | " Show @@@ in the last line if it is truncated. 18 | set display=truncate 19 | 20 | " Show a few lines of context around the cursor. Note that this makes the 21 | " text scroll if you mouse-click near the start or end of the window. 22 | set scrolloff=2 23 | 24 | " For Win32 GUI: remove 't' flag from 'guioptions': no tearoff menu entries. 25 | if has('win32') 26 | set guioptions-=t 27 | endif 28 | 29 | if has('mouse') 30 | " disable the mouse by default, it's annoying 31 | set mouse= 32 | endif 33 | 34 | " Only do this part when compiled with support for autocommands. 35 | if has("autocmd") 36 | 37 | " Put these in an autocmd group, so that you can revert them with: 38 | " ":augroup vimStartup | au! | augroup END" 39 | augroup vimStartup 40 | au! 41 | 42 | " When editing a file, always jump to the last known cursor position. 43 | " Don't do it when the position is invalid, when inside an event handler 44 | " (happens when dropping a file on gvim) and for a commit message (it's 45 | " likely a different one than last time). 46 | autocmd BufReadPost * 47 | \ if line("'\"") >= 1 && line("'\"") <= line("$") && &ft !~# 'commit' 48 | \ | exe "normal! g`\"" 49 | \ | endif 50 | 51 | augroup END 52 | 53 | endif " has("autocmd") 54 | 55 | " Convenient command to see the difference between the current buffer and the 56 | " file it was loaded from, thus the changes you made. 57 | " Only define it when not defined already. 58 | " Revert with: ":delcommand DiffOrig". 59 | if !exists(":DiffOrig") 60 | command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ | diffthis 61 | \ | wincmd p | diffthis 62 | endif 63 | 64 | if has('langmap') && exists('+langremap') 65 | " Prevent that the langmap option applies to characters that result from a 66 | " mapping. If set (default), this may break plugins (but it's backward 67 | " compatible). 68 | set nolangremap 69 | endif 70 | -------------------------------------------------------------------------------- /vimrc.d/alternate-dockerfile-names.vim: -------------------------------------------------------------------------------- 1 | " match more filename variations as Dockerfiles 2 | au BufNewFile,BufRead [Dd]ockerfile,[Dd]ockerfile*.*,*.*[Dd]ockerfile setlocal filetype=dockerfile 3 | -------------------------------------------------------------------------------- /vimrc.d/ctrl-c.vim: -------------------------------------------------------------------------------- 1 | " allow Ctrl+C to be magic 2 | map "+yy 3 | map "+p 4 | map "+dd 5 | imap "+yya 6 | imap "+pa 7 | imap "+dda 8 | vmap "+y 9 | vmap d"+P 10 | vmap "+d 11 | -------------------------------------------------------------------------------- /vimrc.d/sort-words.vim: -------------------------------------------------------------------------------- 1 | " https://stackoverflow.com/a/1328392 2 | 3 | command! -nargs=0 -range SortWords call SortWords() 4 | " Add a mapping, go to your string, then press vi",s 5 | " vi" selects everything inside the quotation 6 | " ,s calls the sorting algorithm 7 | "vmap ,s :SortWords 8 | " Normal mode one: ,s to select the string and sort it 9 | "nmap ,s vi",s 10 | function! SortWords() 11 | " Get the visual mark points 12 | let StartPosition = getpos("'<") 13 | let EndPosition = getpos("'>") 14 | 15 | if StartPosition[0] != EndPosition[0] 16 | echoerr "Range spans multiple buffers" 17 | elseif StartPosition[1] != EndPosition[1] 18 | " This is a multiple line range, probably easiest to work line wise 19 | 20 | " This could be made a lot more complicated and sort the whole 21 | " lot, but that would require thoughts on how many 22 | " words/characters on each line, so that can be an exercise for 23 | " the reader! 24 | for LineNum in range(StartPosition[1], EndPosition[1]) 25 | call setline(LineNum, join(sort(split(getline('.'), ' ')), " ")) 26 | endfor 27 | else 28 | " Single line range, sort words 29 | let CurrentLine = getline(StartPosition[1]) 30 | 31 | " Split the line into the prefix, the selected bit and the suffix 32 | 33 | " The start bit 34 | if StartPosition[2] > 1 35 | let StartOfLine = CurrentLine[:StartPosition[2]-2] 36 | else 37 | let StartOfLine = "" 38 | endif 39 | " The end bit 40 | if EndPosition[2] < len(CurrentLine) 41 | let EndOfLine = CurrentLine[EndPosition[2]:] 42 | else 43 | let EndOfLine = "" 44 | endif 45 | " The middle bit 46 | let BitToSort = CurrentLine[StartPosition[2]-1:EndPosition[2]-1] 47 | 48 | " Move spaces at the start of the section to variable StartOfLine 49 | while BitToSort[0] == ' ' 50 | let BitToSort = BitToSort[1:] 51 | let StartOfLine .= ' ' 52 | endwhile 53 | " Move spaces at the end of the section to variable EndOfLine 54 | while BitToSort[len(BitToSort)-1] == ' ' 55 | let BitToSort = BitToSort[:len(BitToSort)-2] 56 | let EndOfLine = ' ' . EndOfLine 57 | endwhile 58 | 59 | " Sort the middle bit 60 | let Sorted = join(sort(split(BitToSort, ' ')), ' ') 61 | " Reform the line 62 | let NewLine = StartOfLine . Sorted . EndOfLine 63 | " Write it out 64 | call setline(StartPosition[1], NewLine) 65 | endif 66 | endfunction 67 | -------------------------------------------------------------------------------- /vimrc.d/theme.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | " ^^ this should be the first line, always 3 | 4 | colorscheme jellybeans 5 | 6 | " adjust markdown code colors 7 | au FileType markdown highlight markdownCode ctermfg=DarkGreen guifg=DarkGreen 8 | 9 | " visual (and colorful) whitespace 10 | if has('multi_byte') 11 | set list listchars=tab:»·,nbsp:_,extends:¬ 12 | if &t_Co == 256 13 | au BufEnter * highlight SpecialKey ctermfg=Green ctermbg=Black guifg=Green guibg=Black 14 | au BufEnter * highlight Whitespace ctermfg=Green ctermbg=Black guifg=Green guibg=Black 15 | else 16 | au BufEnter * highlight SpecialKey ctermfg=DarkGreen ctermbg=DarkBlue guifg=DarkGreen guibg=DarkBlue 17 | au BufEnter * highlight Whitespace ctermfg=DarkGreen ctermbg=DarkBlue guifg=DarkGreen guibg=DarkBlue 18 | endif 19 | endif 20 | -------------------------------------------------------------------------------- /vimrc.d/tianon-defaults.vim: -------------------------------------------------------------------------------- 1 | set nobackup " no backup files 2 | set nowritebackup " seriously, stahp with the backup files 3 | set noswapfile " no swap files 4 | 5 | set noexpandtab tabstop=4 shiftwidth=4 6 | set nohlsearch 7 | 8 | " highlight strings inside C comments 9 | let c_comment_strings = 1 10 | 11 | " if it's .sh, it's bash 12 | let g:bash_is_sh = 1 13 | let g:is_bash = 1 14 | 15 | " highlight fenced languages in markdown! 16 | let g:markdown_fenced_languages = [ 17 | \ 'bash=sh', 18 | \ 'console=sh', 19 | \ 'dockerfile', 20 | \ 'go', 21 | \ 'html', 22 | \ 'ini=dosini', 23 | \ 'json', 24 | \ 'perl', 25 | \ 'python', 26 | \ 'sh', 27 | \ 'shell=sh', 28 | \ 'yaml' ] 29 | " don't add 'markdown' here until 30 | " https://github.com/tpope/vim-markdown/issues/121 is resolved 😬 31 | 32 | " https://github.com/bfrg/vim-jq#syntax-highlighting-options 33 | let g:jq_highlight_objects = 1 34 | 35 | " enable optional support for Perl's "method signatures" highlighting :D 36 | let g:perl_sub_signatures = 1 37 | -------------------------------------------------------------------------------- /yt-dlp.conf: -------------------------------------------------------------------------------- 1 | # per https://github.com/yt-dlp/yt-dlp#configuration, this should be symlinked next to the yt-dlp binary -- it *could* be installed in one of the "user" locations per the "User Configuration" section, but that's more error-prone for how I deploy this to my systems 2 | 3 | # --write-subs Write subtitle file 4 | --write-sub 5 | 6 | # --sub-langs LANGS Languages of the subtitles to download (can 7 | # be regex) or "all" separated by commas. 8 | # (Eg: --sub-langs "en.*,ja") You can prefix 9 | # the language code with a "-" to exempt it 10 | # from the requested languages. (Eg: --sub- 11 | # langs all,-live_chat) Use --list-subs for a 12 | # list of available language tags 13 | --sub-langs all,-live_chat 14 | 15 | # --embed-metadata Embed metadata to the video file. Also 16 | # embeds chapters/infojson if present unless 17 | # --no-embed-chapters/--no-embed-info-json are 18 | # used (Alias: --add-metadata) 19 | #--embed-metadata 20 | --------------------------------------------------------------------------------