0e29f5ad3481

Merge
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Fri, 07 Jul 2023 16:11:02 -0400
parents b324801ea16a (current diff) 953ea9d04afd (diff)
children 23b6ca12aedf
branches/tags (none)
files remote/bash_profile vim/custom-dictionary.utf-8.add weechat/python/autoload/autosort.py

Changes

--- a/.hgignore	Fri Apr 14 15:01:35 2023 -0400
+++ b/.hgignore	Fri Jul 07 16:11:02 2023 -0400
@@ -48,3 +48,4 @@
 lisp/man
 mutt/accounts
 weechat/plugins.conf
+fish/fish_variables
--- a/.hgsub	Fri Apr 14 15:01:35 2023 -0400
+++ b/.hgsub	Fri Jul 07 16:11:02 2023 -0400
@@ -10,16 +10,13 @@
 vim/bundle/delimitmate           = [git]https://github.com/Raimondi/delimitMate
 vim/bundle/fugitive              = [git]https://github.com/tpope/vim-fugitive
 vim/bundle/gdl                   = [hg]ssh://hg.stevelosh.com/repos/gdl.vim/
-vim/bundle/glsl                  = [git]https://github.com/tikhomirov/vim-glsl
 vim/bundle/gnupg                 = [git]https://github.com/jamessan/vim-gnupg
 vim/bundle/gnuplot               = [git]https://github.com/vim-scripts/gnuplot.vim
 vim/bundle/gundo                 = [hg]ssh://hg.stevelosh.com/repos/gundo.vim/
 vim/bundle/html5                 = [git]https://github.com/othree/html5.vim
-vim/bundle/indent-object         = [git]https://github.com/michaeljsmith/vim-indent-object
 vim/bundle/javascript            = [git]https://github.com/pangloss/vim-javascript
-vim/bundle/jsx                   = [git]https://github.com/mxw/vim-jsx
 vim/bundle/markdown              = [git]https://github.com/sjl/vim-markdown
-vim/bundle/miniyank              = [git]https://github.com/bfredl/nvim-miniyank
+vim/bundle/neoformat             = [git]https://github.com/sbdchd/neoformat
 vim/bundle/nerdtree              = [git]https://github.com/scrooloose/nerdtree
 vim/bundle/paredit               = [git]https://github.com/kovisoft/paredit
 vim/bundle/pgsql                 = [git]https://github.com/exu/pgsql.vim
@@ -29,9 +26,8 @@
 vim/bundle/rhubarb               = [git]https://github.com/tpope/vim-rhubarb
 vim/bundle/securemodelines       = [git]https://github.com/ciaranm/securemodelines
 vim/bundle/sexp                  = [git]https://github.com/guns/vim-sexp
-vim/bundle/shaderhighlight       = [git]https://github.com/vim-scripts/ShaderHighLight
 vim/bundle/shellcheck            = [git]https://github.com/itspriddle/vim-shellcheck
-vim/bundle/sparkup               = [git]https://github.com/rstacruz/sparkup
+vim/bundle/simpylfold            = [git]https://github.com/tmhedberg/SimpylFold
 vim/bundle/splice                = [hg]ssh://hg.stevelosh.com/repos/splice.vim
 vim/bundle/strftimedammit        = [hg]ssh://hg.stevelosh.com/repos/strftimedammit.vim/
 vim/bundle/surround              = [git]https://github.com/tpope/vim-surround
--- a/.hgsubstate	Fri Apr 14 15:01:35 2023 -0400
+++ b/.hgsubstate	Fri Jul 07 16:11:02 2023 -0400
@@ -1,8 +1,8 @@
-0d3229120aff331970cba4591c1304f7fc59b394 mercurial/hg-prompt
+16aa2def1d5b91f2f38c0bf50a955d28559c7ebe mercurial/hg-prompt
 1fc4a9fbead7e0acc4c828b346f3be2658ec3df9 mercurial/templates
 b6a8b49e2173ba5a1b34d00e68e0ed8addac3ebd vim/bundle/abolish
 a16a9b63eb85cc0960a7f25c54647ac1f99f3360 vim/bundle/ack
-e7f8786668bb9b7ac3b68198437e11f9c5c465b6 vim/bundle/badwolf
+599e1bb1aee98e563132553cf8b7bc32cb402b75 vim/bundle/badwolf
 24f6d94dd03ba0fdc703265fe281f70cf2b45ba6 vim/bundle/boxdraw
 b542a7bc4d9bc5da8fb12e110fe7975131fb57a4 vim/bundle/clam
 8295187ea1210138c0b171d8e3ec3569936f4c1a vim/bundle/commentary
@@ -10,17 +10,14 @@
 38487bbec8ba50834e257940b357de03991fa8f9 vim/bundle/delimitmate
 755554bb3c44944f70f4b2048acf0c69261782ac vim/bundle/fugitive
 127d706f2def96876605e6bd5d366c973cb8e406 vim/bundle/gdl
-6ea4e1983b18cf440c8f800a3e94b57338a3e99f vim/bundle/glsl
 7fcea1a08423da3012aac87f5224738c85d212a1 vim/bundle/gnupg
 0d57b080f9fae8573c688b6679b31eb1666edc4c vim/bundle/gnuplot
 1d84591fff04caebab75cba2294fc3843f0a4a29 vim/bundle/gundo
 fccd580f5f11d576169ee347907c9fbd77af410a vim/bundle/html5
-78fffa609b3e6b84ef01ee4c9aba6d7435d7b18e vim/bundle/indent-object
 dd84369d731bcb8feee0901cbb9b63a2b219bf28 vim/bundle/javascript
-ffc0bfd9da15d0fce02d117b843f718160f7ad27 vim/bundle/jsx
 e2d7fcd682a461a3951e8b5067cc8a0083e75e35 vim/bundle/markdown
-1362fdc7c32855794659cafe6e65d3239843d9df vim/bundle/miniyank
-d6032c876c6d6932ab7f07e262a16c9a85a31d5b vim/bundle/nerdtree
+964c66fa22500ae7375114342d212d7fe15da341 vim/bundle/neoformat
+9310f91476a94ee9c2f3a587171893743a343e26 vim/bundle/nerdtree
 c76e0987ec45c84103b408691ec0506e7b99cb30 vim/bundle/paredit
 1a436f7d875b4ec630da081b041c73264235c7e7 vim/bundle/pgsql
 d241974f40e8d206f9970e51fb0069951862ba35 vim/bundle/python-mode
@@ -29,15 +26,14 @@
 e57ed3b6be2c4a49656f1a816919f0af22fae324 vim/bundle/rhubarb
 10d6c6b52fcdd12f3ba457126f66fee4ccceec04 vim/bundle/securemodelines
 b4398689f7483b01684044ab6b55bf369744c9b3 vim/bundle/sexp
-e02c3e218c51c1e2ea1821a3fe412d4e09ca1502 vim/bundle/shaderhighlight
 4346419ac57ef341a15aa39c827c0848f17c6faf vim/bundle/shellcheck
-d400a570bf64b0c216aa7c8e1795820b911a7404 vim/bundle/sparkup
+0459df8a0bbfc8ef1bfd88db889e881626f65914 vim/bundle/simpylfold
 062b18eebd153c13e6f36577707acb17893cd959 vim/bundle/splice
 26fbdd7d1f1aa5600d2ebf39bbdd292c38aac16e vim/bundle/strftimedammit
 aa1f120ad3a29c27cc41d581cda3751c59343cce vim/bundle/surround
 19c3d966440b6cfe8d74251881a48e961ddb8648 vim/bundle/swig
 f6f2d6618a321f5b0065586a7bc934325fec81ab vim/bundle/targets
-2c6bffb492f4f9b101e45610b0d7b9c328916894 vim/bundle/vim-go
+e9d7ff3eb4a369f0cb2069c8f77ae68796bca308 vim/bundle/vim-go
 5d5c71044880443035e07009497962feacb56b20 vim/bundle/vimtex
 54feb567738398ab65d783e096bc84938e7620a0 vim/bundle/vlime
 6876fe38b33732cb124d415ffc4156f16da5e118 vim/bundle/windowswap
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.mbsyncrc	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,81 @@
+# tweaked https://raw.githubusercontent.com/bm4cs/dots/Far/.mbsyncrc
+
+IMAPAccount fastmail
+Host imap.fastmail.com
+Port 993
+User steve@stevelosh.com
+PassCmd "pass show mutt/ouroboros/steve@stevelosh.com | head -n 1"
+SSLType IMAPS
+SSLVersion TLSv1.2
+CertificateFile /etc/ssl/certs/ca-certificates.crt
+
+# Remote
+IMAPStore mail-remote
+Account fastmail
+
+# Local
+MaildirStore mail-local
+Subfolders Verbatim
+Path ~/.mail2/sjl/
+Inbox ~/.mail2/sjl/INBOX
+
+# CONNECTIONS SPECIFY LINKS BETWEEN REMOTE AND LOCAL FOLDERS
+# CONNECTIONS ARE SPECIFIED USING PATTERNS, WHICH MATCH REMOTE MAIl
+# FOLDERS. SOME COMMONLY USED PATTERS INCLUDE:
+#
+# 1 "*" TO MATCH EVERYTHING
+# 2 "!DIR" TO EXCLUDE "DIR"
+# 3 "DIR" TO MATCH DIR
+
+Channel mail-inbox
+Far :mail-remote:
+Near :mail-local:
+Patterns INBOX
+Create Near
+Sync All
+Expunge Both
+SyncState *
+
+Channel mail-sent
+Far :mail-remote:
+Near :mail-local:
+Patterns "Sent"
+Create Both
+Sync All
+Expunge Both
+SyncState *
+
+Channel mail-spam
+Far :mail-remote:
+Near :mail-local:
+Patterns "Uncaught Spam"
+Create Near
+Sync All
+Expunge Both
+SyncState *
+
+Channel mail-drafts
+Far :mail-remote:
+Near :mail-local:
+Patterns "Drafts"
+Create Near
+Sync All
+Expunge Both
+SyncState *
+
+Channel mail-archive
+Far :mail-remote:
+Near :mail-local:
+Patterns "Arc*"
+Create Near
+Sync All
+Expunge Both
+SyncState *
+
+Group mail
+Channel mail-inbox
+Channel mail-spam
+Channel mail-drafts
+Channel mail-sent
+Channel mail-archive
+
--- a/Xmodmap	Fri Apr 14 15:01:35 2023 -0400
+++ b/Xmodmap	Fri Jul 07 16:11:02 2023 -0400
@@ -13,28 +13,41 @@
 keycode 47 = minus colon
 keycode 20 = semicolon underscore
 keycode 108 = Mode_switch
+! F14 to compose
+keycode 192 = Multi_key
+keycode 193 = F15
+keycode 194 = F16
+keycode 195 = F17
+keycode 196 = F18
+keycode 197 = F19
+keycode 198 = F20
+keycode 199 = F21
+keycode 200 = F22
+keycode 201 = F23
+keycode 202 = F24
+keycode 203 = F25
 
-keycode 900 = F16
+! keycode 900 = F16
 ! for some reason this fucks up keycode 133.  I have no idea why this happens.
 ! keycode 901 = F17
-keycode 902 = F18
-keycode 903 = F19
-keycode 904 = F20
-keycode 905 = F21
-keycode 906 = F22
-keycode 907 = F23
-keycode 908 = F24
-keycode 909 = F25
+! keycode 902 = F18
+! keycode 903 = F19
+! keycode 904 = F20
+! keycode 905 = F21
+! keycode 906 = F22
+! keycode 907 = F23
+! keycode 908 = F24
+! keycode 909 = F25
 keycode 910 = F26
-keycode 911 = F27
-keycode 912 = F28
-keycode 913 = F29
-keycode 914 = F30
-keycode 915 = F31
-keycode 916 = F32
-keycode 917 = F33
-keycode 918 = F34
-keycode 919 = F35
+! keycode 911 = F27
+! keycode 912 = F28
+! keycode 913 = F29
+! keycode 914 = F30
+! keycode 915 = F31
+! keycode 916 = F32
+! keycode 917 = F33
+! keycode 918 = F34
+! keycode 919 = F35
 
 add control = Control_L
 add mod1 = Alt_L
--- a/bash_profile	Fri Apr 14 15:01:35 2023 -0400
+++ b/bash_profile	Fri Jul 07 16:11:02 2023 -0400
@@ -1,5 +1,9 @@
 #!/usr/bin/env bash
 
+if test -e /etc/profile; then
+    source /etc/profile
+fi
+
 shopt -s expand_aliases
 shopt -s histappend
 
@@ -107,3 +111,6 @@
 export GPG_TTY
 
 export EDITOR=nvim
+
+export NVM_DIR="$HOME/.nvm"
+[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/addcontact	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+# USAGE: addcontact 'Kevin Wu <kevinwuhoo@gmail.com>'
+
+RAW="$1"
+
+EMAIL="$(echo "$1" | grep -Po '<.+>' | tr -d '<>')"
+NAME="$(echo "$1" | sed -e 's/ [^ ]*$//')"
+
+printf "$EMAIL"'\t'"$NAME"'\t\n' >> ~/.contacts
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/backpackfor	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+cp ~/Dropbox/tasks/backpack-archive ~/Dropbox/tasks/backpack.txt
+nvim ~/Dropbox/tasks/backpack.txt
--- a/bin/bootstrap.sh	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/bootstrap.sh	Fri Jul 07 16:11:02 2023 -0400
@@ -54,7 +54,6 @@
 ensure_link "src/dotfiles/sqliterc"                    ".sqliterc"
 ensure_link "src/dotfiles/stumpwmrc"                   ".stumpwmrc"
 ensure_link "src/dotfiles/stumpwm/local-share-stumpwm" ".local/share/stumpwm"
-ensure_link "src/dotfiles/tmux/tmux.conf"              ".tmux.conf"
 ensure_link "src/dotfiles/vim"                         ".vim"
 ensure_link "src/dotfiles/vim/vimrc"                   ".vimrc"
 ensure_link "src/dotfiles/w3m-keymap"                  ".w3m/keymap"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/c	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+cacl --no-inform --batch "$@"
--- a/bin/cacl	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/cacl	Fri Jul 07 16:11:02 2023 -0400
@@ -2,8 +2,7 @@
 
 set -e
 
-LISPS=("sbcl" "ccl" "abcl" "ecl")
+# LISPS=("sbcl" "ccl" "abcl")
 LISPS=("sbcl" "ccl")
-LISPS=("sbcl")
 rlwrap ~/src/cacl/build/cacl-$(shuf -n1 -e "${LISPS[@]}") "$@"
 
--- a/bin/clean_mail	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/clean_mail	Fri Jul 07 16:11:02 2023 -0400
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import sys
 
--- a/bin/disks	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/disks	Fri Jul 07 16:11:02 2023 -0400
@@ -8,9 +8,14 @@
 '
 echo
 echo
-echo
 
 OUT=$(df -h)
 echo "$OUT" | head -1
 echo "$OUT" | head -1 | sed 's/./-/g'
 echo "$OUT" | tail +2 | grep -Pv '^/dev/loop' | grep -Pv tmpfs | sort -k6
+
+echo
+OUT=$(df -i)
+echo "$OUT" | head -1
+echo "$OUT" | head -1 | sed 's/./-/g'
+echo "$OUT" | tail +2 | grep -Pv '^/dev/loop' | grep -Pv tmpfs | sort -k6
--- a/bin/e	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/e	Fri Jul 07 16:11:02 2023 -0400
@@ -2,4 +2,8 @@
 
 set -euo pipefail
 
-"$EDITOR" "$@"
+if test "$#" -eq 0; then
+    "$EDITOR" .
+else
+    "$EDITOR" "$@"
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/ecl-raw	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+set -e
+/usr/local/bin/ecl "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/ecl-vlime	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+set -e
+ecl --eval "(load \"~/src/dotfiles/vim/bundle/vlime/lisp/start-vlime.lisp\")" "$@"
--- a/bin/ee	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-e .
--- a/bin/external-ip	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/external-ip	Fri Jul 07 16:11:02 2023 -0400
@@ -2,5 +2,7 @@
 
 set -euo pipefail
 
-dig @resolver1.opendns.com ANY myip.opendns.com +short
 
+#dig @resolver1.opendns.com ANY myip.opendns.com +short
+curl https://whatismyip.stevelosh.com
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/git-du	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+ROOT="$1"
+shift
+
+git-object-sizes \
+    | head -200 \
+    | grep -P "^\d+,\d+,[0-9a-f]+,$ROOT.*" \
+    | awk --field-separator , '
+    {
+        sums[$4] += $1
+    }
+    END {
+        for (x in sums) {
+            print sums[x], x
+        }
+    }
+    '
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/git-object-sizes	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+
+# Shows you the largest objects in your repo's pack file.
+# Written for osx.
+#
+# @see http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
+# @author Antony Stubbs
+#
+# Edited by sjl
+
+# set the internal field spereator to line break, so that we can iterate easily over the verify-pack output
+IFS=$'\n';
+
+# list all objects including their size, sort by size
+objects=`git verify-pack -v .git/objects/pack/pack-*.idx | grep -P '(tree|blob|commit)'`
+
+# echo "All sizes are in bytes. The pack column is the size of the object, compressed, inside the pack file." >&2
+
+# echo "size,pack,SHA,location"
+for y in $objects
+do
+    # echo "$y"
+
+    # extract the size in bytes
+    size=`echo $y | f 3`
+
+    # extract the compressed size in bytes
+    compressedSize=`echo $y | f 4`
+
+    # extract the SHA
+    sha=`echo $y | f 1`
+
+    # find the objects location in the repository tree
+    loc=`git rev-list --all --objects | grep $sha | f 2`
+
+    #lineBreak=`echo -e "\n"`
+    echo "${size},${compressedSize},${sha},${loc}"
+done
--- a/bin/hist	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/hist	Fri Jul 07 16:11:02 2023 -0400
@@ -7,9 +7,14 @@
 
 USAGE: $0 [OPTIONS]
 
+Note that the output lines will be unsorted.  For sorted output you can pipe the
+output to sort:
+
+    cat foo.dat | hist | sort -n -k3
+
 Options:
-  -h, --help       display this help text and exit
-  -w N, --width N  how wide the histograms should be
+  -h, --help             display this help text and exit
+  -w COLS, --width COLS  how wide the histogram bars should be
 "
 }
 
@@ -49,7 +54,7 @@
         bars = int(val * x * width)
         pads = width - bars
 
-        printf "%s ", val
+        printf "%s |", val
         for(i=0; i<bars; i++) printf "█"
         for(i=0; i<pads; i++) printf " "
         print key
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/hl	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+less -R
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/isbinary	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+grep -om1 '' "$1" | grep '^Binary' >/dev/null
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/join-regex-or	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,4 @@
+#!/usr/bin/env python3
+
+import sys
+print("|".join(sys.stdin.readlines()).replace('\n', ''))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/join-strings	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,4 @@
+#!/usr/bin/env python3
+
+import sys
+print(sys.argv[1].join(sys.stdin.readlines()))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/kpa	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+killall pulseaudio
--- a/bin/myctags	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/myctags	Fri Jul 07 16:11:02 2023 -0400
@@ -2,14 +2,16 @@
 
 set -e
 
-/usr/local/bin/ctags -R . && sed -i .bak -E -e '/^[^	]+	[^	]+.py	.+v$/d' tags
+CTAGS=$(command -v ctags)
+# $CTAGS -R . && sed -i.bak -E -e '/^[^	]+	[^	]+.py	.+v$/d' tags
 
-mv tags tags1
-touch tags2
+$CTAGS -R --sort=yes --exclude='bazel-*' .
+# mv tags tags1
+# touch tags2
 
-echo '!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/' > tags
-echo '!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/' >> tags
+# echo '!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/' >> tags2
+# echo '!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/' >> tags2
 
-cat tags1 tags2 | grep -Ev '^!' | grep -v 'anonymous_function' | sort >> tags
+# cat tags1 tags2 | grep -Ev '^!' | grep -v 'anonymous_function' | sort >> tags
 
-rm tags1 tags2
+# rm tags1 tags2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/o	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+if test "$#" -eq 0; then
+    open .
+else
+    open "$@"
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/packfor	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+cp ~/Dropbox/tasks/pack-archive ~/Dropbox/tasks/pack.txt
+nvim ~/Dropbox/tasks/pack.txt
--- a/bin/pastebin	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/pastebin	Fri Jul 07 16:11:02 2023 -0400
@@ -2,7 +2,7 @@
 
 set -euo pipefail
 
-PASTE_SHA=$(ssh paste.stevelosh.com -- 'cat > tmppaste && sha1sum tmppaste | cut -d" " -f1 && mv tmppaste /var/www/paste/`sha1sum tmppaste | cut -d" " -f1`')
+PASTE_SHA=$(ssh paste.stevelosh.com -- 'cat > tmppaste && sha1sum tmppaste | cut -d" " -f1 && mv tmppaste /var/www/paste.stevelosh.com/`sha1sum tmppaste | cut -d" " -f1`')
 URL="https://paste.stevelosh.com/$PASTE_SHA"
 
 echo -n "$URL" | pbcopy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/pf	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+P="$1"
+F=$(basename "$P")
+
+scp "$P" paste.stevelosh.com:"/var/www/paste/$F"
+URL="https://paste.stevelosh.com/$F"
+
+echo -n "$URL" | pbcopy
+echo "Copied $URL to the clipboard."
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/posix	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+if [ -z "$1" ]; then
+    w3m "$HOME/Dropbox/docs/posix/idx/utilities.html"
+else
+    HTMLFILE="$HOME/Dropbox/docs/posix/utilities/$1.html"
+    if [ -s "$HTMLFILE" ]; then
+        w3m "$HTMLFILE"
+    else
+        echo "No matching file for '$1'"
+    fi
+fi
--- a/bin/sbcl-raw	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/sbcl-raw	Fri Jul 07 16:11:02 2023 -0400
@@ -2,7 +2,4 @@
 
 set -e
 
-rlwrap --quote-characters '' \
-       --histsize 1000 \
-       --history-filename "$HOME/.rlwrap-lisp-history" \
-       /usr/local/bin/sbcl --noinform "$@"
+/usr/local/bin/sbcl --noinform "$@"
--- a/bin/t	Fri Apr 14 15:01:35 2023 -0400
+++ b/bin/t	Fri Jul 07 16:11:02 2023 -0400
@@ -2,4 +2,4 @@
 
 set -euo pipefail
 
-python ~/src/t/t.py --task-dir ~/plan --list TODO "$@"
+python3 ~/src/t/t.py --task-dir ~/Dropbox/tasks/ --list tasks.txt "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/unheic	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+for f in *.HEIC; do heif-convert -q 100 "$f" "$f.jpg"; done
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/unix-timestamp-seconds	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+date '+%s'
--- a/ffignore	Fri Apr 14 15:01:35 2023 -0400
+++ b/ffignore	Fri Jul 07 16:11:02 2023 -0400
@@ -1,9 +1,13 @@
 syntax:literal
+venv
+.venv
+.vagrant
 .DS_Store
 cookbook
 banner.txt
 UnityTempFile
 .m2
+.mail
 node_modules
 fake-gopath
 slug
@@ -17,3 +21,4 @@
 \.dx64fsl$
 \.lx64fsl$
 \.pyc$
+bazel-.*
--- a/fish/config.fish	Fri Apr 14 15:01:35 2023 -0400
+++ b/fish/config.fish	Fri Jul 07 16:11:02 2023 -0400
@@ -6,6 +6,7 @@
 function eg; nvim ~/.gitconfig; end
 function eh; nvim ~/.hgrc; end
 function ei; hg -R ~/src/inventory/ pull -u; and nvim ~/src/inventory/inventory.markdown; and hg -R ~/src/inventory/ ci -m 'Update inventory'; and hg -R ~/src/inventory/ push; end
+function el; cd ~/Dropbox/life; nvim .; end
 function em; nvim ~/.mutt/muttrc; end
 function es; cd ~/src/stumpwm; nvim ~/.stumpwmrc; end
 function ev; nvim ~/.vimrc; end
@@ -67,6 +68,7 @@
 function please_fish_just_bind_the_keys
     bind \cn accept-autosuggestion
     bind \cw backward-kill-word
+    fzf_key_bindings
 end
 function fish_user_keybindings
     please_fish_just_bind_the_keys
@@ -125,6 +127,21 @@
 set -g -x LESS_TERMCAP_ue (printf '\e[0m')           # end underline
 set -g -x LESS_TERMCAP_us (printf '\e[04;38;5;146m') # begin underline
 
+set -g -x FZF_DEFAULT_COMMAND 'ffind | head -10000'
+set -g -x FZF_DEFAULT_OPTS '--height 15'
+
+set -g -x ANSIBLE_NOCOWS 1
+
+# }}}
+# Disable Spyware {{{
+
+set -g -x DO_NOT_TRACK 1
+set -g -x STRIPE_CLI_TELEMETRY_OPTOUT 1
+set -g -x GOTELEMETRY off
+set -g -x GOPROXY direct
+set -g -x VAGRANT_CHECKPOINT_DISABLE 1
+set -g -x CHECKPOINT_DISABLE 1
+
 # }}}
 # Python {{{
 
@@ -189,7 +206,7 @@
             set_color normal
             printf ' on '
             set_color magenta
-            printf '%s' (git current-branch ^/dev/null)
+            printf '%s' (git current-branch 2>/dev/null)
             set_color green
             git_prompt_status
             set_color normal
@@ -201,6 +218,22 @@
     echo $PWD | sed -e "s|^$HOME|~|"
 end
 
+set elapsed_start 0
+set elapsed 0
+
+function prompt_time_elapsed --description 'Print the time taken by the previous command, if significant.'
+    if test $elapsed -gt 2
+        echo -n ' ('$elapsed's)'
+    end
+end
+
+function elapsed_timer_pre -e fish_preexec
+    set elapsed_start (date '+%s')
+end
+
+function elapsed_timer_post -e fish_postexec
+    set elapsed (math (date '+%s') - $elapsed_start)
+end
 
 function fish_prompt
     set last_status $status
@@ -225,6 +258,9 @@
         git_prompt
     end
 
+    set_color brblack
+    prompt_time_elapsed
+
     echo
 
     if test $last_status -eq 0
--- a/fish/functions/hl.fish	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function hl -d "Highlighted Less"
-    less -R
-end
--- a/fish/functions/o.fish	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function o -d "open" --wraps "open"
-    open $argv
-end
--- a/fish/functions/oo.fish	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function oo -d "open ."
-    open .
-end
--- a/fish/functions/packfor.fish	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-function packfor
-    cp ~/Dropbox/tasks/pack-archive ~/Dropbox/tasks/pack.txt
-end
--- a/fish/functions/serve-this.fish	Fri Apr 14 15:01:35 2023 -0400
+++ b/fish/functions/serve-this.fish	Fri Jul 07 16:11:02 2023 -0400
@@ -1,3 +1,3 @@
 function serve-this -d "Launch a webserver on 8000 serving the cwd"
-    python -m SimpleHTTPServer
+    python3 -m http.server
 end
--- a/gitconfig	Fri Apr 14 15:01:35 2023 -0400
+++ b/gitconfig	Fri Jul 07 16:11:02 2023 -0400
@@ -8,11 +8,18 @@
     excludesfile = ~/.gitignore
 
 [alias]
+    mainbranch = "!f() { git branch | grep -P ' (master|main)$' | sed -Ee 's/.* //'; }; f"
     tags = tag -l
     branches = branch -a
     remotes = remote -v
 
     make-the-fucking-branch-point-at-the-fucking-commit = "!sh -c 'git checkout $1 && git reset --hard $2' -"
+    mtfbpatfc                                           = "!sh -c 'git checkout $1 && git reset --hard $2' -"
+
+    reset-main-to-origin = "!sh -c 'git mtfbpatfc $(git mainbranch) origin/$(git mainbranch)' -"
+
+    repoint = "!sh -c 'git update-ref HEAD $1 && git reset' -"
+
     root = rev-parse --show-toplevel
 
     l   = log -18 --color=always --all --topo-order --pretty='format:%Cgreen%h%Creset %s%Cred%d%Creset %C(black bold)(by %an)%Creset'
@@ -30,12 +37,12 @@
 
     ack = log --color=always --all --topo-order --pretty='format:%Cgreen%h%Creset %s%Cred%d%Creset %C(black bold)(by %an)%Creset' --full-history -S
 
+    # not much what's up with you
+    upsub = submodule update --init --recursive
+
     ci = commit
     cm = commit -m
 
-    rom = rebase origin/master
-    rec = rebase --continue
-
     d = diff
     di = diff --cached
     dl = "!f() { git diff \"$@\" | nvim -R -c 'set ft=diff' -; }; f"
@@ -61,10 +68,13 @@
     delete-remote-branch = "!sh -c 'git push $1 --delete $2' -"
     delete-branch = "!sh -c 'git delete-local-branch $1; git remotes | cut -f1 | sort | uniq | xargs -n1 -I % git delete-local-reference-to-remote-branch % $1' -"
     delete-current-branch = "!bash -c 'git checkout master && git delete-branch $1' - $(git current-branch)"
+    purge-branch = "!sh -c 'set -x; git delete-local-branch $1; git delete-local-reference-to-remote-branch origin $1 && git delete-remote-branch origin $1' -"
     clean-local-branches = "!sh -c 'git branch --merged master | grep -v master$ | xargs git branch -d' -"
     clean-remote-tracking-branches = "!sh -c 'git branch -r --merged master | grep -v /master$ | xargs git branch -rd' -"
     clean-branches = "!sh -c 'git checkout master && git fetch origin && git merge --ff-only origin/master && git clean-local-branches && git clean-remote-tracking-branches' -"
 
+    branch-activity = "!sh -c 'git log -n1 --pretty=format:\"%aI%d\n\" $1 --' -"
+
     current-branch = rev-parse --abbrev-ref HEAD
 
     fo = fetch origin
@@ -81,7 +91,10 @@
 
     fuu = "!sh -c 'git fu && git uu' -"
     fuo = "!sh -c 'git fo && git uo' -"
-    fuom = "!sh -c 'git co master && git fo && git uo' -"
+    fuom = "!sh -c 'git co $(git mainbranch) && git fo && git uo' -"
+    fuum = "!sh -c 'git co $(git mainbranch) && git fu && git uu' -"
+    rom =  "!sh -c 'git fo && git rebase origin/$(git mainbranch)' -"
+    recon =  rebase --continue
 
     addremove = !git add . && git add -u
     addrem = !git addremove
@@ -96,6 +109,8 @@
     purge = "!sh -c 'git untracked && confirm && git actually-purge'"
     actually-purge = "!sh -c 'git untracked | xargs rm'"
 
+    bazel-log = log --pretty=bazel --date=raw --all --graph --topo-order 
+
 [push]
     default = current
 
@@ -123,7 +138,20 @@
     path = ~/.gitconfig_local
 
 [credential]
-    helper = store
+	helper = store
+	useHttpPath = true
 
 [sendemail]
     smtpserver = "/home/sjl/src/dotfiles/bin/msmtp-stevelosh"
+
+[pretty]
+    bazel = %C(auto)%H %Cgreen%cd %C(auto)%s %Cred%al %C(auto)%d
+[pull]
+	ff = only
+[filter "lfs"]
+	clean = git-lfs clean -- %f
+	smudge = git-lfs smudge -- %f
+	process = git-lfs filter-process
+	required = true
+[diff "lfs"]
+	textconv = cat
--- a/gitignore	Fri Apr 14 15:01:35 2023 -0400
+++ b/gitignore	Fri Jul 07 16:11:02 2023 -0400
@@ -16,5 +16,6 @@
 *.lx64fsl
 *.dx64fsl
 .sjl-rsync-exclude
+sjl-jupyter
 
 *.waiting
--- a/gnuplot	Fri Apr 14 15:01:35 2023 -0400
+++ b/gnuplot	Fri Jul 07 16:11:02 2023 -0400
@@ -23,8 +23,8 @@
 tau = 2 * pi
 e = 2.71828182845905
 r2 = sqrt(2.0)
-rfc3339 = "%Y-%m-%d %H:%M:%S."
-iso8601 = "%Y-%m-%dT%H:%M:%S."
+rfc3339 = "%Y-%m-%dT%H:%M:%S"
+iso8601 = "%Y-%m-%dT%H:%M:%S"
 
 # }}}
 # Utility Functions ------------------------------------------------------- {{{
@@ -52,6 +52,24 @@
 lrt4(mp, bp) = baselrt(m4, b4, mp, bp)
 
 # }}}
+# Convenience Wrappers ---------------------------------------------------- {{{
+# usage: @xrfc3339
+
+csvinput = 'set datafile separator ","'
+xrfc3339 = "set xdata time; set timefmt rfc3339"
+yrfc3339 = "set ydata time; set timefmt rfc3339"
+
+y_def = sprintf("set ytics format '%h'") # eval y_def()
+y_eng(n) = sprintf("set ytics format '%." . n . "sx10^%S'") # eval y_eng(1) → 100.1 x 10⁶
+
+# }}}
+# Quick Plots ------------------------------------------------------------- {{{
+# usage: @qpng
+
+qpng = 'set terminal pngcairo size 1600,1200; set termoption font "Routed Gothic,18"; set output "plot.png"'
+qpdf = 'set terminal pdfcairo size 16in,12in; set termoption font "Routed Gothic,20"; set output "plot.pdf"'
+
+# }}}
 # Exporting --------------------------------------------------------------- {{{
 
 export(file, terminal) = sprintf( \
@@ -71,6 +89,16 @@
 png = "eval export_png('graph')"
 
 # }}}
+# Histograms -------------------------------------------------------------- {{{
+
+histogram_bin_width=1024*256
+histogram_bin(x,width)=width*floor(x/width) + width/2.0
+set boxwidth histogram_bin_width*0.9
+set style fill solid 0.5 
+
+# plot 'sizes' using (histogram_bin($1,histogram_bin_width)):(1.0) smooth freq with boxes
+
+# }}}
 # Other ------------------------------------------------------------------- {{{
 
 kdens(file, column, bandwidth) = sprintf( \
--- a/gnuplot-scripts/black-and-white-lines-points.gp	Fri Apr 14 15:01:35 2023 -0400
+++ b/gnuplot-scripts/black-and-white-lines-points.gp	Fri Jul 07 16:11:02 2023 -0400
@@ -1,15 +1,15 @@
 set palette defined (0 '#111111', 1 '#eeeeee')
 
-set linetype  1 linewidth 1.25 pointtype 7  ps 1.0 linecolor rgb 'black' pointinterval -1 dt solid
-set linetype  2 linewidth 1.25 pointtype 1  ps 1.1 linecolor rgb 'black' pointinterval -1 dt '-'
-set linetype  3 linewidth 1.25 pointtype 9  ps 1.3 linecolor rgb 'black' pointinterval -1 dt '.'
-set linetype  4 linewidth 1.25 pointtype 6  ps 1.0 linecolor rgb 'black' pointinterval -1 dt (10, 5, 2, 5)
-set linetype  5 linewidth 1.25 pointtype 10 ps 1.3 linecolor rgb 'black' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
-set linetype  6 linewidth 1.25 pointtype 7  ps 1.0 linecolor rgb 'black' pointinterval -1 dt solid
-set linetype  7 linewidth 1.25 pointtype 1  ps 1.1 linecolor rgb 'black' pointinterval -1 dt '-'
-set linetype  8 linewidth 1.25 pointtype 9  ps 1.3 linecolor rgb 'black' pointinterval -1 dt '.'
-set linetype  9 linewidth 1.25 pointtype 6  ps 1.0 linecolor rgb 'black' pointinterval -1 dt (10, 5, 2, 5)
-set linetype 10 linewidth 1.25 pointtype 10 ps 1.3 linecolor rgb 'black' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
+set linetype  1 linewidth 2 pointtype 7  ps 1.0 linecolor rgb 'black' pointinterval -1 dt solid
+set linetype  2 linewidth 2 pointtype 1  ps 1.3 linecolor rgb 'black' pointinterval -1 dt '-'
+set linetype  3 linewidth 2 pointtype 9  ps 1.3 linecolor rgb 'black' pointinterval -1 dt '.'
+set linetype  4 linewidth 2 pointtype 6  ps 1.0 linecolor rgb 'black' pointinterval -1 dt (10, 5, 2, 5)
+set linetype  5 linewidth 2 pointtype 10 ps 1.3 linecolor rgb 'black' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
+set linetype  6 linewidth 2 pointtype 7  ps 1.0 linecolor rgb 'black' pointinterval -1 dt solid
+set linetype  7 linewidth 2 pointtype 1  ps 1.1 linecolor rgb 'black' pointinterval -1 dt '-'
+set linetype  8 linewidth 2 pointtype 9  ps 1.3 linecolor rgb 'black' pointinterval -1 dt '.'
+set linetype  9 linewidth 2 pointtype 6  ps 1.0 linecolor rgb 'black' pointinterval -1 dt (10, 5, 2, 5)
+set linetype 10 linewidth 2 pointtype 10 ps 1.3 linecolor rgb 'black' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
 
 unset linetype 11
 unset linetype 12
--- a/gnuplot-scripts/black-and-white-lines.gp	Fri Apr 14 15:01:35 2023 -0400
+++ b/gnuplot-scripts/black-and-white-lines.gp	Fri Jul 07 16:11:02 2023 -0400
@@ -1,15 +1,15 @@
 set palette defined (0 '#111111', 1 '#eeeeee')
 
-set linetype  1 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt solid
-set linetype  2 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt '-'
-set linetype  3 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt '.'
-set linetype  4 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt (10, 5, 2, 5)
-set linetype  5 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
-set linetype  6 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt solid
-set linetype  7 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt '-'
-set linetype  8 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt '.'
-set linetype  9 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt (10, 5, 2, 5)
-set linetype 10 linewidth 1.25 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
+set linetype  1 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt solid
+set linetype  2 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt '-'
+set linetype  3 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt '.'
+set linetype  4 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt (10, 5, 2, 5)
+set linetype  5 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
+set linetype  6 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt solid
+set linetype  7 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt '-'
+set linetype  8 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt '.'
+set linetype  9 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt (10, 5, 2, 5)
+set linetype 10 linewidth 3 pointtype 7 ps 1.0 linecolor rgb 'black' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
 
 unset linetype 11
 unset linetype 12
--- a/gnuplot-scripts/color.gp	Fri Apr 14 15:01:35 2023 -0400
+++ b/gnuplot-scripts/color.gp	Fri Jul 07 16:11:02 2023 -0400
@@ -1,16 +1,16 @@
 set palette defined (0 '#fef0d9', 1 '#d7301f', 2 '#fc8d59', 3 '#d7301f')
 
-set linetype  1 linewidth 1.25 pointtype 7  ps 1.0 linecolor rgb '#1f78b4' pointinterval -1 dashtype solid
-set linetype  2 linewidth 1.25 pointtype 1  ps 1.1 linecolor rgb '#33a02c' pointinterval -1 dashtype solid
-set linetype  3 linewidth 1.25 pointtype 9  ps 1.2 linecolor rgb '#e31a1c' pointinterval -1 dashtype solid
-set linetype  4 linewidth 1.25 pointtype 6  ps 1.0 linecolor rgb '#ff7f00' pointinterval -1 dashtype solid
-set linetype  5 linewidth 1.25 pointtype 10 ps 1.2 linecolor rgb '#6a3d9a' pointinterval -1 dashtype solid
+set linetype  1 linewidth 2 pointtype 7  ps 1.0 linecolor rgb '#1f78b4' pointinterval -1 dashtype solid
+set linetype  2 linewidth 2 pointtype 1  ps 1.1 linecolor rgb '#33a02c' pointinterval -1 dashtype solid
+set linetype  3 linewidth 2 pointtype 9  ps 1.2 linecolor rgb '#e31a1c' pointinterval -1 dashtype solid
+set linetype  4 linewidth 2 pointtype 6  ps 1.0 linecolor rgb '#ff7f00' pointinterval -1 dashtype solid
+set linetype  5 linewidth 2 pointtype 10 ps 1.2 linecolor rgb '#6a3d9a' pointinterval -1 dashtype solid
 
-set linetype  6 linewidth 1.5 pointtype 7  ps 1.0 linecolor rgb '#1f78b4' pointinterval -1 dt (10, 6)
-set linetype  7 linewidth 1.5 pointtype 1  ps 1.1 linecolor rgb '#33a02c' pointinterval -1 dt (2, 4)
-set linetype  8 linewidth 1.5 pointtype 9  ps 1.2 linecolor rgb '#e31a1c' pointinterval -1 dt (10, 5, 2, 5)
-set linetype  9 linewidth 1.5 pointtype 6  ps 1.0 linecolor rgb '#ff7f00' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
-set linetype 10 linewidth 1.5 pointtype 10 ps 1.2 linecolor rgb '#6a3d9a' pointinterval -1 dt (8, 4, 2, 4, 2, 4, 2, 4)
+set linetype  6 linewidth 3.5 pointtype 7  ps 1.0 linecolor rgb '#1f78b4' pointinterval -1 dt (10, 6)
+set linetype  7 linewidth 3.5 pointtype 1  ps 1.1 linecolor rgb '#33a02c' pointinterval -1 dt (2, 4)
+set linetype  8 linewidth 3.5 pointtype 9  ps 1.2 linecolor rgb '#e31a1c' pointinterval -1 dt (10, 5, 2, 5)
+set linetype  9 linewidth 3.5 pointtype 6  ps 1.0 linecolor rgb '#ff7f00' pointinterval -1 dt (8, 7, 2, 7, 2, 7)
+set linetype 10 linewidth 3.5 pointtype 10 ps 1.2 linecolor rgb '#6a3d9a' pointinterval -1 dt (8, 4, 2, 4, 2, 4, 2, 4)
 
 unset linetype 11
 unset linetype 12
--- a/grcat/conf.curl	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# request
-regexp=(^\* .*)
-colours=bright_black
-=======
-# request
-regexp=(^> .*)
-colours=bright_black
-=======
-# response
-regexp=(^< .*)
-colours=blue
-=======
-# ok response code
-regexp=^< HTTP.+ ([23]...*)
-colours=blue, bold green
-=======
-# error response code
-regexp=^< HTTP.+ ([45]...*)
-colours=blue, bold red
-=======
-regexp=.*\[.* bytes data\]
-colours=bright_black
--- a/grcat/conf.go-test	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-regexp=(^=== RUN).*
-colours=cyan,bold cyan
-=======
-regexp=(^--- PASS).*
-colours=green,bold green
-=======
-regexp=(^--- FAIL).*
-colours=red,bold red
-=======
-regexp=(^(ok|FAIL|\?)\s.*$)
-colours=bright_black,bright_black
-
-
--- a/grcat/conf.tail-vm	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-# err
-regexp=(ERR )
-colours=default,red
-=======
-# warn
-regexp=(WARNING )
-colours=default,yellow
-=======
-# info
-regexp=(INFO )
-colours=default,cyan
-=======
-# time
-regexp=(^\d\d:\d\d:\d\d)
-colours=bright_black
--- a/hgrc	Fri Apr 14 15:01:35 2023 -0400
+++ b/hgrc	Fri Jul 07 16:11:02 2023 -0400
@@ -22,9 +22,23 @@
 fetch =
 shelve = 
 histedit = 
+absorb = 
 prompt   = ~/src/dotfiles/mercurial/hg-prompt/prompt.py
 hggit    = ~/.hg-git/hggit
 
+[absorb]
+# only check 50 recent non-public changesets at most
+max-stack-size = 50
+# whether to add noise to new commits to avoid obsolescence cycle
+add-noise = 1
+# make `amend --correlated` a shortcut to the main command
+amend-flag = correlated
+
+[color]
+absorb.description = yellow
+absorb.node = blue bold
+absorb.path = bold
+
 [progress]
 delay = 1.0
 
--- a/lisp/Makefile	Fri Apr 14 15:01:35 2023 -0400
+++ b/lisp/Makefile	Fri Jul 07 16:11:02 2023 -0400
@@ -1,4 +1,4 @@
-files := $(shell ls *.lisp)
+files := $(wildcard *.lisp)
 names := $(files:.lisp=)
 
 .PHONY: all clean $(names)
@@ -7,14 +7,14 @@
 
 $(names): %: bin/% man/man1/%.1
 
-bin/%: %.lisp build-binary
+bin/%: %.lisp build-binary.sh Makefile
 	mkdir -p bin
-	./build-binary $<
+	./build-binary.sh $<
 	mv $(@F) bin/
 
-man/man1/%.1: %.lisp build-manual
+man/man1/%.1: %.lisp build-manual.sh Makefile
 	mkdir -p man/man1
-	./build-manual $<
+	./build-manual.sh $<
 	mv $(@F) man/man1/
 
 clean:
--- a/lisp/batchcolor.lisp	Fri Apr 14 15:01:35 2023 -0400
+++ b/lisp/batchcolor.lisp	Fri Jul 07 16:11:02 2023 -0400
@@ -8,34 +8,8 @@
 (in-package :batchcolor)
 
 ;;;; Configuration ------------------------------------------------------------
-(defparameter *version* "1.0.0")
 (defparameter *start* 0)
 (defparameter *dark* t)
-(defparameter *only-matching* nil)
-
-
-;;;; Colors -------------------------------------------------------------------
-(defun rgb-code (r g b)
-  ;; The 256 color mode color values are essentially r/g/b in base 6, but
-  ;; shifted 16 higher to account for the intiial 8+8 colors.
-  (+ (* r 36)
-     (* g 6)
-     (* b 1)
-     16))
-
-(defun make-colors (excludep)
-  (let ((result (make-array 256 :fill-pointer 0)))
-    (dotimes (r 6)
-      (dotimes (g 6)
-        (dotimes (b 6)
-          (unless (funcall excludep (+ r g b))
-            (vector-push-extend (rgb-code r g b) result)))))
-    result))
-
-(defparameter *dark-colors*  (make-colors (lambda (v) (< v 3))))
-(defparameter *light-colors* (make-colors (lambda (v) (> v 11))))
-
-(defparameter *explicits* (make-hash-table :test #'equal))
 
 
 ;;;; Errors -------------------------------------------------------------------
@@ -60,6 +34,29 @@
 
 
 ;;;; Functionality ------------------------------------------------------------
+(defun rgb-code (r g b)
+  ;; The 256 color mode color values are essentially r/g/b in base 6, but
+  ;; shifted 16 higher to account for the intiial 8+8 colors.
+  (+ (* r 36)
+     (* g 6)
+     (* b 1)
+     16))
+
+(defun make-colors (excludep)
+  (let ((result (make-array 256 :fill-pointer 0)))
+    (dotimes (r 6)
+      (dotimes (g 6)
+        (dotimes (b 6)
+          (unless (funcall excludep (+ r g b))
+            (vector-push-extend (rgb-code r g b) result)))))
+    result))
+
+(defparameter *dark-colors*  (make-colors (lambda (v) (< v 3))))
+(defparameter *light-colors* (make-colors (lambda (v) (> v 11))))
+
+(defparameter *explicits* (make-hash-table :test #'equal))
+
+
 (defun djb2 (string)
   ;; http://www.cse.yorku.ca/~oz/hash.html
   (reduce (lambda (hash c)
@@ -101,8 +98,7 @@
                  (print-colorized (subseq line word-start word-end))
                  (setf start word-end))
            starts ends)))
-  (unless (and (zerop start) *only-matching*)
-    (write-line line *standard-output* :start start))
+  (write-line line *standard-output* :start start)
   (values))
 
 
@@ -156,13 +152,6 @@
     :help-no "Optimize for light terminals."
     :initial-value t))
 
-(adopt:defparameters (*option-only-matching* *option-no-only-matching*)
-  (adopt:make-boolean-options 'only-matching
-    :long "only-matching"
-    :long-no "all-lines"
-    :short #\o
-    :help "Only print lines with at least one match."
-    :help-no "Print all lines, even if they don't have any matches (the default)."))
 
 (defparameter *option-explicit*
   (adopt:make-option 'explicit
@@ -185,12 +174,6 @@
     :short #\h
     :reduce (constantly t)))
 
-(defparameter *option-version*
-  (adopt:make-option 'version
-    :help "Display version information and exit."
-    :long "version"
-    :reduce (constantly t)))
-
 
 (adopt:define-string *help-text*
   "batchcolor takes a regular expression and matches it against standard ~
@@ -219,8 +202,8 @@
      . "tail -f /var/log/foo | batchcolor '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}'")
     ("Colorize some keywords explicitly and IPv4 addresses randomly (note that the keywords have to be in the main regex too, not just in the -e options):"
      . "batchcolor 'WARN|INFO|ERR|(?:[0-9]{1,3}\\\\.){3}[0-9]{1,3}' -e '5,0,0:ERR' -e '5,4,0:WARN' -e '2,2,5:INFO' foo.log")
-    ("Colorize earmuffed symbols in a Lisp file, only printing lines with at least one such symbol:"
-     . "batchcolor --only-matching '(?:^|[^*])([*][-a-zA-Z0-9]+[*])(?:$|[^*])' tests/test.lisp")))
+    ("Colorize earmuffed symbols in a Lisp file:"
+     . "batchcolor '(?:^|[^*])([*][-a-zA-Z0-9]+[*])(?:$|[^*])' tests/test.lisp")))
 
 
 (defparameter *ui*
@@ -229,11 +212,10 @@
     :usage "[OPTIONS] REGEX [FILE...]"
     :summary "colorize regex matches in batches"
     :help *help-text*
-    :manual (concatenate 'string *help-text* (format nil "~2%") *extra-manual-text*)
+    :manual (format nil "~A~2%~A" *help-text* *extra-manual-text*)
     :examples *examples*
     :contents (list
                 *option-help*
-                *option-version*
                 *option-debug*
                 *option-no-debug*
                 (adopt:make-group 'color-options
@@ -242,11 +224,7 @@
                                                  *option-no-randomize*
                                                  *option-dark*
                                                  *option-light*
-                                                 *option-explicit*))
-                (adopt:make-group 'output-options
-                                  :title "Output Options"
-                                  :options (list *option-only-matching*
-                                                 *option-no-only-matching*)))))
+                                                 *option-explicit*)))))
 
 
 (defmacro exit-on-ctrl-c (&body body)
@@ -259,8 +237,7 @@
   (setf *start* (if (gethash 'randomize options)
                   (random 256 (make-random-state t))
                   0)
-        *dark* (gethash 'dark options)
-        *only-matching* (gethash 'only-matching options)))
+        *dark* (gethash 'dark options)))
 
 (defun toplevel ()
   (sb-ext:disable-debugger)
@@ -271,7 +248,6 @@
       (handler-case
           (cond
             ((gethash 'help options) (adopt:print-help-and-exit *ui*))
-            ((gethash 'version options) (write-line *version*) (adopt:exit))
             ((null arguments) (error 'missing-regex))
             (t (destructuring-bind (pattern . files) arguments
                  (configure options)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/bucket.lisp	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,247 @@
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (ql:quickload '(:adopt :alexandria :cl-ppcre :with-user-abort :local-time)
+                :silent t))
+
+(defpackage :bucket
+  (:use :cl)
+  (:export :toplevel :*ui*))
+
+(in-package :bucket)
+
+;;;; Configuration ------------------------------------------------------------
+(setf local-time:*default-timezone* local-time:+utc-zone+)
+
+
+;;;; Functionality ------------------------------------------------------------
+(defun collect-values (time-mode path)
+  (flet ((collect (stream)
+           (loop :for line = (read-line stream nil nil)
+                 :while line
+                 :for value = (if time-mode
+                                (local-time:parse-rfc3339-timestring line)
+                                (parse-integer line :junk-allowed t))
+                 :when value :collect value)))
+    (if (string= path "-")
+      (collect *standard-input*)
+      (with-open-file (s path)
+        (collect s)))))
+
+
+(defun floor-to-nearest (n divisor)
+  (* divisor (floor n divisor)))
+
+(declaim (inline in-range-p in-time-p))
+(defun in-range-p (val start end)
+  (and (<= start val)
+       (< val end)))
+
+(defun in-time-p (val start end)
+  (and (local-time:timestamp<= start val)
+       (local-time:timestamp< val end)))
+
+(defun bucket-numeric (data width skip-empty output)
+  (loop :with data = (sort (coerce data 'vector) #'<)
+        :with len = (length data)
+        :with i = 0
+        :for bs :from (floor-to-nearest (aref data 0) width) :by width
+        :for be = (+ bs width)
+        :while (< i len)
+        :for count = (loop :while (< i len)
+                           :while (in-range-p (aref data i) bs be)
+                           :sum 1
+                           :do (incf i))
+        :do (unless (and skip-empty (zerop count))
+              (format t "~12F ~10D~%"
+                      (ecase output
+                        (:lower bs)
+                        (:upper be)
+                        (:mid (/ (+ bs bs width) 2.0d0)))
+                      count))))
+
+(defun bucket-temporal (data width skip-empty output)
+  (loop :with data = (sort (coerce data 'vector) #'local-time:timestamp<)
+        :with len = (length data)
+        :with i = 0
+        :with bs = (local-time:timestamp-minimize-part (aref data 0) :sec)
+        :for be = (local-time:timestamp+ bs width :sec)
+        :while (< i len)
+        :for count = (loop :while (< i len)
+                           :while (in-time-p (aref data i) bs be)
+                           :sum 1
+                           :do (incf i))
+        :do (unless (and skip-empty (zerop count))
+              (format t "~A ~10D~%"
+                      (local-time:format-rfc3339-timestring
+                        nil
+                        (ecase output
+                          (:lower bs)
+                          (:upper be)
+                          (:mid (local-time:timestamp+ bs (truncate (* width 1000000000) 2) :nsec)))) ; hack
+                      count))
+        :do (setf bs (local-time:timestamp+ bs width :sec))))
+
+(defun run (paths &key time-mode width skip-empty (output :mid))
+  (when (null width)
+    (error "Bucket width must be specified."))
+  (let ((data (mapcan (alexandria:curry #'collect-values time-mode)
+                      (or paths '("-")))))
+    (when (null data)
+      (error "No data found."))
+    (if time-mode
+      (bucket-temporal data width skip-empty output)
+      (bucket-numeric data width skip-empty output))))
+
+
+;;;; User Interface -----------------------------------------------------------
+(defparameter *option/help*
+  (adopt:make-option 'help
+    :help "Display help and exit."
+    :long "help"
+    :short #\h
+    :reduce (constantly t)))
+
+(adopt:defparameters (*option/time* *option/no-time*)
+  (adopt:make-boolean-options 'time
+    :help "Bucket in timestamp (RFC3339) mode."
+    :help-no "Bucket in numeric mode (the default)."
+    :long "time"
+    :short #\t))
+
+(adopt:defparameters (*option/skip-empty* *option/no-skip-empty*)
+  (adopt:make-boolean-options 'skip-empty
+    :help "Skip outputting empty buckets."
+    :help-no "Include empty buckets (the default)."
+    :long "skip-empty"
+    :short #\e))
+
+
+(defparameter *option/output/lower*
+  (adopt:make-option 'output/lower
+    :result-key 'output
+    :help "Output the lower bound of the bucket."
+    :long "lower"
+    :short #\l
+    :reduce (constantly :lower)))
+
+(defparameter *option/output/mid*
+  (adopt:make-option 'output/mid
+    :result-key 'output
+    :help "Output the midpoint of the bucket (the default)."
+    :long "mid"
+    :short #\m
+    :initial-value :mid
+    :reduce (constantly :mid)))
+
+(defparameter *option/output/upper*
+  (adopt:make-option 'output/upper
+    :result-key 'output
+    :help "Output the upper bound of the bucket."
+    :long "upper"
+    :short #\u
+    :reduce (constantly :upper)))
+
+
+(defparameter *option/width*
+  (adopt:make-option 'width
+    :result-key 'width
+    :help "Set bucket width to N."
+    :parameter "N"
+    :long "width"
+    :short #\W
+    :initial-value nil
+    :key #'parse-integer
+    :reduce #'adopt:last))
+
+(defparameter *option/width/seconds*
+  (adopt:make-option 'width/seconds
+    :result-key 'width
+    :help "Set bucket width to N seconds."
+    :parameter "N"
+    :long "seconds"
+    :short #\S
+    :key (lambda (n)
+           (parse-integer n))
+    :reduce #'adopt:last))
+
+(defparameter *option/width/minutes*
+  (adopt:make-option 'width/minutes
+    :result-key 'width
+    :help "Set bucket width to N minutes."
+    :parameter "N"
+    :long "minutes"
+    :short #\M
+    :key (lambda (n)
+           (* 60 (parse-integer n)))
+    :reduce #'adopt:last))
+
+(defparameter *option/width/hours*
+  (adopt:make-option 'width/hours
+    :result-key 'width
+    :help "Set bucket width to N hours."
+    :parameter "N"
+    :long "hours"
+    :short #\H
+    :key (lambda (n)
+           (* 60 60 (parse-integer n)))
+    :reduce #'adopt:last))
+
+
+(adopt:define-string *help-text*
+  "bucket groups lines into histogrammy buckets.~@
+   ~@
+   This is handy if you have some non-bucketed data that you want to graph as ~
+   a histogram with gnuplot, because gnuplot unbelievably does not have built-in ~
+   histogramming.")
+
+(defparameter *examples*
+  '())
+
+
+(defparameter *ui*
+  (adopt:make-interface
+    :name "bucket"
+    :usage "[OPTIONS] [FILE...]"
+    :summary "bucket things for easier histogramming"
+    :help *help-text*
+    :examples *examples*
+    :contents (list *option/help*
+                    *option/time*
+                    *option/no-time*
+                    *option/skip-empty*
+                    *option/no-skip-empty*
+                    (adopt:make-group 'bucket-width
+                      :title "Bucket Widths"
+                      :options (list
+                                 *option/width*
+                                 *option/width/seconds*
+                                 *option/width/minutes*
+                                 *option/width/hours*))
+                    (adopt:make-group 'bucket-labels
+                      :title "Bucket Labels"
+                      :options (list
+                                 *option/output/lower*
+                                 *option/output/mid*
+                                 *option/output/upper*)))))
+
+
+(defun toplevel ()
+  ;; #+sbcl (sb-ext:disable-debugger)
+  (handler-case
+      (adopt::quit-on-ctrl-c ()
+        (multiple-value-bind (arguments options) (adopt:parse-options-or-exit *ui*)
+          (cond
+            ((gethash 'help options) (adopt:print-help-and-exit *ui*))
+            (t (progn (local-time:reread-timezone-repository)
+                      (run arguments
+                           :time-mode (gethash 'time options)
+                           :width (gethash 'width options)
+                           :skip-empty (gethash 'skip-empty options)
+                           :output (gethash 'output options)))))))
+    (error (c) (adopt:print-error-and-exit c))))
+
+
+#; Scratch --------------------------------------------------------------------
+
+
+(ppcre:scan "(\\d{4})-(\\d{2})-(\\d{2})[ T](\\d{2}):(\\d{2}):(\\d{2})(?:\\.\\d+)?([+-]\\d{2}:\\d{2}|Z)?"
+            "2022-04-25T17:00:41.289049Z")
--- a/lisp/build-binary	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-LISP=$1
-BINARY=$(basename "$1" .lisp)
-shift
-
-sbcl --load "$LISP" --eval "(sb-ext:save-lisp-and-die \"$BINARY\" :executable t :save-runtime-options t :toplevel '$BINARY:toplevel)" "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/build-binary.sh	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+LISP=$1
+NAME=$(basename "$1" .lisp)
+shift
+
+sbcl --load "$LISP" \
+    --eval "(sb-ext:save-lisp-and-die \"$NAME\"
+              :executable t
+              :compression t
+              :save-runtime-options t
+              :toplevel '$NAME:toplevel)"
--- a/lisp/build-manual	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-LISP=$1
-NAME=$(basename "$LISP" .lisp)
-OUT="$NAME.1"
-shift
-
-sbcl --disable-debugger --load "$LISP" --eval "(with-open-file (f \"$OUT\" :direction :output :if-exists :supersede) (adopt:print-manual $NAME:*ui* :stream f))" --quit "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/build-manual.sh	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+LISP=$1
+NAME=$(basename "$LISP" .lisp)
+OUT="$NAME.1"
+shift
+
+sbcl --load "$LISP" \
+    --eval "(with-open-file (f \"$OUT\" :direction :output :if-exists :supersede)
+              (adopt:print-manual $NAME:*ui* :stream f))" \
+    --quit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/drivethru.lisp	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,115 @@
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (ql:quickload
+    '(:adopt :with-user-abort :iterate :losh :hunchentoot :lparallel)
+    :silent t))
+
+(defpackage :drivethru
+  (:use :cl :iterate :losh)
+  (:export :toplevel :*ui*))
+
+(in-package :drivethru)
+
+;;;; State --------------------------------------------------------------------
+(defvar *acceptor* nil)
+
+;; in: (req . promise)
+;;              ↑
+;; out: (status . body)
+(defvar *q* (lparallel.queue:make-queue))
+
+
+;;;; Server -------------------------------------------------------------------
+(defun prompt (message)
+  (write-string message)
+  (finish-output))
+
+(defun handle ()
+  (let ((p (lparallel:promise)))
+    (lparallel.queue:push-queue (cons hunchentoot:*request* p) *q*)
+    (destructuring-bind (status . body) (lparallel:force p)
+      (setf (hunchentoot:return-code*) status)
+      body)))
+
+(defun serve (r)
+  (destructuring-bind (request . promise) r
+    (let ((auth (multiple-value-list (hunchentoot:authorization request))))
+      (format t "~%~C[1;96m;;;; ~A ~A --------------~%~C[0m"
+              #\esc
+              (hunchentoot:request-method request)
+              (hunchentoot:request-uri request)
+              #\esc)
+      (when auth
+        (format t ";; User: ~S~%;; Pass: ~S~%" (first auth) (second auth))))
+    (let ((status (progn (prompt "Reponse code: ")
+                         (parse-integer (read-line))))
+          (body (progn (prompt "Reponse body: ")
+                       (read-line))))
+      (lparallel:fulfill promise (cons status body)))))
+
+(defun dispatch (request)
+  (declare (ignore request))
+  #'handle)
+
+
+;;;; Run ----------------------------------------------------------------------
+(defun run (port)
+  (setf hunchentoot:*dispatch-table* '(dispatch)
+        *acceptor* (hunchentoot:start (make-instance 'hunchentoot:easy-acceptor
+                                        :port port)))
+  (unwind-protect (loop (serve (lparallel.queue:pop-queue *q*)))
+    (hunchentoot:stop *acceptor*)))
+
+
+;;;; User Interface -----------------------------------------------------------
+(defparameter *option-help*
+  (adopt:make-option 'help
+    :help "Display help and exit."
+    :long "help"
+    :short #\h
+    :reduce (constantly t)))
+
+(defparameter *option-port*
+  (adopt:make-option 'port
+    :help "Listen on port N (default 33455)."
+    :parameter "N"
+    :long "port"
+    :short #\p
+    :reduce #'adopt:last
+    :key #'parse-integer
+    :initial-value 33455))
+
+(adopt:define-string *help-text*
+  "drivethru listens for HTTP requests and lets you give responses by hand on ~
+   the fly, as a low-tech mock when testing an API.")
+
+(defparameter *examples*
+  '(("Run on port 80:" . "drivethru -p 80")))
+
+(defparameter *ui*
+  (adopt:make-interface
+    :name "drivethru"
+    :usage "[OPTIONS]"
+    :summary "serve HTTP requests by hand"
+    :help *help-text*
+    :examples *examples*
+    :contents (list *option-port*
+                    *option-help*)))
+
+
+(defmacro exit-on-ctrl-c (&body body)
+  `(handler-case
+       (with-user-abort:with-user-abort (progn ,@body))
+     (with-user-abort:user-abort () (adopt:exit 130))))
+
+
+(defun toplevel ()
+  (exit-on-ctrl-c
+    (multiple-value-bind (arguments options) (adopt:parse-options-or-exit *ui*)
+      (handler-case
+          (if (gethash 'help options)
+            (adopt:print-help-and-exit *ui*)
+            (progn
+              (assert (null arguments))
+              (run (gethash 'port options))))
+        (error (e) (adopt:print-error-and-exit e))))))
+
--- a/lisp/genpass.lisp	Fri Apr 14 15:01:35 2023 -0400
+++ b/lisp/genpass.lisp	Fri Jul 07 16:11:02 2023 -0400
@@ -12,7 +12,8 @@
 (defparameter *words* nil)
 (defparameter *version* "0.0.1")
 (defparameter *random-path* "/dev/urandom")
-(defparameter *wordlist-path* "/usr/share/dict/words")
+(defparameter *wordlist-path* "/usr/share/dict/scowl/english-words.20")
+(defparameter *wordlist-encoding* :ISO-8859-1)
 
 
 ;;;; Functionality ------------------------------------------------------------
@@ -30,10 +31,11 @@
 (defun word-list ()
   (unless *words*
     (setf *words*
-          (iterate
-            (for line :in-file *wordlist-path* :using #'read-line)
-            (when (every #'safep line)
-              (collect line :result-type vector)))))
+          (with-open-file (s *wordlist-path* :external-format *wordlist-encoding*)
+            (iterate
+              (for line :in-stream s :using #'read-line)
+              (when (every #'safep line)
+                (collect line :result-type vector))))))
   *words*)
 
 (defun random-unsigned-byte-32 ()
--- a/lisp/gtp.lisp	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,351 +0,0 @@
-(eval-when (:compile-toplevel :load-toplevel :execute)
-  (ql:quickload '(:adopt :alexandria :cl-ppcre :with-user-abort :local-time)
-                :silent t))
-
-(defpackage :gtp
-  (:use :cl)
-  (:export :toplevel :*ui*))
-
-(in-package :gtp)
-
-;;;; Configuration ------------------------------------------------------------
-(defparameter *version* "1.0.0")
-(setf local-time:*default-timezone* local-time:+utc-zone+)
-
-(defparameter *time-formats*
-  `((:rfc-3339 . ("(\\d{4})-(\\d{2})-(\\d{2})[ T](\\d{2}):(\\d{2}):(\\d{2})(?:[.]\\d{4-})?([+-]\\d{2}:\\d{2}|Z)?"
-                  ,local-time:+rfc3339-format+))
-    (:iso-8601 . ("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:,\\d{4-})?([+-]\\d{2}:\\d{2}|Z)?"
-                  ,local-time:+iso-8601-format+))
-    (:simple   . ("(\\d{4})/(\\d{2})/(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})()"
-                  ((:year 4) #\/ (:month 2) #\/ (:day 2) #\space (:hour 2) #\: (:min 2) #\: (:sec 2))))
-    (:gnuplot  . ("(\\d{2})/(\\d{2})/(\\d{2}),(\\d{2}):(\\d{2})"
-                  ((:day 2) #\/ (:month 2) #\/ #\Y #\, (:hour 2) #\: (:min 2))))
-    (:unix-milliseconds . ("(\\d{13,14})" nil))
-    (:unix-seconds . ("(\\d{10,11})" nil))))
-
-
-;;;; Utilities ----------------------------------------------------------------
-(defmacro match ((register-vars (start end) (regex target)) &body body)
-  (alexandria:with-gensyms (rs re)
-    (alexandria:once-only (regex target)
-      `(multiple-value-bind (,start ,end ,rs ,re) (ppcre:scan ,regex ,target)
-         (when ,start
-           (let (,@(loop :for r :from 0
-                         :for var :in register-vars
-                         :collect `(,var (when (aref ,rs ,r)
-                                           (subseq ,target (aref ,rs ,r) (aref ,re ,r))))))
-             ,@body))))))
-
-(defun i (s)
-  (parse-integer s))
-
-(defun keywordize (s)
-  (alexandria:make-keyword (string-upcase s)))
-
-
-;;;; Time Formats -------------------------------------------------------------
-
-(defun get-format (format)
-  (or (alexandria:assoc-value *time-formats* format)
-      (error "Unknown time format ~S" format)))
-
-(defun get-regex (format)
-  (first (get-format format)))
-
-(defun get-local-time-format (format)
-  (second (get-format format)))
-
-(defun parse-timezone (string)
-  (if (member string '(nil "" "Z" "UTC" "+00:00" "-00:00") :test #'equal)
-    local-time:+utc-zone+
-    (or (local-time:find-timezone-by-location-name string)
-        (error "TODO: handle timezone ~S" string))))
-
-
-(defgeneric make-parser (format))
-
-(defmethod make-parser (format)
-  (let ((scanner (ppcre:create-scanner (get-regex format))))
-    (lambda (s)
-      (match ((year month day hour minute second timezone)
-              (start end)
-              (scanner s))
-        (values
-          (local-time:encode-timestamp
-            0 (i second) (i minute) (i hour) (i day) (i month) (i year)
-            :timezone (parse-timezone timezone))
-          start end)))))
-
-(defmethod make-parser ((format (eql :gnuplot)))
-  (let ((scanner (ppcre:create-scanner (get-regex format))))
-    (lambda (s)
-      (match ((day month year hour minute)
-              (start end)
-              (scanner s))
-        (values (local-time:encode-timestamp
-                  0 0 (i minute) (i hour) (i day) (i month) (+ 2000 (i year)))
-                start end)))))
-
-(defmethod make-parser ((format (eql :unix-seconds)))
-  (let ((scanner (ppcre:create-scanner (get-regex format))))
-    (lambda (s)
-      (match ((unix)
-              (start end)
-              (scanner s))
-        (when unix ; shut up sbcl
-          (values (local-time:unix-to-timestamp (parse-integer unix)) start end))))))
-
-(defmethod make-parser ((format (eql :unix-milliseconds)))
-  (let ((scanner (ppcre:create-scanner (get-regex format))))
-    (lambda (s)
-      (match ((unix)
-              (start end)
-              (scanner s))
-        (when unix ; shut up sbcl
-          (multiple-value-bind (sec ms) (truncate (parse-integer unix) 1000)
-            (values (local-time:unix-to-timestamp sec :nsec (* ms 1000 1000))
-                    start end)))))))
-
-
-(defun make-predicate (format start end)
-  (let ((parser (make-parser format)))
-    (lambda (line)
-      (multiple-value-bind (line-time s e) (funcall parser line)
-        (when (and line-time
-                   (or (null start) (local-time:timestamp<= start line-time))
-                   (or (null end) (local-time:timestamp<= line-time end)))
-          (values line-time s e))))))
-
-
-(defgeneric make-formatter (format))
-
-(defmethod make-formatter (format)
-  (let ((local-time-format (get-local-time-format format)))
-    (lambda (time stream)
-      (local-time:format-timestring stream time :format local-time-format))))
-
-(defmethod make-formatter ((format (eql :gnuplot)))
-  (let ((local-time-format (get-local-time-format :gnuplot)))
-    (lambda (time stream)
-      (let ((s (local-time:format-timestring nil time :format local-time-format)))
-        ;; "16/07/Y,15:05"
-        (write-string s stream :start 0 :end 6)
-        (format stream "~2,'0D" (mod (local-time:timestamp-year time) 100))
-        (write-string s stream :start 7)))))
-
-(defmethod make-formatter ((format (eql :unix-seconds)))
-  (lambda (time stream)
-    (format stream "~D" (local-time:timestamp-to-unix time))))
-
-(defmethod make-formatter ((format (eql :unix-milliseconds)))
-  (lambda (time stream)
-    (format stream "~D" (+ (* 1000 (local-time:timestamp-to-unix time))
-                           (local-time:timestamp-millisecond time)))))
-
-
-(defun parse-time-flexibly (string)
-  ;; todo optimize this
-  (loop :for format :in *time-formats*
-        :for parser = (make-parser (car format))
-        :for result = (funcall parser string)
-        :when result :do (return-from parse-time-flexibly result))
-  (error "Don't know how to parse ~S as a time." string))
-
-
-;;;; Run ----------------------------------------------------------------------
-(defun run% (predicate in out path prefix reformat)
-  (loop
-    :for line = (read-line in nil)
-    :while line
-    :do (multiple-value-bind (time start end) (funcall predicate line)
-          (when time
-            (when prefix
-              (write-string path out)
-              (write-char #\: out))
-            (if reformat
-              (progn (write-string line out :start 0 :end start)
-                     (funcall reformat time out)
-                     (write-line line out :start end))
-              (write-line line out))))))
-
-(defun run (paths &key format start end prefix reformat)
-  (when (null paths)
-    (setf paths '("-")))
-  (when (and start end (local-time:timestamp< end start))
-    (error "Start ~S is after end ~S." start end))
-  (when reformat
-    (setf reformat (make-formatter reformat)))
-  (let ((pred (make-predicate format start end)))
-    (dolist (path paths)
-      (if (string= "-" path)
-        (run% pred *standard-input* *standard-output* path prefix reformat)
-        (with-open-file (stream path :direction :input)
-          (run% pred stream *standard-output* path prefix reformat))))))
-
-
-;;;; User Interface -----------------------------------------------------------
-(defparameter *option-help*
-  (adopt:make-option 'help
-    :help "Display help and exit."
-    :long "help"
-    :short #\h
-    :reduce (constantly t)))
-
-(defparameter *option-version*
-  (adopt:make-option 'version
-    :help "Display version information and exit."
-    :long "version"
-    :reduce (constantly t)))
-
-
-(defparameter *option-prefix*
-  (adopt:make-option 'prefix
-    :help "Prefix output lines with their path."
-    :short #\p
-    :long "prefix"
-    :reduce (constantly t)))
-
-(defparameter *option-no-prefix*
-  (adopt:make-option 'no-prefix
-    :result-key 'prefix
-    :help "Do not prefix output lines with their path (default)."
-    :short #\P
-    :long "no-prefix"
-    :reduce (constantly nil)))
-
-
-(defparameter *option-format*
-  (adopt:make-option 'format
-    :help "The time format used to parse times from lines."
-    :parameter "FORMAT"
-    :long "format"
-    :short #\f
-    :initial-value :simple
-    :key #'keywordize
-    :reduce #'adopt:last))
-
-(defparameter *option-reformat*
-  (adopt:make-option 'reformat
-    :help "Reformat parsed timestamps into FORMAT before outputting them."
-    :parameter "FORMAT"
-    :long "reformat"
-    :short #\r
-    :initial-value nil
-    :key #'keywordize
-    :reduce #'adopt:last))
-
-(defparameter *option-no-reformat*
-  (adopt:make-option 'reformat
-    :help "Do not reformat parsed timestamps (default)."
-    :long "no-reformat"
-    :short #\R
-    :reduce (constantly nil)))
-
-
-(defparameter *option-start*
-  (adopt:make-option 'start
-    :help "Only show lines at or after START."
-    :parameter "START"
-    :long "start"
-    :short #\s
-    :initial-value nil
-    :key #'parse-time-flexibly
-    :reduce #'adopt:last))
-
-(defparameter *option-end*
-  (adopt:make-option 'end
-    :help "Only show lines at or before END."
-    :parameter "END"
-    :long "end"
-    :short #\e
-    :initial-value nil
-    :key #'parse-time-flexibly
-    :reduce #'adopt:last))
-
-
-(adopt:define-string *help-text*
-  "gtp filters lines by time.  Instead of g/re/p it's g/time/p.~@
-   ~@
-   gtp will only print lines that have a timestamp somewhere in them.  Use ~
-   --format to select the timestamp format.  Supported formats:~@
-   ~@
-   ~:
-   * simple:   2020/11/23 18:55:30 (default)
-   * rfc-3339: 2020-11-23 18:55:30Z
-   * iso-8601: 2020-11-23T18:55:30Z
-   * gnuplot:  11/23/20,18:55~@
-   ~@
-   You can additionally filter based on a time range using --start and/or --end. ~
-   For convenience, these parameters can be given in any supported timestamp ~
-   format, they don't have to match --format.")
-
-(defparameter *examples*
-  '(("Filter standard input and only print lines with an RFC-3339 time:"
-     . "gtp --format rfc-3339")
-    ("Print log lines after a particular time, and prefix each output line with its source filename:"
-     . "gtp **.log --prefix --after '2020/06/14 12:22:01'")
-    ("Print RFC-3339 log lines starting now, with now given in a different format:"
-     . "tail -f foo | gtp --format rfc-3339 --after \"$(date --utc --iso-8601=sec)\"")))
-
-
-(defparameter *ui*
-  (adopt:make-interface
-    :name "gtp"
-    :usage "[OPTIONS] [FILE...]"
-    :summary "filter lines by timestamp"
-    :help *help-text*
-    :examples *examples*
-    :contents (list *option-help*
-                    *option-version*
-                    *option-format*
-                    *option-reformat*
-                    *option-no-reformat*
-                    *option-start*
-                    *option-end*
-                    *option-prefix*
-                    *option-no-prefix*)))
-
-
-(defmacro exit-on-error (&body body)
-  `(handler-case (progn ,@body)
-     (error (c) (adopt:print-error-and-exit c))))
-
-(defmacro exit-on-ctrl-c (&body body)
-  `(handler-case
-       (with-user-abort:with-user-abort (progn ,@body))
-     (with-user-abort:user-abort () (adopt:exit 130))))
-
-
-(defun toplevel ()
-  #+sbcl (sb-ext:disable-debugger)
-  (exit-on-error
-    (exit-on-ctrl-c
-      (multiple-value-bind (arguments options) (adopt:parse-options-or-exit *ui*)
-        (cond
-          ((gethash 'help options) (adopt:print-help-and-exit *ui*))
-          ((gethash 'version options) (write-line *version*) (adopt:exit))
-          (t (progn (local-time:reread-timezone-repository)
-                    (run arguments
-                         :format (gethash 'format options)
-                         :start (gethash 'start options)
-                         :end (gethash 'end options)
-                         :prefix (gethash 'prefix options)
-                         :reformat (gethash 'reformat options)))))))))
-
-
-#; Scratch --------------------------------------------------------------------
-
-(run
-  '("/home/sjl/scratch/logs/test/passport/passport.172.24.20.49.log")
-  :format :simple
-  :start (parse-time-flexibly "2020-07-15T17:31:00.000000")
-  :end (parse-time-flexibly "2020-07-15T17:31:55")
-  :prefix nil
-  :reformat :iso-8601)
-
-(parse-time-flexibly "2020-07-15 16:08:15.0000Z")
-
-(local-time:find-timezone-by-location-name "EDT")
-
-(local-time:reread-timezone-repository)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/parsre.lisp	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,227 @@
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (ql:quickload '(:adopt :cl-ppcre :iterate :with-user-abort
+                  :jarl :conserve :losh)
+                :silent t))
+
+(defpackage :parsre
+  (:use :cl :iterate)
+  (:export :toplevel :*ui*))
+
+(in-package :parsre)
+
+;;;; Configuration ------------------------------------------------------------
+(defparameter *output-format* :text)
+(defparameter *case-sensitive* t)
+
+
+;;;; Errors -------------------------------------------------------------------
+(define-condition user-error (error) ())
+
+(define-condition missing-regex (user-error) ()
+  (:report "A regular expression is required."))
+
+(define-condition missing-registers (user-error) ()
+  (:report "Invalid regex, at least one named register is required."))
+
+(define-condition anonymous-register (user-error) ()
+  (:report "Invalid regex, anonymous registers are not supported.  Use non-capturing groups (?:…) if you need grouping but not capturing."))
+
+(define-condition malformed-regex (user-error)
+  ((underlying-error :initarg :underlying-error))
+  (:report (lambda (c s)
+             (format s "Invalid regex: ~A" (slot-value c 'underlying-error)))))
+
+
+;;;; Functionality ------------------------------------------------------------
+(defgeneric header (format names))
+(defmethod header (format names) nil)
+(defmethod header ((format (eql :csv)) names) (conserve:write-row names))
+
+
+(defmethod output (format names values))
+
+(defmethod output ((format (eql :text)) names values)
+  (iterate (for name :in names)
+           (for value :in values)
+           (format t "~A: ~A~%" name value))
+  (terpri))
+
+(defmethod output ((format (eql :json)) names values)
+  (jarl:print (alexandria:alist-hash-table (mapcar #'cons names values) :test #'equal))
+  (terpri))
+
+(defmethod output ((format (eql :csv)) names values)
+  (declare (ignore names))
+  (conserve:write-row values))
+
+
+(defun register-values (string register-starts register-ends)
+  (iterate
+    (for start :in-vector register-starts)
+    (for end :in-vector register-ends)
+    (collect (subseq string start end))))
+
+(defun run%% (scanner register-names string)
+  (iterate (with start = 0)
+           (for (values ms me rs re) = (ppcre:scan scanner string :start start))
+           (while ms)
+           (output *output-format* register-names (register-values string rs re))
+           (setf start (max (1+ start) me))))
+
+(defun run% (scanner register-names stream)
+  (iterate (for line :in-stream stream :using #'read-line)
+           (run%% scanner register-names line)
+           (force-output)))
+
+
+(defun make-scanner (pattern)
+  (handler-case
+      (ppcre:create-scanner pattern
+                            :case-insensitive-mode (not *case-sensitive*)
+                            :single-line-mode t)
+    (ppcre:ppcre-syntax-error (c) (error 'malformed-regex :underlying-error c))))
+
+(defun run (pattern paths)
+  (let ((ppcre:*allow-named-registers* t)
+        (ppcre:*use-bmh-matchers* t)
+        (paths (or paths '("-"))))
+    (multiple-value-bind (scanner register-names) (make-scanner pattern)
+      (cond ((null register-names) (error 'missing-registers))
+            ((member nil register-names) (error 'anonymous-register)))
+      (header *output-format* register-names)
+      (dolist (path paths)
+        (if (string= "-" path)
+          (run% scanner register-names *standard-input*)
+          (with-open-file (stream path :direction :input)
+            (run% scanner register-names stream)))))))
+
+
+;;;; User Interface -----------------------------------------------------------
+(defparameter *examples*
+  '(("Parse some web service logs:" .
+     "parsre '^(?<timestamp>\\\\S+) (?<level>INFO|WARN|ERROR|DEBUG) (?<message>.*)$'")
+    ("Parse wordcount report into JSON:" .
+     "wc **.lisp | parsre --json '^ *(?<lines>\\\\d+) +(?<words>\\\\d+) +(?<bytes>\\\\d+) +(?<path>.+)$'")))
+
+
+(defparameter *option/help*
+  (adopt:make-option 'help
+    :help "Display help and exit."
+    :long "help"
+    :short #\h
+    :reduce (constantly t)))
+
+(defparameter *option/version*
+  (adopt:make-option 'version
+    :help "Display version information and exit."
+    :long "version"
+    :reduce (constantly t)))
+
+(adopt:defparameters (*option/debug* *option/no-debug*)
+  (adopt:make-boolean-options 'debug
+    :long "debug"
+    :short #\d
+    :help "Enable the Lisp debugger."
+    :help-no "Disable the Lisp debugger (default)."))
+
+(adopt:defparameters (*option/profile* *option/no-profile*)
+  (adopt:make-boolean-options 'profile
+    :long "profile"
+    :help "Profile the run and write results to lisp.prof."
+    :help-no "Do not profile (default)."))
+
+(adopt:defparameters (*option/matching/ignore-case* *option/matching/no-ignore-case*)
+  (adopt:make-boolean-options 'ignore-case
+    :long "ignore-case"
+    :short #\i
+    :help "Ignore case (i.e. case-insensitive)."
+    :help-no "Do not ignore case (i.e. case-sensitive) (default)."
+    :initial-value nil))
+
+(defparameter *option/output-format/text*
+  (adopt:make-option 'output-format/text
+    :result-key 'output-format
+    :help "Output results as text (default)."
+    :long "text"
+    :short #\t
+    :initial-value :text
+    :reduce (constantly :text)))
+
+(defparameter *option/output-format/json*
+  (adopt:make-option 'output-format/json
+    :result-key 'output-format
+    :help "Output results as JSON."
+    :long "json"
+    :short #\j
+    :reduce (constantly :json)))
+
+(defparameter *option/output-format/csv*
+  (adopt:make-option 'output-format/csv
+    :result-key 'output-format
+    :help "Output results as CSV."
+    :long "csv"
+    :short #\c
+    :reduce (constantly :csv)))
+
+
+(adopt:define-string *help-text*
+  "Parsre takes a Perl-compatible regular expression, matches it against input, ~
+   and outputs the expression's registers in a variety of formats.~@
+   ~@
+   The regular expression will be matched against the input line-by-line.  ~
+   Multiple matches per line are supported.~@
+   ~@
+   Registers can be named or anonymous.  Anonymous registers will be named ~
+   arbitrarily (the scheme may change in the future).")
+
+
+(defparameter *ui*
+  (adopt:make-interface
+    :name "parsre"
+    :usage "[OPTIONS] REGEX [FILE...]"
+    :summary "almost a parser"
+    :help *help-text*
+    :examples *examples*
+    :contents (list *option/help*
+                    *option/version*
+                    (adopt:make-group
+                      'matching-options
+                      :title "Matching Options"
+                      :options (list *option/matching/ignore-case*
+                                     *option/matching/no-ignore-case*))
+                    (adopt:make-group
+                      'output-options
+                      :title "Output Options"
+                      :options (list *option/output-format/text*
+                                     *option/output-format/json*
+                                     *option/output-format/csv*))
+                    (adopt:make-group
+                      'debugging-options
+                      :title "Debugging Options"
+                      :options (list *option/debug*
+                                *option/no-debug*
+                                *option/profile*
+                                *option/no-profile*)))))
+
+(defun configure (options)
+  (setf *output-format* (gethash 'output-format options)
+        *case-sensitive* (not (gethash 'ignore-case options)))
+  (values))
+
+(defun toplevel ()
+  (sb-ext:disable-debugger)
+  (multiple-value-bind (arguments options) (adopt:parse-options-or-exit *ui*)
+    (when (gethash 'debug options)
+      (sb-ext:enable-debugger))
+    (handler-case
+        (with-user-abort:with-user-abort
+          (cond
+            ((gethash 'help options) (adopt:print-help-and-exit *ui*))
+            ((null arguments) (error 'missing-regex))
+            (t (destructuring-bind (pattern . files) arguments
+                 (configure options)
+                 (if (gethash 'profile options)
+                   (losh:profile (run pattern files))
+                   (run pattern files))))))
+      (with-user-abort:user-abort () (adopt:exit 130))
+      (user-error (e) (adopt:print-error-and-exit e)))))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/twizzle.lisp	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,394 @@
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (ql:quickload '(:adopt :alexandria :cl-ppcre :with-user-abort :local-time)
+                :silent t))
+
+(defpackage :twizzle
+  (:use :cl)
+  (:export :toplevel :*ui*))
+
+(in-package :twizzle)
+
+;;;; Configuration ------------------------------------------------------------
+(setf local-time:*default-timezone* local-time:+utc-zone+)
+
+(defparameter *time-formats*
+  ;; An alist of (name . (parse-regex local-time-format-spec)), or (name . nil)
+  ;; for more complicated formats.
+  `((:rfc-3339 . ("(\\d{4})-(\\d{2})-(\\d{2})[ T](\\d{2}):(\\d{2}):(\\d{2})(?:[.]\\d+)?([+-]\\d{2}:\\d{2}|Z)?"
+                  ,local-time:+rfc3339-format+))
+    (:iso-8601 . ("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:,\\d+)?([+-]\\d{2}:\\d{2}|Z)?"
+                  ,local-time:+iso-8601-format+))
+    (:simple   . ("(\\d{4})/(\\d{2})/(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})()"
+                  ((:year 4) #\/ (:month 2) #\/ (:day 2) #\space (:hour 2) #\: (:min 2) #\: (:sec 2))))
+    (:gnuplot           . nil)
+    (:golang            . nil)
+    (:unix-seconds      . nil)
+    (:unix-milliseconds . nil)))
+
+
+;;;; Utilities ----------------------------------------------------------------
+(defmacro match ((register-vars (start end) (regex target)) &body body)
+  (alexandria:with-gensyms (rs re)
+    (alexandria:once-only (regex target)
+      `(multiple-value-bind (,start ,end ,rs ,re) (ppcre:scan ,regex ,target)
+         (when ,start
+           (let (,@(loop :for r :from 0
+                         :for var :in register-vars
+                         :collect `(,var (when (aref ,rs ,r)
+                                           (subseq ,target (aref ,rs ,r) (aref ,re ,r))))))
+             ,@body))))))
+
+(defun i (s)
+  (parse-integer s))
+
+(defun keywordize (s)
+  (alexandria:make-keyword (string-upcase s)))
+
+
+;;;; Time Formats -------------------------------------------------------------
+(defun microseconds->nanoseconds (msec)
+  (* msec 1000))
+
+(defun milliseconds->nanoseconds (msec)
+  (* msec 1000 1000))
+
+
+(defun get-format (format)
+  (or (alexandria:assoc-value *time-formats* format)
+      (error "Unknown time format ~S" format)))
+
+(defun get-regex (format)
+  (first (get-format format)))
+
+(defun get-local-time-format (format)
+  (second (get-format format)))
+
+
+(defun parse-timezone (string)
+  (if (member string '(nil "" "Z" "UTC" "+00:00" "-00:00") :test #'equal)
+    local-time:+utc-zone+
+    (or (local-time:find-timezone-by-location-name string)
+        (error "TODO: handle timezone ~S" string))))
+
+
+(defgeneric make-parser (format)
+  (:documentation "Return a parsing function for the given format."))
+
+(defmethod make-parser (format)
+  (let ((scanner (ppcre:create-scanner (get-regex format))))
+    (lambda (s)
+      (match ((year month day hour minute second timezone)
+              (start end)
+              (scanner s))
+        (values
+          (local-time:encode-timestamp
+            0 (i second) (i minute) (i hour) (i day) (i month) (i year)
+            :timezone (parse-timezone timezone))
+          start end)))))
+
+(defmethod make-parser ((format (eql :golang)))
+  (let ((scanner (ppcre:create-scanner "(\\d{4})/(\\d{2})/(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d{6}))?")))
+    (lambda (s)
+      (match ((year month day hour minute seconds microseconds)
+              (start end)
+              (scanner s))
+        (values (local-time:encode-timestamp
+                  (microseconds->nanoseconds (i microseconds))
+                  (i seconds) (i minute) (i hour) (i day) (i month) (i year))
+                start end)))))
+
+(defmethod make-parser ((format (eql :gnuplot)))
+  (let ((scanner (ppcre:create-scanner "(\\d{2})/(\\d{2})/(\\d{2}),(\\d{2}):(\\d{2})")))
+    (lambda (s)
+      (match ((day month year hour minute)
+              (start end)
+              (scanner s))
+        (values (local-time:encode-timestamp
+                  0 0 (i minute) (i hour) (i day) (i month) (+ 2000 (i year)))
+                start end)))))
+
+(defmethod make-parser ((format (eql :unix-seconds)))
+  (let ((scanner (ppcre:create-scanner "(\\d{13,14})")))
+    (lambda (s)
+      (match ((unix)
+              (start end)
+              (scanner s))
+        (when unix ; shut up sbcl
+          (values (local-time:unix-to-timestamp (i unix)) start end))))))
+
+(defmethod make-parser ((format (eql :unix-milliseconds)))
+  (let ((scanner (ppcre:create-scanner "(\\d{10,11})")))
+    (lambda (s)
+      (match ((unix)
+              (start end)
+              (scanner s))
+        (when unix ; shut up sbcl
+          (multiple-value-bind (sec ms) (truncate (i unix) 1000)
+            (values (local-time:unix-to-timestamp sec :nsec (milliseconds->nanoseconds ms))
+                    start end)))))))
+
+
+(defun make-predicate (format start end)
+  "Return a matching predicate for the user's query.
+
+  This predicate will taka a line and return four values:
+
+  * The timestamp found, if any.
+  * Whether the timestamp is inside the filtering bounds, if any.
+  * The start of the timestamp in the string, if any.
+  * The end of the timestamp in the string, if any.
+
+  "
+  (let ((parser (make-parser format)))
+    (lambda (line)
+      (multiple-value-bind (line-time s e) (funcall parser line)
+        (values line-time
+                (and line-time
+                     (or (null start) (local-time:timestamp<= start line-time))
+                     (or (null end) (local-time:timestamp<= line-time end)))
+                s
+                e)))))
+
+
+(defgeneric make-formatter (format))
+
+(defmethod make-formatter (format)
+  (let ((local-time-format (get-local-time-format format)))
+    (lambda (time stream)
+      (local-time:format-timestring stream time :format local-time-format))))
+
+(defmethod make-formatter ((format (eql :golang)))
+  (lambda (time stream)
+    (local-time:format-timestring
+      stream time
+      :format '((:year 4) #\/ (:month 2) #\/ (:day 2) #\space (:hour 2) #\: (:min 2) #\: (:sec 2)))))
+
+(defmethod make-formatter ((format (eql :gnuplot)))
+  (lambda (time stream)
+    (let* ((f '((:day 2) #\/ (:month 2) #\/ #\Y #\, (:hour 2) #\: (:min 2)))
+           (s (local-time:format-timestring nil time :format f)))
+      ;; "16/07/Y,15:05"
+      (write-string s stream :start 0 :end 6)
+      (format stream "~2,'0D" (mod (local-time:timestamp-year time) 100))
+      (write-string s stream :start 7))))
+
+(defmethod make-formatter ((format (eql :unix-seconds)))
+  (lambda (time stream)
+    (format stream "~D" (local-time:timestamp-to-unix time))))
+
+(defmethod make-formatter ((format (eql :unix-milliseconds)))
+  (lambda (time stream)
+    (format stream "~D" (+ (* 1000 (local-time:timestamp-to-unix time))
+                           (local-time:timestamp-millisecond time)))))
+
+
+(defun parse-time-flexibly (string)
+  ;; todo optimize this
+  (loop :for format :in *time-formats*
+        :for parser = (make-parser (car format))
+        :for result = (funcall parser string)
+        :when result :do (return-from parse-time-flexibly result))
+  (error "Don't know how to parse ~S as a time." string))
+
+
+;;;; Run ----------------------------------------------------------------------
+(defun run% (predicate in out path prefix reformat only)
+  (loop
+    :for line = (read-line in nil)
+    :while line
+    ; todo support multiple timestamps per line
+    :do (multiple-value-bind (time in-bounds start end) (funcall predicate line)
+          (if (null time)
+            (unless only
+              (write-line line out))
+            (when in-bounds
+              (when prefix
+                (write-string path out)
+                (write-char #\: out))
+              (if reformat
+                (progn (write-string line out :start 0 :end start)
+                       (funcall reformat time out)
+                       (write-line line out :start end))
+                (write-line line out)))))))
+
+(defun run (paths &key format start end prefix reformat only)
+  (when (null paths)
+    (setf paths '("-")))
+  (when (and start end (local-time:timestamp< end start))
+    (error "Start ~S is after end ~S." start end))
+  (when reformat
+    (setf reformat (make-formatter reformat)))
+  (let ((pred (make-predicate format start end)))
+    (dolist (path paths)
+      (if (string= "-" path)
+        (run% pred *standard-input* *standard-output* path prefix reformat only)
+        (with-open-file (stream path :direction :input)
+          (run% pred stream *standard-output* path prefix reformat only))))))
+
+
+;;;; User Interface -----------------------------------------------------------
+(defparameter *option-help*
+  (adopt:make-option 'help
+    :help "Display help and exit."
+    :long "help"
+    :short #\h
+    :reduce (constantly t)))
+
+
+(adopt:defparameters (*option-prefix* *option-no-prefix*)
+  (adopt:make-boolean-options 'prefix
+    :help "Prefix output lines with their path."
+    :help-no "Do not prefix output lines with their path (default)."
+    :short #\p
+    :long "prefix"))
+
+
+(adopt:defparameters (*option-only* *option-all*)
+  (adopt:make-boolean-options 'only
+    :help "Only output lines containing a timestamp."
+    :help-no "Output all lines, even those without a timestamp (default)."
+    :short #\o
+    :short-no #\a
+    :long "only"
+    :long-no "all"))
+
+
+(defparameter *option-format*
+  (adopt:make-option 'format
+    :help "The time format used to parse times from lines."
+    :parameter "FORMAT"
+    :long "format"
+    :short #\f
+    :initial-value :simple
+    :key #'keywordize
+    :reduce #'adopt:last))
+
+(defparameter *option-reformat*
+  (adopt:make-option 'reformat
+    :help "Reformat parsed timestamps into FORMAT before outputting them."
+    :parameter "FORMAT"
+    :long "reformat"
+    :short #\r
+    :initial-value nil
+    :key #'keywordize
+    :reduce #'adopt:last))
+
+(defparameter *option-no-reformat*
+  (adopt:make-option 'reformat
+    :help "Do not reformat parsed timestamps (default)."
+    :long "no-reformat"
+    :short #\R
+    :reduce (constantly nil)))
+
+
+(defparameter *option-start*
+  (adopt:make-option 'start
+    :help "Only show lines at or after START."
+    :parameter "START"
+    :long "start"
+    :short #\s
+    :initial-value nil
+    :key #'parse-time-flexibly
+    :reduce #'adopt:last))
+
+(defparameter *option-end*
+  (adopt:make-option 'end
+    :help "Only show lines at or before END."
+    :parameter "END"
+    :long "end"
+    :short #\e
+    :initial-value nil
+    :key #'parse-time-flexibly
+    :reduce #'adopt:last))
+
+
+(adopt:define-string *help-text*
+  "twizzle lets you swizzle timestamps.~@
+   ~@
+   Use --format to select the incoming timestamp format, and --reformat to ~
+   swizzle them into a different format if desired.  Supported formats:~@
+   ~@
+   ~:
+   * simple:   2020/11/23 18:55:30 (default)
+   * rfc-3339: 2020-11-23 18:55:30Z
+   * iso-8601: 2020-11-23T18:55:30Z
+   * gnuplot:  11/23/20,18:55~@
+   ~@
+   You can additionally filter based on a time range using --start and/or --end. ~
+   For convenience, these parameters can be given in any supported timestamp ~
+   format, they don't have to match --format.~@
+   ~@
+   Currently only the first timestamp per line is considered.")
+
+(defparameter *examples*
+  '(("Filter standard input and only print lines with an RFC-3339 time:"
+     . "twizzle --format rfc-3339")
+    ("Print log lines after a particular time, and prefix each output line with its source filename:"
+     . "twizzle **.log --prefix --after '2020/06/14 12:22:01'")
+    ("Print RFC-3339 log lines starting now, with now given in a different format:"
+     . "tail -f foo | twizzle --format rfc-3339 --after \"$(date --utc --iso-8601=sec)\"")))
+
+
+(defparameter *ui*
+  (adopt:make-interface
+    :name "twizzle"
+    :usage "[OPTIONS] [FILE...]"
+    :summary "swizzle timestamps"
+    :help *help-text*
+    :examples *examples*
+    :contents (list *option-help*
+                    (adopt:make-group 'timestamp-formats
+                      :title "Timestamp Formats"
+                      :options (list *option-format*
+                                     *option-reformat*
+                                     *option-no-reformat*))
+                    (adopt:make-group 'output-filtering
+                      :title "Output Control"
+                      :options (list *option-only*
+                                     *option-all*
+                                     *option-start*
+                                     *option-end*
+                                     *option-prefix*
+                                     *option-no-prefix*)))))
+
+
+(defmacro exit-on-error (&body body)
+  `(handler-case (progn ,@body)
+     (error (c) (adopt:print-error-and-exit c))))
+
+(defmacro exit-on-ctrl-c (&body body)
+  `(handler-case
+       (with-user-abort:with-user-abort (progn ,@body))
+     (with-user-abort:user-abort () (adopt:exit 130))))
+
+
+(defun toplevel ()
+  #+sbcl (sb-ext:disable-debugger)
+  (exit-on-error
+    (exit-on-ctrl-c
+      (multiple-value-bind (arguments options) (adopt:parse-options-or-exit *ui*)
+        (cond
+          ((gethash 'help options) (adopt:print-help-and-exit *ui*))
+          (t (progn (local-time:reread-timezone-repository)
+                    (run arguments
+                         :format (gethash 'format options)
+                         :start (gethash 'start options)
+                         :end (gethash 'end options)
+                         :prefix (gethash 'prefix options)
+                         :only (gethash 'only options)
+                         :reformat (gethash 'reformat options)))))))))
+
+
+#; Scratch --------------------------------------------------------------------
+
+(run
+  '("/home/sjl/scratch/logs/logs/prod/saas-warehouse-i-06b0ea6fe4e6dd3fd.log")
+  :format :golang
+  :prefix nil
+  :reformat :rfc-3339)
+
+(parse-time-flexibly "2020-07-15 16:08:15.0000Z")
+
+(local-time:find-timezone-by-location-name "EDT")
+
+(local-time:reread-timezone-repository)
--- a/lisp/weather.lisp	Fri Apr 14 15:01:35 2023 -0400
+++ b/lisp/weather.lisp	Fri Jul 07 16:11:02 2023 -0400
@@ -45,6 +45,10 @@
 
 
 ;;;; OpenWeatherMap -----------------------------------------------------------
+;;; TODO Switch to weather.gov some day to get my taxes' worth, e.g.
+;;; https://forecast.weather.gov/MapClick.php?lat=43.1577&lon=-77.6066&FcstType=digitalDWML
+;;; Sadly this is XML.
+
 (defclass* response ()
   ((hourly :json (vector hour)))
   (:metaclass jarl:json-class))
@@ -175,7 +179,7 @@
             (adopt:print-help-and-exit *ui*)
             (progn
               (load-config)
-              (run (or (first arguments) "14604")
+              (run (or (first arguments) "14607")
                    :hours (gethash 'hours options))))
         (error (e) (adopt:print-error-and-exit e))))))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/when.lisp	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,211 @@
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (ql:quickload '(:adopt :iterate :chronicity :local-time :losh)
+                :silent t))
+
+(defpackage :when
+  (:use :cl :iterate :losh)
+  (:export :toplevel :*ui*))
+
+(in-package :when)
+
+;;;; Configuration ------------------------------------------------------------
+(defparameter +iso-8601-seconds-format+
+  '((:year 4) #\- (:month 2) #\- (:day 2)
+    #\T
+    (:hour 2) #\: (:min 2) #\: (:sec 2)
+    :gmt-offset-or-z))
+
+
+(defparameter *time-formats*
+  `((:rfc-3339 . ,local-time:+rfc3339-format+)
+    (:iso-8601 . ,local-time:+iso-8601-format+)
+    (:iso-8601-seconds . ,+iso-8601-seconds-format+)
+    (:gnuplot . ((:day 2) #\/ (:month 2) #\/ (:year 4) #\, (:hour 2) #\: (:min 2)))))
+
+
+;;;; Errors -------------------------------------------------------------------
+(define-condition user-error (error) ())
+
+(define-condition need-one-time-string (user-error) ()
+  (:report "Exactly one time string is required."))
+
+
+
+;;;; Functionality ------------------------------------------------------------
+(defun jitter-ns (seconds)
+  (if (zerop seconds)
+    0
+    (_ (coerce seconds 'double-float)
+      random
+      (* 1000000000 _)
+      floor)))
+
+(defun run (time-string &key (output-format :iso-8601) (jitter 0) timezone)
+  (local-time:format-timestring
+    *standard-output*
+    (local-time:timestamp+ (chronicity:parse time-string :endian-preference :middle)
+                           (jitter-ns jitter)
+                           :nsec)
+    :format (or (assocdr output-format *time-formats*)
+                (error "Unknown time format ~S." output-format))
+    :timezone (or timezone local-time:*default-timezone*)))
+
+
+;;;; User Interface -----------------------------------------------------------
+(defparameter *examples*
+  '(("Print the current time in RFC 3339 format:" . "when now --rfc-3339")
+    ("Print a randomish time from a while ago:" . "when '12 hours ago' --jitter-hours 4")
+    ("Print a randomish time next year in UTC:" . "when '1 year from now' --jitter-days 30 --utc")))
+
+
+(defparameter *option/help*
+  (adopt:make-option 'help
+    :help "Display help and exit."
+    :long "help"
+    :short #\h
+    :reduce (constantly t)))
+
+
+(defparameter *option/output-format/iso-8601*
+  (adopt:make-option 'output-format/iso-8601
+    :result-key 'output-format
+    :help "Output results as ISO-8601 (default)."
+    :long "iso-8601"
+    :short #\i
+    :initial-value :iso-8601
+    :reduce (constantly :iso-8601)))
+
+(defparameter *option/output-format/iso-8601-seconds*
+  (adopt:make-option 'output-format/iso-8601-seconds
+    :result-key 'output-format
+    :help "Output results as ISO-8601 with a precision of seconds (no nanoseconds)."
+    :long "iso-8601-seconds"
+    :short #\I
+    :reduce (constantly :iso-8601-seconds)))
+
+(defparameter *option/output-format/rfc-3339*
+  (adopt:make-option 'output-format/rfc-3339
+    :result-key 'output-format
+    :help "Output results as RFC 3339."
+    :long "rfc-3339"
+    :short #\r
+    :reduce (constantly :rfc-3339)))
+
+(defparameter *option/output-format/gnuplot*
+  (adopt:make-option 'output-format/gnuplot
+    :result-key 'output-format
+    :help "Output results as Gnuplot timestamps."
+    :long "gnuplot"
+    :short #\g
+    :reduce (constantly :gnuplot)))
+
+
+(defparameter *option/jitter/seconds*
+  (adopt:make-option 'jitter/seconds
+    :result-key 'jitter
+    :parameter "N"
+    :help "Jitter result by up to N seconds."
+    :long "jitter-seconds"
+    :short #\S
+    :initial-value 0
+    :key #'parse-integer
+    :reduce (lambda (old n) (declare (ignore old)) n)))
+
+(defparameter *option/jitter/minutes*
+  (adopt:make-option 'jitter/minutes
+    :result-key 'jitter
+    :parameter "N"
+    :help "Jitter result by up to N minutes."
+    :long "jitter-minutes"
+    :short #\M
+    :key #'parse-integer
+    :reduce (lambda (old n) (declare (ignore old)) (* 60 n))))
+
+(defparameter *option/jitter/hours*
+  (adopt:make-option 'jitter/hours
+    :result-key 'jitter
+    :parameter "N"
+    :help "Jitter result by up to N hours."
+    :long "jitter-hours"
+    :short #\H
+    :key #'parse-integer
+    :reduce (lambda (old n) (declare (ignore old)) (* 60 60 n))))
+
+(defparameter *option/jitter/days*
+  (adopt:make-option 'jitter/days
+    :result-key 'jitter
+    :parameter "N"
+    :help "Jitter result by up to N days."
+    :long "jitter-days"
+    :short #\D
+    :key #'parse-integer
+    :reduce (lambda (old n) (declare (ignore old)) (* 24 60 60 n))))
+
+
+(defparameter *option/timezone/local*
+  (adopt:make-option 'jitter/timezone/local
+    :result-key 'timezone
+    :help "Print result in current local computer timezone (default)."
+    :long "local-timezone"
+    :short #\l
+    :initial-value nil
+    :reduce (constantly nil)))
+
+(defparameter *option/timezone/utc*
+  (adopt:make-option 'jitter/timezone/utc*
+    :result-key 'timezone
+    :help "Print the result in UTC."
+    :long "utc"
+    :short #\u
+    :reduce (constantly local-time:+utc-zone+)))
+
+
+(adopt:define-string *help-text*
+  "when takes a human-readable time like '2 hours ago' and prints it as a ~
+  computer-readable time.  It can also jitter the time by a random amount if ~
+  you want to produce randomish data.")
+
+
+(defparameter *ui*
+  (adopt:make-interface
+    :name "when"
+    :usage "[OPTIONS] TIME-STRING"
+    :summary "convert human time to computer time"
+    :help *help-text*
+    :examples *examples*
+    :contents (list *option/help*
+                    (adopt:make-group
+                      'output-options
+                      :title "Output Options"
+                      :options (list *option/output-format/iso-8601*
+                                     *option/output-format/iso-8601-seconds*
+                                     *option/output-format/rfc-3339*
+                                     *option/output-format/gnuplot*))
+                    (adopt:make-group
+                      'timezone-options
+                      :title "Timezone Options"
+                      :options (list *option/timezone/local*
+                                     *option/timezone/utc*))
+                    (adopt:make-group
+                      'jitter-options
+                      :title "Jitter Options"
+                      :options (list *option/jitter/seconds*
+                                     *option/jitter/minutes*
+                                     *option/jitter/hours*
+                                     *option/jitter/days*)))))
+
+
+(defun toplevel ()
+  (sb-ext:disable-debugger)
+  (setf *random-state* (make-random-state t))
+  (multiple-value-bind (arguments options) (adopt:parse-options-or-exit *ui*)
+    (handler-case
+        (adopt::quit-on-ctrl-c ()
+          (cond
+            ((gethash 'help options) (adopt:print-help-and-exit *ui*))
+            ((/= (length arguments) 1) (error 'need-one-time-string))
+            (t (run (first arguments)
+                    :output-format (gethash 'output-format options)
+                    :jitter (gethash 'jitter options)
+                    :timezone (gethash 'timezone options)))))
+      (user-error (e) (adopt:print-error-and-exit e)))))
--- a/lispwords	Fri Apr 14 15:01:35 2023 -0400
+++ b/lispwords	Fri Jul 07 16:11:02 2023 -0400
@@ -49,12 +49,15 @@
 ; arrows
 (1 -> ->> -<> -<>> _)
 
+; drakma
+(1 http-request)
+
 ; sketch
 (1 with-pen with-font)
 (2 defsketch)
 
 ; sbcl
-(1 with-profiling)
+(1 with-profiling save-lisp-and-die)
 
 ; policy-cond
 (1 policy-if)
@@ -87,8 +90,8 @@
 (1 if-let* if-let)
 (1 gathering-vector)
 (1 multiple-value-bind*)
-(1 do-repeat)
-(1 do-range do-irange)
+(1 do-repeat do-range do-irange do-ring-buffer do-vector do-file do-hash-set)
+(1 timing profile-when)
 
 ; qtools
 (1 qtenumcase)
@@ -122,10 +125,11 @@
 
 ; stumpwm
 (3 defcommand)
+(1 when-let-window)
 
 ; adopt
 (2 define-interface)
-(1 make-option make-boolean-options)
+(1 make-option make-boolean-options make-group)
 (1 quit-on-ctrl-c)
 
 
@@ -139,3 +143,8 @@
 (1 dovec)
 (1 dolist)
 
+; boots
+(1 event-case)
+
+; parsnip
+(1 let!)
--- a/mutt/muttrc	Fri Apr 14 15:01:35 2023 -0400
+++ b/mutt/muttrc	Fri Jul 07 16:11:02 2023 -0400
@@ -25,7 +25,7 @@
 
 source ~/.vim/bundle/badwolf/contrib/badwolf.muttrc
 
-set folder = ~/.mail     # mail location
+set folder = ~/.mail2    # mail location
 
 set wait_key = no        # shut up, mutt
 set mbox_type = Maildir  # mailbox type
@@ -183,8 +183,8 @@
 macro index \Cr "T~U<enter><tag-prefix><clear-flag>N<untag-pattern>.<enter>" "mark all messages as read"
 
 # Sync email
-macro index O "<shell-escape>offlineimap<enter>"           "run offlineimap to sync all mail"
-macro index o "<shell-escape>offlineimap -qf INBOX<enter>" "run offlineimap to sync inbox"
+macro index O "<sync-mailbox><shell-escape>mbsync --all<enter><sync-mailbox>"      "run mbsync to sync all mail"
+macro index o "<sync-mailbox><shell-escape>mbsync mail-inbox<enter><sync-mailbox>" "run mbsync to sync inbox"
 
 # Saner copy/move dialogs
 macro index C "<copy-message>?<toggle-mailboxes>" "copy a message to a mailbox"
@@ -226,7 +226,7 @@
 bind compose p postpone-message
 bind compose P pgp-menu
 
-macro compose H "| htmlify-email<enter><attach-file>~/.mutt/temp/neomutt-alternative.html<enter><tag-entry><previous-entry><tag-entry><group-alternatives>"
+macro compose H "| htmlify-email<enter><attach-file>~/.mutt/temp/neomutt-alternative.html<enter><tag-entry><previous-entry><tag-entry><toggle-disposition><group-alternatives>"
 
 # }}}
 # Attachment {{{
--- a/mutt/view_attachment.sh	Fri Apr 14 15:01:35 2023 -0400
+++ b/mutt/view_attachment.sh	Fri Jul 07 16:11:02 2023 -0400
@@ -57,7 +57,7 @@
 #
 
 # the tmp directory to use.
-tmpdir="$HOME/.tmp/mutt_attach"
+tmpdir="$HOME/scratch/mutt_attach"
 
 # the name of the debug file if debugging is turned on.
 debug_file=$tmpdir/debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdu-excludes	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,2 @@
+/cryo
+/dump
--- a/psqlrc	Fri Apr 14 15:01:35 2023 -0400
+++ b/psqlrc	Fri Jul 07 16:11:02 2023 -0400
@@ -5,8 +5,11 @@
 \pset pager on
 \pset null '∅'
 
+
 \set PROMPT1 '%[%033[1;34m%]%M:%> %n@%/%R%#%x%[%033[0m%] '
 \timing
 
 \setenv PAGER less
 \setenv LESS -iS
+
+set time zone 'etc/UTC';
--- a/remote/bash_profile	Fri Apr 14 15:01:35 2023 -0400
+++ b/remote/bash_profile	Fri Jul 07 16:11:02 2023 -0400
@@ -1,1 +1,103 @@
-../bash_profile
\ No newline at end of file
+#!/usr/bin/env bash
+
+# Similar to my normal bash_profile, but stripped down for running on servers.
+
+if test -e /etc/profile; then
+    source /etc/profile
+fi
+
+shopt -s expand_aliases
+shopt -s histappend
+
+# Save multiline commands as a single history entry.
+shopt -s cmdhist
+
+HISTFILESIZE=100000
+HISTSIZE=100000
+HISTCONTROL=ignoreboth
+
+# Flush commands to history immediately instead of waiting for logout.
+PROMPT_COMMAND='history -a'
+
+if test -e ~/.dircolors; then
+    eval "$(dircolors -b ~/.dircolors)"
+fi
+
+D=$'\e[37m'
+RED=$'\e[31m'
+GREEN=$'\e[32m'
+ORANGE=$'\e[33m'
+BLUE=$'\e[34m'
+PINK=$'\e[35m'
+# CYAN=$'\e[36m'
+
+function last_return_value() {
+    x="$?"
+    if test "$x" -ne 0; then
+        echo -n "${RED}[$x] ${D}"
+    fi
+}
+
+function histgrep {
+    history | grep "$@" | tac | f 2-
+}
+
+if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
+  HOST_COLOR="$BLUE"
+else
+  HOST_COLOR="$ORANGE"
+fi
+
+export PS1='\n${PINK}\u ${D}at ${HOST_COLOR}\h ${D}in ${GREEN}\w${D} $(last_return_value)$ '
+
+alias ..="cd .."
+alias ...="cd ../.."
+alias ....="cd ../../.."
+alias .....="cd ../../../.."
+alias ......="cd ../../../../.."
+
+alias js='cd ~/scratch'
+
+alias :q=exit
+alias :qa=exit
+alias :wqa=exit
+
+if command -v ag >/dev/null; then
+    AG_BIN="$(command -v ag)"
+    function ag() {
+        if test -f '.agignore' && grep -q 'pragma: skipvcs' '.agignore'; then
+            $AG_BIN --search-files -U "$@"
+        else
+            $AG_BIN --search-files "$@"
+        fi
+    }
+fi
+
+function prepend_to_path {
+    if test -d "$1"; then
+        PATH="$1":"$PATH"
+    fi
+}
+
+prepend_to_path "$HOME/src/dotfiles/lisp/bin"
+prepend_to_path "$HOME/src/dotfiles/bin"
+prepend_to_path "$HOME/bin"
+export PATH
+
+export LESS_TERMCAP_mb=$(printf '\e[01;31m')       # begin blinking
+export LESS_TERMCAP_md=$(printf '\e[01;38;5;74m')  # begin bold
+export LESS_TERMCAP_me=$(printf '\e[0m')           # end mode
+export LESS_TERMCAP_se=$(printf '\e[0m')           # end standout-mode
+export LESS_TERMCAP_so=$(printf '\e[38;5;246m')    # begin standout-mode - info box
+export LESS_TERMCAP_ue=$(printf '\e[0m')           # end underline
+export LESS_TERMCAP_us=$(printf '\e[04;38;5;146m') # begin underline
+export PAGER='less -iX'
+
+function psg() {
+    ps auxww | grep --color=always "$@" | grep -v grep | collapse | cuts -f 2,11-
+}
+
+GPG_TTY=$(tty)
+export GPG_TTY
+
+export EDITOR=vim
--- a/remote/bootstrap.sh	Fri Apr 14 15:01:35 2023 -0400
+++ b/remote/bootstrap.sh	Fri Jul 07 16:11:02 2023 -0400
@@ -9,8 +9,7 @@
         # Already linked.
         true
     elif test -e "$dst"; then
-        echo File "$dst" already exists and is not a symbolic link.
-        exit 1
+        echo File "$dst" already exists, skipping.
     elif test ! -e "$src"; then
         echo File "$src" does not exist.
         exit 1
@@ -30,5 +29,4 @@
 ensure_link "src/dotfiles/dircolors"     ".dircolors"
 ensure_link "src/dotfiles/ffignore"      ".ffignore"
 ensure_link "src/dotfiles/config.fish"   ".config/fish/config.fish"
-ensure_link "src/dotfiles/tmux.conf"     ".tmux.conf"
 ensure_link "src/dotfiles/hushlogin"     ".hushlogin"
--- a/remote/tmux.conf	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-../tmux/tmux.conf
\ No newline at end of file
--- a/restic/excludes.txt	Fri Apr 14 15:01:35 2023 -0400
+++ b/restic/excludes.txt	Fri Jul 07 16:11:02 2023 -0400
@@ -23,6 +23,7 @@
 /home/sjl/.slime
 /home/sjl/.steam
 /home/sjl/.virtualenvs
+/home/sjl/.xsession-errors
 /home/sjl/Dropbox/.dropbox.cache
 /home/sjl/Pictures
 /home/sjl/Videos
@@ -33,4 +34,6 @@
 /home/sjl/src/dotfiles/vim/tmp
 /home/sjl/Pictures/Webcam
 /home/sjl/Pictures/darktable_export
+/home/sjl/bin/tetrio-desktop
+/home/sjl/.config/tetrio-desktop
 cache2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stumpwm/local-share-stumpwm/thirds.dump	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,7 @@
+#S(GDUMP
+   :NUMBER 1
+   :NAME "Default"
+   :TREE ((#S(FDUMP  :NUMBER 0 :X 0    :Y 0 :WIDTH 1200 :HEIGHT 1440 :WINDOWS NIL :CURRENT NIL)
+           (#S(FDUMP :NUMBER 1 :X 1200 :Y 0 :WIDTH 2720 :HEIGHT 1440 :WINDOWS NIL :CURRENT NIL)
+            #S(FDUMP :NUMBER 2 :X 3920 :Y 0 :WIDTH 1200 :HEIGHT 1440 :WINDOWS NIL :CURRENT NIL))))
+   :CURRENT 1)
--- a/stumpwm/local-share-stumpwm/work.dump	Fri Apr 14 15:01:35 2023 -0400
+++ b/stumpwm/local-share-stumpwm/work.dump	Fri Jul 07 16:11:02 2023 -0400
@@ -1,44 +1,9 @@
 #S(GDUMP
-   :NUMBER 1
-   :NAME "Default"
-   :TREE ((#S(FDUMP
-              :NUMBER 0
-              :X 0
-              :Y 0
-              :WIDTH 1920
-              :HEIGHT 2160
-              :WINDOWS (41943045 39845893 54525957 16777221)
-              :CURRENT 41943045)
-           #S(FDUMP
-              :NUMBER 4
-              :X 1920
-              :Y 0
-              :WIDTH 1920
-              :HEIGHT 2160
-              :WINDOWS (44040195 77594629)
-              :CURRENT 44040195))
-          (#S(FDUMP
-              :NUMBER 1
-              :X 3840
-              :Y 0
-              :WIDTH 960
-              :HEIGHT 1080
-              :WINDOWS (23068677)
-              :CURRENT 23068677)
-           (#S(FDUMP
-               :NUMBER 2
-               :X 4800
-               :Y 0
-               :WIDTH 960
-               :HEIGHT 465
-               :WINDOWS (35651589)
-               :CURRENT 35651589)
-            #S(FDUMP
-               :NUMBER 3
-               :X 4800
-               :Y 465
-               :WIDTH 960
-               :HEIGHT 615
-               :WINDOWS (27262977)
-               :CURRENT 27262977))))
-   :CURRENT 4)
+        :NUMBER 1
+        :NAME "Default"
+        :TREE ((#S(FDUMP :NUMBER 0 :X 0 :Y 0 :WIDTH 1920 :HEIGHT 2160 :WINDOWS (41943045 39845893 54525957 16777221) :CURRENT 41943045)
+                #S(FDUMP :NUMBER 4 :X 1920 :Y 0 :WIDTH 1920 :HEIGHT 2160 :WINDOWS (44040195 77594629) :CURRENT 44040195))
+               (#S(FDUMP :NUMBER 1 :X 3840 :Y 0 :WIDTH 960 :HEIGHT 1080 :WINDOWS (23068677) :CURRENT 23068677)
+                (#S(FDUMP :NUMBER 2 :X 4800 :Y 0 :WIDTH 960 :HEIGHT 465 :WINDOWS (35651589) :CURRENT 35651589)
+                 #S(FDUMP :NUMBER 3 :X 4800 :Y 465 :WIDTH 960 :HEIGHT 615 :WINDOWS (27262977) :CURRENT 27262977))))
+        :CURRENT 4)
--- a/stumpwmrc	Fri Apr 14 15:01:35 2023 -0400
+++ b/stumpwmrc	Fri Jul 07 16:11:02 2023 -0400
@@ -1,13 +1,16 @@
 (in-package :stumpwm-user)
+(shadow :window)
 
-(ql:quickload '(:losh :split-sequence :alexandria :parse-number :str :cl-ppcre :bordeaux-threads) :silent t)
+(ql:quickload '(:losh :split-sequence :alexandria :parse-number :str :cl-ppcre :bordeaux-threads :jarl :local-time)
+              :silent t)
+
 (use-package :losh)
 
-
 ;;;; Config -------------------------------------------------------------------
 (set-prefix-key (kbd "C-space"))
+(local-time:reread-timezone-repository)
 
-(redirect-all-output (data-dir-file "debug" "log"))
+(defvar *redirected* (redirect-all-output (data-dir-file "debug" "log")))
 
 (setf *mouse-focus-policy* :click
       *message-window-gravity* :center
@@ -28,47 +31,47 @@
   (and (search needle string :test #'char=) t))
 
 (defun string-grep (needle text &key first-only)
-  (-<> text
-    (split-sequence:split-sequence #\newline <>)
+  (_ text
+    (split-sequence:split-sequence #\newline _)
     (if first-only
-      (find needle <> :test #'string-contains)
-      (remove-if-not (alexandria:curry #'string-contains needle) <>))))
+      (find needle _ :test #'string-contains)
+      (remove-if-not (alexandria:curry #'string-contains needle) _))))
 
 (defun string-split (delimiters string)
   (split-sequence:split-sequence delimiters string
                                  :test (lambda (bag ch)
                                          (find ch bag :test #'char=))))
 
+(defun run-and-echo-shell-command (command &rest args)
+  (message command)
+  (apply #'run-shell-command command args))
+
 
 (defun mod+ (n increment modulo)
   (mod (+ n increment) modulo))
 
 
 (defun volume ()
-  (-<> (run-shell-command "amixer sget Master" t)
-    (string-grep "Front Left:" <> :first-only t)
-    (string-split "[]" <>)
+  (_ (run-shell-command "amixer sget Master" t)
+    (string-grep "Front Left:" _ :first-only t)
+    (string-split "[]" _)
     second
-    (string-trim "%" <>)
+    (string-trim "%" _)
     parse-integer))
 
-(defun battery ()
-  (run-shell-command
-    "acpi -b | tail -n1 | awk -F '[ ,]' '{printf \"%s%s\", $3, $5}' | sed s/Discharging// | sed s/Unknown// | sed s/Full// | sed s/Charging/+/"
-    t))
-
 
 (defun current-frame ()
   (stumpwm::tile-group-current-frame (current-group)))
 
 
 (defun keywordize (string)
-  (-<> string
-    (string-trim (string #\newline) <>)
+  (_ string
+    (string-trim (string #\newline) _)
     string-upcase
-    (intern <> (find-package :keyword))))
+    (intern _ (find-package :keyword))))
 
-(defparameter *host* (keywordize (run-shell-command "hostname" t)))
+(defparameter *host* (keywordize (machine-instance)))
+
 
 (defmacro ehostcase (&body clauses)
   `(ecase *host* ,@clauses))
@@ -144,6 +147,10 @@
   "Find and return a fresh list of all windows that match `query` under `window-match-p`."
   (remove-if-not (lambda (w) (window-match-p query w)) (all-windows)))
 
+(defmacro when-let-window ((symbol title-query) &body body)
+  `(when-let ((,symbol (find-window `(:title ,(ppcre:create-scanner ,title-query)))))
+     ,@body))
+
 
 ;;;; Posture ------------------------------------------------------------------
 (defparameter *posture-thread* nil)
@@ -229,6 +236,57 @@
             :name "Posture thread"))))
 
 
+;;;; Budget ------------------------------------------------------------------
+(defparameter *tz/eastern*
+  (local-time:find-timezone-by-location-name "US/Eastern"))
+
+(defparameter *budget/start*
+  (local-time:encode-timestamp 0 0 0 0 21 5 2023 :timezone *tz/eastern*))
+
+(defun budget/per-day ()
+  (first (losh:read-all-from-file "/home/sjl/Dropbox/budget/per-day")))
+
+(defun budget/elapsed ()
+  (local-time:timestamp-difference (local-time:now) *budget/start*))
+
+(defun budget/days-elapsed ()
+  (floor (/ (budget/elapsed) (* 60 60 24))))
+
+(defun budget/in ()
+  (* (budget/days-elapsed) (budget/per-day)))
+
+(defun budget/out ()
+  (loop :for path :in (directory "/home/sjl/Dropbox/budget/hosts/*/total")
+        :summing (print (first (read-all-from-file (print path))))))
+
+(defun budget/current ()
+  (- (budget/in) (budget/out)))
+
+(defcommand budget-dump () ()
+  (message
+    (sh '("sh" "-c" "tail -n 5 /home/sjl/Dropbox/budget/hosts/*/records")
+        :result-type 'string)))
+
+(defcommand budget () ()
+  (message "$~D" (budget/current)))
+
+(defmacro with-budget-file ((f file &rest open-args) &body body)
+  `(with-open-file
+     (,f (format nil "/home/sjl/Dropbox/budget/hosts/~(~A~)/~A" *host* ,file)
+      ,@open-args)
+     ,@body))
+
+(defcommand spend (amount what) ((:integer "Amount: $") (:string "For: "))
+  (let ((current (with-budget-file (total "total")
+                   (first (read-all-from-file total))))
+        (timestamp (local-time:to-rfc3339-timestring (local-time:now))))
+    (with-budget-file (total "total" :direction :output :if-exists :supersede)
+      (print (+ current amount) total))
+    (with-budget-file (records "records" :direction :output :if-exists :append :if-does-not-exist :create)
+      (print (list timestamp amount what) records))
+    (message "Spent $~D for ~A at ~A" amount what timestamp)))
+
+
 ;;;; Load ---------------------------------------------------------------------
 (load-module "pass")
 
@@ -251,10 +309,13 @@
   (aref *brightness-values* *brightness-index*))
 
 (defun set-brightness (value)
-  (run-shell-command
+  (run-and-echo-shell-command
     (hostcase
-      ((:mobius :alephnull) (format nil "xbacklight -set ~D" value))
-      ((:papyrifera) (format nil "xrandr --output eDP --brightness ~D" (/ value 100.0)))
+      ((:mobius) (format nil "xbacklight -set ~D" value))
+      ((:papyrifera :alephnull) (format nil "xrandr --output ~A --brightness ~D"
+                                        (hostcase (:papyrifera "eDP")
+                                                  (:alephnull "eDP-1"))
+                                        (/ value 100.0)))
       (t (message "Not sure how to set brightness on this machine.")))))
 
 (defun rotate-brightness (delta)
@@ -262,6 +323,7 @@
         (mod+ *brightness-index* delta (length *brightness-values*)))
   (set-brightness (brightness)))
 
+
 (defcommand rotate-brightness-up () ()
   (rotate-brightness 1))
 
@@ -311,8 +373,8 @@
 
 (defcommand screen-laptop () ()
   (only)
-  (loop :with laptop = "eDP1"
-        :with extern = "DP1"
+  (loop :with laptop = "eDP-1"
+        :with extern = "DP-1"
         :for (output commands) :in `((,laptop ("--auto"))
                                    (,laptop ("--primary"))
                                    (,extern ("--off")))
@@ -320,14 +382,14 @@
 
 (defcommand screen-external () ()
   (only)
-  (loop :with laptop = "eDP1"
-        :with extern = "DP1"
+  (loop :with laptop = "eDP-1"
+        :with extern = "DP-1"
         :for (output commands) :in `(
-                                     (,laptop ("--off"))
+                                     ;; (,laptop ("--off"))
                                      (,extern ("--auto"))
                                      (,extern ("--primary"))
-                                     ;; (,laptop ("--auto"))
-                                     ;; (,laptop ("--right-of" ,extern))
+                                     (,laptop ("--auto"))
+                                     (,laptop ("--left-of" ,extern))
                                      )
         :do (uiop:run-program `("xrandr" "--output" ,output ,@commands))))
 
@@ -369,7 +431,7 @@
     ((:alephnull :mobius :papyrifera)
      (run-shell-command "exec lock-screen")
      (run-shell-command "systemctl suspend"))
-    (t (message "Not sleeping this machine for safety.."))))
+    (t (message "Not sleeping this machine for safety."))))
 
 (defcommand copy-clhs-url (s)
     ((:string "Symbol: "))
@@ -378,25 +440,30 @@
 (defcommand describe-window () ()
   (show-window-properties))
 
-(defcommand unfuck-zoom-link () ()
-  (let ((url (pbpaste)))
-    (ppcre:register-groups-bind
-        (meeting-id meeting-pass)
-        ("^https://[a-zA-Z0-9]+[.]zoom[.]us/j/(\\d+)[?]pwd=([A-Za-z0-9]+)$" url)
-      (pbcopy meeting-id)
-      (message "Zoom meeting ID copied.")
-      (bt:make-thread (lambda ()
-                        (sleep 3)
-                        (pbcopy meeting-pass)
-                        (message "Zoom meeting password copied.")
-                        (sleep 5)
-                        (pbcopy ""))
-                      :name "Zoom Link Defuckulator")
-      (return-from unfuck-zoom-link))
-    (message "Clipboard doesn't seem to be a Zoom link.")))
+(defcommand rain () ()
+  (_ '("/home/sjl/src/dotfiles/lisp/bin/weather" "-H" "36")
+    (losh:sh _ :result-type 'list)
+    (mapcar (lambda (line) (ppcre:regex-replace " 1[0-9]:00 " line "^6\\&^*")) _)
+    (message "~{~A~^~%~}" _)))
+
+(defcommand mark (thing) ((:string "Mark: "))
+  (run-shell-command (format nil "mark ~A" thing)))
 
-(defcommand rain () ()
-  (message (run-shell-command "weather -H 36" t)))
+(defcommand toggle-zoom-mute () ()
+  (when-let-window (win "^Zoom Meeting.*")
+    ;; Zoom stupidly won't accept the shortcut unless it's in focus
+    (unless (eql (window-group win) (current-group))
+      ;;        jesus            christ        stump just export switch-to-group come on
+      (gselect (princ-to-string (group-number (window-group win)))))
+    (focus-window win t)
+    (meta (kbd "M-a"))))
+
+(defcommand end-zoom () ()
+  (when-let-window (win "^Zoom Meeting.*")
+    (kill-window win))
+  (sleep 2)
+  (when-let-window (win "^Zoom -.*")
+    (kill-window win)))
 
 
 ;;;; Terminal Fonts -----------------------------------------------------------
@@ -408,8 +475,8 @@
             (read f))
           11)))
 
-(defparameter *terminal-font-size* (if (probe-file "~/.terminal-font")
-                                     (with-open-file (f "~/.terminal-font")
+(defparameter *terminal-font-size* (if (probe-file "/home/sjl/.terminal-font")
+                                     (with-open-file (f "/home/sjl/.terminal-font")
                                        (read f))
                                      11))
 
@@ -427,6 +494,9 @@
 
 
 ;;;; Clipboard/Data Generation ------------------------------------------------
+(load-module "clipboard-history")
+(clipboard-history:start-clipboard-manager)
+
 (defcommand generate-random-uuid () ()
   (run-shell-command "uuidgen | tr -d '\\n' | ~/src/dotfiles/bin/pbcopy")
   (message "Copied random UUID to clipboard."))
@@ -453,7 +523,7 @@
   (run-shell-command "open $HOME"))
 
 (defcommand browser () ()
-  (run-or-raise "firefox" '(:class "Firefox")))
+  (run-or-raise "firefox" '(:class "firefox")))
 
 (defcommand vlc () ()
   (run-or-raise "vlc" '(:class "vlc")))
@@ -465,8 +535,8 @@
   (run-or-raise "gcontrol" '(:class "Gnome-control-center")))
 
 (defcommand zoom () ()
-  (when-let ((window (find-window `(:title ,(ppcre:create-scanner "^Zoom Meeting.*")))))
-    (focus-window window t)))
+  (when-let-window (w "^Zoom Meeting.*")
+    (focus-window w t)))
 
 
 ;;;; Timers -------------------------------------------------------------------
@@ -507,6 +577,65 @@
   (run-shell-command (format nil "tea ~D" seconds)))
 
 
+;;;; Isk ----------------------------------------------------------------------
+(defcommand send-key (key &optional (win (current-window))) (:key)
+  "Send key press and key release events for KEY to window WIN."
+  ;; from https://github.com/alezost/stumpwm-config/blob/master/utils.lisp
+  (let ((xwin (window-xwin win)))
+    (multiple-value-bind (code state) (stumpwm::key-to-keycode+state key)
+      (flet ((send (event)
+               (xlib:send-event xwin event (xlib:make-event-mask event)
+                                :display *display*
+                                :root (screen-root (window-screen win))
+                                :x 0 :y 0 :root-x 0 :root-y 0
+                                :window xwin :event-window xwin
+                                :code code
+                                :state state)))
+        (send :key-press)
+        (send :key-release)
+        (xlib:display-finish-output *display*)))))
+
+(defun send-keys (keys &key (win (current-window)) (sleep 0))
+  (dolist (k keys)
+    (send-key (kbd k) win)
+    (sleep sleep)))
+
+(defmacro defmultikey (name key compose-keys)
+  ;; Unfortunately we can't reliably autogen the name with something like
+  ;; (symb 'mk- compose-key) here because things like đ (th) and Đ (TH) would
+  ;; case fold to the same name.
+  `(progn
+     (defcommand ,name () ()
+       (send-keys '("Multi_key" ,@(map 'list #'string compose-keys))))
+     (define-key *top-map*
+       (kbd ,key) ,(string name))))
+
+(defmacro defmultikeys (&rest bindings)
+  `(progn ,@(loop for binding :in bindings :collect `(defmultikey ,@binding))))
+
+(defmultikeys
+  (isk-l-á "M-a" "'a")
+  (isk-u-Á "M-A" "'A")
+  (isk-l-é "M-e" "'e")
+  (isk-u-É "M-E" "'E")
+  (isk-l-í "M-i" "'i")
+  (isk-u-Í "M-I" "'I")
+  (isk-l-ó "M-o" "'o")
+  (isk-u-Ó "M-O" "'O")
+  (isk-l-ö "M-m" "\"o")
+  (isk-u-Ö "M-M" "\"O")
+  (isk-l-ú "M-u" "'u")
+  (isk-u-Ú "M-U" "'U")
+  (isk-l-ý "M-y" "'y")
+  (isk-u-Ý "M-Y" "'Y")
+  (isk-l-þ "M-t" "th")
+  (isk-u-Þ "M-T" "TH")
+  (isk-l-đ "M-d" "dh")
+  (isk-u-Đ "M-D" "DH")
+  (isk-l-æ "M-h" "ae")
+  (isk-u-Æ "M-H" "AE"))
+
+
 ;;;; Key Mapping --------------------------------------------------------------
 ;;; Conventions:
 ;;;
@@ -527,16 +656,20 @@
 
 (define-top-keys ;; miscellaneous
   ("H-m" "terminal")
+  ("H-M" "mark")
   ("H-SunPageUp" "st-font-up")
   ("H-SunPageDown" "st-font-down")
   ("H-Home" "st-font-reset")
   ("H-\\" "pass-personal")
   ("H-|" "generate-password")
   ("H-b" "browser")
-  ("H-B" "exec firefox")
   ("H-O" "spotify")
   ("H-o" "files")
   ("H-z" "zoom")
+  ("H-Z" "toggle-zoom-mute")
+  ("C-H-Z" "end-zoom")
+  ("F26"   "prev")
+  ("S-F26" "next")
   ("H-q" "exec lock-screen")
   ("H-y" "screenshot")
   ("H-g" "gcontrol")
@@ -544,13 +677,17 @@
   ("H-F" "delete-fucked-screenshot")
   ("H-R" "loadrc")
   ("H-r" "rain")
-  ("H-V" "vlc"))
+  ("H-V" "vlc")
+  ("H-4" "budget")
+  ("H-$" "spend")
+  )
 
 (define-top-keys ;; clipboard
+  ("H-c" "show-clipboard-history")
+  ("H-C" "clear-clipboard-history")
   ("H-u" "generate-random-uuid")
-  ("H-U" "bee-movie-script")
-  ("M-H-u" "urlize-jira-issue")
-  ("H-Z" "unfuck-zoom-link"))
+  ("H-B" "bee-movie-script")
+  ("M-H-u" "urlize-jira-issue"))
 
 (define-top-keys ;; movement
   ("H-h" "move-focus* left")
@@ -563,12 +700,13 @@
   ("H-K" "move-window up")
   ("H-L" "move-window right")
 
-  ("H-1" "gmove 1")
-  ("H-2" "gmove 2")
-  ("H-3" "gmove 3")
-  ("H-4" "gmove 4")
-  ("H-5" "gmove 5")
-  ("H-6" "gmove 6")
+  ("H-1" "gselect 1")
+  ("H-2" "gselect 2")
+  ("H-3" "gselect 3")
+
+  ("H-!" "gmove 1")
+  ("H-@" "gmove 2")
+  ("H-#" "gmove 3")
 
   ("C-H-H" "exchange-direction left")
   ("C-H-J" "exchange-direction down")
@@ -608,6 +746,7 @@
   ("H-F8" "screen-external"))
 
 (define-top-keys ;; layout
+  ("s-H-t" "restore-from-file thirds")
   ("s-H-m" "restore-from-file dev")
   ("s-H-s" "restore-from-file streaming")
   ("s-H-w" "restore-from-file work")
@@ -627,7 +766,7 @@
 
 (define-top-keys ;; stump
   ("Pause" "terminal") ; jesus christ
-  ("H-F9" "sleep-machine")
+  ("H-F9"  "sleep-machine")
   ("H-F10" "toggle-stumptray")
   ("H-F11" "toggle-current-mode-line")
   ("H-F12" "refresh-heads"))
@@ -641,7 +780,7 @@
      ("C-=" . "S-C-SunPageUp")
      ("C--" . "S-C-SunPageDown")
      ("C-0" . "S-C-Home"))
-    ("(Firefox|Google-chrome|Chromium-browser)"
+    ("(firefox|Google-chrome|Chromium-browser)"
      ("s-1" . "C-S-Tab")
      ("s-2" . "C-Tab")
      ("C-a" . "Home")
@@ -651,7 +790,6 @@
      ;; interest of not having a random collection of bookmarks grow over time,
      ;; I'll just add a mapping to compensate for my stupid brain.
      ("C-d" . "C-w")
-     ("C-w" . "C-BackSpace")
      ;; todo debug why this breaks a really fast C-a-k roll
      ;; ("C-a" . "Home")
      ;; ("C-e" . "End")
@@ -673,36 +811,101 @@
      ("s-v" . "C-v"))))
 
 
+;;;; Sensors ------------------------------------------------------------------
+(defun ? (obj &rest keys)
+  (if (null keys)
+      obj
+      (apply #'? (etypecase obj
+                   (hash-table (gethash (first keys) obj)))
+             (rest keys))))
+
+(defun parse-sensors ()
+  ;; sensors -j is stupid and will output errors before the actual output on
+  ;; standard out, instead of putting them on standard err like a reasonable
+  ;; program, e.g.:
+  ;;
+  ;;     ERROR: Can't get value of subfeature temp1_input: Can't read
+  ;;     {
+  ;;        "iwlwifi_1-virtual-0":{ … },
+  ;;        …
+  ;;
+  ;; So we'll have to drop the `ERROR` lines before we can get to the actual
+  ;; goddamn JSON.  UNIX programs are so great.
+  (let ((s (losh:sh '("sensors" "-j") :result-type 'stream)))
+    (loop :while (char= #\E (peek-char nil s)) :do (read-line s))
+    (jarl:read t s)))
+
+(defparameter *sensors-refresh-delay* 5.0 "How long between sensor refreshes (in seconds).")
+(defparameter *sensors-next-refresh* nil)
+(defparameter *sensors-cache* nil)
+
+(defun sensors% (&aux (sensors (parse-sensors)))
+  (hostcase
+    (:ouroboros (format nil "[CPU ~D°C] [GPU ~D°C ~D°C ~D°C]"
+                        (round (? sensors "nct6779-isa-0290" "CPUTIN" "temp2_input"))
+                        (round (? sensors "amdgpu-pci-4500"  "edge"     "temp1_input"))
+                        (round (? sensors "amdgpu-pci-4500"  "junction" "temp2_input"))
+                        (round (? sensors "amdgpu-pci-4500"  "mem"      "temp3_input"))))
+    (t "?")))
+
+(defun sensors (&aux (now (get-internal-real-time)))
+  (if (or (null *sensors-next-refresh*)
+          (>= now *sensors-next-refresh*))
+      (setf *sensors-next-refresh* (+ now (* internal-time-units-per-second *sensors-refresh-delay*))
+            *sensors-cache* (sensors%))
+      *sensors-cache*))
+
+(defun sensors-modeline (ml)
+  (declare (ignore ml))
+  (sensors))
+
+(add-screen-mode-line-formatter #\S #'sensors-modeline)
+
+
 ;;;; Modeline -----------------------------------------------------------------
+(load-module "battery-portable")
+(load-module "cpu")
+(load-module "hostname")
+(load-module "mem")
+
 (defun ensure-mode-line ()
   (when (not (stumpwm::head-mode-line (current-head)))
     (toggle-mode-line (current-screen) (current-head))))
 
+
 (defun configure-modeline ()
   (setf
     *time-modeline-string*
     "%a %b %e %H:%M"
 
+    cpu::*cpu-usage-modeline-fmt*
+    "^[~A~3D%^]"
+
+    cpu::*cpu-modeline-fmt*
+    "[%c] [%f]"
+
+    mem::*mem-modeline-fmt*
+    "%b"
+
     *screen-mode-line-format*
     (append
-      (list "[^B%n^b] %W^>")
+      (list "[^B%n^b@%h] %W^>")
 
       #+todo-some-day (list ;; "(V "
                             ;; ;; '(:eval (volume))
                             ;; ")"
                             " ")
 
+      ;; battery and brightness for laptops
       (hostcase
         ((:mobius :alephnull :papyrifera)
-         '("(B "
-           (:eval (princ-to-string (battery)))
-           ")"
+         '("(B %B)"
            " (BR "
            (:eval (princ-to-string (brightness)))
            "%)")))
 
-      ;; time and tray
-      (list " %d %T")))
+      ;; temp, cpu, mem, time, tray
+      (list "(TEMP %S) (CPU %C) (MEM %M) %d %T")))
 
   (setf *mode-line-timeout* 10)
   (setf *mode-line-background-color* "#111111")
@@ -724,15 +927,14 @@
 
 
 ;;;; Startup ------------------------------------------------------------------
-;; (defvar *network-manager*
-  ;; (run-shell-command "nm-applet --sm-disable"))
-
 ;; (defvar *dropbox*
   ;; (run-shell-command "~/.dropbox-dist/dropboxd"))
 
 (defvar *dunst*
   (run-shell-command "/usr/bin/dunst -conf ~/.dunstrc"))
 
+(when (probe-file "/home/sjl/.stumpwmrc.local")
+  (load "/home/sjl/.stumpwmrc.local"))
+
+
 #;;; Scratch ------------------------------------------------------------------
-(message (format nil "~S" (remove #\newline (run-shell-command "acpi" t))))
-
--- a/tmux/tmux.conf	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-# Use something easier to type as the prefix.
-set -g prefix C-f
-unbind C-b
-bind C-f send-prefix
-
-# Relax!
-set -sg escape-time 0
-set -sg repeat-time 600
-
-# Shut up.
-#set -g quiet on
-
-# Focus
-set -g focus-events
-
-# Mouse
-set -g mouse on
-
-# Less stretching to get to the first item.
-set -g base-index 1
-setw -g pane-base-index 1
-
-# Reload the config.
-bind R source-file ~/.tmux.conf \; display "Reloaded ~/.tmux.conf"
-
-# Rename session.
-bind r command-prompt -I "#S" "rename-session '%%'"
-
-# Saner splitting.
-bind v split-window -h -c '#{pane_current_path}'
-bind s split-window -v -c '#{pane_current_path}'
-bind S choose-session
-
-# Pane movement
-bind h select-pane -L
-bind j select-pane -D
-bind k select-pane -U
-bind l select-pane -R
-
-# DVTM style pane selection
-# bind 1 select-pane -t 1
-# bind 2 select-pane -t 2
-# bind 3 select-pane -t 3
-# bind 4 select-pane -t 4
-# bind 5 select-pane -t 5
-# bind 6 select-pane -t 6
-# bind 7 select-pane -t 7
-# bind 8 select-pane -t 8
-# bind 9 select-pane -t 9
-
-# Layouts
-# set -g main-pane-width 260
-# bind M select-layout main-vertical
-# bind E select-layout even-horizontal
-
-# Pane resizing
-bind -r C-h resize-pane -L 5
-bind -r C-j resize-pane -D 5
-bind -r C-k resize-pane -U 5
-bind -r C-l resize-pane -R 5
-
-# Window movement
-# Only really makes sense if you have your parens bound to shifts like me.
-bind -r ( select-window -t :-
-bind -r ) select-window -t :+
-bind-key -r H swap-window -t -1
-bind-key -r L swap-window -t +1
-bind m command-prompt "move-window -t %%"
-bind - choose-tree
-
-# 256 colors please
-set -g default-terminal "screen-256color"
-# set -g default-terminal "tmux-256color"
-
-# Bad Wolf
-set -g status-fg white
-set -g status-bg colour234
-set -g window-status-activity-attr bold
-set -g pane-border-fg colour245
-set -g pane-active-border-fg colour39
-set -g message-fg colour16
-set -g message-bg colour221
-set -g message-attr bold
-
-# Custom status bar
-# Powerline symbols: ⮂ ⮃ ⮀ ⮁ ⭤
-set -g status-left-length 32
-set -g status-right-length 150
-set -g status-interval 5
-
-set -g status-left '#[fg=colour16,bg=colour254,bold] #S #[fg=colour238,bg=colour234,nobold] '
-
-set -g status-right "#[fg=colour245]#(date -u +%%H:%%M) UTC %d %b #[fg=colour16,bg=colour254,bold] #h "
-
-set -g window-status-format "#[fg=white,bg=colour234] #I #W "
-set -g window-status-current-format "#[fg=colour16,bg=colour39,noreverse,bold] #I #W #[fg=colour39,bg=colour234,nobold] "
-
-# Activity
-setw -g monitor-activity on
-set -g visual-activity off
-
-# Autorename sanely.
-# setw -g automatic-rename on
-
-# Better name management
-bind c new-window -a
-bind , command-prompt "rename-window '%%'"
-bind > run-shell "tmux rename-window `basename #{pane_current_path}`"
-
-# Copy mode
-setw -g mode-keys vi
-bind ` copy-mode
-unbind [
-unbind p
-bind p paste-buffer
-
-bind -T copy-mode-vi 'v' send -X begin-selection
-bind -T copy-mode-vi 'y' send -X copy-pipe-and-cancel pbcopy
-bind -T copy-mode-vi Escape send -X cancel
-bind -T copy-mode-vi V send -X rectangle-toggle
-bind -T copy-mode-vi H send-keys -X start-of-line
-bind -T copy-mode-vi L send-keys -X end-of-line
-bind y run "tmux save-buffer - | xsel --clipboard --input"
-
-# Toggle synchronized panes for the current window
-bind S set synchronize-panes
-
-# Let neovim change the cursor shape
-set -g -a terminal-overrides ',*:Ss=\E[%p1%d q:Se=\E[2 q'
-
--- a/uhk.json	Fri Apr 14 15:01:35 2023 -0400
+++ b/uhk.json	Fri Jul 07 16:11:02 2023 -0400
@@ -373,7 +373,48 @@
             },
             {
               "id": 2,
-              "keyActions": []
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -660,6 +701,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -828,6 +914,51 @@
                 null,
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -999,6 +1130,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         }
@@ -1358,7 +1534,48 @@
             },
             {
               "id": 2,
-              "keyActions": []
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -1655,6 +1872,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -1822,6 +2084,51 @@
                 null,
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -1993,6 +2300,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         }
@@ -2352,7 +2704,48 @@
             },
             {
               "id": 2,
-              "keyActions": []
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -2639,6 +3032,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -2807,6 +3245,51 @@
                 null,
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -2978,6 +3461,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         }
@@ -3337,7 +3865,48 @@
             },
             {
               "id": 2,
-              "keyActions": []
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -3634,6 +4203,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -3801,6 +4415,51 @@
                 null,
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -3972,6 +4631,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         }
@@ -4331,7 +5035,48 @@
             },
             {
               "id": 2,
-              "keyActions": []
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -4618,6 +5363,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -4786,6 +5576,51 @@
                 null,
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -4951,6 +5786,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         }
@@ -5310,7 +6190,48 @@
             },
             {
               "id": 2,
-              "keyActions": []
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -5607,6 +6528,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -5774,6 +6740,51 @@
                 null,
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         },
@@ -5939,6 +6950,51 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         }
@@ -6286,7 +7342,7 @@
                 {
                   "keyActionType": "keystroke",
                   "type": "basic",
-                  "scancode": 101
+                  "scancode": 70
                 },
                 {
                   "keyActionType": "switchLayer",
@@ -6298,7 +7354,50 @@
             },
             {
               "id": 2,
-              "keyActions": []
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 108
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 104
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 105
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 106
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 107
+                }
+              ]
             }
           ]
         },
@@ -6428,7 +7527,11 @@
                   "modifierMask": 32
                 },
                 null,
-                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 57
+                },
                 null,
                 {
                   "keyActionType": "switchLayer",
@@ -6492,7 +7595,7 @@
                 },
                 {
                   "keyActionType": "switchKeymap",
-                  "keymapAbbreviation": "COL"
+                  "keymapAbbreviation": "WIN"
                 },
                 {
                   "keyActionType": "keystroke",
@@ -6612,6 +7715,52 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 104
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 106
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 107
+                }
+              ]
             }
           ]
         },
@@ -6812,6 +7961,52 @@
                 null,
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 104
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 106
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 107
+                }
+              ]
             }
           ]
         },
@@ -6982,6 +8177,1279 @@
                 },
                 null
               ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 104
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 106
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 107
+                }
+              ]
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "isDefault": false,
+      "abbreviation": "WIN",
+      "name": "SJL Windows",
+      "description": "My personal mappings.",
+      "layers": [
+        {
+          "modules": [
+            {
+              "id": 0,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 36
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 37
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 38
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 39
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 45
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 46
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 24
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 12
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 18
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 19
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 47
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 48
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 49
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 28
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 13
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 14
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 15
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 51
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 52
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 11
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 17
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 16
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 54
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 55
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 56
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 32
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 44
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 72
+                },
+                {
+                  "keyActionType": "switchLayer",
+                  "layer": "mod",
+                  "switchLayerMode": "hold"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 64
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 1
+                }
+              ]
+            },
+            {
+              "id": 1,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 53
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 30
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 31
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 32
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 33
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 34
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 35
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 43
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 20
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 26
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 21
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 23
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 41,
+                  "secondaryRoleAction": "leftCtrl"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 4
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 22
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 7
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 9
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 10
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 2
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 100
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 29
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 27
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 6
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 25
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 5
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 1
+                },
+                {
+                  "keyActionType": "switchLayer",
+                  "layer": "mouse",
+                  "switchLayerMode": "toggle"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 4
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 70
+                },
+                {
+                  "keyActionType": "switchLayer",
+                  "layer": "mod",
+                  "switchLayerMode": "hold"
+                },
+                null
+              ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 104
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 105
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 106
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "modules": [
+            {
+              "id": 0,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 64
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 65
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 66
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 67
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 68
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 69
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 78
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 75
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 77
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 70
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 71
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 108
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 74
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 81
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 82
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 79
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 73
+                },
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 80
+                },
+                {
+                  "keyActionType": "playMacro",
+                  "macroIndex": 2
+                },
+                {
+                  "keyActionType": "playMacro",
+                  "macroIndex": 3
+                },
+                {
+                  "keyActionType": "playMacro",
+                  "macroIndex": 4
+                },
+                {
+                  "keyActionType": "playMacro",
+                  "macroIndex": 5
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 101
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 32
+                },
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "switchLayer",
+                  "layer": "mod",
+                  "switchLayerMode": "hold"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 64
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 1
+                }
+              ]
+            },
+            {
+              "id": 1,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 41
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 58
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 59
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 60
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 61
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 62
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 63
+                },
+                {
+                  "keyActionType": "switchKeymap",
+                  "keymapAbbreviation": "SJL"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 41
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 75,
+                  "modifierMask": 1
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 23,
+                  "modifierMask": 1
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 78,
+                  "modifierMask": 1
+                },
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 57
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 57
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 80,
+                  "modifierMask": 5
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 43,
+                  "modifierMask": 4
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 79,
+                  "modifierMask": 5
+                },
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 2
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 29,
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 27,
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 6,
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 25,
+                  "modifierMask": 8
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 1
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 4
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 1
+                },
+                {
+                  "keyActionType": "switchLayer",
+                  "layer": "mod",
+                  "switchLayerMode": "hold"
+                },
+                null
+              ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "modules": [
+            {
+              "id": 0,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 84
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 85
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 86
+                },
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 95
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 37
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 97
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 87
+                },
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 83
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 92
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 93
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 94
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 51
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 88
+                },
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 89
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 90
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 91
+                },
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 44
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 98
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 99
+                },
+                null,
+                null
+              ]
+            },
+            {
+              "id": 1,
+              "keyActions": [
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 43
+                },
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 57
+                },
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 2
+                },
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 1
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 4
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 1
+                },
+                null,
+                null
+              ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            }
+          ]
+        },
+        {
+          "modules": [
+            {
+              "id": 0,
+              "keyActions": [
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "scrollDown"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "scrollUp"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "scrollRight"
+                },
+                null,
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "scrollLeft"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 81
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 82
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 79
+                },
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 80
+                },
+                null,
+                null,
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 32
+                },
+                null,
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 64
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 1
+                }
+              ]
+            },
+            {
+              "id": 1,
+              "keyActions": [
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 57
+                },
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 27
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 24
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 19
+                },
+                null,
+                null,
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 2
+                },
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                {
+                  "keyActionType": "switchLayer",
+                  "layer": "mouse",
+                  "switchLayerMode": "toggle"
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 8
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 4
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "modifierMask": 1
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "accelerate"
+                },
+                null
+              ]
+            },
+            {
+              "id": 2,
+              "keyActions": [
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 76
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 42
+                },
+                {
+                  "keyActionType": "keystroke",
+                  "type": "basic",
+                  "scancode": 40
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "middleClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
+            },
+            {
+              "id": 4,
+              "keyActions": [
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "leftClick"
+                },
+                {
+                  "keyActionType": "mouse",
+                  "mouseAction": "rightClick"
+                }
+              ]
             }
           ]
         }
@@ -7027,6 +9495,110 @@
     {
       "isLooped": false,
       "isPrivate": true,
+      "name": "TE:C Emote 1",
+      "macroActions": [
+        {
+          "macroActionType": "key",
+          "action": "press",
+          "type": "basic",
+          "scancode": 41
+        },
+        {
+          "macroActionType": "key",
+          "action": "press",
+          "type": "basic",
+          "scancode": 80,
+          "modifierMask": 4
+        },
+        {
+          "macroActionType": "key",
+          "action": "release",
+          "type": "basic",
+          "scancode": 41
+        }
+      ]
+    },
+    {
+      "isLooped": false,
+      "isPrivate": true,
+      "name": "TE:C Emote 2",
+      "macroActions": [
+        {
+          "macroActionType": "key",
+          "action": "press",
+          "type": "basic",
+          "scancode": 41
+        },
+        {
+          "macroActionType": "key",
+          "action": "press",
+          "type": "basic",
+          "scancode": 79,
+          "modifierMask": 4
+        },
+        {
+          "macroActionType": "key",
+          "action": "release",
+          "type": "basic",
+          "scancode": 41
+        }
+      ]
+    },
+    {
+      "isLooped": false,
+      "isPrivate": true,
+      "name": "TE:C Emote 3",
+      "macroActions": [
+        {
+          "macroActionType": "key",
+          "action": "press",
+          "type": "basic",
+          "scancode": 41
+        },
+        {
+          "macroActionType": "key",
+          "action": "press",
+          "type": "basic",
+          "scancode": 82,
+          "modifierMask": 4
+        },
+        {
+          "macroActionType": "key",
+          "action": "release",
+          "type": "basic",
+          "scancode": 41
+        }
+      ]
+    },
+    {
+      "isLooped": false,
+      "isPrivate": true,
+      "name": "TE:C Emote 4",
+      "macroActions": [
+        {
+          "macroActionType": "key",
+          "action": "press",
+          "type": "basic",
+          "scancode": 41
+        },
+        {
+          "macroActionType": "key",
+          "action": "press",
+          "type": "basic",
+          "scancode": 81,
+          "modifierMask": 4
+        },
+        {
+          "macroActionType": "key",
+          "action": "release",
+          "type": "basic",
+          "scancode": 41
+        }
+      ]
+    },
+    {
+      "isLooped": false,
+      "isPrivate": true,
       "name": "Type Silent Bob's address",
       "macroActions": [
         {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/userContent.css	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,4 @@
+@-moz-document domain(sumologic.com) {
+    table#search_query_results_view_table td.message { padding: 0 !important; }
+    table#search_query_results_view_table td.offset  { padding: 0 !important; }
+}
--- a/vim/autoload/Powerline/Colorschemes/badwolf.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-call Pl#Hi#Allocate({
-        \ 'black'          : 16,
-        \ 'white'          : 231,
-        \
-        \ 'darkestgreen'   : 22,
-        \ 'darkgreen'      : 28,
-        \ 'mediumgreen'    : 70,
-        \ 'brightgreen'    : 148,
-        \
-        \ 'darkestcyan'    : 23,
-        \ 'mediumcyan'     : 117,
-        \
-        \ 'darkestblue'    : 24,
-        \ 'darkblue'       : 31,
-        \
-        \ 'darkestred'     : 52,
-        \ 'darkred'        : 88,
-        \ 'mediumred'      : 124,
-        \ 'brightred'      : 160,
-        \ 'brightestred'   : 196,
-        \
-        \ 'darkestpurple'  : 55,
-        \ 'mediumpurple'   : 98,
-        \ 'brightpurple'   : 189,
-        \
-        \ 'brightorange'   : 208,
-        \ 'brightestorange': 214,
-        \
-        \ 'gray0'          : 234,
-        \ 'gray1'          : 235,
-        \ 'gray2'          : 236,
-        \ 'gray3'          : 238,
-        \ 'gray4'          : 240,
-        \ 'gray5'          : 241,
-        \ 'gray6'          : 244,
-        \ 'gray7'          : 245,
-        \ 'gray8'          : 247,
-        \ 'gray9'          : 250,
-        \ 'gray10'         : 252,
-        \ })
-
-let g:Powerline#Colorschemes#badwolf#colorscheme = Pl#Colorscheme#Init([
-        \ Pl#Hi#Segments(['SPLIT'], {
-                \ 'n': ['white', 'gray2'],
-                \ 'N': ['white', 'gray1'],
-                \ 'i': ['white', 'darkestblue'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['mode_indicator'], {
-                \ 'n': ['darkestgreen', 'brightgreen', ['bold']],
-                \ 'i': ['darkestcyan', 'white', ['bold']],
-                \ 'v': ['darkred', 'brightorange', ['bold']],
-                \ 'r': ['white', 'brightred', ['bold']],
-                \ 's': ['white', 'gray5', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['branch', 'scrollpercent', 'raw', 'filesize'], {
-                \ 'n': ['gray9', 'gray4'],
-                \ 'N': ['gray4', 'gray2'],
-                \ 'i': ['mediumcyan', 'darkblue'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['fileinfo', 'filename'], {
-                \ 'n': ['white', 'gray4', ['bold']],
-                \ 'N': ['gray7', 'gray2', ['bold']],
-                \ 'i': ['white', 'darkblue', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['fileinfo.filepath'], {
-                \ 'n': ['gray10'],
-                \ 'N': ['gray6'],
-                \ 'i': ['mediumcyan'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['static_str'], {
-                \ 'n': ['white', 'gray4'],
-                \ 'N': ['gray7', 'gray1'],
-                \ 'i': ['white', 'darkblue'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['fileinfo.flags'], {
-                \ 'n': ['brightestred', ['bold']],
-                \ 'N': ['darkred'],
-                \ 'i': ['brightestred', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['currenttag', 'fullcurrenttag', 'fileformat', 'fileencoding', 'pwd', 'filetype', 'rvm:string', 'rvm:statusline', 'virtualenv:statusline', 'charcode', 'currhigroup'], {
-                \ 'n': ['gray8', 'gray2'],
-                \ 'i': ['mediumcyan', 'darkestblue'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['lineinfo'], {
-                \ 'n': ['gray2', 'gray10', ['bold']],
-                \ 'N': ['gray7', 'gray3', ['bold']],
-                \ 'i': ['darkestcyan', 'mediumcyan', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['errors'], {
-                \ 'n': ['brightestorange', 'gray2', ['bold']],
-                \ 'i': ['brightestorange', 'darkestblue', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['lineinfo.line.tot'], {
-                \ 'n': ['gray6'],
-                \ 'N': ['gray5'],
-                \ 'i': ['darkestcyan'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['paste_indicator', 'ws_marker'], {
-                \ 'n': ['white', 'brightred', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['gundo:static_str.name', 'command_t:static_str.name'], {
-                \ 'n': ['white', 'mediumred', ['bold']],
-                \ 'N': ['brightred', 'darkestred', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['gundo:static_str.buffer', 'command_t:raw.line'], {
-                \ 'n': ['white', 'darkred'],
-                \ 'N': ['brightred', 'darkestred'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['gundo:SPLIT', 'command_t:SPLIT'], {
-                \ 'n': ['white', 'darkred'],
-                \ 'N': ['white', 'darkestred'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['lustyexplorer:static_str.name', 'minibufexplorer:static_str.name', 'nerdtree:raw.name', 'tagbar:static_str.name'], {
-                \ 'n': ['white', 'mediumgreen', ['bold']],
-                \ 'N': ['mediumgreen', 'darkestgreen', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['lustyexplorer:static_str.buffer', 'tagbar:static_str.buffer'], {
-                \ 'n': ['brightgreen', 'darkgreen'],
-                \ 'N': ['mediumgreen', 'darkestgreen'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['lustyexplorer:SPLIT', 'minibufexplorer:SPLIT', 'nerdtree:SPLIT', 'tagbar:SPLIT'], {
-                \ 'n': ['white', 'darkgreen'],
-                \ 'N': ['white', 'darkestgreen'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['ctrlp:focus', 'ctrlp:byfname'], {
-                \ 'n': ['brightpurple', 'darkestpurple'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['ctrlp:prev', 'ctrlp:next', 'ctrlp:pwd'], {
-                \ 'n': ['white', 'mediumpurple'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['ctrlp:item'], {
-                \ 'n': ['darkestpurple', 'white', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['ctrlp:marked'], {
-                \ 'n': ['brightestred', 'darkestpurple', ['bold']],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['ctrlp:count'], {
-                \ 'n': ['darkestpurple', 'white'],
-                \ }),
-        \
-        \ Pl#Hi#Segments(['ctrlp:SPLIT'], {
-                \ 'n': ['white', 'darkestpurple'],
-                \ }),
-        \ ])
--- a/vim/colors/molokai.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-" Vim color file
-"
-" Author: Tomas Restrepo <tomas@winterdom.com>
-" Modified by: Steve Losh <steve@stevelosh.com>
-"
-" Note: Based on the monokai theme for textmate
-" by Wimer Hazenberg and its darker variant 
-" by Hamish Stuart Macpherson
-"
-
-set background=dark
-let g:colors_name="molokai"
-
-" Basic Layout {{{
-
-hi Normal          guifg=#F8F8F2 guibg=#1B1E1F
-hi Folded          guifg=#666666 guibg=bg
-hi CursorLine                    guibg=#232728
-hi CursorColumn                  guibg=#232728
-hi ColorColumn                   guibg=#232728
-hi LineNr          guifg=#AAAAAA guibg=bg
-hi FoldColumn      guifg=#AAAAAA guibg=bg
-hi VertSplit       guifg=#AAAAAA guibg=bg gui=none
-hi Search          guifg=#000000 guibg=#E4E500
-hi IncSearch       guibg=#000000 guifg=#FF8D00
-hi Operator        guifg=#F92672
-hi MatchParen      guifg=#ffec00 guibg=#232728 gui=bold
-
-" }}}
-" Syntax {{{
-
-hi Boolean         guifg=#AE81FF
-hi Comment         guifg=#5c7176
-hi Character       guifg=#E6DB74
-hi Number          guifg=#AE81FF
-hi String          guifg=#E6DB74
-hi Conditional     guifg=#F92672               gui=bold
-hi Constant        guifg=#AE81FF               gui=bold
-hi Debug           guifg=#BCA3A3               gui=bold
-hi Define          guifg=#66D9EF
-hi Delimiter       guifg=#8F8F8F
-hi Float           guifg=#AE81FF
-hi Function        guifg=#A6E22E
-hi Identifier      guifg=#FD971F
-hi Error           guifg=#960050 guibg=#1E0010
-hi Keyword         guifg=#F92672               gui=bold
-hi Label           guifg=#E6DB74               gui=none
-hi Macro           guifg=#C4BE89               gui=italic
-hi SpecialKey      guifg=#66D9EF               gui=italic
-
-" }}}
-" Diffs {{{
-
-hi DiffAdd                       guibg=#1e4313
-hi DiffChange      guifg=#89807D guibg=#322F2D
-hi DiffDelete      guifg=#ff0088 guibg=#1B1E1F
-hi DiffText                      guibg=#4A4340 gui=italic,bold
-
-" }}}
-" Cursor {{{
-
-hi Cursor          guifg=#000000 guibg=#F35FBC
-hi iCursor         guifg=#000000 guibg=#FDFF00
-hi vCursor         guifg=#000000 guibg=#AAF412
-
-" }}}
-" Block Colors {{{
-
-hi BlockColor1 guibg=#2a2a2a
-hi BlockColor2 guibg=#333333
-hi BlockColor3 guibg=#3b3b3b
-hi BlockColor4 guibg=#424242
-
-" }}}
-" Makegreen {{{
-
-hi GreenBar term=reverse ctermfg=white ctermbg=green guifg=black guibg=#9edf1c
-hi RedBar   term=reverse ctermfg=white ctermbg=red guifg=white guibg=#C50048
-
-" }}}
-" EasyMotion {{{
-
-hi EasyMotionTarget guifg=#E4E500 guibg=bg gui=bold
-hi EasyMotionShade  guifg=#444444 guibg=bg
-
-" }}}
-
-hi Directory       guifg=#A6E22E               gui=bold
-hi ErrorMsg        guifg=#F92672 guibg=#232526 gui=bold
-hi Exception       guifg=#A6E22E               gui=bold
-hi Ignore          guifg=#808080 guibg=bg
-
-
-hi InterestingWord1 guifg=#000000 guibg=#FFA700
-hi InterestingWord2 guifg=#000000 guibg=#53FF00
-hi InterestingWord3 guifg=#000000 guibg=#FF74F8
-
-
-hi ModeMsg         guifg=#E6DB74
-hi MoreMsg         guifg=#E6DB74
-
-" Completion Menu {{{
-hi Pmenu           guifg=#cccccc guibg=#232728
-hi PmenuSel        guifg=#000000 guibg=#AAF412
-hi PmenuSbar                     guibg=#131414
-hi PmenuThumb      guifg=#777777
-" }}}
-
-hi PreCondit       guifg=#A6E22E               gui=bold
-hi PreProc         guifg=#A6E22E
-hi Question        guifg=#66D9EF
-hi Repeat          guifg=#F92672               gui=bold
-
-" marks column
-hi IndentGuides                  guibg=#373737
-hi SignColumn      guifg=#A6E22E guibg=#151617
-hi SpecialChar     guifg=#F92672               gui=bold
-hi SpecialComment  guifg=#465457               gui=bold
-hi Special         guifg=#66D9EF guibg=bg      gui=italic
-hi SpecialKey      guifg=#888A85               gui=italic
-hi Statement       guifg=#F92672               gui=bold
-hi StatusLine      guifg=#262626 guibg=fg
-hi StatusLineNC    guifg=#262626 guibg=#080808
-hi StorageClass    guifg=#FD971F               gui=italic
-hi Structure       guifg=#66D9EF
-hi Tag             guifg=#F92672               gui=italic
-hi Title           guifg=#ef5939
-hi Todo            guifg=#FFFFFF guibg=bg      gui=bold
-
-hi Typedef         guifg=#66D9EF
-hi Type            guifg=#66D9EF               gui=none
-hi Underlined      guifg=#808080               gui=underline
-
-hi WarningMsg      guifg=#FFFFFF guibg=#333333 gui=bold
-hi WildMenu        guifg=#66D9EF guibg=#000000
-
-hi MyTagListFileName guifg=#F92672 guibg=bg gui=bold
-
-" Spelling {{{
-if has("spell")
-    hi SpellBad    guisp=#FF0000 gui=undercurl
-    hi SpellCap    guisp=#7070F0 gui=undercurl
-    hi SpellLocal  guisp=#70F0F0 gui=undercurl
-    hi SpellRare   guisp=#FFFFFF gui=undercurl
-endif
-" }}}
-" Visual Mode {{{
-hi VisualNOS  guibg=#403D3D
-hi Visual     guibg=#403D3D
-" }}}
-" Invisible character colors {{{
-highlight NonText    guifg=#444444 guibg=bg
-highlight SpecialKey guifg=#444444 guibg=bg
-" }}}
-
-" Support for 256-color terminals {{{
-if &t_Co > 255
-   hi Boolean         ctermfg=135
-   hi Character       ctermfg=144
-   hi Number          ctermfg=135
-   hi String          ctermfg=144
-   hi Conditional     ctermfg=161               cterm=bold
-   hi Constant        ctermfg=135               cterm=bold
-   hi Cursor          ctermfg=16  ctermbg=253
-   hi Debug           ctermfg=225               cterm=bold
-   hi Define          ctermfg=81
-   hi Delimiter       ctermfg=241
-
-   hi EasyMotionTarget ctermfg=11
-   hi EasyMotionShade  ctermfg=8
-
-   hi DiffAdd                     ctermbg=24
-   hi DiffChange      ctermfg=181 ctermbg=239
-   hi DiffDelete      ctermfg=162 ctermbg=53
-   hi DiffText                    ctermbg=102 cterm=bold
-
-   hi Directory       ctermfg=118               cterm=bold
-   hi Error           ctermfg=219 ctermbg=89
-   hi ErrorMsg        ctermfg=199 ctermbg=16    cterm=bold
-   hi Exception       ctermfg=118               cterm=bold
-   hi Float           ctermfg=135
-   hi FoldColumn      ctermfg=67  ctermbg=233
-   hi Folded          ctermfg=67  ctermbg=233
-   hi Function        ctermfg=118
-   hi Identifier      ctermfg=208
-   hi Ignore          ctermfg=244 ctermbg=232
-   hi IncSearch       ctermfg=193 ctermbg=16
-
-   hi Keyword         ctermfg=161               cterm=bold
-   hi Label           ctermfg=229               cterm=none
-   hi Macro           ctermfg=193
-   hi SpecialKey      ctermfg=81
-   hi MailHeaderEmail ctermfg=3  ctermbg=233
-   hi MailEmail       ctermfg=3  ctermbg=233
-
-   hi MatchParen      ctermfg=16  ctermbg=208 cterm=bold
-   hi ModeMsg         ctermfg=229
-   hi MoreMsg         ctermfg=229
-   hi Operator        ctermfg=161
-
-   " complete menu
-   hi Pmenu           ctermfg=81  ctermbg=16
-   hi PmenuSel                    ctermbg=244
-   hi PmenuSbar                   ctermbg=232
-   hi PmenuThumb      ctermfg=81
-
-   hi PreCondit       ctermfg=118               cterm=bold
-   hi PreProc         ctermfg=118
-   hi Question        ctermfg=81
-   hi Repeat          ctermfg=161               cterm=bold
-   hi Search          ctermfg=253 ctermbg=66
-
-   " marks column
-   hi SignColumn      ctermfg=118 ctermbg=235
-   hi SpecialChar     ctermfg=161               cterm=bold
-   hi SpecialComment  ctermfg=245               cterm=bold
-   hi Special         ctermfg=81  ctermbg=232
-   hi SpecialKey      ctermfg=245
-
-   hi Statement       ctermfg=161               cterm=bold
-   hi StatusLine      ctermfg=130 ctermbg=15
-   hi StatusLineNC    ctermfg=242 ctermbg=15
-   hi StorageClass    ctermfg=208
-   hi Structure       ctermfg=81
-   hi Tag             ctermfg=161
-   hi Title           ctermfg=166
-   hi Todo            ctermfg=231 ctermbg=232   cterm=bold
-
-   hi Typedef         ctermfg=81
-   hi Type            ctermfg=81                cterm=none
-   hi Underlined      ctermfg=244               cterm=underline
-
-   hi VertSplit       ctermfg=244 ctermbg=232   cterm=bold
-   hi VisualNOS                   ctermbg=238
-   hi Visual                      ctermbg=235
-   hi WarningMsg      ctermfg=231 ctermbg=238   cterm=bold
-   hi WildMenu        ctermfg=81  ctermbg=16
-
-   hi Normal          ctermfg=252 ctermbg=233
-   hi Comment         ctermfg=59
-   hi CursorLine                  ctermbg=234   cterm=none
-   hi CursorColumn                ctermbg=234
-   hi ColorColumn                 ctermbg=234
-   hi LineNr          ctermfg=250 ctermbg=233
-   hi NonText         ctermfg=240 ctermbg=233
-end " }}}
--- a/vim/colors/mustang.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-" Maintainer:	Henrique C. Alves (hcarvalhoalves@gmail.com)
-" Version:      1.0
-" Last Change:	September 25 2008
-
-set background=dark
-
-hi clear
-
-if exists("syntax_on")
-  syntax reset
-endif
-
-let colors_name = "mustang"
-
-" Vim >= 7.0 specific colors
-if version >= 700
-  hi CursorLine guibg=#2d2d2d ctermbg=236
-  hi ColorColumn guibg=#2d2d2d ctermbg=236
-  hi CursorColumn guibg=#2D2D2D ctermbg=236
-  hi MatchParen guifg=#d0ffc0 guibg=#2f2f2f gui=bold ctermfg=157 ctermbg=237 cterm=bold
-  hi Pmenu 		guifg=#ffffff guibg=#444444 ctermfg=255 ctermbg=238
-  hi PmenuSel 	guifg=#000000 guibg=#b1d631 ctermfg=0 ctermbg=148
-endif
-
-" General colors
-hi Cursor 		guifg=NONE    guibg=#626262 gui=none ctermbg=241
-hi Normal 		guifg=#e2e2e5 guibg=#202020 gui=none ctermfg=253 ctermbg=234
-hi NonText 		guifg=#808080 guibg=#202020 gui=none ctermfg=244 ctermbg=235
-hi LineNr 		guifg=#808080 guibg=#000000 gui=none ctermfg=244 ctermbg=232
-hi StatusLine 	guifg=#d3d3d5 guibg=#444444 gui=italic ctermfg=253 ctermbg=238 cterm=italic
-hi StatusLineNC guifg=#939395 guibg=#444444 gui=none ctermfg=246 ctermbg=238
-hi VertSplit 	guifg=#444444 guibg=#444444 gui=none ctermfg=238 ctermbg=238
-hi Folded 		guibg=#202020 guifg=#808080 gui=none ctermbg=4 ctermfg=248
-hi Title		guifg=#f6f3e8 guibg=NONE	gui=bold ctermfg=254 cterm=bold
-hi Visual		guifg=#faf4c6 guibg=#3c414c gui=none ctermfg=254 ctermbg=4
-hi SpecialKey	guifg=#808080 guibg=#202020 gui=none ctermfg=244 ctermbg=236
-
-" Syntax highlighting
-hi Comment 		guifg=#606060 gui=italic ctermfg=244
-hi Todo 		guifg=#8f8f8f gui=italic ctermfg=245
-hi Boolean      guifg=#b1d631 gui=none ctermfg=148
-hi String 		guifg=#b1d631 gui=italic ctermfg=148
-hi Identifier 	guifg=#b1d631 gui=none ctermfg=148
-hi Function 	guifg=#ffffff gui=bold ctermfg=255
-hi Type 		guifg=#7e8aa2 gui=none ctermfg=103
-hi Statement 	guifg=#7e8aa2 gui=none ctermfg=103
-hi Keyword		guifg=#ff9800 gui=none ctermfg=208
-hi Constant 	guifg=#ff9800 gui=none  ctermfg=208
-hi Number		guifg=#ff9800 gui=none ctermfg=208
-hi Special		guifg=#ff9800 gui=none ctermfg=208
-hi PreProc 		guifg=#faf4c6 gui=none ctermfg=230
-hi Todo         guifg=#000000 guibg=#e6ea50 gui=italic
-
-" Code-specific colors
-hi pythonOperator guifg=#7e8aa2 gui=none ctermfg=103
-
-" Cursor Colors
-hi Cursor  guifg=#000000 guibg=#F35FBC
-hi iCursor guifg=#000000 guibg=#FDFF00
-hi vCursor guifg=#000000 guibg=#AAF412
--- a/vim/colors/vitamins.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-" Maintainer:	Henrique C. Alves (hcarvalhoalves@gmail.com)
-" Version:      1.1
-" Last Change:	September 23 2008
-
-set background=dark
-
-hi clear
-
-if exists("syntax_on")
-  syntax reset
-endif
-
-let colors_name = "vitamins"
-
-" Vim >= 7.0 specific colors
-if version >= 700
-  hi CursorLine guibg=#2d2d2d ctermbg=236
-  hi ColorColumn guibg=#2d2d2d ctermbg=236
-  hi CursorColumn guibg=#2d2d2d ctermbg=236
-  hi MatchParen guifg=#f6f3e8 guibg=#857b6f gui=bold ctermbg=59
-  hi Pmenu 		guifg=#f6f3e8 guibg=#444444 ctermbg=242
-  hi PmenuSel 	guifg=#000000 guibg=#cdd129 ctermfg=0 ctermbg=184
-endif
-
-" General colors
-hi Cursor 		guifg=NONE    guibg=#656565 gui=none ctermbg=0x241
-hi Normal 		guifg=#f6f3f0 guibg=#212121 gui=none ctermfg=254 ctermbg=235
-hi NonText 		guifg=#808080 guibg=#212121 gui=none ctermfg=242 ctermbg=237
-hi LineNr 		guifg=#5c5a4f guibg=#000000 gui=none ctermfg=239 ctermbg=232
-hi StatusLine 	guifg=#f6f3e8 guibg=#444444 gui=italic
-hi StatusLineNC guifg=#857b6f guibg=#444444 gui=none
-hi VertSplit 	guifg=#777777 guibg=#212121 gui=none 
-hi Folded 		guibg=#212121 guifg=#777777 gui=none
-hi Title		guifg=#f6f3e8 guibg=NONE	gui=bold 
-hi Visual		guifg=#ffffd7 guibg=#444444 gui=none ctermfg=186 ctermbg=238
-hi SpecialKey	guifg=#808080 guibg=#212121 gui=none
-
-" Syntax highlighting
-hi Comment 		guifg=#aaaaaa gui=italic ctermfg=244
-hi Todo 		guifg=#8f8f8f gui=italic ctermfg=245
-hi Constant 	guifg=#acf0f2 gui=none ctermfg=159
-hi String 		guifg=#ff5d28 gui=italic ctermfg=202
-hi Identifier 	guifg=#ff5d28 gui=none ctermfg=202
-hi Function 	guifg=#cdd129 gui=none ctermfg=184
-hi Type 		guifg=#cdd129 gui=none ctermfg=184
-hi Statement 	guifg=#af5f5f gui=none ctermfg=131
-hi Keyword		guifg=#cdd129 gui=none ctermfg=184
-hi PreProc 		guifg=#ede39e gui=none ctermfg=187
-hi Number		guifg=#ede39e gui=none ctermfg=187
-hi Special		guifg=#acf0f2 gui=none ctermfg=159
-
-" Cursor Colors
-hi Cursor  guifg=#000000 guibg=#AAF412
-hi iCursor guifg=#000000 guibg=#FDFF00
-hi vCursor guifg=#000000 guibg=#FDFF00
--- a/vim/compiler/cake-test-wrapper.py	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-#!/usr/bin/env python
-
-import os, subprocess
-
-def parse_filename(l):
-    ns = l.split(' ', 3)[-1].rsplit('/', 1)[0]
-    return os.path.join('./test', *ns.split('.')) + '.clj'
-
-def process_error(fn, l, lines):
-    lnum = int(l.rsplit(' ', 1)[-1].split(':')[-1])
-
-    message = lines.pop(0)
-
-    print '%s:%d:%s' % (fn, lnum, message)
-
-    return message
-
-if __name__ == '__main__':
-    out = subprocess.check_output(r"cake test | perl -pe 's/\e\[?.*?[\@-~]//g'", shell=True)
-
-    prev = ""
-    fn = None
-    lines = out.splitlines()
-    while lines:
-        l = lines.pop(0)
-        if l.startswith('cake test ') and '/' in l:
-            fn = parse_filename(l)
-
-        if l.startswith('FAIL!'):
-            prev = process_error(fn, l, lines)
-        else:
-            prev = l
-
--- a/vim/compiler/clojure.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-"============================================================================
-"Compiler:    Clojure (cake test)
-"Maintainer:  Steve Losh <steve@stevelosh.com>
-"License:     MIT/X11
-"============================================================================
-
-" if exists("current_compiler")
-"   finish
-" endif
-let current_compiler = "clojure"
-
-let s:cpo_save = &cpo
-set cpo-=C"endif
-
-let &l:makeprg=fnameescape(globpath(&runtimepath, 'compiler/cake-test-wrapper.py'))
-
-setlocal errorformat=%f:%l:%m
-
-let &cpo = s:cpo_save
-unlet s:cpo_save
--- a/vim/custom-dictionary.utf-8.add	Fri Apr 14 15:01:35 2023 -0400
+++ b/vim/custom-dictionary.utf-8.add	Fri Jul 07 16:11:02 2023 -0400
@@ -318,3 +318,20 @@
 Astron
 Rethe
 Forelithe
+UUIDs
+metaclass
+async
+valkyrie
+Greatshield
+sudoers
+Virtualbox
+libvirt
+qemu
+superclasses
+metaclasses
+Metaobject
+memoize
+metaobjects
+memoized
+skald
+dwarven
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftdetect/hcl.vim	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,7 @@
+" vint: -ProhibitAutocmdWithNoGroup
+" By default, Vim associates .tf files with TinyFugue - tell it not to.
+silent! autocmd! filetypedetect BufRead,BufNewFile *.tf
+autocmd BufRead,BufNewFile *.hcl set filetype=hcl
+autocmd BufRead,BufNewFile .terraformrc,terraform.rc set filetype=hcl
+autocmd BufRead,BufNewFile *.tf,*.tfvars set filetype=terraform
+autocmd BufRead,BufNewFile *.tfstate,*.tfstate.backup set filetype=json
--- a/vim/ftdetect/io.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-" Io
-au BufNewFile,BufRead *.io set filetype=io
-
-" Ikefile
-au BufNewFile,BufRead [iI]kefile,*.ike set filetype=io
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftdetect/martian.vim	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,1 @@
+autocmd BufRead,BufNewFile *.mro set filetype=martian
--- a/vim/haskellmode.config	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
--- 7.4.1
-AlternativeLayoutRule
-AlternativeLayoutRuleTransitional
-Arrows
-BangPatterns
-CApiFFI
-CPP
-ConstrainedClassMethods
-ConstraintKinds
-DataKinds
-DatatypeContexts
-DefaultSignatures
-DeriveDataTypeable
-DeriveFoldable
-DeriveFunctor
-DeriveGeneric
-DeriveTraversable
-DisambiguateRecordFields
-DoAndIfThenElse
-DoRec
-EmptyDataDecls
-ExistentialQuantification
-ExplicitForAll
-ExtendedDefaultRules
-FlexibleContexts
-FlexibleInstances
-ForeignFunctionInterface
-FunctionalDependencies
-GADTSyntax
-GADTs
-GHCForeignImportPrim
-GeneralizedNewtypeDeriving
-Haskell2010
-Haskell98
-ImplicitParams
-ImplicitPrelude
-ImpredicativeTypes
-IncoherentInstances
-InterruptibleFFI
-KindSignatures
-LiberalTypeSynonyms
-MagicHash
-MonadComprehensions
-MonoLocalBinds
-MonoPatBinds
-MonomorphismRestriction
-MultiParamTypeClasses
-NPlusKPatterns
-NamedFieldPuns
-NoAlternativeLayoutRule
-NoAlternativeLayoutRuleTransitional
-NoArrows
-NoBangPatterns
-NoCApiFFI
-NoCPP
-NoConstrainedClassMethods
-NoConstraintKinds
-NoDataKinds
-NoDatatypeContexts
-NoDefaultSignatures
-NoDeriveDataTypeable
-NoDeriveFoldable
-NoDeriveFunctor
-NoDeriveGeneric
-NoDeriveTraversable
-NoDisambiguateRecordFields
-NoDoAndIfThenElse
-NoDoRec
-NoEmptyDataDecls
-NoExistentialQuantification
-NoExplicitForAll
-NoExtendedDefaultRules
-NoFlexibleContexts
-NoFlexibleInstances
-NoForeignFunctionInterface
-NoFunctionalDependencies
-NoGADTSyntax
-NoGADTs
-NoGHCForeignImportPrim
-NoGeneralizedNewtypeDeriving
-NoImplicitParams
-NoImplicitPrelude
-NoImpredicativeTypes
-NoIncoherentInstances
-NoInterruptibleFFI
-NoKindSignatures
-NoLiberalTypeSynonyms
-NoMagicHash
-NoMonadComprehensions
-NoMonoLocalBinds
-NoMonoPatBinds
-NoMonomorphismRestriction
-NoMultiParamTypeClasses
-NoNPlusKPatterns
-NoNamedFieldPuns
-NoNondecreasingIndentation
-NoOverlappingInstances
-NoOverloadedStrings
-NoPackageImports
-NoParallelArrays
-NoParallelListComp
-NoPatternGuards
-NoPatternSignatures
-NoPolyKinds
-NoPolymorphicComponents
-NoPostfixOperators
-NoQuasiQuotes
-NoRank2Types
-NoRankNTypes
-NoRebindableSyntax
-NoRecordPuns
-NoRecordWildCards
-NoRecursiveDo
-NoRelaxedLayout
-NoRelaxedPolyRec
-NoScopedTypeVariables
-NoStandaloneDeriving
-NoTemplateHaskell
-NoTraditionalRecordSyntax
-NoTransformListComp
-NoTupleSections
-NoTypeFamilies
-NoTypeOperators
-NoTypeSynonymInstances
-NoUnboxedTuples
-NoUndecidableInstances
-NoUnicodeSyntax
-NoUnliftedFFITypes
-NoViewPatterns
-NondecreasingIndentation
-OverlappingInstances
-OverloadedStrings
-PackageImports
-ParallelArrays
-ParallelListComp
-PatternGuards
-PatternSignatures
-PolyKinds
-PolymorphicComponents
-PostfixOperators
-QuasiQuotes
-Rank2Types
-RankNTypes
-RebindableSyntax
-RecordPuns
-RecordWildCards
-RecursiveDo
-RelaxedLayout
-RelaxedPolyRec
-Safe
-ScopedTypeVariables
-StandaloneDeriving
-TemplateHaskell
-TraditionalRecordSyntax
-TransformListComp
-Trustworthy
-TupleSections
-TypeFamilies
-TypeOperators
-TypeSynonymInstances
-UnboxedTuples
-UndecidableInstances
-UnicodeSyntax
-UnliftedFFITypes
-Unsafe
-ViewPatterns
---
--fdo-lambda-eta-expansion
--fembed-manifest
--fgen-manifest
--fghci-history
--fghci-sandbox
--fhelpful-errors
--fignore-interface-pragmas
--fimplicit-import-qualified
--fno-break-on-error
--fno-break-on-exception
--fno-building-cabal-package
--fno-case-merge
--fno-cse
--fno-dicts-cheap
--fno-do-eta-reduction
--fno-eager-blackholing
--fno-enable-rewrite-rules
--fno-excess-precision
--fno-expose-all-unfoldings
--fno-ext-core
--fno-float-in
--fno-force-recomp
--fno-full-laziness
--fno-hpc-no-auto
--fno-ignore-asserts
--fno-liberate-case
--fno-new-codegen
--fno-pedantic-bottoms
--fno-print-bind-result
--fno-print-evld-with-show
--fno-print-explicit-foralls
--fno-prof-cafs
--fno-regs-graph
--fno-regs-iterative
--fno-rewrite-rules
--fno-run-cps
--fno-run-cpsz
--fno-spec-constr
--fno-specialise
--fno-static-argument-transformation
--fno-strictness
--fno-unbox-strict-fields
--fno-vectorise
--fno-warn-auto-orphans
--fno-warn-dodgy-exports
--fno-warn-dodgy-imports
--fno-warn-hi-shadowing
--fno-warn-identities
--fno-warn-implicit-prelude
--fno-warn-incomplete-patterns
--fno-warn-incomplete-record-updates
--fno-warn-incomplete-uni-patterns
--fno-warn-missing-import-lists
--fno-warn-missing-local-sigs
--fno-warn-missing-signatures
--fno-warn-monomorphism-restriction
--fno-warn-name-shadowing
--fno-warn-orphans
--fno-warn-safe
--fno-warn-tabs
--fno-warn-type-defaults
--fno-warn-unsafe
--fno-warn-unused-binds
--fno-warn-unused-do-bind
--fno-warn-unused-imports
--fno-warn-unused-matches
--fomit-interface-pragmas
--fprint-bind-contents
--fprof-count-entries
--fshared-implib
--fwarn-alternative-layout-rule-transitional
--fwarn-deprecated-flags
--fwarn-deprecations
--fwarn-dodgy-foreign-imports
--fwarn-duplicate-exports
--fwarn-lazy-unlifted-bindings
--fwarn-missing-fields
--fwarn-missing-methods
--fwarn-overlapping-patterns
--fwarn-unrecognised-pragmas
--fwarn-warnings-deprecations
--fwarn-wrong-do-bind
--- a/vim/init.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-/Users/sjl/.vimrc
\ No newline at end of file
--- a/vim/jsl.conf	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-#
-# Configuration File for JavaScript Lint 0.3.0
-# Developed by Matthias Miller (http://www.JavaScriptLint.com)
-#
-# This configuration file can be used to lint a collection of scripts, or to enable
-# or disable warnings for scripts that are linted via the command line.
-#
-
-### Warnings
-# Enable or disable warnings based on requirements.
-# Use "+WarningName" to display or "-WarningName" to suppress.
-#
-+no_return_value              # function {0} does not always return a value
-+duplicate_formal             # duplicate formal argument {0}
-+equal_as_assign              # test for equality (==) mistyped as assignment (=)?{0}
-+var_hides_arg                # variable {0} hides argument
-+redeclared_var               # redeclaration of {0} {1}
-+anon_no_return_value         # anonymous function does not always return a value
-+missing_semicolon            # missing semicolon
-+meaningless_block            # meaningless block; curly braces have no impact
-+comma_separated_stmts        # multiple statements separated by commas (use semicolons?)
-+unreachable_code             # unreachable code
-+missing_break                # missing break statement
-+missing_break_for_last_case  # miss-+-------------+ent for last case in switch
-+comparison_type_conv         # compa|isons against|null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
-+inc_dec_within_stmt          # incre|ent (++) and |ecrement (--) operators used as part of greater statement
-+useless_void                 # use o| the void typ| may be unnecessary (void is always undefined)
-+multiple_plus_minus          # unkno|n order of op|rations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
-+use_of_label                 # use o| label       |
-+block_without_braces         # block|statement wit|out curly braces
-+leading_decimal_point        # leadi|g decimal poi|t may indicate a number or an object member
-+trailing_decimal_point       # trail|ng decimal po|nt may indicate a number or an object member
-+octal_number                 # leadi|g zeros make |n octal number
-+nested_comment               # neste+-------------+
-+misplaced_regex              # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
--ambiguous_newline            # unexpected end of line; it is ambiguous whether these lines are part of the same statement
-+empty_statement              # empty statement or extra semicolon
--missing_option_explicit      # the "option explicit" control comment is missing
-+partial_option_explicit      # the "option explicit" control comment, if used, must be in the first script tag
-+dup_option_explicit          # duplicate "option explicit" control comment
-+useless_assign               # useless assignment
-+ambiguous_nested_stmt        # block statements containing block statements should use curly braces to resolve ambiguity
-+ambiguous_else_stmt          # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
-+missing_default_case         # missing default case in switch statement
-+duplicate_case_in_switch     # duplicate case in switch statements
-+default_not_at_end           # the default case is not at the end of the switch statement
-+legacy_cc_not_understood     # couldn't understand control comment using /*@keyword@*/ syntax
-+jsl_cc_not_understood        # couldn't understand control comment using /*jsl:keyword*/ syntax
-+useless_comparison           # useless comparison; comparing identical expressions
-+with_statement               # with statement hides undeclared variables; use temporary variable instead
-+trailing_comma_in_array      # extra comma is not recommended in array initializers
-+assign_to_function_call      # assignment to a function call
-+parseint_missing_radix       # parseInt missing radix parameter
-
-
-### Output format
-# Customize the format of the error message.
-#    __FILE__ indicates current file path
-#    __FILENAME__ indicates current file name
-#    __LINE__ indicates current line
-#    __ERROR__ indicates error message
-#
-# Visual Studio syntax (default):
-+output-format __FILE__(__LINE__): __ERROR__
-# Alternative syntax:
-#+output-format __FILE__:__LINE__: __ERROR__
-
-
-### Context
-# Show the in-line position of the error.
-# Use "+context" to display or "-context" to suppress.
-#
-+context
-
-
-### Semicolons
-# By default, assignments of an anonymous function to a variable or
-# property (such as a function prototype) must be followed by a semicolon.
-#
-+lambda_assign_requires_semicolon
-
-
-### Control Comments
-# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
-# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
-# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
-# although legacy control comments are enabled by default for backward compatibility.
-#
-+legacy_control_comments
-
-
-### JScript Function Extensions
-# JScript allows member functions to be defined like this:
-#     function MyObj() { /*constructor*/ }
-#     function MyObj.prototype.go() { /*member function*/ }
-#
-# It also allows events to be attached like this:
-#     function window::onload() { /*init page*/ }
-#
-# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
-#
--jscript_function_extensions
-
-
-### Defining identifiers
-# By default, "option explicit" is enabled on a per-file basis.
-# To enable this for all files, use "+always_use_option_explicit"
--always_use_option_explicit
-
-# Define certain identifiers of which the lint is not aware.
-# (Use this in conjunction with the "undeclared identifier" warning.)
-#
-# Common uses for webpages might be:
-+define window
-+define document
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/plugin/redact_pass.vim	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,58 @@
+"
+" redact_pass.vim: Switch off the 'viminfo', 'backup', 'writebackup',
+" 'swapfile', and 'undofile' globally when editing a password in pass(1).
+"
+" This is to prevent anyone being able to extract passwords from your Vim
+" cache files in the event of a compromise.
+"
+" Author: Tom Ryder <tom@sanctum.geek.nz>
+" License: Same as Vim itself
+"
+if exists('g:loaded_redact_pass') || &compatible
+  finish
+endif
+if !has('autocmd') || v:version < 600
+  finish
+endif
+let g:loaded_redact_pass = 1
+
+" Check whether we should set redacting options or not
+function! s:CheckArgsRedact()
+
+  " Ensure there's one argument and it's the matched file
+  if argc() != 1 || fnamemodify(argv(0), ':p') !=# expand('<afile>:p')
+    return
+  endif
+
+  " Disable all the leaky options globally
+  set nobackup
+  set nowritebackup
+  set noswapfile
+  set viminfo=
+  if has('persistent_undo')
+    set noundofile
+  endif
+
+  " Tell the user what we're doing so they know this worked, via a message and
+  " a global variable they can check
+  redraw
+  echomsg 'Editing password file--disabled leaky options!'
+  let g:redact_pass_redacted = 1
+
+endfunction
+
+" Auto function loads only when Vim starts up
+augroup redact_pass
+  autocmd!
+  autocmd VimEnter
+        \ /dev/shm/pass.?*/?*.txt
+        \,$TMPDIR/pass.?*/?*.txt
+        \,/tmp/pass.?*/?*.txt
+        \ call s:CheckArgsRedact()
+  " Work around macOS' dynamic symlink structure for temporary directories
+  if has('mac')
+    autocmd VimEnter
+          \ /private/var/?*/pass.?*/?*.txt
+          \ call s:CheckArgsRedact()
+  endif
+augroup END
--- a/vim/snippets/_.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-# Global snippets
-
-# (c) holds no legal value ;)
-snippet c)
-	`&enc[:2] == "utf" ? "©" : "(c)"` Copyright `strftime("%Y")` ${1:`g:snips_author`}. All Rights Reserved.${2}
-snippet date
-	`strftime("%Y-%m-%d")`
-snippet sl
-	http://stevelosh.com/
-snippet gh
-	http://github.com/
-snippet ghs
-	http://github.com/sjl/
-snippet bb
-	http://bitbucket.org/
-snippet bbs
-	http://bitbucket.org/sjl/
--- a/vim/snippets/autoit.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-snippet if
-	If ${1:condition} Then
-		${2:; True code}
-	EndIf
-snippet el
-	Else
-		${1}
-snippet elif
-	ElseIf ${1:condition} Then
-		${2:; True code}
-# If/Else block
-snippet ifel
-	If ${1:condition} Then
-		${2:; True code}
-	Else
-		${3:; Else code}
-	EndIf
-# If/ElseIf/Else block
-snippet ifelif
-	If ${1:condition 1} Then
-		${2:; True code}
-	ElseIf ${3:condition 2} Then
-		${4:; True code}
-	Else
-		${5:; Else code}
-	EndIf
-# Switch block
-snippet switch
-	Switch (${1:condition})
-	Case {$2:case1}:
-		{$3:; Case 1 code}
-	Case Else:
-		{$4:; Else code}
-	EndSwitch
-# Select block
-snippet select
-	Select (${1:condition})
-	Case {$2:case1}:
-		{$3:; Case 1 code}
-	Case Else:
-		{$4:; Else code}
-	EndSelect
-# While loop
-snippet while
-	While (${1:condition})
-		${2:; code...}
-	WEnd
-# For loop
-snippet for
-	For ${1:n} = ${3:1} to ${2:count}
-		${4:; code...}
-	Next
-# New Function
-snippet func
-	Func ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
-		${4:Return}
-	EndFunc
-# Message box
-snippet msg
-	MsgBox(${3:MsgType}, ${1:"Title"}, ${2:"Message Text"})
-# Debug Message
-snippet debug
-	MsgBox(0, "Debug", ${1:"Debug Message"})
-# Show Variable Debug Message
-snippet showvar
-	MsgBox(0, "${1:VarName}", $1)
--- a/vim/snippets/c.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-# main()
-snippet main
-	int main(int argc, const char *argv[])
-	{
-		${1}
-		return 0;
-	}
-# #include <...>
-snippet inc
-	#include <${1:stdio}.h>${2}
-# #include "..."
-snippet Inc
-	#include "${1:`Filename("$1.h")`}"${2}
-# #ifndef ... #define ... #endif
-snippet Def
-	#ifndef $1
-	#define ${1:SYMBOL} ${2:value}
-	#endif${3}
-snippet def
-	#define 
-snippet ifdef
-	#ifdef ${1:FOO}
-		${2:#define }
-	#endif
-snippet #if
-	#if ${1:FOO}
-		${2}
-	#endif
-# Header Include-Guard
-# (the randomizer code is taken directly from TextMate; it could probably be
-# cleaner, I don't know how to do it in vim script)
-snippet once
-	#ifndef ${1:`toupper(Filename('', 'UNTITLED').'_'.system("/usr/bin/ruby -e 'print (rand * 2821109907455).round.to_s(36)'"))`}
-
-	#define $1
-
-	${2}
-
-	#endif /* end of include guard: $1 */
-# If Condition
-snippet if
-	if (${1:/* condition */}) {
-		${2:/* code */}
-	}
-snippet el
-	else {
-		${1}
-	}
-# Tertiary conditional
-snippet t
-	${1:/* condition */} ? ${2:a} : ${3:b}
-# Do While Loop
-snippet do
-	do {
-		${2:/* code */}
-	} while (${1:/* condition */});
-# While Loop
-snippet wh
-	while (${1:/* condition */}) {
-		${2:/* code */}
-	}
-# For Loop
-snippet for
-	for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) {
-		${4:/* code */}
-	}
-# Custom For Loop
-snippet forr
-	for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) {
-		${5:/* code */}
-	}
-# Function
-snippet fun
-	${1:void} ${2:function_name}(${3})
-	{
-		${4:/* code */}
-	}
-# Function Declaration
-snippet fund
-	${1:void} ${2:function_name}(${3});${4}
-# Typedef
-snippet td
-	typedef ${1:int} ${2:MyCustomType};${3}
-# Struct
-snippet st
-	struct ${1:`Filename('$1_t', 'name')`} {
-		${2:/* data */}
-	}${3: /* optional variable list */};${4}
-# Typedef struct
-snippet tds
-	typedef struct ${2:_$1 }{
-		${3:/* data */}
-	} ${1:`Filename('$1_t', 'name')`};
-# Typdef enum
-snippet tde
-	typedef enum {
-		${1:/* data */}
-	} ${2:foo};
-# printf
-# unfortunately version this isn't as nice as TextMates's, given the lack of a
-# dynamic `...`
-snippet pr
-	printf("${1:%s}\n"${2});${3}
-# fprintf (again, this isn't as nice as TextMate's version, but it works)
-snippet fpr
-	fprintf(${1:stderr}, "${2:%s}\n"${3});${4}
-snippet .
-	[${1}]${2}
-snippet un
-	unsigned
--- a/vim/snippets/clojure.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-# Fucking imports, how do they work?
-snippet nfis
-	(:use ${1:foo.core})
-snippet nfi
-	(:use [${1:foo.core} :only (${2:bar})])
-snippet ni
-	(:require [${1:foo.core}])
-snippet nia
-	(:require [${1:foo.core} :as ${2:bar}])
-snippet niar
-	(:require [${1:foo.core}])
-	(:import [$1 ${2:Bar}])
--- a/vim/snippets/cpp.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-# Read File Into Vector
-snippet readfile
-	std::vector<char> v;
-	if (FILE *${2:fp} = fopen(${1:"filename"}, "r")) {
-		char buf[1024];
-		while (size_t len = fread(buf, 1, sizeof(buf), $2))
-			v.insert(v.end(), buf, buf + len);
-		fclose($2);
-	}${3}
-# std::map
-snippet map
-	std::map<${1:key}, ${2:value}> map${3};
-# std::vector
-snippet vector
-	std::vector<${1:char}> v${2};
-# Namespace
-snippet ns
-	namespace ${1:`Filename('', 'my')`} {
-		${2}
-	} /* $1 */
-# Class
-snippet cl
-	class ${1:`Filename('$1_t', 'name')`} {
-	public:
-		$1 (${2:arguments});
-		virtual ~$1 ();
-	
-	private:
-		${3:/* data */}
-	};
--- a/vim/snippets/django.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-# Model Fields
-
-# Note: Optional arguments are using defaults that match what Django will use
-# as a default, e.g. with max_length fields.  Doing this as a form of self
-# documentation and to make it easy to know whether you should override the
-# default or not.
-
-# Note: Optional arguments that are booleans will use the opposite since you
-# can either not specify them, or override them, e.g. auto_now_add=False.
-
-snippet auto
-	${1:FIELDNAME} = models.AutoField()
-snippet bool
-	${1:FIELDNAME} = models.BooleanField(${2:default=True})
-snippet char
-	${1:FIELDNAME} = models.CharField(max_length=${2}${3:, blank=True})
-snippet comma
-	${1:FIELDNAME} = models.CommaSeparatedIntegerField(max_length=${2}${3:, blank=True})
-snippet date
-	${1:FIELDNAME} = models.DateField()
-snippet datetime
-	${1:FIELDNAME} = models.DateTimeField()
-snippet decimal
-	${1:FIELDNAME} = models.DecimalField(max_digits=${2}, decimal_places=${3})
-snippet email
-	${1:FIELDNAME} = models.EmailField(max_length=${2:75}${3:, blank=True})
-snippet file
-	${1:FIELDNAME} = models.FileField(upload_to=${2:path/for/upload}${3:, max_length=100})
-snippet filepath
-	${1:FIELDNAME} = models.FilePathField(path=${2:"/abs/path/to/dir"}${3:, max_length=100}${4:, match="*.ext"}${5:, recursive=True}${6:, blank=True, })
-snippet float
-	${1:FIELDNAME} = models.FloatField()
-snippet image
-	${1:FIELDNAME} = FileBrowseField(format='Image', max_length=200)
-snippet djangoimage
-	${1:FIELDNAME} = models.ImageField(upload_to=${2:path/for/upload}${3:, height_field=height, width_field=width}${4:, max_length=100})
-snippet int
-	${1:FIELDNAME} = models.IntegerField()
-snippet ip
-	${1:FIELDNAME} = models.IPAddressField()
-snippet nullbool
-	${1:FIELDNAME} = models.NullBooleanField()
-snippet posint
-	${1:FIELDNAME} = models.PositiveIntegerField()
-snippet possmallint
-	${1:FIELDNAME} = models.PositiveSmallIntegerField()
-snippet slug
-	${1:FIELDNAME} = models.SlugField(max_length=${2:50}${3:, blank=True})
-snippet smallint
-	${1:FIELDNAME} = models.SmallIntegerField()
-snippet text
-	${1:FIELDNAME} = models.TextField(${2:blank=True})
-snippet time
-	${1:FIELDNAME} = models.TimeField()
-snippet url
-	${1:FIELDNAME} = models.URLField(${2:verify_exists=False}${3:, max_length=200}${4:, blank=True})
-snippet xml
-	${1:FIELDNAME} = models.XMLField(schema_path=${2:None}${3:, blank=True})
-# Relational Fields
-snippet fk
-	${1:FIELDNAME} = models.ForeignKey(${2:OtherModel})
-snippet m2m
-	${1:FIELDNAME} = models.ManyToManyField(${2:OtherModel})
-snippet bl
-	blank=True
-snippet dc
-	db_column='${1:colname}'
-snippet dt
-	db_table='${1:tablename}'
-snippet o2o
-	${1:FIELDNAME} = models.OneToOneField(${2:OtherModel}${3:, parent_link=True}${4:, related_name=''}${5:, limit_choices_to=}${6:, to_field=''})
-
-# Code Skeletons
-
-snippet form
-	class ${1:FormName}(forms.Form):
-		"""${2:docstring}"""
-		${3}
-
-snippet manager
-	class ${1:ModelName}Manager(models.Manager):
-		def get_query_set(self):
-			return super($1Manager, self).get_query_set()
-		${3}
-
-snippet model
-	class ${1:ModelName}(${2:models.Model}):
-		${4}
-
-		class Meta:
-			ordering = ('${3:-created}',)
-
-		def __unicode__(self):
-			return u'%s' % ''
-
-snippet modeladmin
-	class ${1:ModelName}Admin(admin.ModelAdmin):
-		${2}
-	
-	admin.site.register($1, $1Admin)
-
-snippet r2r
-	return render_to_response('${1:template.html}', {
-			${2}
-		}${3:, context_instance=RequestContext(request)}
-	)
-
-snippet tabularinline
-	class ${1:ModelName}Inline(admin.TabularInline):
-		model = $1
-		extra = ${2:3}
-
-snippet stackedinline
-	class ${1:ModelName}Inline(admin.StackedInline):
-		model = $1
-		extra = ${2:3}
-
-# Ugly crap.
-
-snippet reverse
-	reverse('${1:view-name}'${2:, args=[]}${3:, kwargs=None})${4}
-snippet view
-	@render_to('${1}')
-	def ${2:view_name}(request${3:, ...}):${4}
-		return {}
-snippet defu
-	def __unicode__(self):
-		return u'${1}' % (${2})
--- a/vim/snippets/html.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-# Some useful Unicode entities
-# Non-Breaking Space
-snippet nbs
-	&nbsp;
-# ←
-snippet left
-	&#x2190;
-# →
-snippet right
-	&#x2192;
-# ↑
-snippet up
-	&#x2191;
-# ↓
-snippet down
-	&#x2193;
-# ↩
-snippet return
-	&#x21A9;
-# ⇤
-snippet backtab
-	&#x21E4;
-# ⇥
-snippet tab
-	&#x21E5;
-# ⇧
-snippet shift
-	&#x21E7;
-# ⌃
-snippet control
-	&#x2303;
-# ⌅
-snippet enter
-	&#x2305;
-# ⌘
-snippet command
-	&#x2318;
-# ⌥
-snippet option
-	&#x2325;
-# ⌦
-snippet delete
-	&#x2326;
-# ⌫
-snippet backspace
-	&#x232B;
-# ⎋
-snippet escape
-	&#x238B;
-# Generic Doctype
-snippet doctype HTML 4.01 Strict
-	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""
-	"http://www.w3.org/TR/html4/strict.dtd">
-snippet doctype HTML 4.01 Transitional
-	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""
-	"http://www.w3.org/TR/html4/loose.dtd">
-snippet doctype HTML 5
-	<!DOCTYPE HTML>
-snippet doctype XHTML 1.0 Frameset
-	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-snippet doctype XHTML 1.0 Strict
-	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-snippet doctype XHTML 1.0 Transitional
-	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-snippet doctype XHTML 1.1
-	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
-	"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-# HTML Doctype 4.01 Strict
-snippet docts
-	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""
-	"http://www.w3.org/TR/html4/strict.dtd">
-# HTML Doctype 4.01 Transitional
-snippet doct
-	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""
-	"http://www.w3.org/TR/html4/loose.dtd">
-# HTML Doctype 5
-snippet doct5
-	<!DOCTYPE HTML>
-# XHTML Doctype 1.0 Frameset
-snippet docxf
-	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
-	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
-# XHTML Doctype 1.0 Strict
-snippet docxs
-	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-# XHTML Doctype 1.0 Transitional
-snippet docxt
-	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-# XHTML Doctype 1.1
-snippet docx
-	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
-	"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-snippet html
-	<html>
-	${1}
-	</html>
-snippet xhtml
-	<html xmlns="http://www.w3.org/1999/xhtml">
-	${1}
-	</html>
-snippet body
-	<body>
-		${1}
-	</body>
-snippet head
-	<head>
-		<meta http-equiv="content-type" content="text/html; charset=utf-8"`Close()`>
-
-		<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>
-		${2}
-	</head>
-snippet title
-	<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\u&', '')`}</title>${2}
-snippet script
-	<script type="text/javascript" charset="utf-8">
-		${1}
-	</script>${2}
-snippet scriptsrc
-	<script src="${1}.js" type="text/javascript" charset="utf-8"></script>${2}
-snippet style
-	<style type="text/css" media="${1:screen}">
-		${2}
-	</style>${3}
-snippet base
-	<base href="${1}" target="${2}"`Close()`>
-snippet r
-	<br`Close()[1:]`>
-snippet div
-	<div id="${1:name}">
-		${2}
-	</div>
-# Embed QT Movie
-snippet movie
-	<object width="$2" height="$3" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
-	 codebase="http://www.apple.com/qtactivex/qtplugin.cab">
-		<param name="src" value="$1"`Close()`>
-		<param name="controller" value="$4"`Close()`>
-		<param name="autoplay" value="$5"`Close()`>
-		<embed src="${1:movie.mov}"
-			width="${2:320}" height="${3:240}"
-			controller="${4:true}" autoplay="${5:true}"
-			scale="tofit" cache="true"
-			pluginspage="http://www.apple.com/quicktime/download/"
-		`Close()[1:]`>
-	</object>${6}
-snippet fieldset
-	<fieldset id="$1">
-		<legend>${1:name}</legend>
-
-		${3}
-	</fieldset>
-snippet form
-	<form action="${1:`Filename('$1_submit')`}" method="${2:get}" accept-charset="utf-8">
-		${3}
-
-
-	<p><input type="submit" value="Continue &rarr;"`Close()`></p>
-	</form>
-snippet h1
-	<h1 id="${1:heading}">${2:$1}</h1>
-snippet input
-	<input type="${1:text/submit/hidden/button}" name="${2:some_name}" value="${3}"`Close()`>${4}
-snippet label
-	<label for="${2:$1}">${1:name}</label><input type="${3:text/submit/hidden/button}" name="${4:$2}" value="${5}" id="${6:$2}"`Close()`>${7}
-snippet link
-	<link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" charset="utf-8"`Close()`>${4}
-snippet mailto
-	<a href="mailto:${1:joe@example.com}?subject=${2:feedback}">${3:email me}</a>
-snippet meta
-	<meta name="${1:name}" content="${2:content}"`Close()`>${3}
-snippet opt
-	<option value="${1:option}">${2:$1}</option>${3}
-snippet optt
-	<option>${1:option}</option>${2}
-snippet select
-	<select name="${1:some_name}" id="${2:$1}">
-		<option value="${3:option}">${4:$3}</option>
-	</select>${5}
-snippet table
-	<table border="${1:0}">
-		<tr><th>${2:Header}</th></tr>
-		<tr><th>${3:Data}</th></tr>
-	</table>${4}
-snippet textarea
-	<textarea name="${1:Name}" rows="${2:8}" cols="${3:40}">${4}</textarea>${5}
--- a/vim/snippets/htmldjango.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-# Generic Tags
-snippet %
-	{% ${1} %}${2}
-snippet %%
-	{% ${1:tag_name} %}
-	${2}
-	{% end$1 %}
-snippet {
-	{{ ${1} }}${2}
-snippet gau
-	get_absolute_url${1}
-snippet gfn
-	get_full_name${1}
-# Template Tags
-
-snippet autoescape
-	{% autoescape ${1:off} %}
-	${2}
-	{% endautoescape %}
-snippet block
-	{% block ${1} %}
-	${2}
-	{% endblock %}
-snippet #
-	{# ${1:comment} #}
-snippet comment
-	{% comment %}
-	${1}
-	{% endcomment %}
-snippet cycle
-	{% cycle ${1:val1} ${2:val2} ${3:as ${4}} %}
-snippet debug
-	{% debug %}
-snippet extends
-	{% extends "${1:base.html}" %}
-snippet filter
-	{% filter ${1} %}
-	${2}
-	{% endfilter %}
-snippet firstof
-	{% firstof ${1} %}
-snippet for
-	{% for ${1} in ${2} %}
-	${3}
-	{% endfor %}
-snippet empty
-	{% empty %}
-snippet if
-	{% if ${1} %}
-	${2}
-	{% endif %}
-snippet else
-	{% else %}
-snippet ifchanged
-	{% ifchanged %}${1}{% endifchanged %}
-snippet ifequal
-	{% ifequal ${1} ${2} %}
-	${3}
-	{% endifequal %}
-snippet ifnotequal
-	{% ifnotequal ${1} ${2} %}
-	${3}
-	{% endifnotequal %}
-snippet include
-	{% include "${1}" %}
-snippet load
-	{% load ${1} %}
-snippet now
-	{% now "${1:jS F Y H:i}" %}
-snippet regroup
-	{% regroup ${1} by ${2} as ${3} %}
-snippet spaceless
-	{% spaceless %}${1}{% endspaceless %}
-snippet ssi
-	{% ssi ${1} %}
-snippet trans
-	{% trans "${1:string}" %}
-snippet url
-	{% url ${1} as ${2} %}
-snippet widthratio
-	{% widthratio ${1:this_value} ${2:max_value} ${3:100} %}
-snippet with
-	{% with ${1} as ${2} %}
-# Template Filters
-
-# Note: Since SnipMate can't determine which template filter you are
-# expanding without the "|" character, these do not add the "|"
-# character.  These save a few keystrokes still.
-
-# Note: Template tags that take no arguments are not implemented.
-
-snippet add
-	add:"${1}"
-snippet center
-	center:"${1}"
-snippet cut
-	cut:"${1}"
-snippet date
-	date:"${1}"
-snippet default
-	default:"${1}"
-snippet defaultifnone
-	default_if_none:"${1}"
-snippet dictsort
-	dictsort:"${1}"
-snippet dictsortrev
-	dictsortreversed:"${1}"
-snippet divisibleby
-	divisibleby:"${1}"
-snippet floatformat
-	floatformat:"${1}"
-snippet getdigit
-	get_digit:"${1}"
-snippet join
-	join:"${1}"
-snippet lengthis
-	length_is:"${1}"
-snippet pluralize
-	pluralize:"${1}"
-snippet removetags
-	removetags:"${1}"
-snippet slice
-	slice:"${1}"
-snippet stringformat
-	stringformat:"${1}"
-snippet time
-	time:"${1}"
-snippet truncatewords
-	truncatewords:${1}
-snippet truncatewordshtml
-	truncatewords_html:${1}
-snippet urlizetrunc
-	urlizetrunc:${1}
-snippet wordwrap
-	wordwrap:${1}
--- a/vim/snippets/htmljinja.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-/Users/sjl/lib/dotfiles/vim/snippets/jinja.snippets
\ No newline at end of file
--- a/vim/snippets/java.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-snippet main
-	public static void main (String [] args)
-	{
-		${1:/* code */}
-	}
-snippet pu
-	public
-snippet po
-	protected
-snippet pr
-	private
-snippet st
-	static
-snippet fi
-	final
-snippet ab
-	abstract
-snippet re
-	return
-snippet br
-	break;
-snippet de
-	default:
-		${1}
-snippet ca
-	catch(${1:Exception} ${2:e}) ${3}
-snippet th
-	throw 
-snippet sy
-	synchronized
-snippet im
-	import
-snippet j.u
-	java.util
-snippet j.i
-	java.io.
-snippet j.b
-	java.beans.
-snippet j.n
-	java.net.
-snippet j.m
-	java.math.
-snippet if
-	if (${1}) ${2}
-snippet el
-	else 
-snippet elif
-	else if (${1}) ${2}
-snippet wh
-	while (${1}) ${2}
-snippet for
-	for (${1}; ${2}; ${3}) ${4}
-snippet fore
-	for (${1} : ${2}) ${3}
-snippet sw
-	switch (${1}) ${2}
-snippet cs
-	case ${1}:
-		${2}
-	${3}
-snippet tc
-	public class ${1:`Filename()`} extends ${2:TestCase}
-snippet t
-	public void test${1:Name}() throws Exception ${2}
-snippet cl
-	class ${1:`Filename("", "untitled")`} ${2}
-snippet in
-	interface ${1:`Filename("", "untitled")`} ${2:extends Parent}${3}
-snippet m
-	${1:void} ${2:method}(${3}) ${4:throws }${5}
-snippet v
-	${1:String} ${2:var}${3: = null}${4};${5}
-snippet co
-	static public final ${1:String} ${2:var} = ${3};${4}
-snippet cos
-	static public final String ${1:var} = "${2}";${3}
-snippet as
-	assert ${1:test} : "${2:Failure message}";${3}
--- a/vim/snippets/javascript.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-# Prototype
-snippet proto
-	${1:class_name}.prototype.${2:method_name} =
-	function(${3:first_argument}) {
-		${4:// body...}
-	};
-# Function
-snippet fun
-	function ${1:function_name} (${2:argument}) {
-		${3:// body...}
-	}
-# Anonymous Function
-snippet f
-	function(${1}) {${2}};
-# if
-snippet if
-	if (${1:true}) {${2}};
-# if ... else
-snippet ife
-	if (${1:true}) {${2}}
-	else{${3}};
-# tertiary conditional
-snippet t
-	${1:/* condition */} ? ${2:a} : ${3:b}
-# switch
-snippet switch
-	switch(${1:expression}) {
-		case '${3:case}':
-			${4:// code}
-			break;
-		${5}
-		default:
-			${2:// code}
-	}
-# case
-snippet case
-	case '${1:case}':
-		${2:// code}
-		break;
-	${3}
-# for (...) {...}
-snippet for
-	for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) {
-		${4:$1[$2]}
-	};
-# for (...) {...} (Improved Native For-Loop)
-snippet forr
-	for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) {
-		${4:$1[$2]}
-	};
-# while (...) {...}
-snippet wh
-	while (${1:/* condition */}) {
-		${2:/* code */}
-	}
-# do...while
-snippet do
-	do {
-		${2:/* code */}
-	} while (${1:/* condition */});
-# Object Method
-snippet :f
-	${1:method_name}: function(${2:attribute}) {
-		${4}
-	}${3:,}
-# setTimeout function
-snippet timeout
-	setTimeout(function() {${3}}${2}, ${1:10};
-# Get Elements
-snippet get
-	getElementsBy${1:TagName}('${2}')${3}
-# Get Element
-snippet gett
-	getElementBy${1:Id}('${2}')${3}
-snippet log
-	console.log(${1});${2}
--- a/vim/snippets/jinja.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-# Generic Tags
-snippet %
-	{% ${1} %}${2}
-snippet {
-	{{ ${1} }}${2}
-snippet %%
-	{% ${1:tag_name} %}
-	${2}
-	{% end$1 %}
-
-snippet block
-	{% block ${1:content} %}
-		${2}
-	{% endblock %}
-snippet blocki
-	{% block ${1:content} %}${2}{% endblock %}
-
--- a/vim/snippets/lisp.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-snippet defp
-	(defparameter ${1} ${2})${3}
-snippet defv
-	(defvar ${1} ${2})${3}
-snippet defun
-	(defun ${1} (${2})
-	  ${3})
-snippet defm
-	(defmethod ${1} (${2})
-	  ${3})
-snippet let
-	(let ((${1} ${2})${3})
-	  ${4})
-snippet flet
-	(flet ((${1} (${2})
-	         ${3})${4})
-	  ${5})
-snippet labels
-	(labels ((${1} (${2})
-	           ${3})${4})
-	  ${5})
-snippet when
-	(when ${1}
-	      ${2})
-snippet unless
-	(unless ${1}
-	        ${2})
-snippet cond
-	(cond (${1} ${2})
-		  ${3})
-snippet case
-	(case ${1}
-		 (${2} ${3})
-		 ${4})
--- a/vim/snippets/mako.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-snippet def
-	<%def name="${1:name}">
-		${2:}
-	</%def>
-snippet call
-	<%call expr="${1:name}">
-		${2:}
-	</%call>
-snippet doc
-	<%doc>
-		${1:}
-	</%doc>
-snippet text
-	<%text>
-		${1:}
-	</%text>
-snippet for
-	% for ${1:i} in ${2:iter}:
-		${3:}
-	% endfor
-snippet if if
-	% if ${1:condition}:
-		${2:}
-	% endif
-snippet if if/else
-	% if ${1:condition}:
-		${2:}
-	% else:
-		${3:}
-	% endif
-snippet try
-	% try:
-		${1:}
-	% except${2:}:
-		${3:pass}
-	% endtry
-snippet wh
-	% while ${1:}:
-		${2:}
-	% endwhile
-snippet $
-	${ ${1:} }
-snippet <%
-	<% ${1:} %>
-snippet <!%
-	<!% ${1:} %>
-snippet inherit
-	<%inherit file="${1:filename}" />
-snippet include
-	<%include file="${1:filename}" />
-snippet namespace
-	<%namespace file="${1:name}" />
-snippet page
-	<%page args="${1:}" />
--- a/vim/snippets/markdown.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-snippet notice
-	<span class="label notice">${1:Notice}</span>
-snippet warning
-	<span class="label warning">${1:Warning}</span>
-snippet important
-	<span class="label important">${1:Important}</span>
-snippet success
-	<span class="label success">${1:Success}</span>
-snippet label
-	<span class="label">${1:Note}</span>
--- a/vim/snippets/objc.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-# #import <...>
-snippet Imp
-	#import <${1:Cocoa/Cocoa.h}>${2}
-# #import "..."
-snippet imp
-	#import "${1:`Filename()`.h}"${2}
-# @selector(...)
-snippet sel
-	@selector(${1:method}:)${3}
-# @"..." string
-snippet s
-	@"${1}"${2}
-# Object
-snippet o
-	${1:NSObject} *${2:foo} = [${3:$1 alloc}]${4};${5}
-# NSLog(...)
-snippet log
-	NSLog(@"${1:%@}"${2});${3}
-# Class
-snippet objc
-	@interface ${1:`Filename('', 'someClass')`} : ${2:NSObject}
-	{
-	}
-	@end
-
-	@implementation $1
-	${3}
-	@end
-# Class Interface
-snippet int
-	@interface ${1:`Filename('', 'someClass')`} : ${2:NSObject}
-	{${3}
-	}
-	${4}
-	@end
-# Class Implementation
-snippet impl
-	@implementation ${1:`Filename('', 'someClass')`}
-	${2}
-	@end
-snippet init
-	- (id)init
-	{
-		[super init];
-		return self;
-	}
-snippet ifself
-	if (self = [super init]) {
-		${1:/* code */}
-	}
-	return self;
-snippet ibo
-	IBOutlet ${1:NSSomeClass} *${2:$1};${3}
-# Category
-snippet cat
-	@interface ${1:NSObject} (${2:Category})
-	@end
-
-	@implementation $1 ($2)
-	${3}
-	@end
-# Category Interface
-snippet cath
-	@interface ${1:NSObject} (${2:Category})
-	${3}
-	@end
-# NSArray
-snippet array
-	NSMutableArray *${1:array} = [NSMutable array];${2}
-# NSDictionary
-snippet dict
-	NSMutableDictionary *${1:dict} = [NSMutableDictionary dictionary];${2}
-# NSBezierPath
-snippet bez
-	NSBezierPath *${1:path} = [NSBezierPath bezierPath];${2}
-# Method
-snippet m
-	- (${1:id})${2:method}
-	{
-		${3}
-	}
-# Method declaration
-snippet md
-	- (${1:id})${2:method};${3}
-# IBAction declaration
-snippet ibad
-	- (IBAction)${1:method}:(${2:id})sender;${3}
-# IBAction method
-snippet iba
-	- (IBAction)${1:method}:(${2:id})sender
-	{
-		${3}
-	}
-# awakeFromNib method
-snippet wake
-	- (void)awakeFromNib
-	{
-		${1}
-	}
-# Class Method
-snippet M
-	+ (${1:id})${2:method}
-	{${3}
-		return nil;
-	}
-# Sub-method (Call super)
-snippet sm
-	- (${1:id})${2:method}
-	{
-		[super $2];${3}
-		return self;
-	}
-# Method: Initialize
-snippet I
-	+ (void) initialize
-	{
-		[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWIthObjectsAndKeys:
-			${1}@"value", @"key",
-			nil]];
-	}
-# Accessor Methods For:
-# Object
-snippet objacc
-	- (${1:id})${2:thing}
-	{
-		return $2;
-	}
-
-	- (void)set$2:($1)${3:new$2}
-	{
-		[$3 retain];
-		[$2 release];
-		$2 = $3;
-	}${4}
-# for (object in array)
-snippet forin
-	for (${1:Class} *${2:some$1} in ${3:array}) {
-		${4}
-	}
-snippet forarray
-	unsigned int ${1:object}Count = [${2:array} count];
-
-	for (unsigned int index = 0; index < $1Count; index++) {
-		${3:id} $1 = [$2 $1AtIndex:index];
-		${4}
-	}
-# IBOutlet
-# @property (Objective-C 2.0)
-snippet prop
-	@property (${1:retain}) ${2:NSSomeClass} ${3:*$2};${4}
-# @synthesize (Objective-C 2.0)
-snippet syn
-	@synthesize ${1:property};${2}
-# [[ alloc] init]
-snippet alloc
-	[[${1:foo} alloc] init${2}];${3}
-# retain
-snippet ret
-	[${1:foo} retain];${2}
-# release
-snippet rel
-	[${1:foo} release];
-	${2:$1 = nil;}
-# autorelease
-snippet arel
-	[${1:foo} autorelease];
-# autorelease pool
-snippet pool
-	NSAutoreleasePool *${1:pool} = [[NSAutoreleasePool alloc] init];
-	${2:/* code */}
-	[$1 drain];
-# Throw an exception
-snippet except
-	NSException *${1:badness};
-	$1 = [NSException exceptionWithName:@"${2:$1Name}"
-	                             reason:@"${3}"
-	                           userInfo:nil];
-	[$1 raise];
-snippet prag
-	#pragma mark ${1:foo}
-snippet cl
-	@class ${1:Foo};${2}
-snippet color
-	[[NSColor ${1:blackColor}] set];
--- a/vim/snippets/perl.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-# #!/usr/bin/perl
-snippet #!
-	#!/usr/bin/perl
-	
-# Hash Pointer
-snippet .
-	 =>
-# Function
-snippet sub
-	sub ${1:function_name} {
-		${2:#body ...}
-	}
-# Conditional
-snippet if
-	if (${1}) {
-		${2:# body...}
-	}
-# Conditional if..else
-snippet ife
-	if (${1}) {
-		${2:# body...}
-	} else {
-		${3:# else...}
-	}
-# Conditional if..elsif..else
-snippet ifee
-	if (${1}) {
-		${2:# body...}
-	} elsif (${3}) {
-		${4:# elsif...}
-	} else {
-		${5:# else...}
-	}
-# Conditional One-line
-snippet xif
-	${1:expression} if ${2:condition};${3}
-# Unless conditional
-snippet unless
-	unless (${1}) {
-		${2:# body...}
-	}
-# Unless conditional One-line
-snippet xunless
-	${1:expression} unless ${2:condition};${3}
-# Try/Except
-snippet eval
-	eval {
-		${1:# do something risky...}
-	};
-	if ($@) {
-		${2:# handle failure...}
-	}
-# While Loop
-snippet wh
-	while (${1}) {
-		${2:# body...}
-	}
-# While Loop One-line
-snippet xwh
-	${1:expression} while ${2:condition};${3}
-# For Loop
-snippet for
-	for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) {
-		${4:# body...}
-	}
-# Foreach Loop
-snippet fore
-	foreach my $${1:x} (@${2:array}) {
-		${3:# body...}
-	}
-# Foreach Loop One-line
-snippet xfore
-	${1:expression} foreach @${2:array};${3}
-# Package
-snippet cl
-	package ${1:ClassName};
-	
-	use base qw(${2:ParentClass});
-	
-	sub new {
-		my $class = shift;
-		$class = ref $class if ref $class;
-		my $self = bless {}, $class;
-		$self;
-	}
-	
-	1;${3}
-# Read File
-snippet slurp
-	my $${1:var};
-	{ local $/ = undef; local *FILE; open FILE, "<${2:file}"; $$1 = <FILE>; close FILE }${3}
--- a/vim/snippets/php.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-snippet php
-	<?php
-	${1}
-	?>
-snippet ec
-	echo "${1:string}"${2};
-snippet inc
-	include '${1:file}';${2}
-snippet inc1
-	include_once '${1:file}';${2}
-snippet req
-	require '${1:file}';${2}
-snippet req1
-	require_once '${1:file}';${2}
-# $GLOBALS['...']
-snippet globals
-	$GLOBALS['${1:variable}']${2: = }${3:something}${4:;}${5}
-snippet $_ COOKIE['...']
-	$_COOKIE['${1:variable}']${2}
-snippet $_ ENV['...']
-	$_ENV['${1:variable}']${2}
-snippet $_ FILES['...']
-	$_FILES['${1:variable}']${2}
-snippet $_ Get['...']
-	$_GET['${1:variable}']${2}
-snippet $_ POST['...']
-	$_POST['${1:variable}']${2}
-snippet $_ REQUEST['...']
-	$_REQUEST['${1:variable}']${2}
-snippet $_ SERVER['...']
-	$_SERVER['${1:variable}']${2}
-snippet $_ SESSION['...']
-	$_SESSION['${1:variable}']${2}
-# Start Docblock
-snippet /*
-	/**
-	 * ${1}
-	 **/
-# Class - post doc
-snippet doc_cp
-	/**
-	 * ${1:undocumented class}
-	 *
-	 * @package ${2:default}
-	 * @author ${3:`g:snips_author`}
-	**/${4}
-# Class Variable - post doc
-snippet doc_vp
-	/**
-	 * ${1:undocumented class variable}
-	 *
-	 * @var ${2:string}
-	 **/${3}
-# Class Variable
-snippet doc_v
-	/**
-	 * ${3:undocumented class variable}
-	 *
-	 * @var ${4:string}
-	 **/
-	${1:var} $${2};${5}
-# Class
-snippet doc_c
-	/**
-	 * ${3:undocumented class}
-	 *
-	 * @packaged ${4:default}
-	 * @author ${5:`g:snips_author`}
-	 **/
-	${1:}class ${2:}
-	{${6}
-	} // END $1class $2
-# Constant Definition - post doc
-snippet doc_dp
-	/**
-	 * ${1:undocumented constant}
-	 **/${2}
-# Constant Definition
-snippet doc_d
-	/**
-	 * ${3:undocumented constant}
-	 **/
-	define(${1}, ${2});${4}
-# Function - post doc
-snippet doc_fp
-	/**
-	 * ${1:undocumented function}
-	 *
-	 * @return ${2:void}
-	 * @author ${3:`g:snips_author`}
-	 **/${4}
-# Function signature
-snippet doc_s
-	/**
-	 * ${4:undocumented function}
-	 *
-	 * @return ${5:void}
-	 * @author ${6:`g:snips_author`}
-	 **/
-	${1}function ${2}(${3});${7}
-# Function
-snippet doc_f
-	/**
-	 * ${4:undocumented function}
-	 *
-	 * @return ${5:void}
-	 * @author ${6:`g:snips_author`}
-	 **/
-	${1}function ${2}(${3})
-	{${7}
-	}
-# Header
-snippet doc_h
-	/**
-	 * ${1}
-	 *
-	 * @author ${2:`g:snips_author`}
-	 * @version ${3:$Id$}
-	 * @copyright ${4:$2}, `strftime('%d %B, %Y')`
-	 * @package ${5:default}
-	 **/
-	
-	/**
-	 * Define DocBlock
-	 *//
-# Interface
-snippet doc_i
-	/**
-	 * ${2:undocumented class}
-	 *
-	 * @package ${3:default}
-	 * @author ${4:`g:snips_author`}
-	 **/
-	interface ${1:}
-	{${5}
-	} // END interface $1
-# class ...
-snippet class
-	/**
-	 * ${1}
-	 **/
-	class ${2:ClassName}
-	{
-		${3}
-		function ${4:__construct}(${5:argument})
-		{
-			${6:// code...}
-		}
-	}
-# define(...)
-snippet def
-	define('${1}'${2});${3}
-# defined(...)
-snippet def?
-	${1}defined('${2}')${3}
-snippet wh
-	while (${1:/* condition */}) {
-		${2:// code...}
-	}
-# do ... while
-snippet do
-	do {
-		${2:// code... }
-	} while (${1:/* condition */});
-snippet if
-	if (${1:/* condition */}) {
-		${2:// code...}
-	}
-snippet ife
-	if (${1:/* condition */}) {
-		${2:// code...}
-	} else {
-		${3:// code...}
-	}
-	${4}
-snippet else
-	else {
-		${1:// code...}
-	}
-snippet elseif
-	elseif (${1:/* condition */}) {
-		${2:// code...}
-	}
-# Tertiary conditional
-snippet t
-	$${1:retVal} = (${2:condition}) ? ${3:a} : ${4:b};${5}
-snippet switch
-	switch ($${1:variable}) {
-		case '${2:value}':
-			${3:// code...}
-			break;
-		${5}
-		default:
-			${4:// code...}
-			break;
-	}
-snippet case
-	case '${1:value}':
-		${2:// code...}
-		break;${3}
-snippet for
-	for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) {
-		${4: // code...}
-	}
-snippet foreach
-	foreach ($${1:variable} as $${2:key}) {
-		${3:// code...}
-	}
-snippet fun
-	${1:public }function ${2:FunctionName}(${3})
-	{
-		${4:// code...}
-	}
-# $... = array (...)
-snippet array
-	$${1:arrayName} = array('${2}' => ${3});${4}
--- a/vim/snippets/python.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-snippet #!
-	#!/usr/bin/env python
-snippet from
-	from ${1:sys} import ${2:*}
-snippet while
-	while ${1:True}:
-		${2:pass}
-snippet for
-	for ${1:x} in ${2:xs}:
-		${3:pass}
-snippet def
-	def ${1:function}(${2}):
-		${3:pass}
-snippet defs
-	def ${1:method}(self${2}):
-		${3:pass}
-snippet lam
-	lambda ${1:args}: ${2:action}
-snippet ifmain
-	if __name__ == '__main__':
-		${1:main()}
-snippet _
-	__${1:init}__${2}
-snippet ***
-	*args, **kwargs
-snippet af
-	assert False, repr(${1})$2
-snippet pdbt
-	import pdb; pdb.set_trace()
-snippet pp
-	from pprint import pprint; pprint($1)$2
--- a/vim/snippets/ruby.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,420 +0,0 @@
-# #!/usr/bin/ruby
-snippet #!
-	#!/usr/bin/ruby
-
-# New Block
-snippet =b
-	=begin rdoc
-		${1}
-	=end
-snippet y
-	:yields: ${1:arguments}
-snippet rb
-	#!/usr/bin/env ruby -wKU
-
-snippet req
-	require "${1}"${2}
-snippet #
-	# =>
-snippet end
-	__END__
-snippet case
-	case ${1:object}
-	when ${2:condition}
-		${3}
-	end
-snippet when
-	when ${1:condition}
-		${2}
-snippet def
-	def ${1:method_name}
-		${2}
-	end
-snippet deft
-	def test_${1:case_name}
-		${2}
-	end
-snippet if
-	if ${1:condition}
-		${2}
-	end
-snippet ife
-	if ${1:condition}
-		${2}
-	else
-		${3}
-	end
-snippet elsif
-	elsif ${1:condition}
-		${2}
-snippet unless
-	unless ${1:condition}
-		${2}
-	end
-snippet while
-	while ${1:condition}
-		${2}
-	end
-snippet until
-	until ${1:condition}
-		${2}
-	end
-snippet cla class .. end
-	class ${1:`substitute(Filename(), '^.', '\u&', '')`}
-		${2}
-	end
-snippet cla class .. initialize .. end
-	class ${1:`substitute(Filename(), '^.', '\u&', '')`}
-		def initialize(${2:args})
-			${3}
-		end
-
-
-	end
-snippet cla class .. < ParentClass .. initialize .. end
-	class ${1:`substitute(Filename(), '^.', '\u&', '')`} < ${2:ParentClass}
-		def initialize(${3:args})
-			${4}
-		end
-
-
-	end
-snippet cla ClassName = Struct .. do .. end
-	${1:`substitute(Filename(), '^.', '\u&', '')`} = Struct.new(:${2:attr_names}) do
-		def ${3:method_name}
-			${4}
-		end
-
-
-	end
-snippet cla class BlankSlate .. initialize .. end
-	class ${1:BlankSlate}
-		instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ }
-snippet cla class << self .. end
-	class << ${1:self}
-		${2}
-	end
-# class .. < DelegateClass .. initialize .. end
-snippet cla-
-	class ${1:`substitute(Filename(), '^.', '\u&', '')`} < DelegateClass(${2:ParentClass})
-		def initialize(${3:args})
-			super(${4:del_obj})
-
-			${5}
-		end
-
-
-	end
-snippet mod module .. end
-	module ${1:`substitute(Filename(), '^.', '\u&', '')`}
-		${2}
-	end
-snippet mod module .. module_function .. end
-	module ${1:`substitute(Filename(), '^.', '\u&', '')`}
-		module_function
-
-		${2}
-	end
-snippet mod module .. ClassMethods .. end
-	module ${1:`substitute(Filename(), '^.', '\u&', '')`}
-		module ClassMethods
-			${2}
-		end
-
-		module InstanceMethods
-
-		end
-
-		def self.included(receiver)
-			receiver.extend         ClassMethods
-			receiver.send :include, InstanceMethods
-		end
-	end
-# attr_reader
-snippet r
-	attr_reader :${1:attr_names}
-# attr_writer
-snippet w
-	attr_writer :${1:attr_names}
-# attr_accessor
-snippet rw
-	attr_accessor :${1:attr_names}
-# include Enumerable
-snippet Enum
-	include Enumerable
-
-	def each(&block)
-		${1}
-	end
-# include Comparable
-snippet Comp
-	include Comparable
-
-	def <=>(other)
-		${1}
-	end
-# extend Forwardable
-snippet Forw-
-	extend Forwardable
-# def self
-snippet defs
-	def self.${1:class_method_name}
-		${2}
-	end
-# def method_missing
-snippet defmm
-	def method_missing(meth, *args, &blk)
-		${1}
-	end
-snippet defd
-	def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name}
-snippet defds
-	def_delegators :${1:@del_obj}, :${2:del_methods}
-snippet am
-	alias_method :${1:new_name}, :${2:old_name}
-snippet app
-	if __FILE__ == $PROGRAM_NAME
-		${1}
-	end
-# usage_if()
-snippet usai
-	if ARGV.${1}
-		abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
-	end
-# usage_unless()
-snippet usau
-	unless ARGV.${1}
-		abort "Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}"${3}
-	end
-snippet array
-	Array.new(${1:10}) { |${2:i}| ${3} }
-snippet hash
-	Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} }
-snippet file File.foreach() { |line| .. }
-	File.foreach(${1:"path/to/file"}) { |${2:line}| ${3} }
-snippet file File.read()
-	File.read(${1:"path/to/file"})${2}
-snippet Dir Dir.global() { |file| .. }
-	Dir.glob(${1:"dir/glob/*"}) { |${2:file}| ${3} }
-snippet Dir Dir[".."]
-	Dir[${1:"glob/**/*.rb"}]${2}
-snippet dir
-	Filename.dirname(__FILE__)
-snippet deli
-	delete_if { |${1:e}| ${2} }
-snippet fil
-	fill(${1:range}) { |${2:i}| ${3} }
-# flatten_once()
-snippet flao
-	inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3}
-snippet zip
-	zip(${1:enums}) { |${2:row}| ${3} }
-# downto(0) { |n| .. }
-snippet dow
-	downto(${1:0}) { |${2:n}| ${3} }
-snippet ste
-	step(${1:2}) { |${2:n}| ${3} }
-snippet tim
-	times { |${1:n}| ${2} }
-snippet upt
-	upto(${1:1.0/0.0}) { |${2:n}| ${3} }
-snippet loo
-	loop { ${1} }
-snippet ea
-	each { |${1:e}| ${2} }
-snippet eab
-	each_byte { |${1:byte}| ${2} }
-snippet eac- each_char { |chr| .. }
-	each_char { |${1:chr}| ${2} }
-snippet eac- each_cons(..) { |group| .. }
-	each_cons(${1:2}) { |${2:group}| ${3} }
-snippet eai
-	each_index { |${1:i}| ${2} }
-snippet eak
-	each_key { |${1:key}| ${2} }
-snippet eal
-	each_line { |${1:line}| ${2} }
-snippet eap
-	each_pair { |${1:name}, ${2:val}| ${3} }
-snippet eas-
-	each_slice(${1:2}) { |${2:group}| ${3} }
-snippet eav
-	each_value { |${1:val}| ${2} }
-snippet eawi
-	each_with_index { |${1:e}, ${2:i}| ${3} }
-snippet reve
-	reverse_each { |${1:e}| ${2} }
-snippet inj
-	inject(${1:init}) { |${2:mem}, ${3:var}| ${4} }
-snippet map
-	map { |${1:e}| ${2} }
-snippet mapwi-
-	enum_with_index.map { |${1:e}, ${2:i}| ${3} }
-snippet sor
-	sort { |a, b| ${1} }
-snippet sorb
-	sort_by { |${1:e}| ${2} }
-snippet ran
-	sort_by { rand }
-snippet all
-	all? { |${1:e}| ${2} }
-snippet any
-	any? { |${1:e}| ${2} }
-snippet cl
-	classify { |${1:e}| ${2} }
-snippet col
-	collect { |${1:e}| ${2} }
-snippet det
-	detect { |${1:e}| ${2} }
-snippet fet
-	fetch(${1:name}) { |${2:key}| ${3} }
-snippet fin
-	find { |${1:e}| ${2} }
-snippet fina
-	find_all { |${1:e}| ${2} }
-snippet gre
-	grep(${1:/pattern/}) { |${2:match}| ${3} }
-snippet sub
-	${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} }
-snippet sca
-	scan(${1:/pattern/}) { |${2:match}| ${3} }
-snippet max
-	max { |a, b|, ${1} }
-snippet min
-	min { |a, b|, ${1} }
-snippet par
-	partition { |${1:e}|, ${2} }
-snippet rej
-	reject { |${1:e}|, ${2} }
-snippet sel
-	select { |${1:e}|, ${2} }
-snippet lam
-	lambda { |${1:args}| ${2} }
-snippet do
-	do |${1:variable}|
-		${2}
-	end
-snippet :
-	:${1:key} => ${2:"value"}${3}
-snippet ope
-	open(${1:"path/or/url/or/pipe"}, "${2:w}") { |${3:io}| ${4} }
-# path_from_here()
-snippet patfh
-	File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2}
-# unix_filter {}
-snippet unif
-	ARGF.each_line${1} do |${2:line}|
-		${3}
-	end
-# option_parse {}
-snippet optp
-	require "optparse"
-
-	options = {${1:default => "args"}}
-
-	ARGV.options do |opts|
-		opts.banner = "Usage: #{File.basename($PROGRAM_NAME)}
-snippet opt
-	opts.on( "-${1:o}", "--${2:long-option-name}", ${3:String},
-	         "${4:Option description.}") do |${5:opt}|
-		${6}
-	end
-snippet tc
-	require "test/unit"
-
-	require "${1:library_file_name}"
-
-	class Test${2:$1} < Test::Unit::TestCase
-		def test_${3:case_name}
-			${4}
-		end
-	end
-snippet ts
-	require "test/unit"
-
-	require "tc_${1:test_case_file}"
-	require "tc_${2:test_case_file}"${3}
-snippet as
-	assert(${1:test}, "${2:Failure message.}")${3}
-snippet ase
-	assert_equal(${1:expected}, ${2:actual})${3}
-snippet asne
-	assert_not_equal(${1:unexpected}, ${2:actual})${3}
-snippet asid
-	assert_in_delta(${1:expected_float}, ${2:actual_float}, ${3:2 ** -20})${4}
-snippet asio
-	assert_instance_of(${1:ExpectedClass}, ${2:actual_instance})${3}
-snippet asko
-	assert_kind_of(${1:ExpectedKind}, ${2:actual_instance})${3}
-snippet asn
-	assert_nil(${1:instance})${2}
-snippet asnn
-	assert_not_nil(${1:instance})${2}
-snippet asm
-	assert_match(/${1:expected_pattern}/, ${2:actual_string})${3}
-snippet asnm
-	assert_no_match(/${1:unexpected_pattern}/, ${2:actual_string})${3}
-snippet aso
-	assert_operator(${1:left}, :${2:operator}, ${3:right})${4}
-snippet asr
-	assert_raise(${1:Exception}) { ${2} }
-snippet asnr
-	assert_nothing_raised(${1:Exception}) { ${2} }
-snippet asrt
-	assert_respond_to(${1:object}, :${2:method})${3}
-snippet ass assert_same(..)
-	assert_same(${1:expected}, ${2:actual})${3}
-snippet ass assert_send(..)
-	assert_send([${1:object}, :${2:message}, ${3:args}])${4}
-snippet asns
-	assert_not_same(${1:unexpected}, ${2:actual})${3}
-snippet ast
-	assert_throws(:${1:expected}) { ${2} }
-snippet asnt
-	assert_nothing_thrown { ${1} }
-snippet fl
-	flunk("${1:Failure message.}")${2}
-# Benchmark.bmbm do .. end
-snippet bm-
-	TESTS = ${1:10_000}
-	Benchmark.bmbm do |results|
-		${2}
-	end
-snippet rep
-	results.report("${1:name}:") { TESTS.times { ${2} }}
-# Marshal.dump(.., file)
-snippet Md
-	File.open(${1:"path/to/file.dump"}, "wb") { |${2:file}| Marshal.dump(${3:obj}, $2) }${4}
-# Mashal.load(obj)
-snippet Ml
-	File.open(${1:"path/to/file.dump"}, "rb") { |${2:file}| Marshal.load($2) }${3}
-# deep_copy(..)
-snippet deec
-	Marshal.load(Marshal.dump(${1:obj_to_copy}))${2}
-snippet Pn-
-	PStore.new(${1:"file_name.pstore"})${2}
-snippet tra
-	transaction(${1:true}) { ${2} }
-# xmlread(..)
-snippet xml-
-	REXML::Document.new(File.read(${1:"path/to/file"}))${2}
-# xpath(..) { .. }
-snippet xpa
-	elements.each(${1:"//Xpath"}) do |${2:node}|
-		${3}
-	end
-# class_from_name()
-snippet clafn
-	split("::").inject(Object) { |par, const| par.const_get(const) }
-# singleton_class()
-snippet sinc
-	class << self; self end
-snippet nam
-	namespace :${1:`Filename()`} do
-		${2}
-	end
-snippet tas
-	desc "${1:Task description\}"
-	task :${2:task_name => [:dependent, :tasks]} do
-		${3}
-	end
--- a/vim/snippets/scheme.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-snippet def
-	(define (${1:name} ${2:args})
-		(${3:body}))
--- a/vim/snippets/sh.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-# #!/bin/bash
-snippet #!
-	#!/bin/bash
-	
-snippet if
-	if [[ ${1:condition} ]]; then
-		${2:#statements}
-	fi
-snippet elif
-	elif [[ ${1:condition} ]]; then
-		${2:#statements}
-snippet for
-	for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do
-		${3:#statements}
-	done
-snippet wh
-	while [[ ${1:condition} ]]; do
-		${2:#statements}
-	done
-snippet until
-	until [[ ${1:condition} ]]; do
-		${2:#statements}
-	done
-snippet case
-	case ${1:word} in
-		${2:pattern})
-			${3};;
-	esac
--- a/vim/snippets/snippet.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-# snippets for making snippets :)
-snippet snip
-	snippet ${1:trigger}
-		${2}
-snippet msnip
-	snippet ${1:trigger} ${2:description}
-		${3}
--- a/vim/snippets/tcl.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-# #!/usr/bin/tclsh
-snippet #!
-	#!/usr/bin/tclsh
-	
-# Process
-snippet pro
-	proc ${1:function_name} {${2:args}} {
-		${3:#body ...}
-	}
-#xif
-snippet xif
-	${1:expr}? ${2:true} : ${3:false}
-# Conditional
-snippet if
-	if {${1}} {
-		${2:# body...}
-	}
-# Conditional if..else
-snippet ife
-	if {${1}} {
-		${2:# body...}
-	} else {
-		${3:# else...}
-	}
-# Conditional if..elsif..else
-snippet ifee
-	if {${1}} {
-		${2:# body...}
-	} elseif {${3}} {
-		${4:# elsif...}
-	} else {
-		${5:# else...}
-	}
-# If catch then
-snippet ifc
-	if { [catch {${1:#do something...}} ${2:err}] } {
-		${3:# handle failure...}
-	}
-# Catch
-snippet catch
-	catch {${1}} ${2:err} ${3:options}
-# While Loop
-snippet wh
-	while {${1}} {
-		${2:# body...}
-	}
-# For Loop
-snippet for
-	for {set ${2:var} 0} {$$2 < ${1:count}} {${3:incr} $2} {
-		${4:# body...}
-	}
-# Foreach Loop
-snippet fore
-	foreach ${1:x} {${2:#list}} {
-		${3:# body...}
-	}
-# after ms script...
-snippet af
-	after ${1:ms} ${2:#do something}
-# after cancel id
-snippet afc
-	after cancel ${1:id or script}
-# after idle
-snippet afi
-	after idle ${1:script}
-# after info id
-snippet afin
-	after info ${1:id}
-# Expr
-snippet exp
-	expr {${1:#expression here}}
-# Switch
-snippet sw
-	switch ${1:var} {
-		${3:pattern 1} {
-			${4:#do something}
-		}
-		default {
-			${2:#do something}
-		}
-	}
-# Case
-snippet ca
-	${1:pattern} {
-		${2:#do something}
-	}${3}
-# Namespace eval
-snippet ns
-	namespace eval ${1:path} {${2:#script...}}
-# Namespace current
-snippet nsc
-	namespace current
--- a/vim/snippets/tex.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-# \begin{}...\end{}
-snippet begin
-	\begin{${1:env}}
-		${2}
-	\end{$1}
-# Tabular
-snippet tab
-	\begin{${1:tabular}}{${2:c}}
-	${3}
-	\end{$1}
-# Align(ed)
-snippet ali
-	\begin{align${1:ed}}
-		${2}
-	\end{align$1}
-# Gather(ed)
-snippet gat
-	\begin{gather${1:ed}}
-		${2}
-	\end{gather$1}
-# Equation
-snippet eq
-	\begin{equation}
-		${1}
-	\end{equation}
-# Unnumbered Equation
-snippet \
-	\\[
-		${1}
-	\\]
-# Enumerate
-snippet enum
-	\begin{enumerate}
-		\item ${1}
-	\end{enumerate}
-# Itemize
-snippet item
-	\begin{itemize}
-		\item ${1}
-	\end{itemize}
-# Description
-snippet desc
-	\begin{description}
-		\item[${1}] ${2}
-	\end{description}
-# Matrix
-snippet mat
-	\begin{${1:p/b/v/V/B/small}matrix}
-		${2}
-	\end{$1matrix}
-# Cases
-snippet cas
-	\begin{cases}
-		${1:equation}, &\text{ if }${2:case}\\
-		${3}
-	\end{cases}
-# Split
-snippet spl
-	\begin{split}
-		${1}
-	\end{split}
-# Part
-snippet part
-	\part{${1:part name}} % (fold)
-	\label{prt:${2:$1}}
-	${3}
-	% part $2 (end)
-# Chapter
-snippet cha
-	\chapter{${1:chapter name}} % (fold)
-	\label{cha:${2:$1}}
-	${3}
-	% chapter $2 (end)
-# Section
-snippet sec
-	\section{${1:section name}} % (fold)
-	\label{sec:${2:$1}}
-	${3}
-	% section $2 (end)
-# Sub Section
-snippet sub
-	\subsection{${1:subsection name}} % (fold)
-	\label{sub:${2:$1}}
-	${3}
-	% subsection $2 (end)
-# Sub Sub Section
-snippet subs
-	\subsubsection{${1:subsubsection name}} % (fold)
-	\label{ssub:${2:$1}}
-	${3}
-	% subsubsection $2 (end)
-# Paragraph
-snippet par
-	\paragraph{${1:paragraph name}} % (fold)
-	\label{par:${2:$1}}
-	${3}
-	% paragraph $2 (end)
-# Sub Paragraph
-snippet subp
-	\subparagraph{${1:subparagraph name}} % (fold)
-	\label{subp:${2:$1}}
-	${3}
-	% subparagraph $2 (end)
-snippet itd
-	\item[${1:description}] ${2:item}
-snippet figure
-	${1:Figure}~\ref{${2:fig:}}${3}
-snippet table
-	${1:Table}~\ref{${2:tab:}}${3}
-snippet listing
-	${1:Listing}~\ref{${2:list}}${3}
-snippet section
-	${1:Section}~\ref{${2:sec:}}${3}
-snippet page
-	${1:page}~\pageref{${2}}${3}
--- a/vim/snippets/vim.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-snippet header
-	" File: ${1:`expand('%:t')`}
-	" Author: ${2:`g:snips_author`}
-	" Description: ${3}
-	${4:" Last Modified: `strftime("%B %d, %Y")`}
-snippet guard
-	if exists('${1:did_`Filename()`}') || &cp${2: || version < 700}
-		finish
-	endif
-	let $1 = 1${3}
-snippet f
-	fun ${1:function_name}(${2})
-		${3:" code}
-	endf
-snippet for
-	for ${1:needle} in ${2:haystack}
-		${3:" code}
-	endfor
-snippet wh
-	while ${1:condition}
-		${2:" code}
-	endw
-snippet if
-	if ${1:condition}
-		${2:" code}
-	endif
-snippet ife
-	if ${1:condition}
-		${2}
-	else
-		${3}
-	endif
--- a/vim/snippets/zsh.snippets	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-# #!/bin/zsh
-snippet #!
-	#!/bin/zsh
-
-snippet if
-	if ${1:condition}; then
-		${2:# statements}
-	fi
-snippet ife
-	if ${1:condition}; then
-		${2:# statements}
-	else
-		${3:# statements}
-	fi
-snippet elif
-	elif ${1:condition} ; then
-		${2:# statements}
-snippet for
-	for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do
-		${3:# statements}
-	done
-snippet fore
-	for ${1:item} in ${2:list}; do
-		${3:# statements}
-	done
-snippet wh
-	while ${1:condition}; do
-		${2:# statements}
-	done
-snippet until
-	until ${1:condition}; do
-		${2:# statements}
-	done
-snippet repeat
-	repeat ${1:integer}; do
-		${2:# statements}
-	done
-snippet case
-	case ${1:word} in
-		${2:pattern})
-			${3};;
-	esac
-snippet select
-	select ${1:answer} in ${2:choices}; do
-		${3:# statements}
-	done
-snippet (
-	( ${1:#statements} )
-snippet {
-	{ ${1:#statements} }
-snippet [
-	[[ ${1:test} ]]
-snippet always
-	{ ${1:try} } always { ${2:always} }
-snippet fun
-	function ${1:name} (${2:args}) {
-		${3:# body}
-	}
--- a/vim/syntax/confluencewiki.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-"============================================================================
-"
-" Confluence WIKI syntax file
-"
-" Language:    Confluence WIKI
-" Version:     0.1.0
-" Maintainer:  Daniel Grana <daniel{AT}insophia{DOT}com>
-" Thanks:      Ingo Karkat <swdev{AT}ingo-karkat{DOT}de>
-" License:     GPL (http://www.gnu.org/licenses/gpl.txt)
-"    Copyright (C) 2004  Rainer Thierfelder
-"
-"    This program is free software; you can redistribute it and/or modify
-"    it under the terms of the GNU General Public License as published by
-"    the Free Software Foundation; either version 2 of the License, or
-"    (at your option) any later version.
-"
-"    This program is distributed in the hope that it will be useful,
-"    but WITHOUT ANY WARRANTY; without even the implied warranty of
-"    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-"    GNU General Public License for more details.
-"
-"    You should have received a copy of the GNU General Public License
-"    along with this program; if not, write to the Free Software
-"    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
-"
-"============================================================================
-"
-" For version 5.x: Clear all syntax items
-" For version 6.x: Quit when a syntax file was already loaded
-if !exists("main_syntax")
-  if version < 600
-    syntax clear
-  elseif exists("b:current_syntax")
-    finish
-  endif
-  let main_syntax = 'confluencewiki'
-endif
-
-" Don't use standard HiLink, it will not work with included syntax files
-if version < 508
-  command! -nargs=+ ConfluenceHiLink   highlight link <args>
-  command! -nargs=+ ConfluenceSynColor highlight <args>
-else
-  command! -nargs=+ ConfluenceHiLink   highlight default link <args>
-  command! -nargs=+ ConfluenceSynColor highlight default <args>
-endif
-
-if v:version >= 700
-  syntax spell toplevel
-endif 
-
-
-"============================================================================
-" Group Definitions:    
-"============================================================================
-
-" Emphasis:  
-function! s:ConfluenceCreateEmphasis(token, name)
-    execute 'syntax region confluence'.a:name.
-    \' oneline start="\(^\|[ ]\)\zs'.a:token.'\%('.a:token.'\)\@!'.
-    \'" end="'.a:token.'\ze\([,. ?!()[\]{}:\-]\|$\)"'
-endfunction
-
-syntax region confluenceFixed oneline start="\(^\|[ ]\)\zs{{" end="}}\ze\([,. ?!()[\]{}):\-]\|$\)"
-" Note: Confluence 2.10.1 ignores escaping of \{{monospaced}} (same as {{monospaced}}). 
-syntax region confluenceFixed oneline start="{{" end="}}\ze\([,. ?!()[\]{}):\-]\|$\)" contained
-
-call s:ConfluenceCreateEmphasis('\*', 'Bold')
-call s:ConfluenceCreateEmphasis('_',  'Italic')
-call s:ConfluenceCreateEmphasis('??', 'Citation')
-call s:ConfluenceCreateEmphasis('-', 'Strike')
-call s:ConfluenceCreateEmphasis('+', 'Underlined')
-call s:ConfluenceCreateEmphasis('\^', 'Superscript')
-call s:ConfluenceCreateEmphasis('\~', 'Subscript')
-
-
-" Syntax:  
-" Note: Confluence 2.10.1 ignores escaping of \{{monospaced}} (same as {{monospaced}}). 
-"syntax match confluenceEscaping "\\\%(??\|{{\|[*_\-+^~{!\[(]\)" contains=confluenceEscapeCharacter
-syntax match confluenceEscaping "\\\%(??\|{{\|[*_\-+^~{!\[(]\)" contains=confluenceEscapeCharacter,confluenceFixed
-syntax match confluenceEscapeCharacter "\\" contained
-syntax match confluenceDelimiter "|"
-syntax match confluenceDelimiter "||[^|]" contains=confluenceTableHeader
-syntax match confluenceDelimiter "[^|]||"
-syntax match confluenceTableHeader "||\zs[^|]\+\ze||" contained contains=ALLBUT,confluenceDelimiter
-syntax match confluenceSymbols "\%(^\|\s\)\zs-\{2,3}\ze\%($\|\s\)"
-syntax match confluenceSeparator    "^\s*----\s*$"
-syntax match confluenceList "^[*#]\+\ze "
-syntax match confluenceSingleList "^-\ze "
-
-"syntax match confluenceVariable "\([^!]\|^\)\zs%\w\+%"
-
-" tag support is a limited to no white spaces in tag parameters
-syntax match confluenceTagParameterName      "[:|]\zs\w\+=\?[^|}]\+" contained contains=@NoSpell,confluenceTagParameterValue
-syntax match confluenceTagParameterValue     "\w\+=\zs[^|}]\+" contained contains=@NoSpell
-syntax match confluenceTag                   "{\%(\w\|-\)\+\(:\(\w\+=\?[^|}]\+|\?\)*\)\?}" contains=@NoSpell,confluenceTagParameterName
-
-syntax region confluenceComment start="{HTMLcomment\%(:hidden\)\?}" end="{HTMLcomment}" keepend contains=TOP
-
-syntax match confluenceCodeTag "{code\(:\(\w\+=\?[^|}]\+|\?\)*\)\?}" contains=confluenceTagParameterName,@NoSpell contained
-syntax region confluenceCode start="{code\(:\(\w\+=\?[^|}]\+|\?\)*\)\?}" end="{code}" keepend contains=confluenceCodeTag
-syntax match confluenceVerbatimTag "{noformat\(:\(\w\+=\?[^|}]\+|\?\)*\)\?}" contains=confluenceTagParameterName,@NoSpell contained
-syntax region confluenceVerbatim start="{noformat\(:\(\w\+=\?[^|}]\+|\?\)*\)\?}" end="{noformat}" keepend contains=confluenceVerbatimTag
-
-syntax match confluenceQuoteMarker "^bq. " contains=@NoSpell contained
-syntax match confluenceQuote "^bq. .*$" contains=confluenceQuoteMarker
-syntax region confluenceQuote start="{quote}" end="{quote}" keepend contains=TOP
-
-syntax match confluenceHeadingMarker "^h[1-6]. " contains=@NoSpell contained
-syntax match confluenceHeading "^h[1-6]. .*$" contains=confluenceHeadingMarker
-
-" Note: Confluence 2.10.1 does not escape smileys \:) \:( \:P \:D \;)
-syntax match confluenceEmoticons "\%(^\|\s\)\zs\%(:)\|:(\|:P\|:D\|;)\)\ze\%($\|\s\)"
-syntax match confluenceEmoticons "\%(^\|[^\\]\)\zs([yni/x!+-?*])\|(\%(on\|off\))"
-
-let s:wikiWord = '\u[a-z0-9]\+\(\u[a-z0-9]\+\)\+'
-
-execute 'syntax match confluenceAnchor +^#'.s:wikiWord.'\ze\(\>\|_\)+'
-execute 'syntax match confluenceWord +\(\s\|^\)\zs\(\u\l\+\.\)\='.s:wikiWord.'\(#'.s:wikiWord.'\)\=\ze\(\>\|_\)+'
-" Regex guide:                        ^pre        ^web name       ^wikiword  ^anchor               ^ post
-
-" Images: 
-syntax match confluenceImageParameterName      "[,|]\zs\w\+=\?[^,!]\+" contained contains=confluenceImageParameterValue,@NoSpell
-syntax match confluenceImageParameterValue     "\w\+=\zs[^,!]\+" contained contains=@NoSpell
-syntax match confluenceImageLink               "!\zs\S[^|!]*" contained contains=@NoSpell
-syntax match confluenceImage "!\S[^!]*\S!" contains=confluenceImageLink,confluenceImageParameterName
-
-" Links: 
-syntax match confluenceLink "\[[^|\]]\+\]" contains=confluenceLinkStart,confluenceLinkEnd,@NoSpell
-syntax match confluenceLink "\[[^|\]]\+|[^|\]]\+\]" contains=confluenceLinkMarker,confluenceLinkEnd,confluenceLinkLabel,@NoSpell
-syntax match confluenceLink "\[[^|\]]\+|[^|\]]\+|[^|\]]\+\]" contains=confluenceLinkMarker,confluenceLinkLabel,confluenceLinkTip,@NoSpell
-
-syntax match confluenceLinkLabel    "\[[^|\]]\+\ze|" contained contains=confluenceLinkStart
-syntax match confluenceLinkTip  "[^|\]]\+\]"   contained contains=confluenceLinkEnd
-syntax match confluenceLinkMarker "|"          contained
-syntax match confluenceLinkStart "\["          contained
-syntax match confluenceLinkEnd "\]"            contained
-
-"============================================================================
-" Group Linking:    
-"============================================================================
-
-ConfluenceHiLink confluenceEscapeCharacter Type
-ConfluenceHiLink confluenceHeading       Title
-ConfluenceHiLink confluenceHeadingMarker Type
-ConfluenceHiLink confluenceVariable      PreProc
-ConfluenceHiLink confluenceTagParameterName   Type
-ConfluenceHiLink confluenceTagParameterValue  Constant
-ConfluenceHiLink confluenceCodeTag       PreProc
-ConfluenceHiLink confluenceVerbatimTag   PreProc
-ConfluenceHiLink confluenceTag           PreProc
-ConfluenceHiLink confluenceQuoteMarker   Type
-ConfluenceHiLink confluenceQuote         String
-ConfluenceHiLink confluenceComment       Comment
-ConfluenceHiLink confluenceWord          Tag
-ConfluenceHiLink confluenceAnchor        PreProc
-ConfluenceHiLink confluenceVerbatim      Constant
-ConfluenceHiLink confluenceCode          Constant
-ConfluenceHiLink confluenceList          Type
-ConfluenceHiLink confluenceSingleList    Type
-ConfluenceSynColor confluenceTableHeader term=bold cterm=bold gui=bold
-
-ConfluenceHiLink confluenceDelimiter     Type
-ConfluenceHiLink confluenceSeparator     Type
-
-ConfluenceHiLink confluenceEmoticons     Special
-ConfluenceHiLink confluenceSymbols       Special
-
-" Images
-ConfluenceHiLink confluenceImageParameterName  Type
-ConfluenceHiLink confluenceImageParameterValue Constant
-ConfluenceHiLink confluenceImageLink           Underlined
-ConfluenceHiLink confluenceImage               PreProc
-
-" Links
-ConfluenceHiLink   confluenceLinkMarker Type
-ConfluenceHiLink   confluenceLinkStart  Type
-ConfluenceHiLink   confluenceLinkEnd    Type
-ConfluenceHiLink   confluenceLink       Underlined
-ConfluenceHiLink   confluenceLinkLabel  Identifier
-ConfluenceHiLink   confluenceLinkTip    NonText
-
-" Emphasis
-ConfluenceHiLink   confluenceFixed      Constant
-ConfluenceSynColor confluenceBold       term=bold cterm=bold gui=bold
-ConfluenceSynColor confluenceItalic     term=italic cterm=italic gui=italic
-ConfluenceHiLink   confluenceCitation   String
-ConfluenceHiLink   confluenceStrike     Special
-ConfluenceSynColor confluenceUnderlined term=underline cterm=underline gui=underline
-ConfluenceHiLink   confluenceSuperscript Special
-ConfluenceHiLink   confluenceSubscript  Special
-
-"============================================================================}" Clean Up:    {{{1
-"============================================================================
-
-delcommand ConfluenceHiLink
-delcommand ConfluenceSynColor
-
-if main_syntax == 'confluencewiki'
-  unlet main_syntax
-endif
-
-let b:current_syntax = "confluencewiki"
-
-" vim:fdm=marker
--- a/vim/syntax/creole.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-" Vim syntax file
-" Language:     creole
-" Maintainer:   Peter Hoffmann <ph@peter-hoffmann.com>
-" Last Change:  2007 May 31
-
-" This syntax file is based on the wiki.vim syntax file from Andreas Kneib
-
-" Little syntax file to use a wiki-editor with VIM
-" (if your browser allow this action) 
-" To use this syntax file:
-" 1. mkdir ~/.vim/syntax
-" 2. mv ~/creole.vim ~/.vim/syntax/creole.vim
-" 3. :set syntax=creole
-"
-
-"Some hints to extend wiki creole editing
-"set path=.,~/wiki/
-"au BufRead,BufNewFile *.txt setfiletype creole
-
-"write current file and open file under cursor in new tab
-"nnoremap gF :w<cr> :tabedit <cfile><cr>
-
-"use the snippetsEmu plugin for wiki code
-"Snippet { {{{<CR><{}><CR>}}}<CR><{}>
-"Snippet * **<{}>** <{}> 
-"Snippet _ __<{}>__ <{}> 
-"Snippet - --<{}>-- <{}> 
-"Snippet [ [[<{}>]] <{}> 
-
-
-" Quit if syntax file is already loaded
-if version < 600
-  syntax clear
-elseif exists("b:current_syntax")
-  finish
-endif
-
-if version < 508
-  command! -nargs=+ WikiHiLink hi link <args>
-else
-  command! -nargs=+ WikiHiLink hi def link <args>
-endif
-
-syn match   wikiLine        "^----$"
-"TODO add different markup for [[link|name]] type of links
-syn region  wikiLink        start=+\[\[+hs=s+2 end=+\]\]+he=e-2
-syn match   wikiList        "^[*#]* "
-syn region  wikiCurly       start="{\{3\}" end="}\{3\}"
-syn region  wikiHead        start="^=" end="$"
-"syn region  wikiSubhead     start="^== " end="$"
-"TODO add syntax for tables
-
-"try to not get confused with wikiLink
-syn region  wikiBold        start="\*\*[^ ]" end="\*\*"
-"try to not get confused with http://
-"FIXME does not work at beginning of line
-syn region  wikiItalic      start="[^:]\/\/"hs=s+1   end="[^:]\/\/"
-syn region  wikiUnderline   start="__" end="__"
-"syn region  wikiStrike      start="--" end="--"
-"TODO add regions for mixed markup
-"syn region wikiBoldItalic   contained start=+\([^']\|^\)''[^']+ end=+[^']''\([^']\|$\)+
-"syn region wikiItalicBold   contained start=+'''+ end=+'''+
-
-" The default highlighting.
-if version >= 508 || !exists("did_wiki_syn_inits")
-  if version < 508
-    let did_wiki_syn_inits = 1
-  endif
-  
-WikiHiLink wikiCurly       Type
-WikiHiLink wikiHead        Statement 
-"  WikiHiLink wikiSubhead     PreProc
-WikiHiLink wikiList        String
-WikiHiLink wikiExtLink     Identifier
-WikiHiLink wikiLink        Identifier
-WikiHiLink wikiLine        PreProc
-
-hi def     wikiBold        term=bold cterm=bold gui=bold
- " hi def     wikiBoldItalic  term=bold,italic cterm=bold,italic gui=bold,italic
-hi def     wikiItalic      term=italic cterm=italic gui=italic
- " hi def     wikiItalicBold  term=bold,italic cterm=bold,italic gui=bold,italic
-hi def  wikiUnderline   term=underline cterm=underline gui=underline
-"hi def wikiStrike ???
-
-endif
-
-delcommand WikiHiLink
-  
-let b:current_syntax = "creole"
-
-"EOF vim: tw=78:ft=vim:ts=8
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/syntax/hcl.vim	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,72 @@
+" Forked from Larry Gilbert's syntax file
+" github.com/L2G/vim-syntax-terraform
+if exists('b:current_syntax')
+  finish
+endif
+
+let s:cpo_save = &cpoptions
+set cpoptions&vim
+
+" Identifiers are made up of alphanumeric characters, underscores, and
+" hyphens.
+if has('patch-7.4.1142')
+    syn iskeyword a-z,A-Z,48-57,_,-
+endif
+
+syn case match
+
+" A block is introduced by a type, some number of labels - which are either
+" strings or identifiers - and an opening curly brace.  Match the type.
+syn match hclBlockType /^\s*\zs\K\k*\ze\s\+\(\("\K\k*"\|\K\k*\)\s\+\)*{/
+
+" An attribute name is an identifier followed by an equals sign.
+syn match hclAttributeAssignment /\(\K\k*\.\)*\K\k*\s\+=\s/ contains=hclAttributeName
+syn match hclAttributeName /\<\K\k*\>/ contained
+
+syn keyword hclValueBool true false
+
+syn keyword hclTodo         contained TODO FIXME XXX BUG
+syn region  hclComment      start="/\*" end="\*/" contains=hclTodo,@Spell
+syn region  hclComment      start="#" end="$" contains=hclTodo,@Spell
+syn region  hclComment      start="//" end="$" contains=hclTodo,@Spell
+
+""" misc.
+syn match hclValueDec      "\<[0-9]\+\([kKmMgG]b\?\)\?\>"
+syn match hclValueHexaDec  "\<0x[0-9a-f]\+\([kKmMgG]b\?\)\?\>"
+syn match hclBraces        "[\[\]]"
+
+""" skip \" and \\ in strings.
+syn region hclValueString   start=/"/ skip=/\\\\\|\\"/ end=/"/ contains=hclStringInterp
+syn region hclStringInterp  matchgroup=hclBraces start=/\(^\|[^$]\)\$\zs{/ end=/}/ contained contains=ALLBUT,hclAttributeName
+syn region hclHereDocText   start=/<<-\?\z([a-z0-9A-Z]\+\)/ end=/^\s*\z1/ contains=hclStringInterp
+
+"" Functions.
+syn match hclFunction "[a-z0-9]\+(\@="
+
+""" HCL2
+syn keyword hclRepeat         for in
+syn keyword hclConditional    if
+syn keyword hclValueNull      null
+
+" enable block folding
+syn region hclBlockBody matchgroup=hclBraces start="{" end="}" fold transparent
+
+hi def link hclComment           Comment
+hi def link hclTodo              Todo
+hi def link hclBraces            Delimiter
+hi def link hclAttributeName     Identifier
+hi def link hclBlockType         Type
+hi def link hclValueBool         Boolean
+hi def link hclValueDec          Number
+hi def link hclValueHexaDec      Number
+hi def link hclValueString       String
+hi def link hclHereDocText       String
+hi def link hclFunction          Function
+hi def link hclRepeat            Repeat
+hi def link hclConditional       Conditional
+hi def link hclValueNull         Constant
+
+let b:current_syntax = 'hcl'
+
+let &cpoptions = s:cpo_save
+unlet s:cpo_save
--- a/vim/syntax/io.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-" Vim Syntax File
-" Language:     Io
-" Creator:      Scott Dunlop <swdunlop@verizon.net>
-" Fixes:        Manpreet Singh <junkblocker@yahoo.com>
-"               Jonathan Wright <quaggy@gmail.com>
-"               Erik Garrison <erik.garrison@gmail.com>
-" Last Change:  2006 Nov 16
-
-if version < 600
-    syntax clear
-elseif exists("b:current_syntax")
-    finish
-endif
-
-syntax case match
-
-" equivalent to io-mode-prototype-names in io-mode.el
-syntax keyword ioType Array AudioDevice AudioMixer Block Box Buffer CFunction
-syntax keyword ioType CGI Color Curses DBM DNSResolver DOConnection DOProxy
-syntax keyword ioType DOServer Date Directory Duration DynLib Error Exception
-syntax keyword ioType FFT File Fnmatch Font Future GL GLE GLScissor GLU
-syntax keyword ioType GLUCylinder GLUQuadric GLUSphere GLUT Host Image Importer
-syntax keyword ioType LinkList List Lobby Locals MD5 MP3Decoder MP3Encoder Map
-syntax keyword ioType Message Movie Notification Number Object
-syntax keyword ioType OpenGL Point Protos Regex SGML SGMLElement SGMLParser SQLite Server Sequence
-syntax keyword ioType ShowMessage SleepyCat SleepyCatCursor Socket
-syntax keyword ioType SocketManager Sound Soup Store String Tree UDPSender
-syntax keyword ioType UPDReceiver URL User Warning WeakLink
-syntax keyword ioType true false nil Random BigNum Sequence
-
-" equivalent to io-mode-message-names in io-mode.el
-syntax keyword ioKeyword activate activeCoroCount and asString block break
-syntax keyword ioKeyword catch clone collectGarbage compileString continue
-syntax keyword ioKeyword do doFile doMessage doString else elseif exit for
-syntax keyword ioKeyword foreach forward getSlot getEnvironmentVariable hasSlot if ifFalse
-syntax keyword ioKeyword ifNil ifNilEval ifTrue isActive isNil isResumable list message
-syntax keyword ioKeyword method or parent pass pause perform
-syntax keyword ioKeyword performWithArgList print println proto raise raiseResumable
-syntax keyword ioKeyword removeSlot resend resume return
-syntax keyword ioKeyword schedulerSleepSeconds self sender
-syntax keyword ioKeyword setSchedulerSleepSeconds setSlot shallowCopy
-syntax keyword ioKeyword slotNames super system then thisBlock thisContext
-syntax keyword ioKeyword call try type uniqueId updateSlot wait while
-syntax keyword ioKeyword write yield
-
-syntax region ioOperator start=':' end='='
-syntax region ioOperator start='!' end='='
-syntax region ioOperator start='@' end='@'
-syntax region ioOperator start='@' end='[^@]'he=e-1
-syntax region ioOperator start='?' end='?'
-syntax region ioOperator start='?' end='[^?]'he=e-1
-syntax region ioOperator start=';' end=';'
-syntax region ioOperator start=';' end='[^;]'he=e-1
-syntax region ioOperator start='\.' end='\.'
-syntax region ioOperator start='\.' end='[^\.]'he=e-1
-syntax region ioOperator start='=' end='='
-syntax region ioOperator start='=' end=' 'he=e-1
-syntax region ioOperator start='[*/>=+-]' end='[ 0-9]'he=e-1
-
-syntax region ioString start=/"/ skip=/\\./ end=/"/
-syntax region ioString start=/"""/ skip=/\\./ end=/"""/
-
-syn match   ioHexNumber	"\<0[xX]\x\+[lL]\=\>" display
-syn match   ioHexNumber	"\<0[xX]\>" display
-syn match   ioNumber	"\<\d\+[lLjJ]\=\>" display
-syn match   ioFloat		"\.\d\+\([eE][+-]\=\d\+\)\=[jJ]\=\>" display
-syn match   ioFloat		"\<\d\+[eE][+-]\=\d\+[jJ]\=\>" display
-syn match   ioFloat		"\<\d\+\.\d*\([eE][+-]\=\d\+\)\=[jJ]\=" display
-
-syn match   ioOctalError	"\<0\o*[89]\d*[lL]\=\>" display
-syn match   ioError	"\<0[xX]\X\+[lL]\=\>" display
-
-syntax region ioComment start='#' end='$' keepend
-syntax region ioComment start=/\/\*/ end=/\*\//
-syntax region ioComment start=/\/\// end=/$/ keepend
-
-highlight link ioType Type
-highlight link ioKeyword Function
-highlight link ioString String
-highlight link ioComment Comment
-highlight link ioOperator Operator
-
-highlight link ioHexNumber Number
-highlight link ioNumber Number
-highlight link ioFloat Float
-highlight link ioOctalError Error
-highlight link ioError Error
-
-let b:current_syntax = "io"
\ No newline at end of file
--- a/vim/syntax/less.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,312 +0,0 @@
-" Vim syntax file
-" Language:	LESS Cascading Style Sheets
-" Maintainer:	Leaf Corcoran <leafot@gmail.com>
-" Modifier:	Bryan J Swift <bryan@bryanjswift.com>
-" URL: 		http://leafo.net/lessphp/vim/less.vim
-" URL:		http://gist.github.com/161047
-" Last Change:	2009 August 4
-" LESS by Leaf Corcoran
-" CSS2 by Nikolai Weibull
-" Full CSS2, HTML4 support by Yeti
-
-" For version 5.x: Clear all syntax items
-" For version 6.x: Quit when a syntax file was already loaded
-if !exists("main_syntax")
-  if version < 600
-    syntax clear
-  elseif exists("b:current_syntax")
-  finish
-endif
-  let main_syntax = 'less'
-endif
-
-syn case ignore
-
-
-
-syn keyword cssTagName abbr acronym address applet area a b base
-syn keyword cssTagName basefont bdo big blockquote body br button
-syn keyword cssTagName caption center cite code col colgroup dd del
-syn keyword cssTagName dfn dir div dl dt em fieldset font form frame
-syn keyword cssTagName frameset h1 h2 h3 h4 h5 h6 head hr html img i
-syn keyword cssTagName iframe img input ins isindex kbd label legend li
-syn keyword cssTagName link map menu meta noframes noscript ol optgroup
-syn keyword cssTagName option p param pre q s samp script select small
-syn keyword cssTagName span strike strong style sub sup tbody td
-syn keyword cssTagName textarea tfoot th thead title tr tt ul u var
-syn match cssTagName "\<table\>"
-syn match cssTagName "\*"
-
-" HTML 5
-syn keyword cssTagName article aside header hgroup footer section nav figure
-syn keyword cssTagName figcaption mark summary command datalist details output
-syn keyword cssTagName progress meter time embed keygen wbr audio video canvas
-
-
-syn match cssTagName "@page\>" nextgroup=cssDefinition
-
-syn match cssSelectorOp "[+>.]"
-syn match cssSelectorOp2 "[~|]\?=" contained
-syn region cssAttributeSelector matchgroup=cssSelectorOp start="\[" end="]" transparent contains=cssUnicodeEscape,cssSelectorOp2,cssStringQ,cssStringQQ
-
-try
-syn match cssIdentifier "#[A-Za-zÀ-ÿ_@][A-Za-zÀ-ÿ0-9_@-]*"
-catch /^.*/
-syn match cssIdentifier "#[A-Za-z_@][A-Za-z0-9_@-]*"
-endtry
-
-syn match cssMedia "@media\>" nextgroup=cssMediaType skipwhite skipnl
-syn keyword cssMediaType contained screen print aural braile embosed handheld projection ty tv all nextgroup=cssMediaComma,cssMediaBlock skipwhite skipnl
-syn match cssMediaComma "," nextgroup=cssMediaType skipwhite skipnl
-syn region cssMediaBlock transparent matchgroup=cssBraces start='{' end='}' contains=cssTagName,cssError,cssComment,cssDefinition,cssURL,cssUnicodeEscape,cssIdentifier
-
-syn match cssValueInteger "[-+]\=\d\+"
-syn match cssValueNumber "[-+]\=\d\+\(\.\d*\)\="
-syn match cssValueLength "[-+]\=\d\+\(\.\d*\)\=\(%\|mm\|cm\|in\|pt\|pc\|em\|ex\|px\)"
-
-syn match cssValueAngle contained "[-+]\=\d\+\(\.\d*\)\=\(deg\|grad\|rad\)"
-syn match cssValueTime contained "+\=\d\+\(\.\d*\)\=\(ms\|s\)"
-syn match cssValueFrequency contained "+\=\d\+\(\.\d*\)\=\(Hz\|kHz\)"
-
-syn match cssFontDescriptor "@font-face\>" nextgroup=cssFontDescriptorBlock skipwhite skipnl
-syn region cssFontDescriptorBlock contained transparent matchgroup=cssBraces start="{" end="}" contains=cssComment,cssError,cssUnicodeEscape,cssFontProp,cssFontAttr,cssCommonAttr,cssStringQ,cssStringQQ,cssFontDescriptorProp,cssValue.*,cssFontDescriptorFunction,cssUnicodeRange,cssFontDescriptorAttr
-syn match cssFontDescriptorProp contained "\<\(unicode-range\|unit-per-em\|panose-1\|cap-height\|x-height\|definition-src\)\>"
-syn keyword cssFontDescriptorProp contained src stemv stemh slope ascent descent widths bbox baseline centerline mathline topline
-syn keyword cssFontDescriptorAttr contained all
-syn region cssFontDescriptorFunction contained matchgroup=cssFunctionName start="\<\(uri\|url\|local\|format\)\s*(" end=")" contains=cssStringQ,cssStringQQ oneline keepend
-syn match cssUnicodeRange contained "U+[0-9A-Fa-f?]\+"
-syn match cssUnicodeRange contained "U+\x\+-\x\+"
-
-syn keyword cssColor contained aqua black blue fuchsia gray green lime maroon navy olive purple red silver teal yellow
-" FIXME: These are actually case-insentivie too, but (a) specs recommend using
-" mixed-case (b) it's hard to highlight the word `Background' correctly in
-" all situations
-syn case match
-syn keyword cssColor contained ActiveBorder ActiveCaption AppWorkspace ButtonFace ButtonHighlight ButtonShadow ButtonText CaptionText GrayText Highlight HighlightText InactiveBorder InactiveCaption InactiveCaptionText InfoBackground InfoText Menu MenuText Scrollbar ThreeDDarkShadow ThreeDFace ThreeDHighlight ThreeDLightShadow ThreeDShadow Window WindowFrame WindowText Background
-syn case ignore
-syn match cssColor contained "\<transparent\>"
-syn match cssColor contained "\<white\>"
-syn match cssColor contained "#[0-9A-Fa-f]\{3\}\>"
-syn match cssColor contained "#[0-9A-Fa-f]\{6\}\>"
-"syn match cssColor contained "\<rgb\s*(\s*\d\+\(\.\d*\)\=%\=\s*,\s*\d\+\(\.\d*\)\=%\=\s*,\s*\d\+\(\.\d*\)\=%\=\s*)"
-syn region cssURL contained matchgroup=cssFunctionName start="\<url\s*(" end=")" oneline keepend
-syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgb\|clip\|attr\|counter\|rect\)\s*(" end=")" oneline keepend
-
-syn match cssImportant contained "!\s*important\>"
-
-syn keyword cssCommonAttr contained auto none inherit
-syn keyword cssCommonAttr contained top bottom
-syn keyword cssCommonAttr contained medium normal
-
-syn match cssFontProp contained "\<font\>\(-\(family\|style\|variant\|weight\|size\(-adjust\)\=\|stretch\)\>\)\="
-syn match cssFontAttr contained "\<\(sans-\)\=\<serif\>"
-syn match cssFontAttr contained "\<small\>\(-\(caps\|caption\)\>\)\="
-syn match cssFontAttr contained "\<x\{1,2\}-\(large\|small\)\>"
-syn match cssFontAttr contained "\<message-box\>"
-syn match cssFontAttr contained "\<status-bar\>"
-syn match cssFontAttr contained "\<\(\(ultra\|extra\|semi\|status-bar\)-\)\=\(condensed\|expanded\)\>"
-syn keyword cssFontAttr contained cursive fantasy monospace italic oblique
-syn keyword cssFontAttr contained bold bolder lighter larger smaller
-syn keyword cssFontAttr contained icon menu
-syn match cssFontAttr contained "\<caption\>"
-syn keyword cssFontAttr contained large smaller larger
-syn keyword cssFontAttr contained narrower wider
-
-syn keyword cssColorProp contained color
-syn match cssColorProp contained "\<background\(-\(color\|image\|attachment\|position\)\)\="
-syn keyword cssColorAttr contained center scroll fixed
-syn match cssColorAttr contained "\<repeat\(-[xy]\)\=\>"
-syn match cssColorAttr contained "\<no-repeat\>"
-
-syn match cssTextProp "\<\(\(word\|letter\)-spacing\|text\(-\(decoration\|transform\|align\|index\|shadow\)\)\=\|vertical-align\|unicode-bidi\|line-height\)\>"
-syn match cssTextAttr contained "\<line-through\>"
-syn match cssTextAttr contained "\<text-indent\>"
-syn match cssTextAttr contained "\<\(text-\)\=\(top\|bottom\)\>"
-syn keyword cssTextAttr contained underline overline blink sub super middle
-syn keyword cssTextAttr contained capitalize uppercase lowercase center justify baseline sub super
-
-syn match cssBoxProp contained "\<\(margin\|padding\|border\)\(-\(top\|right\|bottom\|left\)\)\=\>"
-syn match cssBoxProp contained "\<border-\(\(\(top\|right\|bottom\|left\)-\)\=\(width\|color\|style\)\)\=\>"
-syn match cssBoxProp contained "\<\(width\|z-index\)\>"
-syn match cssBoxProp contained "\<\(min\|max\)-\(width\|height\)\>"
-syn keyword cssBoxProp contained width height float clear overflow clip visibility
-syn keyword cssBoxAttr contained thin thick both
-syn keyword cssBoxAttr contained dotted dashed solid double groove ridge inset outset
-syn keyword cssBoxAttr contained hidden visible scroll collapse
-
-syn keyword cssGeneratedContentProp contained content quotes
-syn match cssGeneratedContentProp contained "\<counter-\(reset\|increment\)\>"
-syn match cssGeneratedContentProp contained "\<list-style\(-\(type\|position\|image\)\)\=\>"
-syn match cssGeneratedContentAttr contained "\<\(no-\)\=\(open\|close\)-quote\>"
-syn match cssAuralAttr contained "\<lower\>"
-syn match cssGeneratedContentAttr contained "\<\(lower\|upper\)-\(roman\|alpha\|greek\|latin\)\>"
-syn match cssGeneratedContentAttr contained "\<\(hiragana\|katakana\)\(-iroha\)\=\>"
-syn match cssGeneratedContentAttr contained "\<\(decimal\(-leading-zero\)\=\|cjk-ideographic\)\>"
-syn keyword cssGeneratedContentAttr contained disc circle square hebrew armenian georgian
-syn keyword cssGeneratedContentAttr contained inside outside
-
-syn match cssPagingProp contained "\<page\(-break-\(before\|after\|inside\)\)\=\>"
-syn keyword cssPagingProp contained size marks inside orphans widows
-syn keyword cssPagingAttr contained landscape portrait crop cross always avoid
-
-syn keyword cssUIProp contained cursor
-syn match cssUIProp contained "\<outline\(-\(width\|style\|color\)\)\=\>"
-syn match cssUIAttr contained "\<[ns]\=[ew]\=-resize\>"
-syn keyword cssUIAttr contained default crosshair pointer move wait help
-syn keyword cssUIAttr contained thin thick
-syn keyword cssUIAttr contained dotted dashed solid double groove ridge inset outset
-syn keyword cssUIAttr contained invert
-
-syn match cssRenderAttr contained "\<marker\>"
-syn match cssRenderProp contained "\<\(display\|marker-offset\|unicode-bidi\|white-space\|list-item\|run-in\|inline-table\)\>"
-syn keyword cssRenderProp contained position top bottom direction
-syn match cssRenderProp contained "\<\(left\|right\)\>"
-syn keyword cssRenderAttr contained block inline compact
-syn match cssRenderAttr contained "\<table\(-\(row-gorup\|\(header\|footer\)-group\|row\|column\(-group\)\=\|cell\|caption\)\)\=\>"
-syn keyword cssRenderAttr contained static relative absolute fixed
-syn keyword cssRenderAttr contained ltr rtl embed bidi-override pre nowrap
-syn match cssRenderAttr contained "\<bidi-override\>"
-
-syn match cssAuralProp contained "\<\(pause\|cue\)\(-\(before\|after\)\)\=\>"
-syn match cssAuralProp contained "\<\(play-during\|speech-rate\|voice-family\|pitch\(-range\)\=\|speak\(-\(punctuation\|numerals\)\)\=\)\>"
-syn keyword cssAuralProp contained volume during azimuth elevation stress richness
-syn match cssAuralAttr contained "\<\(x-\)\=\(soft\|loud\)\>"
-syn keyword cssAuralAttr contained silent
-syn match cssAuralAttr contained "\<spell-out\>"
-syn keyword cssAuralAttr contained non mix
-syn match cssAuralAttr contained "\<\(left\|right\)-side\>"
-syn match cssAuralAttr contained "\<\(far\|center\)-\(left\|center\|right\)\>"
-syn keyword cssAuralAttr contained leftwards rightwards behind
-syn keyword cssAuralAttr contained below level above higher
-syn match cssAuralAttr contained "\<\(x-\)\=\(slow\|fast\)\>"
-syn keyword cssAuralAttr contained faster slower
-syn keyword cssAuralAttr contained male female child code digits continuous
-
-syn match cssTableProp contained "\<\(caption-side\|table-layout\|border-collapse\|border-spacing\|empty-cells\|speak-header\)\>"
-syn keyword cssTableAttr contained fixed collapse separate show hide once always
-
-
-
-syn match lessComment "//.*$" contains=@Spell
-syn match lessVariable "@[A-Za-z_-][A-Za-z0-9_-]*"
-syn region lessVariableDefinition start="^@" end=";" contains=css.*Attr,css.*Prop,cssComment,cssValue.*,cssColor,cssURL,cssImportant,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssDefinition,cssClassName,cssTagName,cssIdentifier,lessComment,lessVariable,lessFunction
-
-" captures both the definition and the call
-syn region lessFunction matchgroup=lessFuncDef start="@[A-Za-z_-][A-Za-z0-9_-]*(" end=")" contains=css.*Attr,css.*Prop,cssComment,cssValue.*,cssColor,cssURL,cssImportant,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssDefinition,cssClassName,cssTagName,cssIdentifier,lessComment,lessVariable,lessFunction
-
-
-
-
-
-" FIXME: This allows cssMediaBlock before the semicolon, which is wrong.
-syn region cssInclude start="@import" end=";" contains=cssComment,cssURL,cssUnicodeEscape,cssMediaType
-syn match cssBraces contained "[{}]"
-syn match cssError contained "{@<>"
-syn region cssDefinition transparent matchgroup=cssBraces start='{' end='}' contains=css.*Attr,css.*Prop,cssComment,cssValue.*,cssColor,cssURL,cssImportant,cssStringQ,cssStringQQ,cssFunction,cssUnicodeEscape,cssDefinition,cssClassName,cssTagName,cssIdentifier,lessComment,lessVariable,lessFunction
-" syn match cssBraceError "}"
-
-syn match cssPseudoClass ":\S*" contains=cssPseudoClassId,cssUnicodeEscape
-syn keyword cssPseudoClassId contained link visited active hover focus before after left right
-syn match cssPseudoClassId contained "\<first\(-\(line\|letter\|child\)\)\=\>"
-syn region cssPseudoClassLang matchgroup=cssPseudoClassId start=":lang(" end=")" oneline
-
-syn region cssComment start="/\*" end="\*/" contains=@Spell
-
-syn match cssUnicodeEscape "\\\x\{1,6}\s\?"
-syn match cssSpecialCharQQ +\\"+ contained
-syn match cssSpecialCharQ +\\'+ contained
-syn region cssStringQQ start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=cssUnicodeEscape,cssSpecialCharQQ
-syn region cssStringQ start=+'+ skip=+\\\\\|\\'+ end=+'+ contains=cssUnicodeEscape,cssSpecialCharQ
-syn match cssClassName "\.[A-Za-z][A-Za-z0-9_-]\+"
-
-
-
-
-if main_syntax == "css"
-  syn sync minlines=10
-endif
-
-" Define the default highlighting.
-" For version 5.7 and earlier: only when not done already
-" For version 5.8 and later: only when an item doesn't have highlighting yet
-if version >= 508 || !exists("did_less_syn_inits")
-  if version < 508
-    let did_less_syn_inits = 1
-    command -nargs=+ HiLink hi link <args>
-  else
-    command -nargs=+ HiLink hi def link <args>
-  endif
-
-  HiLink lessComment Comment
-  HiLink lessVariable Special
-  HiLink lessFuncDef Function
-  HiLink cssComment Comment
-  HiLink cssTagName Statement
-  HiLink cssSelectorOp Special
-  HiLink cssSelectorOp2 Special
-  HiLink cssFontProp StorageClass
-  HiLink cssColorProp storageClass
-  HiLink cssTextProp StorageClass
-  HiLink cssBoxProp StorageClass
-  HiLink cssRenderProp StorageClass
-  HiLink cssAuralProp StorageClass
-  HiLink cssRenderProp StorageClass
-  HiLink cssGeneratedContentProp StorageClass
-  HiLink cssPagingProp StorageClass
-  HiLink cssTableProp StorageClass
-  HiLink cssUIProp StorageClass
-  HiLink cssFontAttr Type
-  HiLink cssColorAttr Type
-  HiLink cssTextAttr Type
-  HiLink cssBoxAttr Type
-  HiLink cssRenderAttr Type
-  HiLink cssAuralAttr Type
-  HiLink cssGeneratedContentAttr Type
-  HiLink cssPagingAttr Type
-  HiLink cssTableAttr Type
-  HiLink cssUIAttr Type
-  HiLink cssCommonAttr Type
-  HiLink cssPseudoClassId PreProc
-  HiLink cssPseudoClassLang Constant
-  HiLink cssValueLength Number
-  HiLink cssValueInteger Number
-  HiLink cssValueNumber Number
-  HiLink cssValueAngle Number
-  HiLink cssValueTime Number
-  HiLink cssValueFrequency Number
-  HiLink cssFunction Constant
-  HiLink cssURL String
-  HiLink cssFunctionName Function
-  HiLink cssColor Constant
-  HiLink cssIdentifier Function
-  HiLink cssInclude Include
-  HiLink cssImportant Special
-  HiLink cssBraces SpecialChar
-  HiLink cssBraceError Error
-  HiLink cssError Error
-  HiLink cssInclude Include
-  HiLink cssUnicodeEscape Special
-  HiLink cssStringQQ String
-  HiLink cssStringQ String
-  HiLink cssMedia Special
-  HiLink cssMediaType Special
-  HiLink cssMediaComma Normal
-  HiLink cssFontDescriptor Special
-  HiLink cssFontDescriptorFunction Constant
-  HiLink cssFontDescriptorProp StorageClass
-  HiLink cssFontDescriptorAttr Type
-  HiLink cssUnicodeRange Constant
-  HiLink cssClassName Function
-  delcommand HiLink
-endif
-
-let b:current_syntax = "less"
-
-if main_syntax == 'less'
-  unlet main_syntax
-endif
-
-
-" vim: ts=8
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/syntax/martian.vim	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,98 @@
+" Martian (MRO) Syntax
+" Author: Matt Sooknah
+
+if exists("b:current_syntax")
+  finish
+endif
+
+syn match include '^\s*@include' nextgroup=mroString skipwhite
+
+syn keyword filetype  filetype nextgroup=parType skipwhite
+syn keyword parameter in out  nextgroup=parType skipwhite contained
+syn keyword src       src nextgroup=srctype skipwhite contained
+syn keyword srctype   py comp exe nextgroup=mroString contained skipwhite
+syn keyword restype   mem_gb vmem_gb threads special volatile nextgroup=assign contained skipwhite
+syn keyword modifier  local preflight volatile nextgroup=modifier,callTarg skipwhite contained
+syn keyword boundMod  local preflight volatile disabled nextgroup=assign contained skipwhite
+syn keyword sweep     sweep nextgroup=sweepArray contained
+
+syn keyword declaration pipeline stage nextgroup=pipeName skipwhite
+syn keyword call        call nextgroup=modifier,callTarg skipwhite
+syn keyword return      return nextgroup=callParams skipwhite contained
+
+syn keyword mroNull  null       contained
+syn keyword mroBool  true false contained
+
+syn keyword split      split  nextgroup=splitUsing,paramBlock skipwhite contained
+syn keyword splitUsing using  nextgroup=paramBlock skipwhite contained
+syn keyword using      using  nextgroup=resParams  skipwhite contained
+syn keyword retain     retain nextgroup=idList     skipwhite contained
+syn keyword callUsing  using  nextgroup=modBlock   skipwhite contained
+syn keyword as         as     nextgroup=callTarg   skipwhite contained
+syn keyword self       self   nextgroup=dot contained
+
+syn match dot    '\.' nextgroup=parName contained
+syn match mapSep ':'  nextgroup=mroString,mroNull,mroBool,arrayLit,mapLit skipwhite contained
+syn match assign '='  nextgroup=self,sweep,mroString,mroNumber,mroNull,mroBool,parName,arrayLit,mapLit skipwhite contained
+
+syn match assignment '_\?[A-Za-z][A-Za-z0-9_]*\s*=' contains=parName,assign contained skipwhite nextgroup=self,sweep,mroString,mroNumber,mroNull,mroBool,parName,arrayLit,mapLit
+syn match parType '_\?[A-Za-z][.A-Za-z0-9_]*' nextgroup=arrayDim,parName skipwhite contained
+syn match arrayDim '\[\]' nextgroup=arraydim,parName skipwhite contained
+syn match parName '_\?[A-Za-z][A-Za-z0-9_]*' nextgroup=dot,mroString skipwhite contained
+syn match pipeName '_\?[A-Za-z][A-Za-z0-9_]*' nextgroup=paramBlock contained
+syn match callTarg '_\?[A-Za-z][A-Za-z0-9_]*' nextgroup=as,callParams skipwhite contained
+
+syn match commentLine '#.*$'
+
+syn match mroNumber '\v<\d+>' contained skipwhite nextgroup=mapSep
+syn match mroNumber '\v<\d+\.\d+>' contained skipwhite nextgroup=mapSep
+
+syn region paramBlock start="(" end=")" fold transparent nextgroup=split,using,retain,callBlock skipwhite skipnl contained contains=parameter,src
+syn region callParams start="(" end=")" fold transparent nextgroup=callUsing,retain skipwhite contained contains=assignment
+syn region resParams  start="(" end=")" fold transparent nextgroup=retain contained skipwhite skipnl contains=restype
+syn region idList     start="(" end=")" fold transparent contained contains=parName
+syn region modBlock   start="(" end=")" fold transparent contained contains=boundMod
+syn region callBlock  start="{" end="}" fold transparent contains=call,return contained skipwhite
+syn region mroString  start=/"/ skip=/\\"/ end=/"/ nextgroup=mapSep skipwhite contained
+syn region arrayLit   start='\[' end='\]' transparent contains=mroString,mroNumber,mroNull,mroBool,arrayLit,mapLit,parName contained
+syn region sweepArray start='(' end=')' transparent contains=mroString,mroNumber,mroNull,mroBool,arrayLit,mapLit contained
+syn region mapLit     start="{" end="}" transparent contains=mroString,mroNumber contained
+
+let b:current_syntax = "mro"
+
+hi def link commentLine   Comment
+
+hi def link include       PreProcessor
+hi def link filetype      Statement
+hi def link parameter     Statement
+hi def link src           Statement
+hi def link declaration   Statement
+hi def link return        Statement
+hi def link call          Statement
+hi def link modifier      Statement
+hi def link split         Statement
+hi def link splitUsing    Statement
+hi def link callUsing     Statement
+hi def link using         Statement
+hi def link as            Keyword
+hi def link restype       Keyword
+hi def link boundMod      Keyword
+hi def link self          Keyword
+hi def link sweep         Keyword
+hi def link using         Statement
+hi def link retain        Statement
+
+hi def link parType       Type
+hi def link srcType       Type
+
+hi def link pipeName      Type
+hi def link callTarg      Type
+hi def link parName       Identifier
+
+hi def link dot       Operator
+
+hi def link mroNumber Constant
+hi def link mroString Constant
+hi def link mroNull   Constant
+hi def link mroTrue   Constant
+hi def link mroFalse  Constant
--- a/vim/syntax/pandabt.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-if version < 600
-    syntax clear
-elseif exists("b:current_syntax")
-    finish
-endif
-
-syntax region pandabtString start=/"/ skip=/\\./ end=/"/
-syntax region pandabtComment start=/\/\// end=/$/ keepend
-
-highlight link pandabtString String
-highlight link pandabtComment Comment
-
-let b:current_syntax = "pandabt"
--- a/vim/syntax/pentadactyl.vim	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-" Vim syntax file
-" Language:         Pentadactyl configuration file
-" Maintainer:       Doug Kearns <dougkearns@gmail.com>
-
-" TODO: make this pentadactyl specific - shared dactyl config?
-
-if exists("b:current_syntax")
-  finish
-endif
-
-let s:cpo_save = &cpo
-set cpo&vim
-
-syn include @javascriptTop syntax/javascript.vim
-unlet b:current_syntax
-
-syn include @cssTop syntax/css.vim
-unlet b:current_syntax
-
-syn match pentadactylCommandStart "\%(^\s*:\=\)\@<=" nextgroup=pentadactylCommand,pentadactylAutoCmd
-
-syn keyword pentadactylCommand run ab[breviate] abc[lear] addo[ns] au[tocmd] ba[ck] bd[elete] bw[ipeout] bun[load]
-    \ tabc[lose] bma[rk] bmarks b[uffer] buffers files ls tabs ca[bbrev] cabc[lear] cd chd[ir] cm[ap] cmapc[lear] cno[remap]
-    \ colo[rscheme] comc[lear] com[mand] contexts cuna[bbrev] cunm[ap] delbm[arks] delc[ommand] delmac[ros] delm[arks] delqm[arks]
-    \ dels[tyle] dia[log] doautoa[ll] do[autocmd] downl[oads] dl ec[ho] echoe[rr] echom[sg] em[enu] exe[cute] exta[dd] extde[lete]
-    \ extd[isable] exte[nable] extens[ions] exts exto[ptions] extp[references] exu[sage] fini[sh] fo[rward] fw frameo[nly]
-    \ ha[rdcopy] h[elp] helpa[ll] hi[ghlight] hist[ory] hs ia[bbrev] iabc[lear] im[ap] imapc[lear] ino[remap] iuna[bbrev] iunm[ap]
-    \ javas[cript] js ju[mps] keepa[lt] let loadplugins lpl macros map mapc[lear] ma[rk] marks mes[sages] messc[lear]
-    \ mkp[entadactylrc] nm[ap] nmapc[lear] nno[remap] noh[lsearch] no[remap] norm[al] nunm[ap] o[pen] optionu[sage] pa[geinfo]
-    \ pagest[yle] pas pref[erences] prefs pw[d] qma[rk] qmarks q[uit] quita[ll] qa[ll] redr[aw] re[load] reloada[ll] res[tart]
-    \ runt[ime] sa[nitize] sav[eas] w[rite] sbcl[ose] scrip[tnames] se[t] setg[lobal] setl[ocal] sideb[ar] sb[ar] sbope[n]
-    \ sil[ent] so[urce] st[op] stopa[ll] sty[le] styled[isable] styd[isable] stylee[nable] stye[nable] stylet[oggle] styt[oggle]
-    \ tab taba[ttach] tabde[tach] tabd[o] bufd[o] tabdu[plicate] tabl[ast] bl[ast] tabm[ove] tabn[ext] tn[ext] bn[ext] tabo[nly]
-    \ tabopen t[open] tabnew tabp[revious] tp[revious] tabN[ext] tN[ext] bp[revious] bN[ext] tabr[ewind] tabfir[st] br[ewind]
-    \ bf[irst] time toolbarh[ide] tbh[ide] toolbars[how] tbs[how] toolbart[oggle] tbt[oggle] una[bbreviate] u[ndo] undoa[ll]
-    \ unl[et] unm[ap] verb[ose] ve[rsion] vie[wsource] viu[sage] vm[ap] vmapc[lear] vno[remap] vunm[ap] winc[lose] wc[lose]
-    \ wind[ow] winon[ly] wino[pen] wo[pen] wqa[ll] wq xa[ll] zo[om]
-    \ contained
-
-syn match pentadactylCommand "!" contained
-
-syn keyword pentadactylAutoCmd au[tocmd] contained nextgroup=pentadactylAutoEventList skipwhite
-
-syn keyword pentadactylAutoEvent BookmarkAdd BookmarkChange BookmarkRemove ColorScheme DOMLoad DownloadPost Fullscreen
-    \ LocationChange PageLoadPre PageLoad PrivateMode Sanitize ShellCmdPost Enter LeavePre Leave
-    \ contained
-
-syn match pentadactylAutoEventList "\(\a\+,\)*\a\+" contained contains=pentadactylAutoEvent
-
-syn region pentadactylSet matchgroup=pentadactylCommand start="\%(^\s*:\=\)\@<=\<\%(setl\%[ocal]\|setg\%[lobal]\|set\=\)\=\>"
-    \ end="$" keepend oneline contains=pentadactylOption,pentadactylString
-
-syn keyword pentadactylOption activate act altwildmode awim autocomplete au cdpath cd complete cpt cookies ck defsearch ds
-    \ editor encoding enc eventignore ei extendedhinttags eht fbwhitelist fbw fileencoding fenc followhints fh guioptions go
-    \ helpfile hf hintinputs hin hintkeys hk hintmatching hm hinttags ht hinttimeout hto history hi laststatus ls loadplugins lpl
-    \ maxitems messages msgs newtab nextpattern pageinfo pa popups pps previouspattern runtimepath rtp sanitizeitems si
-    \ sanitizetimespan sts scroll scr shell sh shellcmdflag shcf showstatuslinks ssli showtabline stal suggestengines titlestring
-    \ urlseparator verbose vbs wildanchor wia wildcase wic wildignore wig wildmode wim wildsort wis wordseparators wsp
-    \ contained nextgroup=pentadactylSetMod
-
-let s:toggleOptions = ["banghist", "bh", "errorbells", "eb", "exrc", "ex", "flashblock", "fb", "fullscreen", "fs", "hlsearch",
-    \ "hls", "ignorecase", "ic", "incsearch", "is", "insertmode", "im", "jsdebugger", "jsd", "linksearch", "lks", "more",
-    \ "online", "private", "pornmode", "showmode", "smd", "smartcase", "scs", "strictfocus", "sf", "usermode", "um", "visualbell",
-    \ "vb"]
-execute 'syn match pentadactylOption "\<\%(no\|inv\)\=\%(' .
-    \ join(s:toggleOptions, '\|') . 
-    \ '\)\>!\=" contained nextgroup=pentadactylSetMod'
-
-syn match pentadactylSetMod "\%(\<[a-z_]\+\)\@<=&" contained
-
-syn region pentadactylJavaScript start="\%(^\s*\%(javascript\|js\)\s\+\)\@<=" end="$" contains=@javascriptTop keepend oneline
-syn region pentadactylJavaScript matchgroup=pentadactylJavaScriptDelimiter
-    \ start="\%(^\s*\%(javascript\|js\)\s\+\)\@<=<<\s*\z(\h\w*\)"hs=s+2 end="^\z1$" contains=@javascriptTop fold
-
-let s:cssRegionStart = '\%(^\s*sty\%[le]!\=\s\+\%(-\%(n\|name\)\%(\s\+\|=\)\S\+\s\+\)\=[^-]\S\+\s\+\)\@<='
-execute 'syn region pentadactylCss start="' . s:cssRegionStart . '" end="$" contains=@cssTop keepend oneline'
-execute 'syn region pentadactylCss matchgroup=pentadactylCssDelimiter'
-    \ 'start="' . s:cssRegionStart . '<<\s*\z(\h\w*\)"hs=s+2 end="^\z1$" contains=@cssTop fold'
-
-syn match pentadactylNotation "<[0-9A-Za-z-]\+>"
-
-syn match   pentadactylComment +".*$+ contains=pentadactylTodo,@Spell
-syn keyword pentadactylTodo FIXME NOTE TODO XXX contained
-
-syn region pentadactylString start="\z(["']\)" end="\z1" skip="\\\\\|\\\z1" oneline
-
-syn match pentadactylLineComment +^\s*".*$+ contains=pentadactylTodo,@Spell
-
-" NOTE: match vim.vim highlighting group names
-hi def link pentadactylAutoCmd               pentadactylCommand
-hi def link pentadactylAutoEvent             Type
-hi def link pentadactylCommand               Statement
-hi def link pentadactylComment               Comment
-hi def link pentadactylJavaScriptDelimiter   Delimiter
-hi def link pentadactylCssDelimiter          Delimiter
-hi def link pentadactylNotation              Special
-hi def link pentadactylLineComment           Comment
-hi def link pentadactylOption                PreProc
-hi def link pentadactylSetMod                pentadactylOption
-hi def link pentadactylString                String
-hi def link pentadactylTodo                  Todo
-
-let b:current_syntax = "pentadactyl"
-
-let &cpo = s:cpo_save
-unlet s:cpo_save
-
-" vim: tw=130 et ts=4 sw=4:
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/syntax/terraform.vim	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,11 @@
+if exists('b:current_syntax')
+  finish
+endif
+runtime! syntax/hcl.vim
+unlet b:current_syntax
+
+syn keyword terraType           string bool number object tuple list map set any
+
+hi def link terraType           Type
+
+let b:current_syntax = 'terraform'
--- a/vim/vimrc	Fri Apr 14 15:01:35 2023 -0400
+++ b/vim/vimrc	Fri Jul 07 16:11:02 2023 -0400
@@ -63,14 +63,8 @@
 set spellfile=~/.vim/custom-dictionary.utf-8.add,~/.vim-local-dictionary.utf-8.add
 nnoremap zG 2zg
 
-" iTerm2 is currently slow as balls at rendering the nice unicode lines, so for
-" now I'll just use ASCII pipes.  They're ugly but at least I won't want to kill
-" myself when trying to move around a file.
-set fillchars=diff:⣿,vert:│
-set fillchars=diff:⣿,vert:\|
-
-" Don't try to highlight lines longer than 800 characters.
-set synmaxcol=800
+" Don't try to highlight lines longer than 500 characters.
+set synmaxcol=500
 
 " Time out on key codes but not mappings.
 " Basically this makes terminal Vim work sanely.
@@ -89,9 +83,6 @@
 " Save when losing focus
 au FocusLost * :silent! wall
 
-" Resize splits when the window is resized
-" au VimResized * :wincmd =
-
 " Leader
 let mapleader = ","
 let maplocalleader = "\\"
@@ -219,39 +210,10 @@
 " }}}
 
 " }}}
-" Abbreviations ----------------------------------------------------------- {{{
-
-function! EatChar(pat)
-    let c = nr2char(getchar(0))
-    return (c =~ a:pat) ? '' : c
-endfunction
-
-function! MakeSpacelessIabbrev(from, to)
-    execute "iabbrev <silent> ".a:from." ".a:to."<C-R>=EatChar('\\s')<CR>"
-endfunction
-function! MakeSpacelessBufferIabbrev(from, to)
-    execute "iabbrev <silent> <buffer> ".a:from." ".a:to."<C-R>=EatChar('\\s')<CR>"
-endfunction
-
-call MakeSpacelessIabbrev('sl/',  'http://stevelosh.com/')
-call MakeSpacelessIabbrev('bb/',  'http://bitbucket.org/')
-call MakeSpacelessIabbrev('bbs/', 'http://bitbucket.org/sjl/')
-call MakeSpacelessIabbrev('gh/',  'http://github.com/')
-call MakeSpacelessIabbrev('ghs/', 'http://github.com/sjl/')
-
-iabbrev ldis ಠ_ಠ
-iabbrev lsad ಥ_ಥ
-iabbrev lhap ಥ‿ಥ
-iabbrev lmis ಠ‿ಠ
-
-iabbrev c8 CHIP-8
+" Abbreviations & Digraphs ------------------------------------------------ {{{
 
 iabbrev todo TODO
 
-iabbrev sl@ steve@stevelosh.com
-
-iabbrev spf set -euo pipefail
-
 silent! digr -. 8230 "U+2026=…    HORIZONTAL ELLIPSIS
 silent! digr !, 8816 "U+2270=≰    NEITHER LESS-THAN NOR EQUAL TO
 silent! digr !. 8817 "U+2271=≱    NEITHER GREATER-THAN NOR EQUAL TO
@@ -313,7 +275,8 @@
 inoremap <c-k><c-k> <esc>:help digraph-table<cr>
 
 " Wrap
-nnoremap <leader>W :set wrap!<cr>
+" mnemonic: less' -S command/option
+nnoremap <leader>S :set wrap!<cr>
 
 " Inserting blank lines
 " I never use the default behavior of <cr> and this saves me a keystroke...
@@ -325,6 +288,18 @@
 nnoremap <leader>y VV"+y
 nnoremap <leader>Y "+y
 
+" Open
+function Open(thing)
+    call system(['open', a:thing])
+endfunction
+
+nnoremap <leader>o "zyiW:call Open(@z)<cr>
+vnoremap <leader>o "zy:call Open(@z)<cr>
+
+" Delete to black hole register
+nnoremap dD "_dd
+vnoremap D "_d
+
 " Yank to end of line
 nnoremap Y y$
 
@@ -427,9 +402,6 @@
 nnoremap <c-s> :%s/
 vnoremap <c-s> :s/
 
-" HTML tag closing
-inoremap <C-_> <space><bs><esc>:call InsertCloseTag()<cr>a
-
 " Marks and Quotes
 noremap ' `
 noremap æ '
@@ -454,13 +426,6 @@
 " Unfuck my screen
 nnoremap U :syntax sync fromstart<cr>:redraw!<cr>
 
-" Pushing
-nnoremap <leader>Go :Start! git push origin<cr>
-nnoremap <leader>Gu :Start! git push upstream<cr>
-
-" Open current directory in Finder
-nnoremap <leader>O :!open .<cr>
-
 " Zip Right
 "
 " Moves the character under the cursor to the end of the line.  Handy when you
@@ -492,6 +457,9 @@
 nnoremap ]Z ]Sz=
 nnoremap [Z [Sz=
 
+" Header Lines
+nnoremap <leader>- o<esc>80a-<esc>kJ079lD
+
 " Insert Mode Completion {{{
 
 inoremap <c-f> <c-x><c-f>
@@ -694,7 +662,7 @@
     call JumpTo("normal! \<c-]>")
 endfunction
 function! JumpToTagInSplit()
-    call JumpToInSplit("normal! \<c-]>")
+    call JumpToInSplit("normal \<c-]>")
 endfunction
 
 nnoremap <c-]> :silent! call JumpToTag()<cr>
@@ -787,7 +755,7 @@
 " 1. Close all folds.
 " 2. Open just the folds containing the current line.
 " 3. Move the line to a bit (25 lines) down from the top of the screen.
-" 4. Pulse the cursor line.  My eyes are bad.
+" 4. Pulse the line.
 "
 " This mapping wipes out the z mark, which I never use.
 "
@@ -820,17 +788,6 @@
 " }}}
 " Filetype-specific ------------------------------------------------------- {{{
 
-" Arduino {{{
-
-augroup ft_arduino
-    au!
-
-    au FileType arduino setlocal noexpandtab shiftwidth=8 tabstop=8 softtabstop=8 foldmethod=syntax
-    au FileType arduino inoremap <buffer> ☃ <esc>A;<cr>
-    au FileType arduino inoremap <buffer> ☂ <esc>mzA;<esc>`z
-augroup END
-
-" }}}
 " Assembly {{{
 
 augroup ft_asm
@@ -840,6 +797,14 @@
 augroup END
 
 " }}}
+" Bazel {{{
+
+augroup ft_bazel
+    au!
+    au FileType bzl nnoremap <buffer> gi :Neoformat buildifier<cr>
+augroup END
+
+" }}}
 " C {{{
 
 augroup ft_c
@@ -869,44 +834,12 @@
 augroup END
 
 " }}}
-" Clojure {{{
-
-" extra folding {{{
-let g:clojure_fold_extra = [ 
-            \ 'defgauge',
-            \ 'defsketch'
-            \
-            \ ]
-" }}}
-
-augroup ft_clojure
+" Contacts {{{
+
+augroup ft_contacts
     au!
-
-    au BufNewFile,BufRead *.edn set filetype=clojure
-
-    au FileType clojure silent! call TurnOnClojureFolding()
-    au FileType clojure compiler clojure
-    au FileType clojure setlocal isk-=.
-
-    au FileType clojure iabbrev <buffer> defun defn
-
-    " Things that should be indented 2-spaced
-    au FileType clojure setlocal lispwords+=when-found,defform,when-valid,try,while-let,try+,throw+
-
-    au FileType clojure RainbowParenthesesActivate
-    au syntax clojure RainbowParenthesesLoadRound
-
-    " Paredit
-    au FileType clojure call EnableParedit()
-    au FileType clojure nnoremap <buffer> <localleader>( :call PareditToggle()<cr>
-    " )
-
-    " Duplicate
-    au FileType clojure nnoremap <buffer> [] :call DuplicateLispForm()<cr>
-
-    " Indent top-level form.
-    au FileType clojure nmap <buffer> gi mz99[(v%='z
-
+    autocmd BufNewFile,BufRead .contacts setlocal ts=32
+    autocmd BufNewFile,BufRead .contacts setlocal noexpandtab
 augroup END
 
 " }}}
@@ -1120,6 +1053,7 @@
             \ 'test>',
             \ 'eval-when>',
             \ 'eval-dammit>',
+            \ 'scratch>',
             \
             \ 'declaim',
             \
@@ -1135,6 +1069,7 @@
     au BufNewFile,BufRead .abclrc set filetype=lisp
     au BufNewFile,BufRead .lisprc set filetype=lisp
     au BufNewFile,BufRead .stumpwmrc set filetype=lisp
+    au BufNewFile,BufRead .stumpwmrc.local set filetype=lisp
 
     au FileType lisp nnoremap <buffer> U :syntax sync fromstart<cr>:redraw!<cr>:call TurnOnLispFolding()<cr>
 
@@ -1178,6 +1113,7 @@
     au FileType lisp nnoremap <buffer> [] :call DuplicateLispForm()<cr>
     au FileType lisp nnoremap <buffer> <localleader>( :call PareditToggle()<cr>
     ")
+    au FileType lisp inoremap <buffer> <c-s> <c-o>:call vlime#plugin#SendToREPL(vlime#ui#CurTopExpr())<cr>
 
     " Navigate trees of sexps with arrows
     au FileType lisp call s:vim_sexp_mappings()
@@ -1185,21 +1121,63 @@
     au FileType lisp noremap <buffer> <right> :<c-u>call SexpForward()<cr>
     au FileType lisp noremap <buffer> <up>    :<c-u>call SexpUp()<cr>
     au FileType lisp noremap <buffer> <down>  :<c-u>call SexpDown()<cr>
+
+    " Writing
+    au FileType lisp noremap <buffer> <localleader>=  I; => <esc>
+
+    " April
+    au FileType lisp inoremap <buffer> <c-j>;  ⍝
+    au FileType lisp inoremap <buffer> <c-j>i  ⍳
+    au FileType lisp inoremap <buffer> <c-j>r  ⍴
+    au FileType lisp inoremap <buffer> <c-j>e  ∊
+    au FileType lisp inoremap <buffer> <c-j>_i ⍸
+    au FileType lisp inoremap <buffer> <c-j>_, ⍪
+    au FileType lisp inoremap <buffer> <c-j>:~ ⍨
+    au FileType lisp inoremap <buffer> <c-j>:^ ¨
+
+    au FileType lisp inoremap <buffer> <c-j>*  ×
+    au FileType lisp inoremap <buffer> <c-j>/  ÷
+    au FileType lisp inoremap <buffer> <c-j>0  ∘
+    au FileType lisp inoremap <buffer> <c-j>-  ¯
+
+    au FileType lisp inoremap <buffer> <c-j>c  ⌈
+    au FileType lisp inoremap <buffer> <c-j>f  ⌊
+
+    au FileType lisp inoremap <buffer> <c-j><  ←
+    au FileType lisp inoremap <buffer> <c-j>>  →
+    au FileType lisp inoremap <buffer> <c-j>^  ↑
+    au FileType lisp inoremap <buffer> <c-j>v  ↓
+
+    au FileType lisp inoremap <buffer> <c-j>G^ ⍋
+    au FileType lisp inoremap <buffer> <c-j>Gv ⍒
+
+    au FileType lisp inoremap <buffer> <c-j>o\| ⌽
+    au FileType lisp inoremap <buffer> <c-j>o/  ⍉
+    au FileType lisp inoremap <buffer> <c-j>o-  ⊖
+
+    au FileType lisp inoremap <buffer> <c-j>A  ∧
+    au FileType lisp inoremap <buffer> <c-j>O  ∨
+
+    au FileType lisp inoremap <buffer> <c-j>=< ≤
+    au FileType lisp inoremap <buffer> <c-j>=< ≥
+    au FileType lisp inoremap <buffer> <c-j>=/ ≠
+    au FileType lisp inoremap <buffer> <c-j>=== ≡
+    au FileType lisp inoremap <buffer> <c-j>==/ ≢
+
+    au FileType lisp inoremap <buffer> <c-j>q  ⎕
+    au FileType lisp inoremap <buffer> <c-j>Q  ⌷
+    au FileType lisp inoremap <buffer> <c-j>t  ⊢
+
+    au FileType lisp inoremap <buffer> <c-j>u  ∪
+    au FileType lisp inoremap <buffer> <c-j>U  ∩
+    au FileType lisp inoremap <buffer> <c-j>+  ⌿
+    au FileType lisp inoremap <buffer> <c-j>[  ⊂
+    au FileType lisp inoremap <buffer> <c-j>]  ⊃
+
+    au FileType lisp inoremap <buffer> <c-j>z  ⍬
 augroup END " }}}
 
 " }}}
-" Confluence {{{
-
-augroup ft_c
-    au!
-
-    au BufRead,BufNewFile *.confluencewiki setlocal filetype=confluencewiki
-
-    " Wiki pages should be soft-wrapped.
-    au FileType confluencewiki setlocal wrap linebreak nolist
-augroup END
-
-" }}}
 " Cram {{{
 
 let cram_fold=1
@@ -1350,29 +1328,12 @@
 augroup END
 
 " }}}
-" GDL {{{
-
-augroup ft_gdl
+" Git {{{
+
+augroup ft_git
     au!
 
-    au FileType gdl nnoremap <localleader>= mzvap=`z
-
-    au FileType gdl RainbowParenthesesActivate
-    au syntax gdl RainbowParenthesesLoadRound
-
-    au FileType gdl call EnableParedit()
-augroup END
-
-" }}}
-" GLSL {{{
-
-augroup ft_glsl
-    au!
-
-    au BufNewFile,BufRead *.shader setlocal filetype=glsl
-
-    au FileType glsl setlocal foldmethod=marker foldmarker={,}
-    au FileType glsl setlocal ts=8 sts=8 sw=8 noexpandtab
+    au FileType gitcommit nnoremap <buffer> <localleader>j /On branch sjl<cr>f/l"zyt/gg0P:nohl<cr>$a <esc>a
 augroup END
 
 " }}}
@@ -1485,6 +1446,11 @@
     return '='
 endfunction
 
+func Eatchar(pat)
+    let c = nr2char(getchar(0))
+    return (c =~ a:pat) ? '' : c
+endfunc
+
 augroup ft_go
     au!
 
@@ -1497,6 +1463,7 @@
     au FileType go nnoremap <buffer> <localleader>t :GoInfo<cr>
     au FileType go nnoremap <buffer> <localleader>h :GoDocBrowser<cr>
     au FileType go nnoremap <buffer> <localleader>c :GoBuild<cr>
+    au FileType go nnoremap <buffer> <localleader>xc :GoCallers<cr>
 
     au FileType go inoremap <c-n> <c-x><c-o>
 
@@ -1504,6 +1471,18 @@
     au FileType go iabbrev <buffer> enil if err != nil
     au FileType go iabbrev <buffer> rete return err
     au FileType go iabbrev <buffer> retne return nil, err
+    au FileType go iabbrev <buffer> retse return "", err
+    au FileType go iabbrev <buffer> retze return "", err
+
+    au FileType go iabbrev <buffer> enilre if err != nil {<cr>return err<down>
+    au FileType go iabbrev <buffer> enilrn if err != nil {<cr>return nil, err<down>
+    au FileType go iabbrev <buffer> enilrs if err != nil {<cr>return "", err<down>
+    au FileType go iabbrev <buffer> enilrz if err != nil {<cr>return 0, err<down>
+
+    au FileType go iabbrev <buffer> enilrw if err != nil {<cr>return fmt.Errorf(": %w", err<left><left><left><left><left><left><left><left><left><left><C-R>=Eatchar('\s')<cr>
+    au FileType go iabbrev <buffer> enilrwn if err != nil {<cr>return nil, fmt.Errorf(": %w", err<left><left><left><left><left><left><left><left><left><left><C-R>=Eatchar('\s')<cr>
+    au FileType go iabbrev <buffer> enilrws if err != nil {<cr>return "", fmt.Errorf(": %w", err<left><left><left><left><left><left><left><left><left><left><C-R>=Eatchar('\s')<cr>
+    au FileType go iabbrev <buffer> enilrwz if err != nil {<cr>return 0, fmt.Errorf(": %w", err<left><left><left><left><left><left><left><left><left><left><C-R>=Eatchar('\s')<cr>
 
     au FileType gohtmltmpl setlocal shiftwidth=4
 augroup END
@@ -1548,16 +1527,6 @@
 augroup END
 
 " }}}
-" Jade Templates {{{
-
-augroup ft_jade
-    au!
-
-    au BufRead,BufNewFile *.jade setlocal filetype=jade
-    au FileType jade setlocal foldmethod=indent
-augroup END
-
-" }}}
 " Java {{{
 
 augroup ft_java
@@ -1576,7 +1545,6 @@
 
     au FileType javascript setlocal foldmethod=marker
     au FileType javascript setlocal foldmarker={,}
-    au FileType javascript call MakeSpacelessBufferIabbrev('clog', 'console.log();<left><left>')
 
     " Make {<cr> insert a pair of brackets in such a way that the cursor is correctly
     " positioned inside of them AND the following code doesn't get unfolded.
@@ -1598,15 +1566,6 @@
 augroup END
 
 " }}}
-" Lilypond {{{
-
-augroup ft_lilypond
-    au!
-
-    au FileType lilypond setlocal foldmethod=marker foldmarker={,}
-augroup END
-
-" }}}
 " Mail {{{
 
 augroup ft_mail
@@ -1702,6 +1661,15 @@
 augroup END
 
 " }}}
+" Martian {{{
+
+augroup ft_martian
+    au!
+
+    au Filetype markdown inoremap <buffer> <c-n> <c-x><c-n>
+augroup END
+
+" }}}
 " Mercurial {{{
 
 augroup ft_mercurial
@@ -1722,48 +1690,18 @@
 augroup END
 
 " }}}
-" Nand2Tetris HDL {{{
-
-augroup ft_n2thdl
-    au!
-
-    au BufNewFile,BufRead *.hdl set filetype=n2thdl
-augroup END
-
-" }}}
 " Nginx {{{
 
 augroup ft_nginx
     au!
 
-    au BufRead,BufNewFile /etc/nginx/conf/*                      set ft=nginx
-    au BufRead,BufNewFile /etc/nginx/sites-available/*           set ft=nginx
-    au BufRead,BufNewFile /usr/local/etc/nginx/sites-available/* set ft=nginx
-    au BufRead,BufNewFile vhost.nginx                            set ft=nginx
+    au BufRead,BufNewFile nginx.conf                             set ft=nginx
+    au BufRead,BufNewFile *.nginx.conf                           set ft=nginx
 
     au FileType nginx setlocal foldmethod=marker foldmarker={,}
 augroup END
 
 " }}}
-" PandaBT {{{
-
-augroup ft_pandabt
-    au!
-    au BufNewFile,BufRead *.BT.txt set filetype=pandabt
-
-    au FileType pandabt setlocal noexpandtab shiftwidth=8
-augroup END
-
-" }}}
-" Pentadactyl {{{
-
-augroup ft_pentadactyl
-    au!
-    au BufNewFile,BufRead .pentadactylrc set filetype=pentadactyl
-    au BufNewFile,BufRead ~/Library/Caches/TemporaryItems/pentadactyl-*.tmp set nolist wrap linebreak columns=100 colorcolumn=0
-augroup END
-
-" }}}
 " .plan {{{
 
 function! PlanLinkPaste()
@@ -1788,7 +1726,7 @@
     au BufNewFile,BufRead *.pgsql set filetype=pgsql
 
     au FileType pgsql set foldmethod=marker foldmarker=\ $$,$$\ 
-    au FileType pgsql set softtabstop=2 shiftwidth=2
+    au FileType pgsql set softtabstop=4 shiftwidth=4
     au FileType pgsql setlocal commentstring=--\ %s comments=:--
 
     " Set up some basic neorepl mappings.
@@ -1820,116 +1758,17 @@
 " }}}
 " Python {{{
 
-function! SelectTopLevelPythonHunk() "{{{
-    " oh darling what have I done
-
-    " if we're on toplevel line that ends in a :, drop down one line before
-    " we move on.  this is bad and i feel bad.
-    let line = getline(".")
-    if len(line) > 0 && line[0] != " " && line[len(line) - 1] == ":"
-        normal! j
-    endif
-
-    normal! v
-
-    " use the non-bang version of normal here because we need to use the
-    " indentation script.  this is also bad and i still feel bad.
-    normal ai
-
-    " keep chomping upwards in the indentation stack til we get to something
-    " that's at the top level.  its bad.
-    while getline(".")[0] == " "
-        normal ai
-    endwhile
-endfunction "}}}
-
-function! OpenPythonRepl() "{{{
-    "fucking kill me
-    NeoRepl fish
-endfunction "}}}
-
-function! SendPythonParagraph() "{{{
-    let view = winsaveview()
-
-    execute "normal! ^vip\<esc>"
-    call NeoReplSendSelection()
-
-    call winrestview(view)
-endfunction "}}}
-function! SendPythonTopLevelHunk() "{{{
-    let view = winsaveview()
-    let old_z = @z
-
-    call SelectTopLevelPythonHunk()
-    normal! gv"zy
-    call NeoReplSendRaw("%cpaste\n" . @z . "\n--\n")
-
-    let @z = old_z
-    call winrestview(view)
-endfunction "}}}
-function! SendPythonSelection() "{{{
-    let view = winsaveview()
-    let old_z = @z
-
-    normal! gv"zy
-    call NeoReplSendRaw("%cpaste\n" . @z . "\n--\n")
-
-    let @z = old_z
-    call winrestview(view)
-endfunction "}}}
-function! SendPythonBuffer() "{{{
-    let view = winsaveview()
-
-    execute "normal! ggVG\<esc>"
-
-    normal! gv"zy
-    call NeoReplSendRaw("%cpaste\n" . @z . "\n--\n")
-
-    call winrestview(view)
-endfunction "}}}
-
 augroup ft_python
     au!
 
     au FileType python setlocal define=^\s*\\(def\\\\|class\\)
+    au FileType python setlocal textwidth=100
 
     " Jesus tapdancing Christ, built-in Python syntax, you couldn't let me
     " override this in a normal way, could you?
     au FileType python if exists("python_space_error_highlight") | unlet python_space_error_highlight | endif
 
-    " Strip REPL-session marks from just-pasted text
-    au FileType python nnoremap <localleader>s mz`[v`]:v/\v^(\>\>\>\|[.][.][.])/d<cr>gv:s/\v^(\>\>\> \|[.][.][.] \|[.][.][.]$)//<cr>:noh<cr>`z
-
-    " Set up some basic neorepl mappings.
-    "
-    " key  desc                   mnemonic
-    " \o - connect neorepl        [o]pen repl
-    " \l - send current line      [l]ine
-    " \p - send current paragraph [p]aragraph
-    " \e - send top-level hunk    [e]val
-    " \e - send selected hunk     [e]val
-    " \r - send entire file       [r]eload file
-    " \c - send ctrl-l            [c]lear
-
-    au FileType python nnoremap <buffer> <silent> <localleader>o :call OpenPythonRepl()<cr>
-
-    " Send the current line to the REPL
-    au FileType python nnoremap <buffer> <silent> <localleader>l :call NeoReplSendCurrentLine()<cr>
-
-    " Send the current paragraph to the REPL
-    au FileType python nnoremap <buffer> <silent> <localleader>p :call SendPythonParagraph()<cr>
-
-    " " Send the current top-level hunk to the REPL
-    au FileType python nnoremap <buffer> <silent> <localleader>e :call SendPythonTopLevelHunk()<cr>
-
-    " Send the current selection to the REPL
-    au FileType python vnoremap <buffer> <silent> <localleader>e :<c-u>call SendPythonSelection()<cr>
-
-    " Send the entire buffer to the REPL ([r]eload)
-    au FileType python nnoremap <buffer> <silent> <localleader>r :call SendPythonBuffer()<cr>
-
-    " Clear the REPL
-    au FileType python nnoremap <buffer> <silent> <localleader>c :call NeoReplSendRaw("")<cr>
+    au FileType python nnoremap <buffer> gi :Neoformat black<cr>zx
 augroup END
 
 " }}}
@@ -1944,46 +1783,6 @@
 augroup END
 
 " }}}
-" ReStructuredText {{{
-
-augroup ft_rest
-    au!
-
-    au Filetype rst nnoremap <buffer> <localleader>1 yypVr=:redraw<cr>
-    au Filetype rst nnoremap <buffer> <localleader>2 yypVr-:redraw<cr>
-    au Filetype rst nnoremap <buffer> <localleader>3 yypVr~:redraw<cr>
-    au Filetype rst nnoremap <buffer> <localleader>4 yypVr`:redraw<cr>
-augroup END
-
-" }}}
-" Rubby {{{
-
-augroup ft_ruby
-    au!
-    au Filetype ruby setlocal foldmethod=syntax
-    au BufRead,BufNewFile Capfile setlocal filetype=ruby
-augroup END
-
-" }}}
-" Scala {{{
-
-augroup ft_scala
-    au!
-
-    au FileType scala setlocal foldmethod=syntax
-    au FileType scala setlocal foldlevel=1
-    au FileType scala setlocal cc=100 tw=100
-    au FileType scala setlocal expandtab
-
-    au FileType scala nnoremap <buffer> <leader>s :SortSimpleScalaImports<cr>
-    au FileType scala nnoremap <buffer> <c-]> :call LanguageClient_textDocument_definition()<CR>
-    au FileType scala nnoremap <buffer> <localleader>r :call LanguageClient_textDocument_references()<CR>
-    au FileType scala inoremap <buffer> <c-n> <c-x><c-o>
-
-    au FileType scala setlocal omnifunc=LanguageClient#complete
-augroup END
-
-" }}}
 " Sh {{{
 
 function! SendShellParagraph() "{{{
@@ -2001,16 +1800,6 @@
 augroup END
 
 " }}}
-" ShaderLab {{{
-
-augroup ft_shaderlab " {{{
-    au!
-
-    au FileType shaderlab setlocal shiftwidth=4
-    au FileType shaderlab setlocal expandtab
-augroup END " }}}
-
-" }}}
 " Standard In {{{
 
 augroup ft_stdin
@@ -2021,15 +1810,6 @@
 augroup END
 
 " }}}
-" stevelosh.com Blog Entries {{{
-
-augroup ft_steveloshcom
-    au!
-    au BufRead,BufNewFile */stevelosh/content/blog/20*/*/*.html set ft=markdown
-    au BufRead,BufNewFile */stevelosh/content/projects/*.html set ft=markdown
-augroup END
-
-" }}}
 " Terminal {{{
 
 augroup ft_terminal
@@ -2038,6 +1818,15 @@
 augroup END
 
 " }}}
+" Terraform {{{
+
+augroup ft_terraform
+    au!
+
+    au FileType terraform setlocal foldmethod=syntax
+augroup END
+
+" }}}
 " Vagrant {{{
 
 augroup ft_vagrant
@@ -2058,7 +1847,7 @@
     au FileType vim vnoremap <localleader>S y:@"<CR>
     au FileType vim nnoremap <localleader>S ^vg_y:execute @@<cr>:echo 'Sourced line.'<cr>
 
-    au FileType vim inoremap <c-n> <c-x><c-n>
+    au FileType vim inoremap <buffer> <c-n> <c-x><c-n>
 augroup END
 
 " }}}
@@ -2071,15 +1860,6 @@
 augroup END
 
 " }}}
-" Wisp {{{
-
-augroup ft_wisp
-    au!
-
-    au BufRead,BufNewFile *.wisp set ft=clojure
-augroup END
-
-" }}}
 " XML {{{
 
 augroup ft_xml
@@ -2193,6 +1973,8 @@
 nnoremap <leader>gci :Gcommit<cr>
 nnoremap <leader>gm :Gmove<cr>
 nnoremap <leader>gr :Gremove<cr>
+nnoremap <leader>gpo :!git push origin<cr>
+nnoremap <leader>gpu :!git push upstream<cr>
 nnoremap <leader>gl :Clam git gll -100 \| stripcolor<cr>
 
 
@@ -2246,26 +2028,12 @@
 let g:atia_attributes_complete = 0
 
 " }}}
-" Language Server Protocol {{{
-
-let g:LanguageClient_serverCommands = {
-    \ 'scala': ['netcat', 'localhost', '62831'],
-    \ 'java': ['netcat', 'localhost', '62831'],
-    \ }
-let g:LanguageClient_autoStart = 1
-
-nnoremap <silent> gd :call LanguageClient_textDocument_definition()<CR>
-
-" nnoremap <silent> K :call LanguageClient_textDocument_hover()<CR>
-" nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
-
-" }}}
 " MiniYank {{{
 
-map p <Plug>(miniyank-autoput)
-map P <Plug>(miniyank-autoPut)
-nmap gp <Plug>(miniyank-cycle)
-nnoremap gP g-
+" map p <Plug>(miniyank-autoput)
+" map P <Plug>(miniyank-autoPut)
+" nmap gp <Plug>(miniyank-cycle)
+" nnoremap gP g-
 
 " }}}
 " NeoFormat {{{
@@ -2309,6 +2077,8 @@
 
 noremap  <F2> :NERDTreeToggle<cr>
 inoremap <F2> <esc>:NERDTreeToggle<cr>
+noremap  <F14> :NERDTreeFind<cr>
+inoremap <F14> <esc>:NERDTreeFind<cr>
 noremap  <S-F2> :NERDTreeFind<cr>
 inoremap <S-F2> <esc>:NERDTreeFind<cr>
 
@@ -2338,13 +2108,14 @@
 let NERDChristmasTree = 1
 let NERDTreeChDirMode = 2
 let NERDTreeMapJumpFirstChild = 'gK'
+let g:NERDTreeMinimalMenu = 1
 
 " }}}
 " Paredit {{{
 
 let g:paredit_smartjump = 1
 let g:paredit_shortmaps = 0
-let g:paredit_electric_return = 1
+let g:paredit_electric_return = 0
 let g:paredit_matchlines = 200
 
 let g:paredit_disable_lisp = 1
@@ -2430,12 +2201,6 @@
 let g:rbpt_max = 1
 
 " }}}
-" Scala {{{
-
-let g:scala_use_builtin_tagbar_defs = 0
-let g:scala_use_default_keymappings = 0
-
-" }}}
 " Scratch {{{
 
 command! ScratchToggle call ScratchToggle()
@@ -2610,13 +2375,6 @@
 endfunction
 
 " }}}
-" Supertab {{{
-
-let g:SuperTabDefaultCompletionType = "<c-n>"
-let g:SuperTabLongestHighlight = 1
-let g:SuperTabCrMapping = 1
-
-"}}}
 " Splice {{{
 
 let g:splice_prefix = "-"
@@ -2684,6 +2442,18 @@
             \ "SPEED": 1
             \ }
 
+let g:vlime_contribs = [
+            \ "SWANK-ASDF",
+            \ "SWANK-PACKAGE-FU",
+            \ "SWANK-PRESENTATIONS",
+            \ "SWANK-FANCY-INSPECTOR",
+            \ "SWANK-C-P-C",
+            \ "SWANK-ARGLISTS",
+            \ "SWANK-REPL",
+            \ "SWANK-FUZZY",
+            \ "SWANK-TRACE-DIALOG"
+            \ ]
+
 " let g:vlime_indent_keywords = {"defsystem": 1}
 
 function! CleanVlimeWindows()
@@ -2760,7 +2530,7 @@
 " Windowswap {{{
 
 let g:windowswap_map_keys = 0 "prevent default bindings
-nnoremap <silent> <leader>W :call WindowSwap#EasyWindowSwap()<CR>
+nnoremap <silent> <leader>ws :call WindowSwap#EasyWindowSwap()<CR>
 
 " }}}
 
@@ -2831,6 +2601,15 @@
 " Stuff that should probably be broken out into plugins, but hasn't proved to be
 " worth the time to do so just yet.
 
+" HTTP Statuses {{{
+
+function! HTTPStatuses()
+    call termopen('w3m /home/sjl/Dropbox/docs/httpstatuses/httpstatuses.com/index.html')
+endfunc
+
+command! HTTPStatuses call HTTPStatuses()
+
+" }}}
 " Synstack {{{
 
 " Show the stack of syntax hilighting classes affecting whatever is under the
@@ -2878,9 +2657,6 @@
 
 nnoremap <leader>V :call ToggleVirtualEdit()<cr>
 
-" TODO: Figure out the diffexpr shit necessary to make this buffer-local.
-" nnoremap <leader>W :call ToggleDiffWhitespace()<CR>
-
 " }}}
 " Error Toggles {{{
 
@@ -3006,15 +2782,6 @@
 nnoremap <leader>h<space> :!hg<space>
 
 " }}}
-" J {{{
-
-function! s:JumpTo(dest)
-  call system("tmux split-window -h 'j " . a:dest . "; and myctags &; and nvim .'")
-endfunction
-
-command! -nargs=1 J call s:JumpTo(<f-args>)
-
-" }}}
 " Ack motions {{{
 
 " Motions to Ack for things.  Works with pretty much everything, including:
@@ -3088,6 +2855,7 @@
 
     execute 'hi ' . old_hi
 endfunction " }}}
+
 command! -nargs=0 Pulse call s:Pulse()
 
 " }}}
@@ -3171,56 +2939,7 @@
 
 if has('gui_running')
     " GUI Vim
-
-    set guifont=Menlo\ Regular\ for\ Powerline:h12
-
-    " Remove all the UI cruft
-    set go-=T
-    set go-=l
-    set go-=L
-    set go-=r
-    set go-=R
-
-    highlight SpellBad term=underline gui=undercurl guisp=Orange
-
-    " Different cursors for different modes.
-    set guicursor=n-c:block-Cursor-blinkon0
-    set guicursor+=v:block-vCursor-blinkon0
-    set guicursor+=i-ci:ver20-iCursor
-
-    if has("gui_macvim")
-        " Full screen means FULL screen
-        set fuoptions=maxvert,maxhorz
-
-        " Use the normal HIG movements, except for M-Up/Down
-        let macvim_skip_cmd_opt_movement = 1
-        no   <D-Left>       <Home>
-        no!  <D-Left>       <Home>
-        no   <M-Left>       <C-Left>
-        no!  <M-Left>       <C-Left>
-
-        no   <D-Right>      <End>
-        no!  <D-Right>      <End>
-        no   <M-Right>      <C-Right>
-        no!  <M-Right>      <C-Right>
-
-        no   <D-Up>         <C-Home>
-        ino  <D-Up>         <C-Home>
-        imap <M-Up>         <C-o>{
-
-        no   <D-Down>       <C-End>
-        ino  <D-Down>       <C-End>
-        imap <M-Down>       <C-o>}
-
-        imap <M-BS>         <C-w>
-        inoremap <D-BS>     <esc>my0c`y
-    else
-        " Non-MacVim GUI, like Gvim
-    end
 else
-    " Console Vim
-    " For me, this means iTerm2, possibly through tmux
-
     " Mouse support
     set mouse=a
 endif
--- a/weechat/alias.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/alias.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [cmd]
--- a/weechat/autosort.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/autosort.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,15 +4,21 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [sorting]
 case_sensitive = off
-group_irc = on
+debug_log = off
 replacements = "[]"
 rules = "[["core", 0], ["irc", 2], ["*", 1], ["irc.irc_raw", 0], ["irc.server", 1]]"
+signal_delay = 5
 signals = "buffer_opened buffer_merged buffer_unmerged buffer_renamed"
+sort_limit = 100
 sort_on_config_change = on
+
+[v3]
+helpers = "{"core_first": "${if:${buffer.full_name}!=core.weechat}", "irc_raw_first": "${if:${buffer.full_name}!=irc.irc_raw}", "irc_raw_last": "${if:${buffer.full_name}==irc.irc_raw}", "hashless_name": "${info:autosort_replace,#,,${info:autosort_escape,${buffer.name}}}", "script_or_plugin": "${if:${script_name}?${script_name}:${plugin}}"}"
+rules = "["${core_first}", "${info:autosort_order,${info:autosort_escape,${script_or_plugin}},core,*,irc,bitlbee,matrix,slack}", "${script_or_plugin}", "${irc_raw_first}", "${server}", "${info:autosort_order,${type},server,*,channel,private}", "${hashless_name}", "${buffer.full_name}"]"
--- a/weechat/buflist.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/buflist.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [look]
@@ -21,6 +21,7 @@
 nick_prefix_empty = on
 signals_refresh = ""
 sort = "number,-active"
+use_items = 1
 
 [format]
 buffer = "${format_number}${indent}${format_nick_prefix}${color_hotlist}${format_name}"
@@ -37,3 +38,4 @@
 name = "${name}"
 nick_prefix = "${color_nick_prefix}${nick_prefix}"
 number = "${color:green}${number}${if:${number_displayed}?.: }"
+tls_version = " ${color:default}(${if:${tls_version}==TLS1.3?${color:green}:${if:${tls_version}==TLS1.2?${color:yellow}:${color:red}}}${translate:${tls_version}}${color:default})"
--- a/weechat/charset.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/charset.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [default]
--- a/weechat/exec.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/exec.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,14 +4,15 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [command]
 default_options = ""
 purge_delay = 0
+shell = "${env:SHELL}"
 
 [color]
 flag_finished = lightred
--- a/weechat/fifo.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/fifo.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [file]
--- a/weechat/fset.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/fset.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,12 +4,13 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [look]
+auto_refresh = "*"
 auto_unmark = off
 condition_catch_set = "${count} >= 1"
 export_help_default = on
--- a/weechat/logger.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/logger.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [look]
@@ -19,6 +19,7 @@
 
 [file]
 auto_log = on
+color_lines = off
 flush_delay = 120
 fsync = off
 info_lines = off
--- a/weechat/perl.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/perl.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,7 +4,7 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
 # For more info, see: https://weechat.org/doc/quickstart
 #
--- a/weechat/python.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/python.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [look]
--- a/weechat/python/autoload/autosort.py	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/python/autoload/autosort.py	Fri Jul 07 16:11:02 2023 -0400
@@ -1,860 +1,1 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2013-2014 Maarten de Vries <maarten@de-vri.es>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-
-#
-# Autosort automatically keeps your buffers sorted and grouped by server.
-# You can define your own sorting rules. See /help autosort for more details.
-#
-# http://github.com/de-vri.es/weechat-autosort
-#
-
-#
-# Changelog:
-# 2.5:
-#   * Fix handling unicode buffer names.
-#   * Add hint to set irc.look.server_buffer to independent and buffers.look.indenting to on.
-# 2.4:
-#   * Make script python3 compatible.
-# 2.3:
-#   * Fix sorting items without score last (regressed in 2.2).
-# 2.2:
-#   * Add configuration option for signals that trigger a sort.
-#   * Add command to manually trigger a sort (/autosort sort).
-#   * Add replacement patterns to apply before sorting.
-# 2.1:
-#   * Fix some minor style issues.
-# 2.0:
-#   * Allow for custom sort rules.
-#
-
-
-import weechat
-import re
-import json
-
-SCRIPT_NAME     = 'autosort'
-SCRIPT_AUTHOR   = 'Maarten de Vries <maarten@de-vri.es>'
-SCRIPT_VERSION  = '2.5'
-SCRIPT_LICENSE  = 'GPL3'
-SCRIPT_DESC     = 'Automatically or manually keep your buffers sorted and grouped by server.'
-
-
-config = None
-hooks  = []
-
-class HumanReadableError(Exception):
-	pass
-
-
-def parse_int(arg, arg_name = 'argument'):
-	''' Parse an integer and provide a more human readable error. '''
-	arg = arg.strip()
-	try:
-		return int(arg)
-	except ValueError:
-		raise HumanReadableError('Invalid {0}: expected integer, got "{1}".'.format(arg_name, arg))
-
-
-class Pattern:
-	''' A simple glob-like pattern for matching buffer names. '''
-
-	def __init__(self, pattern):
-		''' Construct a pattern from a string. '''
-		escaped    = False
-		char_class = 0
-		chars      = ''
-		regex      = ''
-		for c in pattern:
-			if escaped and char_class:
-				escaped = False
-				chars += re.escape(c)
-			elif escaped:
-				escaped = False
-				regex += re.escape(c)
-			elif c == '\\':
-				escaped = True
-			elif c == '*' and not char_class:
-				regex += '[^.]*'
-			elif c == '?' and not char_class:
-				regex += '[^.]'
-			elif c == '[' and not char_class:
-				char_class = 1
-				chars    = ''
-			elif c == '^' and char_class and not chars:
-				chars += '^'
-			elif c == ']' and char_class and chars not in ('', '^'):
-				char_class = False
-				regex += '[' + chars + ']'
-			elif c == '-' and char_class:
-				chars += '-'
-			elif char_class:
-				chars += re.escape(c)
-			else:
-				regex += re.escape(c)
-
-		if char_class:
-			raise ValueError("unmatched opening '['")
-		if escaped:
-			raise ValueError("unexpected trailing '\\'")
-
-		self.regex   = re.compile('^' + regex + '$')
-		self.pattern = pattern
-
-	def match(self, input):
-		''' Match the pattern against a string. '''
-		return self.regex.match(input)
-
-
-class FriendlyList(object):
-	''' A list with human readable errors. '''
-
-	def __init__(self):
-		self.__data = []
-
-	def raw(self):
-		return self.__data
-
-	def append(self, value):
-		''' Add a rule to the list. '''
-		self.__data.append(value)
-
-	def insert(self, index, value):
-		''' Add a rule to the list. '''
-		if not 0 <= index <= len(self): raise HumanReadableError('Index out of range: expected an integer in the range [0, {0}], got {1}.'.format(len(self), index))
-		self.__data.insert(index, value)
-
-	def pop(self, index):
-		''' Remove a rule from the list and return it. '''
-		if not 0 <= index < len(self): raise HumanReadableError('Index out of range: expected an integer in the range [0, {0}), got {1}.'.format(len(self), index))
-		return self.__data.pop(index)
-
-	def move(self, index_a, index_b):
-		''' Move a rule to a new position in the list. '''
-		self.insert(index_b, self.pop(index_a))
-
-	def swap(self, index_a, index_b):
-		''' Swap two elements in the list. '''
-		self[index_a], self[index_b] = self[index_b], self[index_a]
-
-	def __len__(self):
-		return len(self.__data)
-
-	def __getitem__(self, index):
-		if not 0 <= index < len(self): raise HumanReadableError('Index out of range: expected an integer in the range [0, {0}), got {1}.'.format(len(self), index))
-		return self.__data[index]
-
-	def __setitem__(self, index, value):
-		if not 0 <= index < len(self): raise HumanReadableError('Index out of range: expected an integer in the range [0, {0}), got {1}.'.format(len(self), index))
-		self.__data[index] = value
-
-	def __iter__(self):
-		return iter(self.__data)
-
-
-class RuleList(FriendlyList):
-	''' A list of rules to test buffer names against. '''
-	rule_regex = re.compile(r'^(.*)=\s*([+-]?[^=]*)$')
-
-	def __init__(self, rules):
-		''' Construct a RuleList from a list of rules. '''
-		super(RuleList, self).__init__()
-		for rule in rules: self.append(rule)
-
-	def get_score(self, name, rules):
-		''' Get the sort score of a partial name according to a rule list. '''
-		for rule in self:
-			if rule[0].match(name): return rule[1]
-		return 999999999
-
-	def encode(self):
-		''' Encode the rules for storage. '''
-		return json.dumps(list(map(lambda x: (x[0].pattern, x[1]), self)))
-
-	@staticmethod
-	def decode(blob):
-		''' Parse rules from a string blob. '''
-		result = []
-
-		try:
-			decoded = json.loads(blob)
-		except ValueError:
-			log('Invalid rules: expected JSON encoded list of pairs, got "{0}".'.format(blob))
-			return [], 0
-
-		for rule in decoded:
-			# Rules must be a pattern,score pair.
-			if len(rule) != 2:
-				log('Invalid rule: expected (pattern, score), got "{0}". Rule ignored.'.format(rule))
-				continue
-
-			# Rules must have a valid pattern.
-			try:
-				pattern = Pattern(rule[0])
-			except ValueError as e:
-				log('Invalid pattern: {0} in "{1}". Rule ignored.'.format(e, rule[0]))
-				continue
-
-			# Rules must have a valid score.
-			try:
-				score = int(rule[1])
-			except ValueError as e:
-				log('Invalid score: expected an integer, got "{0}". Rule ignored.'.format(score))
-				continue
-
-			result.append((pattern, score))
-
-		return RuleList(result)
-
-	@staticmethod
-	def parse_rule(arg):
-		''' Parse a rule argument. '''
-		arg = arg.strip()
-		match = RuleList.rule_regex.match(arg)
-		if not match:
-			raise HumanReadableError('Invalid rule: expected "<pattern> = <score>", got "{0}".'.format(arg))
-
-		pattern = match.group(1).strip()
-		try:
-			pattern = Pattern(pattern)
-		except ValueError as e:
-			raise HumanReadableError('Invalid pattern: {0} in "{1}".'.format(e, pattern))
-
-		score   = parse_int(match.group(2), 'score')
-		return (pattern, score)
-
-
-def decode_replacements(blob):
-	''' Decode a replacement list encoded as JSON. '''
-	result = FriendlyList()
-	try:
-		decoded = json.loads(blob)
-	except ValueError:
-		log('Invalid replacement list: expected JSON encoded list of pairs, got "{0}".'.format(blob))
-		return [], 0
-
-	for replacement in decoded:
-		# Replacements must be a (string, string) pair.
-		if len(replacement) != 2:
-			log('Invalid replacement pattern: expected (pattern, replacement), got "{0}". Replacement ignored.'.format(rule))
-			continue
-		result.append(replacement)
-
-	return result
-
-
-def encode_replacements(replacements):
-	''' Encode a list of replacement patterns as JSON. '''
-	return json.dumps(replacements.raw())
-
-
-class Config:
-	''' The autosort configuration. '''
-
-	default_rules = json.dumps([
-		('core', 0),
-		('irc',  2),
-		('*',    1),
-
-		('irc.irc_raw', 0),
-		('irc.server',  1),
-	])
-
-	default_replacements = '[]'
-	default_signals      = 'buffer_opened buffer_merged buffer_unmerged buffer_renamed'
-
-	def __init__(self, filename):
-		''' Initialize the configuration. '''
-
-		self.filename         = filename
-		self.config_file      = weechat.config_new(self.filename, '', '')
-		self.sorting_section  = None
-
-		self.case_sensitive   = False
-		self.group_irc        = True
-		self.rules            = []
-		self.replacements     = []
-		self.signals          = []
-		self.sort_on_config   = True
-
-		self.__case_sensitive = None
-		self.__group_irc      = None
-		self.__rules          = None
-		self.__replacements   = None
-		self.__signals        = None
-		self.__sort_on_config = None
-
-		if not self.config_file:
-			log('Failed to initialize configuration file "{0}".'.format(self.filename))
-			return
-
-		self.sorting_section = weechat.config_new_section(self.config_file, 'sorting', False, False, '', '', '', '', '', '', '', '', '', '')
-
-		if not self.sorting_section:
-			log('Failed to initialize section "sorting" of configuration file.')
-			weechat.config_free(self.config_file)
-			return
-
-		self.__case_sensitive = weechat.config_new_option(
-			self.config_file, self.sorting_section,
-			'case_sensitive', 'boolean',
-			'If this option is on, sorting is case sensitive.',
-			'', 0, 0, 'off', 'off', 0,
-			'', '', '', '', '', ''
-		)
-
-		self.__group_irc = weechat.config_new_option(
-			self.config_file, self.sorting_section,
-			'group_irc', 'boolean',
-			'If this option is on, the script pretends that IRC channel/private buffers are renamed to "irc.server.{network}.{channel}" rather than "irc.{network}.{channel}".' +
-			'This ensures that these buffers are grouped with their respective server buffer.',
-			'', 0, 0, 'on', 'on', 0,
-			'', '', '', '', '', ''
-		)
-
-		self.__rules = weechat.config_new_option(
-			self.config_file, self.sorting_section,
-			'rules', 'string',
-			'An ordered list of sorting rules encoded as JSON. See /help autosort for commands to manipulate these rules.',
-			'', 0, 0, Config.default_rules, Config.default_rules, 0,
-			'', '', '', '', '', ''
-		)
-
-		self.__replacements = weechat.config_new_option(
-			self.config_file, self.sorting_section,
-			'replacements', 'string',
-			'An ordered list of replacement patterns to use on buffer name components, encoded as JSON. See /help autosort for commands to manipulate these replacements.',
-			'', 0, 0, Config.default_replacements, Config.default_replacements, 0,
-			'', '', '', '', '', ''
-		)
-
-		self.__signals = weechat.config_new_option(
-			self.config_file, self.sorting_section,
-			'signals', 'string',
-			'The signals that will cause autosort to resort your buffer list. Seperate signals with spaces.',
-			'', 0, 0, Config.default_signals, Config.default_signals, 0,
-			'', '', '', '', '', ''
-		)
-
-		self.__sort_on_config = weechat.config_new_option(
-			self.config_file, self.sorting_section,
-			'sort_on_config_change', 'boolean',
-			'Decides if the buffer list should be sorted when autosort configuration changes.',
-			'', 0, 0, 'on', 'on', 0,
-			'', '', '', '', '', ''
-		)
-
-		if weechat.config_read(self.config_file) != weechat.WEECHAT_RC_OK:
-			log('Failed to load configuration file.')
-
-		if weechat.config_write(self.config_file) != weechat.WEECHAT_RC_OK:
-			log('Failed to write configuration file.')
-
-		self.reload()
-
-	def reload(self):
-		''' Load configuration variables. '''
-
-		self.case_sensitive = weechat.config_boolean(self.__case_sensitive)
-		self.group_irc      = weechat.config_boolean(self.__group_irc)
-
-		rules_blob          = weechat.config_string(self.__rules)
-		replacements_blob   = weechat.config_string(self.__replacements)
-		signals_blob        = weechat.config_string(self.__signals)
-
-		self.rules          = RuleList.decode(rules_blob)
-		self.replacements   = decode_replacements(replacements_blob)
-		self.signals        = signals_blob.split()
-		self.sort_on_config = weechat.config_boolean(self.__sort_on_config)
-
-	def save_rules(self, run_callback = True):
-		''' Save the current rules to the configuration. '''
-		weechat.config_option_set(self.__rules, RuleList.encode(self.rules), run_callback)
-
-	def save_replacements(self, run_callback = True):
-		''' Save the current replacement patterns to the configuration. '''
-		weechat.config_option_set(self.__replacements, encode_replacements(self.replacements), run_callback)
-
-
-def pad(sequence, length, padding = None):
-	''' Pad a list until is has a certain length. '''
-	return sequence + [padding] * max(0, (length - len(sequence)))
-
-
-def log(message, buffer = 'NULL'):
-	weechat.prnt(buffer, 'autosort: {0}'.format(message))
-
-
-def get_buffers():
-	''' Get a list of all the buffers in weechat. '''
-	buffers = []
-
-	buffer_list = weechat.infolist_get('buffer', '', '')
-
-	while weechat.infolist_next(buffer_list):
-		name   = weechat.infolist_string (buffer_list, 'full_name')
-		number = weechat.infolist_integer(buffer_list, 'number')
-
-		# Buffer is merged with one we already have in the list, skip it.
-		if number <= len(buffers):
-			continue
-		buffers.append(name)
-
-	weechat.infolist_free(buffer_list)
-	return buffers
-
-
-def preprocess(buffer, config):
-	'''
-	Preprocess a buffers names.
-	'''
-	if not config.case_sensitive:
-		buffer = buffer.lower()
-
-	for replacement in config.replacements:
-		buffer = buffer.replace(replacement[0], replacement[1])
-
-	buffer = buffer.split('.')
-	if config.group_irc and len(buffer) >= 2 and buffer[0] == 'irc' and buffer[1] not in ('server', 'irc_raw'):
-		buffer.insert(1, 'server')
-
-	return buffer
-
-
-def buffer_sort_key(rules):
-	''' Create a sort key function for a buffer list from a rule list. '''
-	def key(buffer):
-		result  = []
-		name    = ''
-		for word in preprocess(buffer.decode('utf-8'), config):
-			name += ('.' if name else '') + word
-			result.append((rules.get_score(name, rules), word))
-		return result
-
-	return key
-
-
-def apply_buffer_order(buffers):
-	''' Sort the buffers in weechat according to the order in the input list.  '''
-	for i, buffer in enumerate(buffers):
-		weechat.command('', '/buffer swap {0} {1}'.format(buffer, i + 1))
-
-
-def split_args(args, expected, optional = 0):
-	''' Split an argument string in the desired number of arguments. '''
-	split = args.split(' ', expected - 1)
-	if (len(split) < expected):
-		raise HumanReadableError('Expected at least {0} arguments, got {1}.'.format(expected, len(split)))
-	return split[:-1] + pad(split[-1].split(' ', optional), optional + 1, '')
-
-
-def command_sort(buffer, command, args):
-	''' Sort the buffers and print a confirmation. '''
-	on_buffers_changed()
-	log("Finished sorting buffers.", buffer)
-	return weechat.WEECHAT_RC_OK
-
-
-def command_rule_list(buffer, command, args):
-	''' Show the list of sorting rules. '''
-	output = 'Sorting rules:\n'
-	for i, rule in enumerate(config.rules):
-		output += '    {0}: {1} = {2}\n'.format(i, rule[0].pattern, rule[1])
-	if not len(config.rules):
-		output += '    No sorting rules configured.\n'
-	log(output, buffer)
-
-	return weechat.WEECHAT_RC_OK
-
-
-def command_rule_add(buffer, command, args):
-	''' Add a rule to the rule list. '''
-	rule = RuleList.parse_rule(args)
-
-	config.rules.append(rule)
-	config.save_rules()
-	command_rule_list(buffer, command, '')
-
-	return weechat.WEECHAT_RC_OK
-
-
-def command_rule_insert(buffer, command, args):
-	''' Insert a rule at the desired position in the rule list. '''
-	index, rule = split_args(args, 2)
-	index = parse_int(index, 'index')
-	rule  = RuleList.parse_rule(rule)
-
-	config.rules.insert(index, rule)
-	config.save_rules()
-	command_rule_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-def command_rule_update(buffer, command, args):
-	''' Update a rule in the rule list. '''
-	index, rule = split_args(args, 2)
-	index = parse_int(index, 'index')
-	rule  = RuleList.parse_rule(rule)
-
-	config.rules[index] = rule
-	config.save_rules()
-	command_rule_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-def command_rule_delete(buffer, command, args):
-	''' Delete a rule from the rule list. '''
-	index = args.strip()
-	index = parse_int(index, 'index')
-
-	config.rules.pop(index)
-	config.save_rules()
-	command_rule_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-def command_rule_move(buffer, command, args):
-	''' Move a rule to a new position. '''
-	index_a, index_b = split_args(args, 2)
-	index_a = parse_int(index_a, 'index')
-	index_b = parse_int(index_b, 'index')
-
-	config.rules.move(index_a, index_b)
-	config.save_rules()
-	command_rule_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-def command_rule_swap(buffer, command, args):
-	''' Swap two rules. '''
-	index_a, index_b = split_args(args, 2)
-	index_a = parse_int(index_a, 'index')
-	index_b = parse_int(index_b, 'index')
-
-	config.rules.swap(index_a, index_b)
-	config.save_rules()
-	command_rule_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_list(buffer, command, args):
-	''' Show the list of sorting rules. '''
-	output = 'Replacement patterns:\n'
-	for i, pattern in enumerate(config.replacements):
-		output += '    {0}: {1} -> {2}\n'.format(i, pattern[0], pattern[1])
-	if not len(config.replacements):
-		output += '    No replacement patterns configured.'
-	log(output, buffer)
-
-	return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_add(buffer, command, args):
-	''' Add a rule to the rule list. '''
-	pattern, replacement = split_args(args, 1, 1)
-
-	config.replacements.append((pattern, replacement))
-	config.save_replacements()
-	command_replacement_list(buffer, command, '')
-
-	return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_insert(buffer, command, args):
-	''' Insert a rule at the desired position in the rule list. '''
-	index, pattern, replacement = split_args(args, 2, 1)
-	index = parse_int(index, 'index')
-
-	config.replacements.insert(index, (pattern, replacement))
-	config.save_replacements()
-	command_replacement_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_update(buffer, command, args):
-	''' Update a rule in the rule list. '''
-	index, pattern, replacement = split_args(args, 2, 1)
-	index = parse_int(index, 'index')
-
-	config.replacements[index] = (pattern, replacement)
-	config.save_replacements()
-	command_replacement_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_delete(buffer, command, args):
-	''' Delete a rule from the rule list. '''
-	index = args.strip()
-	index = parse_int(index, 'index')
-
-	config.replacements.pop(index)
-	config.save_replacements()
-	command_replacement_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_move(buffer, command, args):
-	''' Move a rule to a new position. '''
-	index_a, index_b = split_args(args, 2)
-	index_a = parse_int(index_a, 'index')
-	index_b = parse_int(index_b, 'index')
-
-	config.replacements.move(index_a, index_b)
-	config.save_replacements()
-	command_replacement_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-def command_replacement_swap(buffer, command, args):
-	''' Swap two rules. '''
-	index_a, index_b = split_args(args, 2)
-	index_a = parse_int(index_a, 'index')
-	index_b = parse_int(index_b, 'index')
-
-	config.replacements.swap(index_a, index_b)
-	config.save_replacements()
-	command_replacement_list(buffer, command, '')
-	return weechat.WEECHAT_RC_OK
-
-
-
-
-def call_command(buffer, command, args, subcommands):
-	''' Call a subccommand from a dictionary. '''
-	subcommand, tail = pad(args.split(' ', 1), 2, '')
-	subcommand = subcommand.strip()
-	if (subcommand == ''):
-		child   = subcommands.get(' ')
-	else:
-		command = command + [subcommand]
-		child   = subcommands.get(subcommand)
-
-	if isinstance(child, dict):
-		return call_command(buffer, command, tail, child)
-	elif callable(child):
-		return child(buffer, command, tail)
-
-	log('{0}: command not found'.format(' '.join(command)))
-	return weechat.WEECHAT_RC_ERROR
-
-
-def on_buffers_changed(*args, **kwargs):
-	''' Called whenever the buffer list changes. '''
-	buffers = get_buffers()
-	buffers.sort(key=buffer_sort_key(config.rules))
-	apply_buffer_order(buffers)
-	return weechat.WEECHAT_RC_OK
-
-
-def on_config_changed(*args, **kwargs):
-	''' Called whenever the configuration changes. '''
-	config.reload()
-
-	# Unhook all signals and hook the new ones.
-	for hook in hooks:
-		weechat.unhook(hook)
-	for signal in config.signals:
-		hooks.append(weechat.hook_signal(signal, 'on_buffers_changed', ''))
-
-	if config.sort_on_config:
-		on_buffers_changed()
-
-	return weechat.WEECHAT_RC_OK
-
-
-def on_autosort_command(data, buffer, args):
-	''' Called when the autosort command is invoked. '''
-	try:
-		return call_command(buffer, ['/autosort'], args, {
-			' ':      command_sort,
-			'sort':   command_sort,
-
-			'rules': {
-				' ':         command_rule_list,
-				'list':      command_rule_list,
-				'add':       command_rule_add,
-				'insert':    command_rule_insert,
-				'update':    command_rule_update,
-				'delete':    command_rule_delete,
-				'move':      command_rule_move,
-				'swap':      command_rule_swap,
-			},
-			'replacements': {
-				' ':      command_replacement_list,
-				'list':   command_replacement_list,
-				'add':    command_replacement_add,
-				'insert': command_replacement_insert,
-				'update': command_replacement_update,
-				'delete': command_replacement_delete,
-				'move':   command_replacement_move,
-				'swap':   command_replacement_swap,
-			},
-			'sort':   on_buffers_changed,
-		})
-	except HumanReadableError as e:
-		log(e, buffer)
-		return weechat.WEECHAT_RC_ERROR
-
-
-command_description = r'''
-NOTE: For the best effect, you may want to consider setting the option irc.look.server_buffer to independent and buffers.look.indenting to on.
-
-# Commands
-
-## Miscellaneous
-/autosort sort
-Manually trigger the buffer sorting.
-
-
-## Sorting rules
-
-/autosort rules list
-Print the list of sort rules.
-
-/autosort rules add <pattern> = <score>
-Add a new rule at the end of the list.
-
-/autosort rules insert <index> <pattern> = <score>
-Insert a new rule at the given index in the list.
-
-/autosort rules update <index> <pattern> = <score>
-Update a rule in the list with a new pattern and score.
-
-/autosort rules delete <index>
-Delete a rule from the list.
-
-/autosort rules move <index_from> <index_to>
-Move a rule from one position in the list to another.
-
-/autosort rules swap <index_a> <index_b>
-Swap two rules in the list
-
-
-## Replacement patterns
-
-/autosort replacements list
-Print the list of replacement patterns.
-
-/autosort replacements add <pattern> <replacement>
-Add a new replacement pattern at the end of the list.
-
-/autosort replacements insert <index> <pattern> <replacement>
-Insert a new replacement pattern at the given index in the list.
-
-/autosort replacements update <index> <pattern> <replacement>
-Update a replacement pattern in the list.
-
-/autosort replacements delete <index>
-Delete a replacement pattern from the list.
-
-/autosort replacements move <index_from> <index_to>
-Move a replacement pattern from one position in the list to another.
-
-/autosort replacements swap <index_a> <index_b>
-Swap two replacement pattern in the list
-
-
-# Introduction
-Autosort is a weechat script to automatically keep your buffers sorted.
-The sort order can be customized by defining your own sort rules,
-but the default should be sane enough for most people.
-It can also group IRC channel/private buffers under their server buffer if you like.
-
-Autosort first turns buffer names into a list of their components by splitting on them on the period character.
-For example, the buffer name "irc.server.freenode" is turned into ['irc', 'server', 'freenode'].
-The list of buffers is then lexicographically sorted.
-
-To facilitate custom sort orders, it is possible to assign a score to each component individually before the sorting is done.
-Any name component that did not get a score assigned will be sorted after those that did receive a score.
-Components are always sorted on their score first and on their name second.
-Lower scores are sorted first.
-
-## Automatic or manual sorting
-By default, autosort will automatically sort your buffer list whenever a buffer is opened, merged, unmerged or renamed.
-This should keep your buffers sorted in almost all situations.
-However, you may wish to change the list of signals that cause your buffer list to be sorted.
-Simply edit the "autosort.sorting.signals" option to add or remove any signal you like.
-If you remove all signals you can still sort your buffers manually with the "/autosort sort" command.
-To prevent all automatic sorting, "autosort.sorting.sort_on_config_change" should also be set to off.
-
-## Grouping IRC buffers
-In weechat, IRC channel/private buffers are named "irc.<network>.<#channel>",
-and IRC server buffers are named "irc.server.<network>".
-This does not work very well with lexicographical sorting if you want all buffers for one network grouped together.
-That is why autosort comes with the "autosort.sorting.group_irc" option,
-which secretly pretends IRC channel/private buffers are called "irc.server.<network>.<#channel>".
-The buffers are not actually renamed, autosort simply pretends they are for sorting purposes.
-
-## Replacement patterns
-Sometimes you may want to ignore some characters for sorting purposes.
-On Freenode for example, you may wish to ignore the difference between channels starting with a double or a single hash sign.
-To do so, simply add a replacement pattern that replaces ## with # with the following command:
-/autosort replacements add ## #
-
-Replacement patterns do not support wildcards or special characters at the moment.
-
-## Sort rules
-You can assign scores to name components by defining sort rules.
-The first rule that matches a component decides the score.
-Further rules are not examined.
-Sort rules use the following syntax:
-<glob-pattern> = <score>
-
-You can use the "/autosort rules" command to show and manipulate the list of sort rules.
-
-
-Allowed special characters in the glob patterns are:
-
-Pattern | Meaning
---------|--------
-*       | Matches a sequence of any characters except for periods.
-?       | Matches a single character, but not a period.
-[a-z]   | Matches a single character in the given regex-like character class.
-[^ab]   | A negated regex-like character class.
-\*      | A backslash escapes the next characters and removes its special meaning.
-\\      | A literal backslash.
-
-
-## Example
-As an example, consider the following rule list:
-0: core            = 0
-1: irc             = 2
-2: *               = 1
-
-3: irc.server.*.#* = 1
-4: irc.server.*.*  = 0
-
-Rule 0 ensures the core buffer is always sorted first.
-Rule 1 sorts IRC buffers last and rule 2 puts all remaining buffers in between the two.
-
-Rule 3 and 4 would make no sense with the group_irc option off.
-With the option on though, these rules will sort private buffers before regular channel buffers.
-Rule 3 matches channel buffers and assigns them a higher score,
-while rule 4 matches the buffers that remain and assigns them a lower score.
-The same effect could also be achieved with a single rule:
-irc.server.*.[^#]* = 0
-'''
-
-command_completion = 'sort||rules list|add|insert|update|delete|move|swap||replacements list|add|insert|update|delete|move|swap'
-
-
-if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
-	config = Config('autosort')
-
-	weechat.hook_config('autosort.*',      'on_config_changed',  '')
-	weechat.hook_command('autosort', command_description, '', '', command_completion, 'on_autosort_command', 'NULL')
-	on_config_changed()
+../autosort.py
\ No newline at end of file
--- a/weechat/python/autoload/brows.py	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/python/autoload/brows.py	Fri Jul 07 16:11:02 2023 -0400
@@ -15,7 +15,7 @@
 try:
     import weechat
 except ImportError:
-    print 'This is a weechat script, what are you doing, run it in weechat, jesus'
+    print('This is a weechat script, what are you doing, run it in weechat, jesus')
     import_ok = False
 
 weechat_version = 0
--- a/weechat/python/autoload/colon_complete.py	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-SCRIPT_NAME='coloncomplete'
-SCRIPT_AUTHOR='Steve Losh <steve@stevelosh.com>'
-SCRIPT_VERSION='1.0'
-SCRIPT_LICENSE='MIT/X11'
-SCRIPT_DESC='Add a colon after nick completion when all the previous words in the input are also nicks.'
-
-EXTRA_NICKS = ['all', 'backend', 'clojerks', 'ops', 'support']
-
-import_ok=True
-
-try:
-    import weechat
-except ImportError:
-    print 'This script must be run under WeeChat'
-    print 'You can obtain a copy of WeeChat, for free, at http://www.weechat.org'
-    import_ok=False
-
-weechat_version=0
-
-def get_nicks(buffer, prefix=''):
-    channel = weechat.buffer_get_string(buffer, 'localvar_channel')
-    server = weechat.buffer_get_string(buffer, 'localvar_server')
-    prefix = prefix.lower()
-
-    matches = []
-
-    infolist = weechat.infolist_get('irc_nick', '', '%s,%s' % (server, channel))
-    while weechat.infolist_next(infolist):
-        nick = weechat.infolist_string(infolist, 'name')
-        if nick != 'localhost' and nick.lower().startswith(prefix):
-            matches.append(nick)
-    weechat.infolist_free(infolist)
-
-    for nick in EXTRA_NICKS:
-        if nick.lower().startswith(prefix):
-            matches.append(nick)
-
-    return matches
-
-def completer(data, buffer, command):
-    cb = weechat.current_buffer()
-    if command == "/input complete_next":
-        line = weechat.buffer_get_string(cb, "input")
-        words = line.split(' ')
-        prefix = words[-1]
-        if prefix and words and all([s.endswith(':') for s in words[:-1] if s]):
-            nicks = get_nicks(cb, prefix)
-            if len(nicks) == 1:
-                for _ in range(len(prefix)):
-                    weechat.command(buffer, "/input delete_previous_char")
-                weechat.command(buffer, "/input insert " + nicks[-1] + ":\\x20")
-            elif len(nicks) > 1:
-                l = min(len(nick) for nick in nicks)
-                for i in range(len(prefix), l):
-                    if len(set(nick[i] for nick in nicks)) > 1:
-                        break
-                    else:
-                        weechat.command(buffer, "/input insert " + nicks[0][i])
-
-                for nick in nicks:
-                    weechat.prnt(cb, "==> " + nick)
-                return weechat.WEECHAT_RC_OK_EAT
-
-    return weechat.WEECHAT_RC_OK
-
-if __name__ == "__main__" and import_ok:
-    if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
-        weechat_version = weechat.info_get("version_number", "") or 0
-        weechat.hook_command_run('/input complete*', 'completer', '')
--- a/weechat/python/autoload/editor.py	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/python/autoload/editor.py	Fri Jul 07 16:11:02 2023 -0400
@@ -16,7 +16,7 @@
 try:
     import weechat
 except ImportError:
-    print 'This is a weechat script, what are you doing, run it in weechat, jesus'
+    print('This is a weechat script, what are you doing, run it in weechat, jesus')
     import_ok = False
 
 weechat_version = 0
@@ -33,9 +33,8 @@
         # Reopen, because most editors do atomic write-tmp+rename saves which
         # fucks with Python here.
         tf.file.close()
-        tf = file(tf.name)
-
-        return tf.read()
+        with open(tf.name) as tf2:
+            return tf2.read()
 
 def editor(data, buffer, args):
     suffix = args or "tmp"
--- a/weechat/python/autoload/quotes.py	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/python/autoload/quotes.py	Fri Jul 07 16:11:02 2023 -0400
@@ -18,7 +18,7 @@
 try:
     import weechat
 except ImportError:
-    print 'This is a weechat script, what are you doing, run it in weechat, jesus'
+    print('This is a weechat script, what are you doing, run it in weechat, jesus')
     import_ok = False
 
 weechat_version = 0
--- a/weechat/python/autoload/sanitize_jira.py	Fri Apr 14 15:01:35 2023 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-import re, weechat, subprocess
-
-SCRIPT_NAME = 'sanitize_jira'
-SCRIPT_AUTHOR = 'Steve Losh <steve@stevelosh.com>'
-SCRIPT_VERSION = '0.0.1'
-SCRIPT_LICENSE = 'MIT'
-SCRIPT_DESC = 'clean up the garbage jirabot sends to channels into something readable'
-
-weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', '')
-
-weechat.hook_line('*', '', 'nick_Jira_Cloud', 'sanitize_jira', '')
-
-first_line_re = re.compile(
-    r'(?P<link>https://[^/]+/browse/[^?]+)[?]atlOrigin=[^ ]+ [(](?P<title>.+)[)]'
-)
-
-detail_line_re = re.compile(
-    r'''Status: \x1a\x01[*](?P<status>[^*]+)[*]\x1b\x01.*Type: \x1a\x01[*](?P<type>[^*]+)[*]\x1b\x01.*Assignee: \x1a\x01[*](?P<assignee>[^*]+)[*]\x1b\x01.*Priority: \x1a\x01[*](?P<priority>[^*]+)[*]\x1b\x01'''
-)
-
-def sanitize_jira(data, line):
-    if 'sign up for an Atlassian account to view this link' in line['message']:
-        return {'message': ' '}
-
-    m = first_line_re.search(line['message'])
-    if m:
-        return {'message': '%s | %s' % (m.group('title'), m.group('link'))}
-
-    m = detail_line_re.search(line['message'])
-    if m:
-        return {'message': '%s / %s / %s' % (m.group('type'), m.group('status'), m.group('assignee'))}
-
-    return {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/python/autosort.py	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,1075 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2013-2017 Maarten de Vries <maarten@de-vri.es>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+#
+# Autosort automatically keeps your buffers sorted and grouped by server.
+# You can define your own sorting rules. See /help autosort for more details.
+#
+# https://github.com/de-vri-es/weechat-autosort
+#
+
+#
+# Changelog:
+# 3.9:
+#   * Remove `buffers.pl` from recommended settings.
+# 3,8:
+#   * Fix relative sorting on script name in default rules.
+#   * Document a useful property of stable sort algorithms.
+# 3.7:
+#   * Make default rules work with bitlbee, matrix and slack.
+# 3.6:
+#   * Add more documentation on provided info hooks.
+# 3.5:
+#   * Add ${info:autosort_escape,...} to escape arguments for other info hooks.
+# 3.4:
+#   * Fix rate-limit of sorting to prevent high CPU load and lock-ups.
+#   * Fix bug in parsing empty arguments for info hooks.
+#   * Add debug_log option to aid with debugging.
+#   * Correct a few typos.
+# 3.3:
+#   * Fix the /autosort debug command for unicode.
+#   * Update the default rules to work better with Slack.
+# 3.2:
+#   * Fix python3 compatiblity.
+# 3.1:
+#   * Use colors to format the help text.
+# 3.0:
+#   * Switch to evaluated expressions for sorting.
+#   * Add `/autosort debug` command.
+#   * Add ${info:autosort_replace,from,to,text} to replace substrings in sort rules.
+#   * Add ${info:autosort_order,value,first,second,third} to ease writing sort rules.
+#   * Make tab completion context aware.
+# 2.8:
+#   * Fix compatibility with python 3 regarding unicode handling.
+# 2.7:
+#   * Fix sorting of buffers with spaces in their name.
+# 2.6:
+#   * Ignore case in rules when doing case insensitive sorting.
+# 2.5:
+#   * Fix handling unicode buffer names.
+#   * Add hint to set irc.look.server_buffer to independent and buffers.look.indenting to on.
+# 2.4:
+#   * Make script python3 compatible.
+# 2.3:
+#   * Fix sorting items without score last (regressed in 2.2).
+# 2.2:
+#   * Add configuration option for signals that trigger a sort.
+#   * Add command to manually trigger a sort (/autosort sort).
+#   * Add replacement patterns to apply before sorting.
+# 2.1:
+#   * Fix some minor style issues.
+# 2.0:
+#   * Allow for custom sort rules.
+#
+
+
+import json
+import math
+import re
+import sys
+import time
+import weechat
+
+SCRIPT_NAME     = 'autosort'
+SCRIPT_AUTHOR   = 'Maarten de Vries <maarten@de-vri.es>'
+SCRIPT_VERSION  = '3.9'
+SCRIPT_LICENSE  = 'GPL3'
+SCRIPT_DESC     = 'Flexible automatic (or manual) buffer sorting based on eval expressions.'
+
+
+config             = None
+hooks              = []
+signal_delay_timer = None
+sort_limit_timer   = None
+sort_queued        = False
+
+
+# Make sure that unicode, bytes and str are always available in python2 and 3.
+# For python 2, str == bytes
+# For python 3, str == unicode
+if sys.version_info[0] >= 3:
+	unicode = str
+
+def ensure_str(input):
+	'''
+	Make sure the given type if the correct string type for the current python version.
+	That means bytes for python2 and unicode for python3.
+	'''
+	if not isinstance(input, str):
+		if isinstance(input, bytes):
+			return input.encode('utf-8')
+		if isinstance(input, unicode):
+			return input.decode('utf-8')
+	return input
+
+
+if hasattr(time, 'perf_counter'):
+	perf_counter = time.perf_counter
+else:
+	perf_counter = time.clock
+
+def casefold(string):
+	if hasattr(string, 'casefold'): return string.casefold()
+	# Fall back to lowercasing for python2.
+	return string.lower()
+
+def list_swap(values, a, b):
+	values[a], values[b] = values[b], values[a]
+
+def list_move(values, old_index, new_index):
+	values.insert(new_index, values.pop(old_index))
+
+def list_find(collection, value):
+	for i, elem in enumerate(collection):
+		if elem == value: return i
+	return None
+
+class HumanReadableError(Exception):
+	pass
+
+def parse_int(arg, arg_name = 'argument'):
+	''' Parse an integer and provide a more human readable error. '''
+	arg = arg.strip()
+	try:
+		return int(arg)
+	except ValueError:
+		raise HumanReadableError('Invalid {0}: expected integer, got "{1}".'.format(arg_name, arg))
+
+def decode_rules(blob):
+	parsed = json.loads(blob)
+	if not isinstance(parsed, list):
+		log('Malformed rules, expected a JSON encoded list of strings, but got a {0}. No rules have been loaded. Please fix the setting manually.'.format(type(parsed)))
+		return []
+
+	for i, entry in enumerate(parsed):
+		if not isinstance(entry, (str, unicode)):
+			log('Rule #{0} is not a string but a {1}. No rules have been loaded. Please fix the setting manually.'.format(i, type(entry)))
+			return []
+
+	return parsed
+
+def decode_helpers(blob):
+	parsed = json.loads(blob)
+	if not isinstance(parsed, dict):
+		log('Malformed helpers, expected a JSON encoded dictionary but got a {0}. No helpers have been loaded. Please fix the setting manually.'.format(type(parsed)))
+		return {}
+
+	for key, value in parsed.items():
+		if not isinstance(value, (str, unicode)):
+			log('Helper "{0}" is not a string but a {1}. No helpers have been loaded. Please fix setting manually.'.format(key, type(value)))
+			return {}
+	return parsed
+
+class Config:
+	''' The autosort configuration. '''
+
+	default_rules = json.dumps([
+		'${core_first}',
+		'${info:autosort_order,${info:autosort_escape,${script_or_plugin}},core,*,irc,bitlbee,matrix,slack}',
+		'${script_or_plugin}',
+		'${irc_raw_first}',
+		'${server}',
+		'${info:autosort_order,${type},server,*,channel,private}',
+		'${hashless_name}',
+		'${buffer.full_name}',
+	])
+
+	default_helpers = json.dumps({
+		'core_first':       '${if:${buffer.full_name}!=core.weechat}',
+		'irc_raw_first':    '${if:${buffer.full_name}!=irc.irc_raw}',
+		'irc_raw_last':     '${if:${buffer.full_name}==irc.irc_raw}',
+		'hashless_name':    '${info:autosort_replace,#,,${info:autosort_escape,${buffer.name}}}',
+		'script_or_plugin': '${if:${script_name}?${script_name}:${plugin}}',
+	})
+
+	default_signal_delay = 5
+	default_sort_limit   = 100
+
+	default_signals = 'buffer_opened buffer_merged buffer_unmerged buffer_renamed'
+
+	def __init__(self, filename):
+		''' Initialize the configuration. '''
+
+		self.filename         = filename
+		self.config_file      = weechat.config_new(self.filename, '', '')
+		self.sorting_section  = None
+		self.v3_section       = None
+
+		self.case_sensitive   = False
+		self.rules            = []
+		self.helpers          = {}
+		self.signals          = []
+		self.signal_delay     = Config.default_signal_delay,
+		self.sort_limit       = Config.default_sort_limit,
+		self.sort_on_config   = True
+		self.debug_log        = False
+
+		self.__case_sensitive = None
+		self.__rules          = None
+		self.__helpers        = None
+		self.__signals        = None
+		self.__signal_delay   = None
+		self.__sort_limit     = None
+		self.__sort_on_config = None
+		self.__debug_log      = None
+
+		if not self.config_file:
+			log('Failed to initialize configuration file "{0}".'.format(self.filename))
+			return
+
+		self.sorting_section = weechat.config_new_section(self.config_file, 'sorting', False, False, '', '', '', '', '', '', '', '', '', '')
+		self.v3_section      = weechat.config_new_section(self.config_file, 'v3',      False, False, '', '', '', '', '', '', '', '', '', '')
+
+		if not self.sorting_section:
+			log('Failed to initialize section "sorting" of configuration file.')
+			weechat.config_free(self.config_file)
+			return
+
+		self.__case_sensitive = weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'case_sensitive', 'boolean',
+			'If this option is on, sorting is case sensitive.',
+			'', 0, 0, 'off', 'off', 0,
+			'', '', '', '', '', ''
+		)
+
+		weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'rules', 'string',
+			'Sort rules used by autosort v2.x and below. Not used by autosort anymore.',
+			'', 0, 0, '', '', 0,
+			'', '', '', '', '', ''
+		)
+
+		weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'replacements', 'string',
+			'Replacement patterns used by autosort v2.x and below. Not used by autosort anymore.',
+			'', 0, 0, '', '', 0,
+			'', '', '', '', '', ''
+		)
+
+		self.__rules = weechat.config_new_option(
+			self.config_file, self.v3_section,
+			'rules', 'string',
+			'An ordered list of sorting rules encoded as JSON. See /help autosort for commands to manipulate these rules.',
+			'', 0, 0, Config.default_rules, Config.default_rules, 0,
+			'', '', '', '', '', ''
+		)
+
+		self.__helpers = weechat.config_new_option(
+			self.config_file, self.v3_section,
+			'helpers', 'string',
+			'A dictionary helper variables to use in the sorting rules, encoded as JSON. See /help autosort for commands to manipulate these helpers.',
+			'', 0, 0, Config.default_helpers, Config.default_helpers, 0,
+			'', '', '', '', '', ''
+		)
+
+		self.__signals = weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'signals', 'string',
+			'A space separated list of signals that will cause autosort to resort your buffer list.',
+			'', 0, 0, Config.default_signals, Config.default_signals, 0,
+			'', '', '', '', '', ''
+		)
+
+		self.__signal_delay = weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'signal_delay', 'integer',
+			'Delay in milliseconds to wait after a signal before sorting the buffer list. This prevents triggering many times if multiple signals arrive in a short time. It can also be needed to wait for buffer localvars to be available.',
+			'', 0, 1000, str(Config.default_signal_delay), str(Config.default_signal_delay), 0,
+			'', '', '', '', '', ''
+		)
+
+		self.__sort_limit = weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'sort_limit', 'integer',
+			'Minimum delay in milliseconds to wait after sorting before signals can trigger a sort again. This is effectively a rate limit on sorting. Keeping signal_delay low while setting this higher can reduce excessive sorting without a long initial delay.',
+			'', 0, 1000, str(Config.default_sort_limit), str(Config.default_sort_limit), 0,
+			'', '', '', '', '', ''
+		)
+
+		self.__sort_on_config = weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'sort_on_config_change', 'boolean',
+			'Decides if the buffer list should be sorted when autosort configuration changes.',
+			'', 0, 0, 'on', 'on', 0,
+			'', '', '', '', '', ''
+		)
+
+		self.__debug_log = weechat.config_new_option(
+			self.config_file, self.sorting_section,
+			'debug_log', 'boolean',
+			'If enabled, print more debug messages. Not recommended for normal usage.',
+			'', 0, 0, 'off', 'off', 0,
+			'', '', '', '', '', ''
+		)
+
+		if weechat.config_read(self.config_file) != weechat.WEECHAT_RC_OK:
+			log('Failed to load configuration file.')
+
+		if weechat.config_write(self.config_file) != weechat.WEECHAT_RC_OK:
+			log('Failed to write configuration file.')
+
+		self.reload()
+
+	def reload(self):
+		''' Load configuration variables. '''
+
+		self.case_sensitive = weechat.config_boolean(self.__case_sensitive)
+
+		rules_blob    = weechat.config_string(self.__rules)
+		helpers_blob  = weechat.config_string(self.__helpers)
+		signals_blob  = weechat.config_string(self.__signals)
+
+		self.rules          = decode_rules(rules_blob)
+		self.helpers        = decode_helpers(helpers_blob)
+		self.signals        = signals_blob.split()
+		self.signal_delay   = weechat.config_integer(self.__signal_delay)
+		self.sort_limit     = weechat.config_integer(self.__sort_limit)
+		self.sort_on_config = weechat.config_boolean(self.__sort_on_config)
+		self.debug_log      = weechat.config_boolean(self.__debug_log)
+
+	def save_rules(self, run_callback = True):
+		''' Save the current rules to the configuration. '''
+		weechat.config_option_set(self.__rules, json.dumps(self.rules), run_callback)
+
+	def save_helpers(self, run_callback = True):
+		''' Save the current helpers to the configuration. '''
+		weechat.config_option_set(self.__helpers, json.dumps(self.helpers), run_callback)
+
+
+def pad(sequence, length, padding = None):
+	''' Pad a list until is has a certain length. '''
+	return sequence + [padding] * max(0, (length - len(sequence)))
+
+def log(message, buffer = 'NULL'):
+	weechat.prnt(buffer, 'autosort: {0}'.format(message))
+
+def debug(message, buffer = 'NULL'):
+	if config.debug_log:
+		weechat.prnt(buffer, 'autosort: debug: {0}'.format(message))
+
+def get_buffers():
+	''' Get a list of all the buffers in weechat. '''
+	hdata  = weechat.hdata_get('buffer')
+	buffer = weechat.hdata_get_list(hdata, "gui_buffers");
+
+	result = []
+	while buffer:
+		number = weechat.hdata_integer(hdata, buffer, 'number')
+		result.append((number, buffer))
+		buffer = weechat.hdata_pointer(hdata, buffer, 'next_buffer')
+	return hdata, result
+
+class MergedBuffers(list):
+	""" A list of merged buffers, possibly of size 1. """
+	def __init__(self, number):
+		super(MergedBuffers, self).__init__()
+		self.number = number
+
+def merge_buffer_list(buffers):
+	'''
+	Group merged buffers together.
+	The output is a list of MergedBuffers.
+	'''
+	if not buffers: return []
+	result = {}
+	for number, buffer in buffers:
+		if number not in result: result[number] = MergedBuffers(number)
+		result[number].append(buffer)
+	return result.values()
+
+def sort_buffers(hdata, buffers, rules, helpers, case_sensitive):
+	for merged in buffers:
+		for buffer in merged:
+			name = weechat.hdata_string(hdata, buffer, 'name')
+
+	return sorted(buffers, key=merged_sort_key(rules, helpers, case_sensitive))
+
+def buffer_sort_key(rules, helpers, case_sensitive):
+	''' Create a sort key function for a list of lists of merged buffers. '''
+	def key(buffer):
+		extra_vars = {}
+		for helper_name, helper in sorted(helpers.items()):
+			expanded = weechat.string_eval_expression(helper, {"buffer": buffer}, {}, {})
+			extra_vars[helper_name] = expanded if case_sensitive else casefold(expanded)
+		result = []
+		for rule in rules:
+			expanded = weechat.string_eval_expression(rule, {"buffer": buffer}, extra_vars, {})
+			result.append(expanded if case_sensitive else casefold(expanded))
+		return result
+
+	return key
+
+def merged_sort_key(rules, helpers, case_sensitive):
+	buffer_key = buffer_sort_key(rules, helpers, case_sensitive)
+	def key(merged):
+		best = None
+		for buffer in merged:
+			this = buffer_key(buffer)
+			if best is None or this < best: best = this
+		return best
+	return key
+
+def apply_buffer_order(buffers):
+	''' Sort the buffers in weechat according to the given order. '''
+	for i, buffer in enumerate(buffers):
+		weechat.buffer_set(buffer[0], "number", str(i + 1))
+
+def split_args(args, expected, optional = 0):
+	''' Split an argument string in the desired number of arguments. '''
+	split = args.split(' ', expected - 1)
+	if (len(split) < expected):
+		raise HumanReadableError('Expected at least {0} arguments, got {1}.'.format(expected, len(split)))
+	return split[:-1] + pad(split[-1].split(' ', optional), optional + 1, '')
+
+def do_sort(verbose = False):
+	start = perf_counter()
+
+	hdata, buffers = get_buffers()
+	buffers = merge_buffer_list(buffers)
+	buffers = sort_buffers(hdata, buffers, config.rules, config.helpers, config.case_sensitive)
+	apply_buffer_order(buffers)
+
+	elapsed = perf_counter() - start
+	if verbose:
+		log("Finished sorting buffers in {0:.4f} seconds.".format(elapsed))
+	else:
+		debug("Finished sorting buffers in {0:.4f} seconds.".format(elapsed))
+
+def command_sort(buffer, command, args):
+	''' Sort the buffers and print a confirmation. '''
+	do_sort(True)
+	return weechat.WEECHAT_RC_OK
+
+def command_debug(buffer, command, args):
+	hdata, buffers = get_buffers()
+	buffers = merge_buffer_list(buffers)
+
+	# Show evaluation results.
+	log('Individual evaluation results:')
+	start = perf_counter()
+	key = buffer_sort_key(config.rules, config.helpers, config.case_sensitive)
+	results = []
+	for merged in buffers:
+		for buffer in merged:
+			fullname = weechat.hdata_string(hdata, buffer, 'full_name')
+			results.append((fullname, key(buffer)))
+	elapsed = perf_counter() - start
+
+	for fullname, result in results:
+		fullname = ensure_str(fullname)
+		result = [ensure_str(x) for x in result]
+		log('{0}: {1}'.format(fullname, result))
+	log('Computing evaluation results took {0:.4f} seconds.'.format(elapsed))
+
+	return weechat.WEECHAT_RC_OK
+
+def command_rule_list(buffer, command, args):
+	''' Show the list of sorting rules. '''
+	output = 'Sorting rules:\n'
+	for i, rule in enumerate(config.rules):
+		output += '    {0}: {1}\n'.format(i, rule)
+	if not len(config.rules):
+		output += '    No sorting rules configured.\n'
+	log(output )
+
+	return weechat.WEECHAT_RC_OK
+
+
+def command_rule_add(buffer, command, args):
+	''' Add a rule to the rule list. '''
+	config.rules.append(args)
+	config.save_rules()
+	command_rule_list(buffer, command, '')
+
+	return weechat.WEECHAT_RC_OK
+
+
+def command_rule_insert(buffer, command, args):
+	''' Insert a rule at the desired position in the rule list. '''
+	index, rule = split_args(args, 2)
+	index = parse_int(index, 'index')
+
+	config.rules.insert(index, rule)
+	config.save_rules()
+	command_rule_list(buffer, command, '')
+	return weechat.WEECHAT_RC_OK
+
+
+def command_rule_update(buffer, command, args):
+	''' Update a rule in the rule list. '''
+	index, rule = split_args(args, 2)
+	index = parse_int(index, 'index')
+
+	config.rules[index] = rule
+	config.save_rules()
+	command_rule_list(buffer, command, '')
+	return weechat.WEECHAT_RC_OK
+
+
+def command_rule_delete(buffer, command, args):
+	''' Delete a rule from the rule list. '''
+	index = args.strip()
+	index = parse_int(index, 'index')
+
+	config.rules.pop(index)
+	config.save_rules()
+	command_rule_list(buffer, command, '')
+	return weechat.WEECHAT_RC_OK
+
+
+def command_rule_move(buffer, command, args):
+	''' Move a rule to a new position. '''
+	index_a, index_b = split_args(args, 2)
+	index_a = parse_int(index_a, 'index')
+	index_b = parse_int(index_b, 'index')
+
+	list_move(config.rules, index_a, index_b)
+	config.save_rules()
+	command_rule_list(buffer, command, '')
+	return weechat.WEECHAT_RC_OK
+
+
+def command_rule_swap(buffer, command, args):
+	''' Swap two rules. '''
+	index_a, index_b = split_args(args, 2)
+	index_a = parse_int(index_a, 'index')
+	index_b = parse_int(index_b, 'index')
+
+	list_swap(config.rules, index_a, index_b)
+	config.save_rules()
+	command_rule_list(buffer, command, '')
+	return weechat.WEECHAT_RC_OK
+
+
+def command_helper_list(buffer, command, args):
+	''' Show the list of helpers. '''
+	output = 'Helper variables:\n'
+
+	width = max(map(lambda x: len(x) if len(x) <= 30 else 0, config.helpers.keys()))
+
+	for name, expression in sorted(config.helpers.items()):
+		output += '    {0:>{width}}: {1}\n'.format(name, expression, width=width)
+	if not len(config.helpers):
+		output += '    No helper variables configured.'
+	log(output)
+
+	return weechat.WEECHAT_RC_OK
+
+
+def command_helper_set(buffer, command, args):
+	''' Add/update a helper to the helper list. '''
+	name, expression = split_args(args, 2)
+
+	config.helpers[name] = expression
+	config.save_helpers()
+	command_helper_list(buffer, command, '')
+
+	return weechat.WEECHAT_RC_OK
+
+def command_helper_delete(buffer, command, args):
+	''' Delete a helper from the helper list. '''
+	name = args.strip()
+
+	del config.helpers[name]
+	config.save_helpers()
+	command_helper_list(buffer, command, '')
+	return weechat.WEECHAT_RC_OK
+
+
+def command_helper_rename(buffer, command, args):
+	''' Rename a helper to a new position. '''
+	old_name, new_name = split_args(args, 2)
+
+	try:
+		config.helpers[new_name] = config.helpers[old_name]
+		del config.helpers[old_name]
+	except KeyError:
+		raise HumanReadableError('No such helper: {0}'.format(old_name))
+	config.save_helpers()
+	command_helper_list(buffer, command, '')
+	return weechat.WEECHAT_RC_OK
+
+
+def command_helper_swap(buffer, command, args):
+	''' Swap two helpers. '''
+	a, b = split_args(args, 2)
+	try:
+		config.helpers[b], config.helpers[a] = config.helpers[a], config.helpers[b]
+	except KeyError as e:
+		raise HumanReadableError('No such helper: {0}'.format(e.args[0]))
+
+	config.helpers.swap(index_a, index_b)
+	config.save_helpers()
+	command_helper_list(buffer, command, '')
+	return weechat.WEECHAT_RC_OK
+
+def call_command(buffer, command, args, subcommands):
+	''' Call a subcommand from a dictionary. '''
+	subcommand, tail = pad(args.split(' ', 1), 2, '')
+	subcommand = subcommand.strip()
+	if (subcommand == ''):
+		child   = subcommands.get(' ')
+	else:
+		command = command + [subcommand]
+		child   = subcommands.get(subcommand)
+
+	if isinstance(child, dict):
+		return call_command(buffer, command, tail, child)
+	elif callable(child):
+		return child(buffer, command, tail)
+
+	log('{0}: command not found'.format(' '.join(command)))
+	return weechat.WEECHAT_RC_ERROR
+
+def on_signal(data, signal, signal_data):
+	global signal_delay_timer
+	global sort_queued
+
+	# If the sort limit timeout is started, we're in the hold-off time after sorting, just queue a sort.
+	if sort_limit_timer is not None:
+		if sort_queued:
+			debug('Signal {0} ignored, sort limit timeout is active and sort is already queued.'.format(signal))
+		else:
+			debug('Signal {0} received but sort limit timeout is active, sort is now queued.'.format(signal))
+		sort_queued = True
+		return weechat.WEECHAT_RC_OK
+
+	# If the signal delay timeout is started, a signal was recently received, so ignore this signal.
+	if signal_delay_timer is not None:
+		debug('Signal {0} ignored, signal delay timeout active.'.format(signal))
+		return weechat.WEECHAT_RC_OK
+
+	# Otherwise, start the signal delay timeout.
+	debug('Signal {0} received, starting signal delay timeout of {1} ms.'.format(signal, config.signal_delay))
+	weechat.hook_timer(config.signal_delay, 0, 1, "on_signal_delay_timeout", "")
+	return weechat.WEECHAT_RC_OK
+
+def on_signal_delay_timeout(pointer, remaining_calls):
+	""" Called when the signal_delay_timer triggers. """
+	global signal_delay_timer
+	global sort_limit_timer
+	global sort_queued
+
+	signal_delay_timer = None
+
+	# If the sort limit timeout was started, we're still in the no-sort period, so just queue a sort.
+	if sort_limit_timer is not None:
+		debug('Signal delay timeout expired, but sort limit timeout is active, sort is now queued.')
+		sort_queued = True
+		return weechat.WEECHAT_RC_OK
+
+	# Time to sort!
+	debug('Signal delay timeout expired, starting sort.')
+	do_sort()
+
+	# Start the sort limit timeout if not disabled.
+	if config.sort_limit > 0:
+		debug('Starting sort limit timeout of {0} ms.'.format(config.sort_limit))
+		sort_limit_timer = weechat.hook_timer(config.sort_limit, 0, 1, "on_sort_limit_timeout", "")
+
+	return weechat.WEECHAT_RC_OK
+
+def on_sort_limit_timeout(pointer, remainin_calls):
+	""" Called when de sort_limit_timer triggers. """
+	global sort_limit_timer
+	global sort_queued
+
+	# If no signal was received during the timeout, we're done.
+	if not sort_queued:
+		debug('Sort limit timeout expired without receiving a signal.')
+		sort_limit_timer = None
+		return weechat.WEECHAT_RC_OK
+
+	# Otherwise it's time to sort.
+	debug('Signal received during sort limit timeout, starting queued sort.')
+	do_sort()
+	sort_queued = False
+
+	# Start the sort limit timeout again if not disabled.
+	if config.sort_limit > 0:
+		debug('Starting sort limit timeout of {0} ms.'.format(config.sort_limit))
+		sort_limit_timer = weechat.hook_timer(config.sort_limit, 0, 1, "on_sort_limit_timeout", "")
+
+	return weechat.WEECHAT_RC_OK
+
+
+def apply_config():
+	# Unhook all signals and hook the new ones.
+	for hook in hooks:
+		weechat.unhook(hook)
+	for signal in config.signals:
+		hooks.append(weechat.hook_signal(signal, 'on_signal', ''))
+
+	if config.sort_on_config:
+		debug('Sorting because configuration changed.')
+		do_sort()
+
+def on_config_changed(*args, **kwargs):
+	''' Called whenever the configuration changes. '''
+	config.reload()
+	apply_config()
+
+	return weechat.WEECHAT_RC_OK
+
+def parse_arg(args):
+	if not args: return '', None
+
+	result  = ''
+	escaped = False
+	for i, c in enumerate(args):
+		if not escaped:
+			if c == '\\':
+				escaped = True
+				continue
+			elif c == ',':
+				return result, args[i+1:]
+		result  += c
+		escaped  = False
+	return result, None
+
+def parse_args(args, max = None):
+	result = []
+	i = 0
+	while max is None or i < max:
+		i += 1
+		arg, args = parse_arg(args)
+		if arg is None: break
+		result.append(arg)
+		if args is None: break
+	return result, args
+
+def on_info_escape(pointer, name, arguments):
+	result = ''
+	for c in arguments:
+		if c == '\\':
+			result += '\\\\'
+		elif c == ',':
+			result += '\\,'
+		else:
+			result +=c
+	return result
+
+def on_info_replace(pointer, name, arguments):
+	arguments, rest = parse_args(arguments, 3)
+	if rest or len(arguments) < 3:
+		log('usage: ${{info:{0},old,new,text}}'.format(name))
+		return ''
+	old, new, text = arguments
+
+	return text.replace(old, new)
+
+def on_info_order(pointer, name, arguments):
+	arguments, rest = parse_args(arguments)
+	if len(arguments) < 1:
+		log('usage: ${{info:{0},value,first,second,third,...}}'.format(name))
+		return ''
+
+	value = arguments[0]
+	keys  = arguments[1:]
+	if not keys: return '0'
+
+	# Find the value in the keys (or '*' if we can't find it)
+	result = list_find(keys, value)
+	if result is None: result = list_find(keys, '*')
+	if result is None: result = len(keys)
+
+	# Pad result with leading zero to make sure string sorting works.
+	width = int(math.log10(len(keys))) + 1
+	return '{0:0{1}}'.format(result, width)
+
+
+def on_autosort_command(data, buffer, args):
+	''' Called when the autosort command is invoked. '''
+	try:
+		return call_command(buffer, ['/autosort'], args, {
+			' ':      command_sort,
+			'sort':   command_sort,
+			'debug':  command_debug,
+
+			'rules': {
+				' ':         command_rule_list,
+				'list':      command_rule_list,
+				'add':       command_rule_add,
+				'insert':    command_rule_insert,
+				'update':    command_rule_update,
+				'delete':    command_rule_delete,
+				'move':      command_rule_move,
+				'swap':      command_rule_swap,
+			},
+			'helpers': {
+				' ':      command_helper_list,
+				'list':   command_helper_list,
+				'set':    command_helper_set,
+				'delete': command_helper_delete,
+				'rename': command_helper_rename,
+				'swap':   command_helper_swap,
+			},
+		})
+	except HumanReadableError as e:
+		log(e)
+		return weechat.WEECHAT_RC_ERROR
+
+def add_completions(completion, words):
+	for word in words:
+		weechat.hook_completion_list_add(completion, word, 0, weechat.WEECHAT_LIST_POS_END)
+
+def autosort_complete_rules(words, completion):
+	if len(words) == 0:
+		add_completions(completion, ['add', 'delete', 'insert', 'list', 'move', 'swap', 'update'])
+	if len(words) == 1 and words[0] in ('delete', 'insert', 'move', 'swap', 'update'):
+		add_completions(completion, map(str, range(len(config.rules))))
+	if len(words) == 2 and words[0] in ('move', 'swap'):
+		add_completions(completion, map(str, range(len(config.rules))))
+	if len(words) == 2 and words[0] in ('update'):
+		try:
+			add_completions(completion, [config.rules[int(words[1])]])
+		except KeyError: pass
+		except ValueError: pass
+	else:
+		add_completions(completion, [''])
+	return weechat.WEECHAT_RC_OK
+
+def autosort_complete_helpers(words, completion):
+	if len(words) == 0:
+		add_completions(completion, ['delete', 'list', 'rename', 'set', 'swap'])
+	elif len(words) == 1 and words[0] in ('delete', 'rename', 'set', 'swap'):
+		add_completions(completion, sorted(config.helpers.keys()))
+	elif len(words) == 2 and words[0] == 'swap':
+		add_completions(completion, sorted(config.helpers.keys()))
+	elif len(words) == 2 and words[0] == 'rename':
+		add_completions(completion, sorted(config.helpers.keys()))
+	elif len(words) == 2 and words[0] == 'set':
+		try:
+			add_completions(completion, [config.helpers[words[1]]])
+		except KeyError: pass
+	return weechat.WEECHAT_RC_OK
+
+def on_autosort_complete(data, name, buffer, completion):
+	cmdline = weechat.buffer_get_string(buffer, "input")
+	cursor  = weechat.buffer_get_integer(buffer, "input_pos")
+	prefix  = cmdline[:cursor]
+	words   = prefix.split()[1:]
+
+	# If the current word isn't finished yet,
+	# ignore it for coming up with completion suggestions.
+	if prefix[-1] != ' ': words = words[:-1]
+
+	if len(words) == 0:
+		add_completions(completion, ['debug', 'helpers', 'rules', 'sort'])
+	elif words[0] == 'rules':
+		return autosort_complete_rules(words[1:], completion)
+	elif words[0] == 'helpers':
+		return autosort_complete_helpers(words[1:], completion)
+	return weechat.WEECHAT_RC_OK
+
+command_description = r'''{*white}# General commands{reset}
+
+{*white}/autosort {brown}sort{reset}
+Manually trigger the buffer sorting.
+
+{*white}/autosort {brown}debug{reset}
+Show the evaluation results of the sort rules for each buffer.
+
+
+{*white}# Sorting rule commands{reset}
+
+{*white}/autosort{brown} rules list{reset}
+Print the list of sort rules.
+
+{*white}/autosort {brown}rules add {cyan}<expression>{reset}
+Add a new rule at the end of the list.
+
+{*white}/autosort {brown}rules insert {cyan}<index> <expression>{reset}
+Insert a new rule at the given index in the list.
+
+{*white}/autosort {brown}rules update {cyan}<index> <expression>{reset}
+Update a rule in the list with a new expression.
+
+{*white}/autosort {brown}rules delete {cyan}<index>
+Delete a rule from the list.
+
+{*white}/autosort {brown}rules move {cyan}<index_from> <index_to>{reset}
+Move a rule from one position in the list to another.
+
+{*white}/autosort {brown}rules swap {cyan}<index_a> <index_b>{reset}
+Swap two rules in the list
+
+
+{*white}# Helper variable commands{reset}
+
+{*white}/autosort {brown}helpers list
+Print the list of helper variables.
+
+{*white}/autosort {brown}helpers set {cyan}<name> <expression>
+Add or update a helper variable with the given name.
+
+{*white}/autosort {brown}helpers delete {cyan}<name>
+Delete a helper variable.
+
+{*white}/autosort {brown}helpers rename {cyan}<old_name> <new_name>
+Rename a helper variable.
+
+{*white}/autosort {brown}helpers swap {cyan}<name_a> <name_b>
+Swap the expressions of two helper variables in the list.
+
+
+{*white}# Info hooks{reset}
+Autosort comes with a number of info hooks to add some extra functionality to regular weechat eval strings.
+Info hooks can be used in eval strings in the form of {cyan}${{info:some_hook,arguments}}{reset}.
+
+Commas and backslashes in arguments to autosort info hooks (except for {cyan}${{info:autosort_escape}}{reset}) must be escaped with a backslash.
+
+{*white}${{info:{brown}autosort_replace{white},{cyan}pattern{white},{cyan}replacement{white},{cyan}source{white}}}{reset}
+Replace all occurrences of {cyan}pattern{reset} with {cyan}replacement{reset} in the string {cyan}source{reset}.
+Can be used to ignore certain strings when sorting by replacing them with an empty string.
+
+For example: {cyan}${{info:autosort_replace,cat,dog,the dog is meowing}}{reset} expands to "the cat is meowing".
+
+{*white}${{info:{brown}autosort_order{white},{cyan}value{white},{cyan}option0{white},{cyan}option1{white},{cyan}option2{white},{cyan}...{white}}}
+Generate a zero-padded number that corresponds to the index of {cyan}value{reset} in the list of options.
+If one of the options is the special value {brown}*{reset}, then any value not explicitly mentioned will be sorted at that position.
+Otherwise, any value that does not match an option is assigned the highest number available.
+Can be used to easily sort buffers based on a manual sequence.
+
+For example: {cyan}${{info:autosort_order,${{server}},freenode,oftc,efnet}}{reset} will sort freenode before oftc, followed by efnet and then any remaining servers.
+Alternatively, {cyan}${{info:autosort_order,${{server}},freenode,oftc,*,efnet}}{reset} will sort any unlisted servers after freenode and oftc, but before efnet.
+
+{*white}${{info:{brown}autosort_escape{white},{cyan}text{white}}}{reset}
+Escape commas and backslashes in {cyan}text{reset} by prepending them with a backslash.
+This is mainly useful to pass arbitrary eval strings as arguments to other autosort info hooks.
+Otherwise, an eval string that expands to something with a comma would be interpreted as multiple arguments.
+
+For example, it can be used to safely pass buffer names to {cyan}${{info:autosort_replace}}{reset} like so:
+{cyan}${{info:autosort_replace,##,#,${{info:autosort_escape,${{buffer.name}}}}}}{reset}.
+
+
+{*white}# Description
+Autosort is a weechat script to automatically keep your buffers sorted. The sort
+order can be customized by defining your own sort rules, but the default should
+be sane enough for most people. It can also group IRC channel/private buffers
+under their server buffer if you like.
+
+Autosort uses a stable sorting algorithm, meaning that you can manually move buffers
+to change their relative order, if they sort equal with your rule set.
+
+{*white}# Sort rules{reset}
+Autosort evaluates a list of eval expressions (see {*default}/help eval{reset}) and sorts the
+buffers based on evaluated result. Earlier rules will be considered first. Only
+if earlier rules produced identical results is the result of the next rule
+considered for sorting purposes.
+
+You can debug your sort rules with the `{*default}/autosort debug{reset}` command, which will
+print the evaluation results of each rule for each buffer.
+
+{*brown}NOTE:{reset} The sort rules for version 3 are not compatible with version 2 or vice
+versa. You will have to manually port your old rules to version 3 if you have any.
+
+{*white}# Helper variables{reset}
+You may define helper variables for the main sort rules to keep your rules
+readable. They can be used in the main sort rules as variables. For example,
+a helper variable named `{cyan}foo{reset}` can be accessed in a main rule with the
+string `{cyan}${{foo}}{reset}`.
+
+{*white}# Automatic or manual sorting{reset}
+By default, autosort will automatically sort your buffer list whenever a buffer
+is opened, merged, unmerged or renamed. This should keep your buffers sorted in
+almost all situations. However, you may wish to change the list of signals that
+cause your buffer list to be sorted. Simply edit the `{cyan}autosort.sorting.signals{reset}`
+option to add or remove any signal you like.
+
+If you remove all signals you can still sort your buffers manually with the
+`{*default}/autosort sort{reset}` command. To prevent all automatic sorting, the option
+`{cyan}autosort.sorting.sort_on_config_change{reset}` should also be disabled.
+
+{*white}# Recommended settings
+For the best visual effect, consider setting the following options:
+  {*white}/set {cyan}irc.look.server_buffer{reset} {brown}independent{reset}
+
+This setting allows server buffers to be sorted independently, which is
+needed to create a hierarchical tree view of the server and channel buffers.
+
+If you are using the {*default}buflist{reset} plugin you can (ab)use Unicode to draw a tree
+structure with the following setting (modify to suit your need):
+  {*white}/set {cyan}buflist.format.indent {brown}"${{color:237}}${{if:${{buffer.next_buffer.local_variables.type}}=~^(channel|private)$?├─:└─}}"{reset}
+'''
+
+command_completion = '%(plugin_autosort) %(plugin_autosort) %(plugin_autosort) %(plugin_autosort) %(plugin_autosort)'
+
+info_replace_description = (
+	'Replace all occurrences of `pattern` with `replacement` in the string `source`. '
+	'Can be used to ignore certain strings when sorting by replacing them with an empty string. '
+	'See /help autosort for examples.'
+)
+info_replace_arguments = 'pattern,replacement,source'
+
+info_order_description = (
+	'Generate a zero-padded number that corresponds to the index of `value` in the list of options. '
+	'If one of the options is the special value `*`, then any value not explicitly mentioned will be sorted at that position. '
+	'Otherwise, any value that does not match an option is assigned the highest number available. '
+	'Can be used to easily sort buffers based on a manual sequence. '
+	'See /help autosort for examples.'
+)
+info_order_arguments = 'value,first,second,third,...'
+
+info_escape_description = (
+	'Escape commas and backslashes in `text` by prepending them with a backslash. '
+	'This is mainly useful to pass arbitrary eval strings as arguments to other autosort info hooks. '
+	'Otherwise, an eval string that expands to something with a comma would be interpreted as multiple arguments.'
+	'See /help autosort for examples.'
+)
+info_escape_arguments = 'text'
+
+
+if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
+	config = Config('autosort')
+
+	colors = {
+		'default':  weechat.color('default'),
+		'reset':    weechat.color('reset'),
+		'black':    weechat.color('black'),
+		'red':      weechat.color('red'),
+		'green':    weechat.color('green'),
+		'brown':    weechat.color('brown'),
+		'yellow':   weechat.color('yellow'),
+		'blue':     weechat.color('blue'),
+		'magenta':  weechat.color('magenta'),
+		'cyan':     weechat.color('cyan'),
+		'white':    weechat.color('white'),
+		'*default': weechat.color('*default'),
+		'*black':   weechat.color('*black'),
+		'*red':     weechat.color('*red'),
+		'*green':   weechat.color('*green'),
+		'*brown':   weechat.color('*brown'),
+		'*yellow':  weechat.color('*yellow'),
+		'*blue':    weechat.color('*blue'),
+		'*magenta': weechat.color('*magenta'),
+		'*cyan':    weechat.color('*cyan'),
+		'*white':   weechat.color('*white'),
+	}
+
+	weechat.hook_config('autosort.*', 'on_config_changed',  '')
+	weechat.hook_completion('plugin_autosort', '', 'on_autosort_complete', '')
+	weechat.hook_command('autosort', command_description.format(**colors), '', '', command_completion, 'on_autosort_command', '')
+	weechat.hook_info('autosort_escape',  info_escape_description,  info_escape_arguments,  'on_info_escape', '')
+	weechat.hook_info('autosort_replace', info_replace_description, info_replace_arguments, 'on_info_replace', '')
+	weechat.hook_info('autosort_order',   info_order_description,   info_order_arguments,   'on_info_order',   '')
+
+	apply_config()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/python/colon_complete.py	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,69 @@
+SCRIPT_NAME='coloncomplete'
+SCRIPT_AUTHOR='Steve Losh <steve@stevelosh.com>'
+SCRIPT_VERSION='1.0'
+SCRIPT_LICENSE='MIT/X11'
+SCRIPT_DESC='Add a colon after nick completion when all the previous words in the input are also nicks.'
+
+EXTRA_NICKS = ['all', 'backend', 'clojerks', 'ops', 'support']
+
+import_ok=True
+
+try:
+    import weechat
+except ImportError:
+    print 'This script must be run under WeeChat'
+    print 'You can obtain a copy of WeeChat, for free, at http://www.weechat.org'
+    import_ok=False
+
+weechat_version=0
+
+def get_nicks(buffer, prefix=''):
+    channel = weechat.buffer_get_string(buffer, 'localvar_channel')
+    server = weechat.buffer_get_string(buffer, 'localvar_server')
+    prefix = prefix.lower()
+
+    matches = []
+
+    infolist = weechat.infolist_get('irc_nick', '', '%s,%s' % (server, channel))
+    while weechat.infolist_next(infolist):
+        nick = weechat.infolist_string(infolist, 'name')
+        if nick != 'localhost' and nick.lower().startswith(prefix):
+            matches.append(nick)
+    weechat.infolist_free(infolist)
+
+    for nick in EXTRA_NICKS:
+        if nick.lower().startswith(prefix):
+            matches.append(nick)
+
+    return matches
+
+def completer(data, buffer, command):
+    cb = weechat.current_buffer()
+    if command == "/input complete_next":
+        line = weechat.buffer_get_string(cb, "input")
+        words = line.split(' ')
+        prefix = words[-1]
+        if prefix and words and all([s.endswith(':') for s in words[:-1] if s]):
+            nicks = get_nicks(cb, prefix)
+            if len(nicks) == 1:
+                for _ in range(len(prefix)):
+                    weechat.command(buffer, "/input delete_previous_char")
+                weechat.command(buffer, "/input insert " + nicks[-1] + ":\\x20")
+            elif len(nicks) > 1:
+                l = min(len(nick) for nick in nicks)
+                for i in range(len(prefix), l):
+                    if len(set(nick[i] for nick in nicks)) > 1:
+                        break
+                    else:
+                        weechat.command(buffer, "/input insert " + nicks[0][i])
+
+                for nick in nicks:
+                    weechat.prnt(cb, "==> " + nick)
+                return weechat.WEECHAT_RC_OK_EAT
+
+    return weechat.WEECHAT_RC_OK
+
+if __name__ == "__main__" and import_ok:
+    if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, "", ""):
+        weechat_version = weechat.info_get("version_number", "") or 0
+        weechat.hook_command_run('/input complete*', 'completer', '')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/python/sanitize_jira.py	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,33 @@
+import re, weechat, subprocess
+
+SCRIPT_NAME = 'sanitize_jira'
+SCRIPT_AUTHOR = 'Steve Losh <steve@stevelosh.com>'
+SCRIPT_VERSION = '0.0.1'
+SCRIPT_LICENSE = 'MIT'
+SCRIPT_DESC = 'clean up the garbage jirabot sends to channels into something readable'
+
+weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, '', '')
+
+weechat.hook_line('*', '', 'nick_Jira_Cloud', 'sanitize_jira', '')
+
+first_line_re = re.compile(
+    r'(?P<link>https://[^/]+/browse/[^?]+)[?]atlOrigin=[^ ]+ [(](?P<title>.+)[)]'
+)
+
+detail_line_re = re.compile(
+    r'''Status: \x1a\x01[*](?P<status>[^*]+)[*]\x1b\x01.*Type: \x1a\x01[*](?P<type>[^*]+)[*]\x1b\x01.*Assignee: \x1a\x01[*](?P<assignee>[^*]+)[*]\x1b\x01.*Priority: \x1a\x01[*](?P<priority>[^*]+)[*]\x1b\x01'''
+)
+
+def sanitize_jira(data, line):
+    if 'sign up for an Atlassian account to view this link' in line['message']:
+        return {'message': ' '}
+
+    m = first_line_re.search(line['message'])
+    if m:
+        return {'message': '%s | %s' % (m.group('title'), m.group('link'))}
+
+    m = detail_line_re.search(line['message'])
+    if m:
+        return {'message': '%s / %s / %s' % (m.group('type'), m.group('status'), m.group('assignee'))}
+
+    return {}
--- a/weechat/relay.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/relay.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [look]
@@ -27,14 +27,20 @@
 [network]
 allow_empty_password = off
 allowed_ips = ""
+auth_timeout = 60
 bind_address = ""
 clients_purge_delay = 0
-compression_level = 6
+compression = 20
 ipv6 = on
 max_clients = 5
+nonce_size = 16
 password = ""
+password_hash_algo = "*"
+password_hash_iterations = 100000
 ssl_cert_key = "%h/ssl/relay.pem"
 ssl_priorities = "NORMAL:-VERS-SSL3.0"
+totp_secret = ""
+totp_window = 0
 websocket_allowed_origins = ""
 
 [irc]
@@ -45,4 +51,9 @@
 backlog_tags = "irc_privmsg"
 backlog_time_format = "[%H:%M] "
 
+[weechat]
+commands = ""
+
 [port]
+
+[path]
--- a/weechat/ruby.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/ruby.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,7 +4,7 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
 # For more info, see: https://weechat.org/doc/quickstart
 #
--- a/weechat/script.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/script.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [look]
@@ -50,6 +50,7 @@
 [scripts]
 autoload = on
 cache_expire = 60
+download_enabled = on
 download_timeout = 30
 hold = ""
 path = "%h/script"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/spell.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,33 @@
+#
+# weechat -- spell.conf
+#
+# WARNING: It is NOT recommended to edit this file by hand,
+# especially if WeeChat is running.
+#
+# Use commands like /set or /fset to change settings in WeeChat.
+#
+# For more info, see: https://weechat.org/doc/quickstart
+#
+
+[color]
+misspelled = lightred
+suggestion = default
+suggestion_delimiter_dict = cyan
+suggestion_delimiter_word = cyan
+
+[check]
+commands = "away,command,cycle,kick,kickban,me,msg,notice,part,query,quit,topic"
+default_dict = ""
+during_search = off
+enabled = off
+real_time = off
+suggestions = -1
+word_min_length = 2
+
+[dict]
+
+[look]
+suggestion_delimiter_dict = " / "
+suggestion_delimiter_word = ","
+
+[option]
--- a/weechat/trigger.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/trigger.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [look]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/weechat/typing.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -0,0 +1,19 @@
+#
+# weechat -- typing.conf
+#
+# WARNING: It is NOT recommended to edit this file by hand,
+# especially if WeeChat is running.
+#
+# Use commands like /set or /fset to change settings in WeeChat.
+#
+# For more info, see: https://weechat.org/doc/quickstart/
+#
+
+[look]
+delay_purge_paused = 30
+delay_purge_typing = 6
+delay_set_paused = 10
+enabled_nicks = off
+enabled_self = off
+input_min_chars = 4
+item_max_length = 0
--- a/weechat/urlgrab.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/urlgrab.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [color]
--- a/weechat/weechat.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/weechat.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -1,10 +1,10 @@
 #
-# weechat -- weechat.conf
+# WeeChat -- weechat.conf
 #
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
 # For more info, see: https://weechat.org/doc/quickstart
 #
@@ -35,6 +35,7 @@
 buffer_search_regex = off
 buffer_search_where = prefix_message
 buffer_time_format = "%H:%M"
+buffer_time_same = ""
 color_basic_force_bold = off
 color_inactive_buffer = off
 color_inactive_message = on
@@ -71,6 +72,7 @@
 hotlist_sort = group_time_asc
 hotlist_suffix = ""
 hotlist_unique_numbers = on
+hotlist_update_on_buffer_switch = on
 input_cursor_scroll = 20
 input_share = none
 input_share_overwrite = off
@@ -89,6 +91,7 @@
 mouse_timer_delay = 100
 nick_color_force = ""
 nick_color_hash = djb2
+nick_color_hash_salt = ""
 nick_color_stop_chars = "_|["
 nick_prefix = ""
 nick_suffix = ""
@@ -111,6 +114,7 @@
 prefix_network = "--"
 prefix_quit = "✘"
 prefix_same_nick = ""
+prefix_same_nick_middle = ""
 prefix_suffix = "|"
 quote_nick_prefix = "<"
 quote_nick_suffix = ">"
@@ -118,6 +122,7 @@
 read_marker = line
 read_marker_always_show = on
 read_marker_string = "─"
+read_marker_update_on_buffer_switch = on
 save_config_on_exit = off
 save_config_with_fsync = off
 save_layout_on_exit = all
@@ -231,7 +236,8 @@
 
 [network]
 connection_timeout = 60
-gnutls_ca_file = "/etc/ssl/certs/ca-certificates.crt"
+gnutls_ca_system = on
+gnutls_ca_user = ""
 gnutls_handshake_timeout = 30
 proxy_curl = ""
 
@@ -242,8 +248,16 @@
 path = "%h/plugins"
 save_config_on_unload = on
 
+[signal]
+sighup = "${if:${info:weechat_headless}?/reload:/quit -yes}"
+sigquit = "/quit -yes"
+sigterm = "/quit -yes"
+sigusr1 = ""
+sigusr2 = ""
+
 [bar]
 buffers.color_bg = default
+buffers.color_bg_inactive = default
 buffers.color_delim = default
 buffers.color_fg = default
 buffers.conditions = ""
@@ -258,6 +272,7 @@
 buffers.size_max = 0
 buffers.type = root
 buflist.color_bg = default
+buflist.color_bg_inactive = default
 buflist.color_delim = default
 buflist.color_fg = default
 buflist.conditions = ""
@@ -272,6 +287,7 @@
 buflist.size_max = 25
 buflist.type = root
 fset.color_bg = default
+fset.color_bg_inactive = default
 fset.color_delim = cyan
 fset.color_fg = default
 fset.conditions = "${buffer.full_name} == fset.fset"
@@ -286,6 +302,7 @@
 fset.size_max = 3
 fset.type = window
 input.color_bg = default
+input.color_bg_inactive = default
 input.color_delim = green
 input.color_fg = default
 input.conditions = ""
@@ -300,6 +317,7 @@
 input.size_max = 0
 input.type = window
 nicklist.color_bg = default
+nicklist.color_bg_inactive = default
 nicklist.color_delim = cyan
 nicklist.color_fg = default
 nicklist.conditions = "nicklist"
@@ -314,6 +332,7 @@
 nicklist.size_max = 0
 nicklist.type = window
 status.color_bg = green
+status.color_bg_inactive = default
 status.color_delim = 0
 status.color_fg = 0
 status.conditions = ""
@@ -328,6 +347,7 @@
 status.size_max = 0
 status.type = window
 title.color_bg = green
+title.color_bg_inactive = default
 title.color_delim = cyan
 title.color_fg = 16
 title.conditions = ""
@@ -345,6 +365,11 @@
 [layout]
 
 [notify]
+python.slack.10xgenomics.&cloud-alerts-pagerduty = highlight
+python.slack.10xgenomics.&cloud-sumo-prod-support-alerts = highlight
+python.slack.10xgenomics.&lacework-10xdev = highlight
+python.slack.10xgenomics.&lacework-10xprod = highlight
+python.slack.10xgenomics.&testing1234 = highlight
 
 [filter]
 irc_smart = on;*;irc_smart_filter;*
@@ -381,6 +406,8 @@
 ctrl-Y = "/input clipboard_paste"
 meta-meta-OP = "/bar scroll buflist * b"
 meta-meta-OQ = "/bar scroll buflist * e"
+meta-meta2-11~ = "/bar scroll buflist * b"
+meta-meta2-12~ = "/bar scroll buflist * e"
 meta-meta2-1~ = "/window scroll_top"
 meta-meta2-23~ = "/bar scroll nicklist * yb"
 meta-meta2-24~ = "/bar scroll nicklist * ye"
@@ -406,6 +433,7 @@
 meta-< = "/input jump_previously_visited_buffer"
 meta-= = "/filter toggle"
 meta-> = "/input jump_next_visited_buffer"
+meta-B = "/buflist toggle"
 meta-OA = "/input history_global_previous"
 meta-OB = "/input history_global_next"
 meta-OC = "/input move_next_word"
@@ -418,6 +446,10 @@
 meta-Ob = "/input history_global_next"
 meta-Oc = "/input move_next_word"
 meta-Od = "/input move_previous_word"
+meta2-11^ = "/bar scroll buflist * -100%"
+meta2-11~ = "/bar scroll buflist * -100%"
+meta2-12^ = "/bar scroll buflist * +100%"
+meta2-12~ = "/bar scroll buflist * +100%"
 meta2-15~ = "/bar scroll nicklist * y-100%"
 meta2-17~ = "/bar scroll nicklist * y+100%"
 meta2-18~ = "/window -1"
@@ -426,8 +458,12 @@
 meta2-1;3B = "/buffer +1"
 meta2-1;3C = "/buffer +1"
 meta2-1;3D = "/buffer -1"
+meta2-1;3P = "/bar scroll buflist * b"
+meta2-1;3Q = "/bar scroll buflist * e"
 meta2-1;5A = "/input history_global_previous"
 meta2-1;5B = "/input history_global_next"
+meta2-1;5P = "/bar scroll buflist * -100%"
+meta2-1;5Q = "/bar scroll buflist * +100%"
 meta2-1;9A = "/buffer move -1"
 meta2-1;9B = "/buffer move +1"
 meta2-1~ = "/input move_beginning_of_line"
@@ -601,6 +637,11 @@
 meta2-B = "/cursor move down"
 meta2-C = "/cursor move right"
 meta2-D = "/cursor move left"
+@chat(python.*):D = "hsignal:slack_cursor_delete"
+@chat(python.*):L = "hsignal:slack_cursor_linkarchive"
+@chat(python.*):M = "hsignal:slack_cursor_message"
+@chat(python.*):R = "hsignal:slack_cursor_reply"
+@chat(python.*):T = "hsignal:slack_cursor_thread"
 @item(buffer_nicklist):K = "/window ${_window_number};/kickban ${nick}"
 @item(buffer_nicklist):b = "/window ${_window_number};/ban ${nick}"
 @item(buffer_nicklist):k = "/window ${_window_number};/kick ${nick}"
@@ -622,6 +663,7 @@
 @chat(fset.fset):button2* = "hsignal:fset_mouse"
 @chat(fset.fset):wheeldown = "/fset -down 5"
 @chat(fset.fset):wheelup = "/fset -up 5"
+@chat(python.*):button2 = "hsignal:slack_mouse"
 @chat(script.scripts):button1 = "/window ${_window_number};/script go ${_chat_line_y}"
 @chat(script.scripts):button2 = "/window ${_window_number};/script go ${_chat_line_y};/script installremove -q ${script_name_with_extension}"
 @chat(script.scripts):wheeldown = "/script down 5"
--- a/weechat/xfer.conf	Fri Apr 14 15:01:35 2023 -0400
+++ b/weechat/xfer.conf	Fri Jul 07 16:11:02 2023 -0400
@@ -4,9 +4,9 @@
 # WARNING: It is NOT recommended to edit this file by hand,
 # especially if WeeChat is running.
 #
-# Use /set or similar command to change settings in WeeChat.
+# Use commands like /set or /fset to change settings in WeeChat.
 #
-# For more info, see: https://weechat.org/doc/quickstart
+# For more info, see: https://weechat.org/doc/quickstart/
 #
 
 [look]
@@ -31,7 +31,8 @@
 own_ip = ""
 port_range = ""
 send_ack = on
-speed_limit = 0
+speed_limit_recv = 0
+speed_limit_send = 0
 timeout = 300
 
 [file]
@@ -43,5 +44,6 @@
 auto_resume = on
 convert_spaces = on
 download_path = "%h/xfer"
+download_temporary_suffix = ".part"
 upload_path = "~"
 use_nick_in_filename = on
--- a/xsessionrc	Fri Apr 14 15:01:35 2023 -0400
+++ b/xsessionrc	Fri Jul 07 16:11:02 2023 -0400
@@ -23,5 +23,9 @@
 
 # /usr/bin/dunst -config $HOME/.dunstrc &
 
+# Fix the fucking GTK scrolling bullshit
+# God bless you https://mmk2410.org/2018/02/15/scrolling-doesnt-work-in-gtk-3-apps-in-stumpwm/
+export GDK_CORE_DEVICE_EVENTS=1
+
 # exec gpg-agent --daemon --enable-ssh-support /usr/local/bin/stumpwm
 exec /usr/local/bin/stumpwm > .stump-xsession-log.out 2> .stump-xsession-log.err