From 435e3479fb6968c3b8d7f6f426f31a011fff536f Mon Sep 17 00:00:00 2001
From: Case Duckworth
Date: Sun, 16 Jul 2023 22:22:28 -0500
Subject: nyahhhhh ~~~~~~

---
 bash/functions.bash | 216 ++++++++--------
 bash/history.bash   |   2 +-
 chicken/csirc       |   8 +-
 emacs.el            | 704 +++++++++++++++++++++++++++++++++++++++-------------
 user-dirs.dirs      |   7 +-
 5 files changed, 654 insertions(+), 283 deletions(-)

diff --git a/bash/functions.bash b/bash/functions.bash
index 4241c8d..66724af 100644
--- a/bash/functions.bash
+++ b/bash/functions.bash
@@ -1,143 +1,144 @@
 # Functions
 
 memq() { # memq ITEM ARRAY
-    ## Test whether an ITEM is a member of ARRAY.
-    ## Pass ARRAY as ${ARRAY[@]}.
-    local e needle="$1"
-    shift
-    for e; do
-        [[ "$e" == "$needle" ]] && {
-            return 0
-        }
-    done
-    return 1
+	## Test whether an ITEM is a member of ARRAY.
+	## Pass ARRAY as ${ARRAY[@]}.
+	local e needle="$1"
+	shift
+	for e; do
+		[[ "$e" == "$needle" ]] && {
+			return 0
+		}
+	done
+	return 1
 }
 
 rebashrc() { # rebashrc
-    ## Reload ~/.bashrc
-    printf "Loading ~/.bashrc..." >&2
-    if source "$HOME/.bashrc"; then
-        echo "OK." >&2
-    else
-        echo "ERROR!" >&2
-    fi
+	## Reload ~/.bashrc
+	printf "Loading ~/.bashrc..." >&2
+	if source "$HOME/.bashrc"; then
+		echo "OK." >&2
+	else
+		echo "ERROR!" >&2
+	fi
 }
 
 first_which() { # first_which COMMAND...
-    ## Return the fully-qualified path of the first COMMAND found in $PATH.
-    while :; do
-        command -v "$1" && break
-        [ -z "$1" ] && return 1
-        shift
-    done
+	## Return the fully-qualified path of the first COMMAND found in $PATH.
+	while :; do
+		command -v "$1" && break
+		[ -z "$1" ] && return 1
+		shift
+	done
 }
 
 please() { # please [COMMAND...]
-    # if run without arguments, run the last command with 'sudo' (aka sudo !!)
-    # if run WITH arguments, alias as sudo
-    history -d -1
-    if [ -z "$1" ]; then
-        #set --	$(HISTTIMEFORMAT=$'\t' history 2 | sed 's/^.*\t//;q')
-        set -- $(fc -lnr | sed 1q)
-    fi
-    echo >&2 sudo "$@"
-    history -s sudo "$@"
-    "${DEBUG:-false}" || sudo "$@"
+	# if run without arguments, run the last command with 'sudo' (aka sudo !!)
+	# if run WITH arguments, alias as sudo
+	history -d -1
+	if [ -z "$1" ]; then
+		#set --	$(HISTTIMEFORMAT=$'\t' history 2 | sed 's/^.*\t//;q')
+		set -- $(fc -lnr | sed 1q)
+	fi
+	echo >&2 sudo "$@"
+	history -s sudo "$@"
+	"${DEBUG:-false}" || sudo "$@"
 }
 
 mkcd() {
-    if [ $# -lt 1 ]; then
-        command cd
-        return "$?"
-    fi
-    if [ "x$1" = x- ]; then
-        command cd -
-        return "$?"
-    fi
-    if ! [ -d "$1" ]; then
-        read -p "$1 doesn't exist.  Create (y/N)? " yn
-        case "$yn" in
-            n* | N*) return 1 ;;
-            y* | Y*) mkdir -p "$1" ;;
-            *) return 1 ;;
-        esac
-    fi
-    command cd "$1"
+	if [ $# -lt 1 ]; then
+		command cd
+		return "$?"
+	fi
+	if [ "x$1" = x- ]; then
+		command cd -
+		return "$?"
+	fi
+	if ! [ -d "$1" ]; then
+		read -p "$1 doesn't exist.  Create (y/N)? " yn
+		case "$yn" in
+			n* | N*) return 1 ;;
+			y* | Y*) mkdir -p "$1" ;;
+			*) return 1 ;;
+		esac
+	fi
+	command cd "$1"
 }
 alias cd='mkcd '
 
 # from tomasino
 # alias julian='echo "x = $(date +%s); scale=5; x / 86400 + 2440587.5" | bc'
 julian() {
-    echo "x = $(date ${1:+-d "$*"} +%s); scale=5; x / 86400 + 2440587.5" | bc
+	echo "x = $(date ${1:+-d "$*"} +%s); scale=5; x / 86400 + 2440587.5" | bc
 }
 
 # find files for pipelines
 f() {
-    find "${1:-$PWD}" -depth |
-        while read -r file; do
-            printf '%q\n' "$file"
-        done
+	find "${1:-$PWD}" -depth |
+		while read -r file; do
+			printf '%q\n' "$file"
+		done
 }
 
 words() {
-    grep -E "$1" /usr/share/dict/words
+	grep -E "$1" /usr/share/dict/words |
+		sed -e '/^[A-Z]/d' -e "/'s$/d"
 }
 
 if ! command -v dict >/dev/null 2>&1; then
-    dict() {
-        curl "dict://dict.org/d:$1" | less
-    }
+	dict() {
+		curl "dict://dict.org/d:$1" | less
+	}
 fi
 
 if command -v thesauracles >/dev/null 2>&1; then
-    thesauraphrase() {
-        for word in "$@"; do
-            thesauracles -q "$word"
-        done | tr '\n' ' '
-        echo
-    }
+	thesauraphrase() {
+		for word in "$@"; do
+			thesauracles -q "$word"
+		done | tr '\n' ' '
+		echo
+	}
 fi
 
 up() {
-    : "${UP_TODIRECTORY:=..}"
-    : "${UP_SPECIALARGS:=true}"
-    local ret=0
-    # echo "$UP_TODIRECTORY" "$UP_SPECIALARGS"
-    if "$UP_SPECIALARGS"; then
-        case "$1" in
-            '') cd "$UP_TODIRECTORY" ;;
-            up) UP_TODIRECTORY="${UP_TODIRECTORY}/.." up "${@:2}" ;;
-            --) UP_SPECIALARGS=false up "${@:2}" ;;
-            -*) if (( "$1" == -1 )); then
-                    up
-                else
-                    UP_TODIRECTORY="${UP_TODIRECTORY}/.." up $(( "$1" + 1 ))
-                fi
-                ;;
-            *) while cd ..; do
-                   case "$PWD" in
-                   /) ret=1; break ;;
-                   */"$1") break ;;
-                   esac
-               done
-            ;;
-        esac
-    else
-        case "$1" in
-            '') cd "$UP_TODIRECTORY" ;;
-            *) while cd ..; do
-                   case "$PWD" in
-                   /) ret=1; break ;;
-                   */"$1") break ;;
-                   esac
-               done
-            ;;
-        esac
-    fi
-    UP_TODIRECTORY=
-    UP_SPECIALARGS=
-    return "$ret"
+	: "${UP_TODIRECTORY:=..}"
+	: "${UP_SPECIALARGS:=true}"
+	local ret=0
+	# echo "$UP_TODIRECTORY" "$UP_SPECIALARGS"
+	if "$UP_SPECIALARGS"; then
+		case "$1" in
+			'') cd "$UP_TODIRECTORY" ;;
+			up) UP_TODIRECTORY="${UP_TODIRECTORY}/.." up "${@:2}" ;;
+			--) UP_SPECIALARGS=false up "${@:2}" ;;
+			-*) if (( "$1" == -1 )); then
+				    up
+			    else
+				    UP_TODIRECTORY="${UP_TODIRECTORY}/.." up $(( "$1" + 1 ))
+			    fi
+			    ;;
+			*) while cd ..; do
+				   case "$PWD" in
+					   /) ret=1; break ;;
+					   */"$1") break ;;
+				   esac
+			   done
+			   ;;
+		esac
+	else
+		case "$1" in
+			'') cd "$UP_TODIRECTORY" ;;
+			*) while cd ..; do
+				   case "$PWD" in
+					   /) ret=1; break ;;
+					   */"$1") break ;;
+				   esac
+			   done
+			   ;;
+		esac
+	fi
+	UP_TODIRECTORY=
+	UP_SPECIALARGS=
+	return "$ret"
 }
 
 apk() { # wrapper for apk(1)
@@ -160,3 +161,12 @@ mkssh() {
 	ssh-keygen -t ed25519 -f "$HOME/.ssh/$1"
 	cat "$HOME/.ssh/$1.pub" | tee /dev/stdout | wl-copy
 }
+
+p() {
+	cmd="$(history |
+		awk '{for(i=4;i<=NF;i++)printf "%s ",$i;print""}' |
+		tail -n2 |
+		head -n1)"
+	echo "$cmd"
+	eval $cmd
+}
diff --git a/bash/history.bash b/bash/history.bash
index d2bdceb..4a458fb 100644
--- a/bash/history.bash
+++ b/bash/history.bash
@@ -29,7 +29,7 @@ HISTCONTROL=erasedups
 # identical to 'ignorespace'." -- info (bash)Bash Variables
 HISTIGNORE='&:[ ]*'
 # Other commands to ignore
-HISTIGNORE="$HISTIGNORE:ls:exit:cd"
+HISTIGNORE="$HISTIGNORE:ls:exit:cd:p"
 
 # Automatically append to HISTFILE on every command
 PROMPT_COMMAND="history -a; ${PROMPT_COMMAND:-:}"
diff --git a/chicken/csirc b/chicken/csirc
index ac2ef22..0d22235 100644
--- a/chicken/csirc
+++ b/chicken/csirc
@@ -3,9 +3,15 @@
 (set! ##sys#notices-enabled #f)
 (import (chicken load))
 (load-verbose #f)
-(import (utf8))
+
+;;; Libraries for interactive development
+;; see also https://www.upyum.com/en/post/7.xhtml
+(import (live-define)
+        (srfi 18))
+
 ;; chicken-doc
 (require-library chicken-doc)
+
 ;; set up breadline
 (let ()
   (import (chicken format))
diff --git a/emacs.el b/emacs.el
index ad79286..7e83277 100644
--- a/emacs.el
+++ b/emacs.el
@@ -8,31 +8,56 @@
 (add-hook 'after-init-hook
           (lambda () (load (locate-user-emacs-file "private") :noerror)))
 
+(require 'package)
 (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
 (package-initialize)
 
 (defun package-ensure (pkg &optional local require)
-  "Ensure PACKAGE is installed.
-If LOCAL is t, add ~/src/PKG.el to `load-path' and generate autoloads.
-If REQUIRE is non-nil, require it as well."
+  "Ensure PKG is installed.
+PKG can be a symbol, a string, or a list. A symbol will be
+installed using `package-install' from `package-archives'.  A
+string will use `package-vc-install', which see.  If given a
+list, it will be interpreted as a full set of arguments to one of
+the above functions, depending on the type of its car.
+
+If LOCAL is t, add ~/src/PKG.el to `load-path' and generate
+autoloads.  If LOCAL is a string, Add that directory to
+`load-path'.
+
+If REQUIRE is non-nil, require the package after installing it."
+  (setq pkg (ensure-list pkg))
+
   (cond
-   ((stringp local)
+   (local
+    (unless (stringp local)
+      (setq local (expand-file-name
+                   (format "~/src/%s.el" (car pkg)))))
     (unless (file-directory-p local)
       (user-error "Package directory does not exist: %s" local))
-    (let ((autoload-file (expand-file-name (format "%s-autoloads.el" pkg) local))
+    (let ((autoload-file (expand-file-name
+                          (format "%s-autoloads.el" (car pkg))
+                          local))
           (backup-inhibited t))
       (add-to-list 'load-path local)
       (loaddefs-generate local autoload-file)
-      (load autoload-file nil t)))
-   (local
-    (package-ensure pkg (expand-file-name (format "~/src/%s.el" pkg)) require))
-   (:else
-    (unless (package-installed-p pkg)
-      (unless (ignore-errors (package-install pkg))
-        (package-refresh-contents)
-        (package-install pkg)))))
+      (load autoload-file nil t))
+    (setq pkg (intern (format "%s" (car pkg)))))
+
+   ((symbolp (car pkg))
+    (unless (ignore-errors (apply #'package-install pkg))
+      (package-refresh-contents)
+      (apply #'package-install pkg))
+    (setq pkg (car pkg)))
+
+   ((stringp (car pkg))
+    (let ((pkg-name  (intern (file-name-base (car pkg)))))
+      (unless (package-installed-p pkg-name)
+        (apply #'package-vc-install pkg))
+      (setq pkg pkg-name))))
+
   (when require
     (require pkg))
+
   pkg)
 
 (defmacro setf/assoc (alist key val &optional keep)
@@ -45,6 +70,11 @@ KEEP is also non-nil."
 
 (defmacro comment (&rest _) (declare (indent defun)) nil)
 
+(defun add-local-mode-hook (mode-hook hook func)
+  "Add FUNC to HOOK locally in buffers with MODE-HOOK."
+  (add-hook mode-hook
+            (lambda () (add-hook hook func nil t))))
+
 (package-ensure 'crux)
 (crux-reopen-as-root-mode)
 
@@ -54,6 +84,12 @@ KEEP is also non-nil."
 
 (keymap-global-set "C-c i" #'crux-find-user-init-file)
 
+(setopt auth-sources '(default
+                       "secrets:passwords"
+                       "~/.authinfo"))
+
+(setq disabled-command-function nil)
+
 
 ;;; Theme
 
@@ -67,6 +103,8 @@ KEEP is also non-nil."
 (scroll-bar-mode -1)
 (tooltip-mode -1)
 
+(setopt scroll-conservatively 101)
+
 (setopt read-answer-short t)
 (setopt use-dialog-box nil)
 (setopt use-file-dialog nil)
@@ -109,20 +147,21 @@ KEEP is also non-nil."
                   font-lock-bracket-face))
     (face-spec-set face '((t :foreground unspecified
                              :background unspecified))))
-  (dolist (face '(font-lock-doc-face
-                  font-lock-string-face))
-    (face-spec-set face '((t :foreground unspecified
-                             :background unspecified
-                             :slant italic))))
   (when-let ((current (cl-loop for modus in '(modus-vivendi modus-operandi)
                                if (memq modus custom-enabled-themes)
                                return modus
                                finally return nil)))
-    (face-spec-set 'font-lock-comment-face
-                   `((t :foreground ; :inherit doesn't work for some reason??
-                        ,(if (eq current 'modus-operandi)
-                             "#7c318f"
-                           "#caa6df"))))))
+    (modus-themes-with-colors
+      (dolist (face '(font-lock-doc-face
+                      font-lock-string-face))
+        (face-spec-set face `((t :foreground unspecified
+                                 :background unspecified
+                                 :slant italic))))
+      ;; (face-spec-set 'font-lock-comment-face
+      ;; :inherit doesn't work for some reason??
+      ;;                `((t :foreground
+      ;;                     ,fg-alt)))
+      )))
 (advice-add 'load-theme :after #'reset-faces)
 
 (load-theme 'modus-vivendi :no-confirm :no-enable)
@@ -274,7 +313,11 @@ mouse-3: Toggle minor modes"
 ;;; Completion and minibuffer
 
 (setopt tab-always-indent 'complete)
-;; (setopt completion-styles '(basic partial-completion substring flex))
+(setopt completion-styles '(basic partial-completion substring flex))
+
+;; XXX: this is 'too good' when I'm in the process of typing out things.
+;; (when (package-ensure "https://git.sr.ht/~pkal/typo")
+;;   (add-to-list 'completion-styles 'typo :append))
 
 (setopt completion-ignore-case t)
 (setopt read-buffer-completion-ignore-case t)
@@ -289,15 +332,30 @@ mouse-3: Toggle minor modes"
 (setopt completions-format 'one-column)
 (setopt completions-max-height 20)
 
+;; (defun minibuffer-next-completion-or-line (n)
+;;   "Move to the next N completion in minibuffer, or Nth next line."
+;;   (interactive "p")
+;;   (if (and (eq last-command 'minibuffer-next-completion)
+;;            (not (minibufferp)))
+;;       (forward-line n)
+;;     (minibuffer-next-completion n)))
+
+;; (defun minibuffer-previous-completion-or-line (n)
+;;   "Move to the previous N completion, or Nth previous line."
+;;   (interactive "p")
+;;   (setq last-command 'minibuffer-next-completion-or-line)
+;;   (minibuffer-next-completion-or-line (- n)))
+
 (progn
   (keymap-set minibuffer-local-map "C-p"
               #'minibuffer-previous-completion)
   (keymap-set minibuffer-local-map "C-n"
               #'minibuffer-next-completion)
-  (keymap-set completion-in-region-mode-map "C-p"
-              #'minibuffer-previous-completion)
-  (keymap-set completion-in-region-mode-map "C-n"
-                #'minibuffer-next-completion))
+  ;; (keymap-set completion-in-region-mode-map "C-p"
+  ;;             #'minibuffer-previous-completion)
+  ;; (keymap-set completion-in-region-mode-map "C-n"
+  ;;             #'minibuffer-next-completion)
+  )
 
 (setf/assoc display-buffer-alist
             "\\*Completions\\*"
@@ -318,11 +376,6 @@ mouse-3: Toggle minor modes"
 (add-hook 'completion-list-mode-hook #'truncate-lines-local-mode)
 (add-hook 'minibuffer-setup-hook #'truncate-lines-local-mode)
 
-(when (package-ensure 'orderless)
-  (setopt completion-styles '(substring orderless basic))
-  (setopt completion-category-overrides
-          '((file (styles basic partial-completion)))))
-
 (when (package-ensure 'consult nil t)
   (keymap-global-set "C-x b" #'consult-buffer)
   (keymap-global-set "C-x 4 b" #'consult-buffer-other-window)
@@ -439,6 +492,8 @@ mouse-3: Toggle minor modes"
 (keymap-global-set "M-/" #'hippie-expand)
 (keymap-global-set "C-x C-b" #'ibuffer)
 
+(add-hook 'ibuffer-mode-hook #'hl-line-mode)
+
 (defun call-with-region-or-buffer (fn &rest _r)
   "Call function FN with current region or buffer.
 Good to use for :around advice."
@@ -481,7 +536,7 @@ Good to use for :around advice."
 (defun org-fk-region (start end)
   "Get the Flesch-Kincaid score of an `org-mode' region."
   (interactive "r")
-  (let ((buf (get-buffer-create "*fk*" t)))
+  (let ((buf (get-buffer-create " *fk*" t)))
     (shell-command-on-region start end
                              "pandoc -t plain -f org | ~/src/fk/fk.perl"
                              buf)
@@ -506,6 +561,8 @@ Good to use for :around advice."
                      (unless (ignore-errors (dictionary-lookup-definition))
                        (call-interactively #'dictionary-search))))
 
+(package-ensure 'markdown-mode)
+
 ;;; Programming
 
 (setopt electric-pair-skip-whitespace 'chomp)
@@ -533,6 +590,7 @@ Good to use for :around advice."
 (setopt tab-width 8)
 
 (defvar space-indent-modes '(emacs-lisp-mode
+                             lisp-interaction-mode
                              lisp-mode
                              scheme-mode
                              python-mode
@@ -552,7 +610,8 @@ Good to use for :around advice."
 
 (when (package-ensure 'geiser)
   (when (executable-find "csi")
-    (package-ensure 'geiser-chicken))
+    (when (package-ensure 'geiser-chicken)
+      (setf/assoc auto-mode-alist "\\.egg\\'" 'scheme-mode))))
   (setopt scheme-program-name (or (executable-find "csi")
                                   "scheme"))
   (add-hook 'scheme-mode-hook #'geiser-mode))
@@ -566,6 +625,19 @@ Good to use for :around advice."
                   _ \n
                   "|#" \n \n))
 
+;; Emacs lisp
+
+(keymap-set emacs-lisp-mode-map "C-c C-c" #'eval-defun)
+(keymap-set emacs-lisp-mode-map "C-c C-b" #'eval-buffer)
+(keymap-set emacs-lisp-mode-map "C-c C-z" #'ielm) ; TODO: better-ize
+(keymap-set lisp-interaction-mode-map "C-c C-c" #'eval-defun)
+(keymap-set lisp-interaction-mode-map "C-c C-b" #'eval-buffer)
+(keymap-set lisp-interaction-mode-map "C-c C-z" #'ielm) ; TODO: better-ize
+
+
+(define-advice eval-buffer (:after (&rest _) message)
+  (message "Buffer %s evaluated." (current-buffer)))
+
 
 ;;; Files
 
@@ -640,18 +712,33 @@ Good to use for :around advice."
 
 ;;; ...
 
+(defun c-w-dwim (num)
+  "Delete NUM words backward, or the region if it's active."
+  (interactive "p")
+  (if (region-active-p)
+      (call-interactively #'kill-region)
+    (call-interactively #'backward-kill-word)))
+(keymap-global-set "C-w" #'c-w-dwim)
+
+(setf/assoc display-buffer-alist
+            "\\`\\*Warnings\\*"
+            '((display-buffer-no-window)))
+
+(winner-mode)
+
 (setopt set-mark-command-repeat-pop t)
 
 (when (package-ensure 'embark nil t)
-  (when (package-installed-p 'consult)
-    (package-ensure 'embark-consult nil t))
+  (when (and (package-installed-p 'consult)
+             (package-ensure 'embark-consult nil t))
+    (add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode))
   (keymap-global-set "C-." #'embark-act)
   (keymap-global-set "M-." #'embark-dwim)
   (keymap-global-set "C-h B" #'embark-bindings)
+  (setopt prefix-help-command #'embark-prefix-help-command)
   (setf/assoc display-buffer-alist
               "\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
-              '(nil (window-parameters (mode-line-format . none))))
-  (add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode))
+              '(nil (window-parameters (mode-line-format . none)))))
 
 (setopt eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)
 (setopt eldoc-idle-delay 0.01)
@@ -692,23 +779,6 @@ Good to use for :around advice."
               (delete-trailing-whitespace (line-end-position)
                                           (point-max)))))
 
-(defcustom browse-url-safe-browser-functions nil
-  "\"Safe\" browser functions."
-  :type '(repeat-function))
-
-(defun browse-url-browser-function-safe-p (fn)
-  "Return t if FN is a \"safe\" browser function."
-  (memq fn (append browse-url-safe-browser-functions
-                   (mapcar (lambda (i)
-                             (plist-get (cdr i) :value))
-                           (seq-filter (lambda (i)
-                                         (eq (car i) 'function-item))
-                                       (cdr (get 'browse-url-browser-function
-                                                 'custom-type)))))))
-
-(put 'browse-url-browser-function 'safe-local-variable
-     'browse-url-browser-function-safe-p)
-
 (defun list-of-strings-p (x)
   "Is X a list of strings?"
   (and x
@@ -732,29 +802,44 @@ Good to use for :around advice."
     (repunctuate-sentences :no-query start end)
     (fill-region start end)))
 
-(defun fill-or-unfill-region (start end)
+(defun unfill-region (start end &optional unfill-func)
+  "Unfill region from START to END."
+  (let ((fill-column most-positive-fixnum)
+        (fill-paragraph-function nil))
+    (funcall (or unfill-func #'fill-region) start end)))
+
+(defun fill-or-unfill-region (start end &optional interactive)
   "Fill or unfill from START to END."
-  (let ((filled-p (cl-every (lambda (ln) (<= (length ln) fill-column))
-                            (string-split (buffer-substring start end)
-                                          "[\n\r]+"))))
-    (if filled-p
-        (let ((fill-column most-positive-fixnum)
-              (fill-paragraph-function nil))
-          (message "Unfilling region")
-          (fill-double-space-sentences-region start end))
-      (message "Filling region")
-      (fill-double-space-sentences-region start end))))
+  (interactive "*r\np")
+  (if (and interactive
+           (eq last-command 'fill-or-unfill-region))
+      ;; If called interactively more than once, toggle filling mode.
+      (if (with-current-buffer "*Messages*"
+            (goto-char (point-max))
+            (goto-char (beginning-of-line))
+            (looking-at "Unfilling"))
+          (fill-double-space-sentences-region start end)
+        (unfill-region start end #'fill-double-space-sentences-region))
+    ;; Otherwise, detect filled status based on the length of lines in the
+    ;; region.  If just one of them is longer than `fill-column', consider the
+    ;; region unfilled.
+    (let ((filled-p (cl-some (lambda (ln) (<= 1 (length ln) fill-column))
+                             (string-split (buffer-substring start end)
+                                           "[\n\r]+"))))
+      (if filled-p
+          (progn
+            (message "Unfilling region")
+            (unfill-region start end #'fill-double-space-sentences-region))
+        (progn
+          (message "Filling region")
+          (fill-double-space-sentences-region start end))))))
 
 (defun fill-or-unfill-dwim ()
   (interactive)
   (save-mark-and-excursion
-    (if (region-active-p)
-        (fill-or-unfill-region (region-beginning)
-                               (region-end))
-      (fill-or-unfill-region (progn (backward-paragraph)
-                                    (point))
-                             (progn (forward-paragraph)
-                                    (point))))))
+    (unless (region-active-p)
+      (mark-paragraph))
+    (call-interactively #'fill-or-unfill-region)))
 
 (keymap-global-set "M-q" #'fill-or-unfill-dwim)
 
@@ -788,6 +873,7 @@ In these cases, switch to the last-used buffer."
       (switch-to-buffer (other-buffer) nil t)
     (other-window 1)))
 (keymap-global-set "M-o" #'other-window-dwim)
+(keymap-global-set "C-x o" #'other-window-dwim)
 
 (defun delete-window-dwim ()
   "Delete the current window or bury its buffer.
@@ -1000,6 +1086,31 @@ ORG-EXPORT-ARGS are passed to `org-export-to-buffer'."
     (org-todo (if (= n-not-done 0) "DONE" "TODO"))))
 (add-hook 'org-after-todo-statistics-hook #'org-summary-todo)
 
+;; Clean up the buffer view
+(defun org-hide-drawers-except-point ()
+  "Hide all drawers except for the one point is in."
+  ;; Most of this bit is taken from `org-fold--hide-drawers'.
+  (let ((pt (point))
+        (begin (point-min))
+        (end (point-max)))
+    (save-excursion
+      (goto-char begin)
+      (while (and (< (point) end)
+                  (re-search-forward org-drawer-regexp end t))
+        (if (org-fold-folded-p nil 'drawer)
+            (goto-char (org-fold-next-folding-state-change 'drawer nil end))
+          (let* ((drawer (org-element-at-point))
+                 (type (org-element-type drawer))
+                 (el-begin (org-element-property :begin drawer))
+                 (el-end (org-element-property :end drawer)))
+            (when (memq type '(drawer property-drawer))
+              (org-fold-hide-drawer-toggle
+               (if (< el-begin pt el-end) 'off 'on)
+               nil drawer)
+              (goto-char el-end))))))))
+(add-local-mode-hook 'org-mode-hook 'before-save-hook
+                     #'org-hide-drawers-except-point)
+
 ;; Fix braindead behavior
 (with-eval-after-load 'org-mouse
   (defun org--mouse-open-at-point (orig-fun &rest args)
@@ -1079,7 +1190,7 @@ the following: `:keys', `:description', `:type', `:target', and
   ;;     (string-chop-newline (buffer-substring-no-properties
   ;;                           (line-beginning-position) (point-max)))))
 
-  (let ((shell-command-buffer-name (format "*fk/%s*" (buffer-name))))
+  (let ((shell-command-buffer-name (format " *fk/%s*" (buffer-name))))
     (shell-command-on-region start end "~/src/fk/fk.perl")
     (with-current-buffer shell-command-buffer-name
       (buffer-substring-no-properties (point-min) (- (point-max) 1))))
@@ -1153,102 +1264,102 @@ the following: `:keys', `:description', `:type', `:target', and
 
 ;;; Jabber
 
-(when (package-ensure 'jabber t t)
-  (setopt jabber-chat-buffer-format "*%n*")
-  (setopt jabber-browse-buffer-format "*%n*")
-  (setopt jabber-groupchat-buffer-format "*%n*")
-  (setopt jabber-muc-private-buffer-format "*%n*")
-
-  (face-spec-set 'jabber-activity-face
-                 '((t :inherit jabber-chat-prompt-foreign
-                      :foreground unspecified
-                      :weight normal)))
-  (face-spec-set 'jabber-activity-personal-face
-                 '((t :inherit jabber-chat-prompt-local
-                      :foreground unspecified
-                      :weight bold)))
-  (face-spec-set 'jabber-chat-prompt-local
-                 '((t :inherit minibuffer-prompt
-                      :foreground unspecified
-                      :weight normal
-                      :slant italic)))
-  (face-spec-set 'jabber-chat-prompt-foreign
-                 '((t :inherit warning
-                      :foreground unspecified
-                      :weight normal)))
-  (face-spec-set 'jabber-chat-prompt-system
-                 '((t :inherit font-lock-doc-face
-                      :foreground unspecified)))
-  (face-spec-set 'jabber-rare-time-face
-                 '((t :inherit font-lock-comment-face
-                      :foreground unspecified
-                      :underline nil)))
-
-  (setopt jabber-auto-reconnect t)
-  (setopt jabber-last-read-marker
-          "-------------------------------------------------------------------")
-  (setopt jabber-muc-decorate-presence-patterns
-          '(("\\( enters the room ([^)]+)\\| has left the chatroom\\)$" . nil)
-            ("Mode #.*" . jabber-muc-presence-dim)
-            ("." . jabber-muc-presence-dim)))
-  (setopt jabber-activity-make-strings #'jabber-activity-make-strings-shorten)
-  (setopt jabber-rare-time-format
-          (format " - - - - - %%H:%d %%F"
-                  (let ((min (string-to-number (format-time-string "%M"))))
-                    (* 5 (floor min 5)))))
-  (setopt jabber-muc-header-line-format '(" " jabber-muc-topic))
-
-  (setopt jabber-groupchat-prompt-format "%n.  ")
-  (setopt jabber-chat-local-prompt-format "%n.  ")
-  (setopt jabber-chat-foreign-prompt-format "%n.  ")
-  (setopt jabber-muc-private-foreign-prompt-format "%g/%n.  ")
-
-  (defun jabber-connect-all* (&optional arg)
-    "Connect to all defined jabber accounts.
-If called with ARG non-nil, or with \\[universal-argument],
-disconnect first."
-    (interactive "P")
-    (when arg (jabber-disconnect))
-    (jabber-connect-all))
-
-  (keymap-global-set "C-c C-SPC" #'jabber-activity-switch-to)
-  (with-eval-after-load 'jabber
-    (require 'jabber-httpupload nil t)
-    (map-keymap (lambda (key command)
-                  (define-key jabber-global-keymap (vector (+ key #x60)) command))
-                jabber-global-keymap)
-    (keymap-global-set "C-x C-j" #'dired-jump))
-  (keymap-global-set "C-x C-j" #'dired-jump)
-  (keymap-set jabber-global-keymap "c" #'jabber-connect-all*)
-  (keymap-global-set "C-c j" jabber-global-keymap)
-
-  (remove-hook 'jabber-alert-muc-hooks #'jabber-muc-echo)
-  (remove-hook 'jabber-alert-presence-hooks #'jabber-presence-echo)
-  (add-hook 'jabber-post-connect-hooks #'jabber-enable-carbons)
-  (add-hook 'jabber-chat-mode-hook #'olivetti-mode)
-  (add-hook 'jabber-chat-mode-hook
-            (defun jabber-chat-mode-no-position ()
-              (setq-local mode-line-position nil)))
-  (add-hook 'jabber-alert-muc-hooks
-            (defun jabber@highlight-acdw (&optional _ _ buf _ _)
-              (when buf
-                (with-current-buffer buf
-                  (let ((regexp (rx word-boundary
-                                    "acdw" ; maybe get from the config?
-                                    word-boundary)))
-                    (hi-lock-unface-buffer regexp)
-                    (highlight-regexp regexp 'jabber-chat-prompt-local))))))
-
-  (add-hook 'jabber-chat-mode-hook
-            (defun electric-pair-local-disable ()
-              (electric-pair-local-mode -1)))
-
-  (when (fboundp 'jabber-chat-update-focus)
-    (add-hook 'window-configuration-change-hook #'jabber-chat-update-focus)))
+;; (when (package-ensure 'jabber t t)
+;;   (setopt jabber-chat-buffer-format "*%n*")
+;;   (setopt jabber-browse-buffer-format "*%n*")
+;;   (setopt jabber-groupchat-buffer-format "*%n*")
+;;   (setopt jabber-muc-private-buffer-format "*%n*")
+
+;;   (face-spec-set 'jabber-activity-face
+;;                  '((t :inherit jabber-chat-prompt-foreign
+;;                       :foreground unspecified
+;;                       :weight normal)))
+;;   (face-spec-set 'jabber-activity-personal-face
+;;                  '((t :inherit jabber-chat-prompt-local
+;;                       :foreground unspecified
+;;                       :weight bold)))
+;;   (face-spec-set 'jabber-chat-prompt-local
+;;                  '((t :inherit minibuffer-prompt
+;;                       :foreground unspecified
+;;                       :weight normal
+;;                       :slant italic)))
+;;   (face-spec-set 'jabber-chat-prompt-foreign
+;;                  '((t :inherit warning
+;;                       :foreground unspecified
+;;                       :weight normal)))
+;;   (face-spec-set 'jabber-chat-prompt-system
+;;                  '((t :inherit font-lock-doc-face
+;;                       :foreground unspecified)))
+;;   (face-spec-set 'jabber-rare-time-face
+;;                  '((t :inherit font-lock-comment-face
+;;                       :foreground unspecified
+;;                       :underline nil)))
+
+;;   (setopt jabber-auto-reconnect t)
+;;   (setopt jabber-last-read-marker
+;;           "-------------------------------------------------------------------")
+;;   (setopt jabber-muc-decorate-presence-patterns
+;;           '(("\\( enters the room ([^)]+)\\| has left the chatroom\\)$" . nil)
+;;             ("Mode #.*" . jabber-muc-presence-dim)
+;;             ("." . jabber-muc-presence-dim)))
+;;   (setopt jabber-activity-make-strings #'jabber-activity-make-strings-shorten)
+;;   (setopt jabber-rare-time-format
+;;           (format " - - - - - %%H:%d %%F"
+;;                   (let ((min (string-to-number (format-time-string "%M"))))
+;;                     (* 5 (floor min 5)))))
+;;   (setopt jabber-muc-header-line-format '(" " jabber-muc-topic))
+
+;;   (setopt jabber-groupchat-prompt-format "%n.  ")
+;;   (setopt jabber-chat-local-prompt-format "%n.  ")
+;;   (setopt jabber-chat-foreign-prompt-format "%n.  ")
+;;   (setopt jabber-muc-private-foreign-prompt-format "%g/%n.  ")
+
+;;   (defun jabber-connect-all* (&optional arg)
+;;     "Connect to all defined jabber accounts.
+;; If called with ARG non-nil, or with \\[universal-argument],
+;; disconnect first."
+;;     (interactive "P")
+;;     (when arg (jabber-disconnect))
+;;     (jabber-connect-all))
+
+;;   (with-eval-after-load 'jabber
+;;     (keymap-global-set "C-c C-SPC" #'jabber-activity-switch-to)
+;;     (require 'jabber-httpupload nil t)
+;;     (map-keymap (lambda (key command)
+;;                   (define-key jabber-global-keymap (vector (+ key #x60)) command))
+;;                 jabber-global-keymap)
+;;     (keymap-global-set "C-x C-j" #'dired-jump)
+;;     (keymap-set jabber-global-keymap "c" #'jabber-connect-all*)
+;;     (keymap-global-set "C-c j" jabber-global-keymap))
+
+;;   (remove-hook 'jabber-alert-muc-hooks #'jabber-muc-echo)
+;;   (remove-hook 'jabber-alert-presence-hooks #'jabber-presence-echo)
+;;   (add-hook 'jabber-post-connect-hooks #'jabber-enable-carbons)
+;;   (add-hook 'jabber-chat-mode-hook #'olivetti-mode)
+;;   (add-hook 'jabber-chat-mode-hook
+;;             (defun jabber-chat-mode-no-position ()
+;;               (setq-local mode-line-position nil)))
+;;   (add-hook 'jabber-alert-muc-hooks
+;;             (defun jabber@highlight-acdw (&optional _ _ buf _ _)
+;;               (when buf
+;;                 (with-current-buffer buf
+;;                   (let ((regexp (rx word-boundary
+;;                                     "acdw" ; maybe get from the config?
+;;                                     word-boundary)))
+;;                     (hi-lock-unface-buffer regexp)
+;;                     (highlight-regexp regexp 'jabber-chat-prompt-local))))))
+
+;;   (add-hook 'jabber-chat-mode-hook
+;;             (defun electric-pair-local-disable ()
+;;               (electric-pair-local-mode -1)))
+
+;;   (when (fboundp 'jabber-chat-update-focus)
+;;     (add-hook 'window-configuration-change-hook #'jabber-chat-update-focus)))
 
 
 ;;; Dired
 
+(keymap-global-set "C-x C-j" #'dired-jump)
 (with-eval-after-load 'dired
   (keymap-set dired-mode-map "C-j" #'dired-up-directory))
 
@@ -1257,6 +1368,23 @@ disconnect first."
 
 (setopt browse-url-browser-function #'eww-browse-url)
 
+(defcustom browse-url-safe-browser-functions nil
+  "\"Safe\" browser functions."
+  :type '(repeat-function))
+
+(defun browse-url-browser-function-safe-p (fn)
+  "Return t if FN is a \"safe\" browser function."
+  (memq fn (append browse-url-safe-browser-functions
+                   (mapcar (lambda (i)
+                             (plist-get (cdr i) :value))
+                           (seq-filter (lambda (i)
+                                         (eq (car i) 'function-item))
+                                       (cdr (get 'browse-url-browser-function
+                                                 'custom-type)))))))
+
+(put 'browse-url-browser-function 'safe-local-variable
+     'browse-url-browser-function-safe-p)
+
 ;;; EWW
 
 (setopt eww-use-browse-url ".")
@@ -1266,6 +1394,15 @@ disconnect first."
             "~/Downloads"))
 (setopt eww-history-limit nil)
 
+(defun eww-readable/olivetti ()
+  (interactive)
+  (olivetti-mode +1)
+  (eww-readable)
+  (eww-reload t))
+
+(with-eval-after-load 'eww
+  (keymap-set eww-mode-map "R" #'eww-readable/olivetti))
+
 ;; Use Emacs bookmarks for EWW
 (defun bookmark-eww--make ()
   "Make eww bookmark record."
@@ -1322,9 +1459,9 @@ disconnect first."
   (hide-minor-mode 'browse-url-transform-mode))
 
 (with-eval-after-load 'browse-url-transform
-  (setopt eww-url-transformers
-          '(eww-remove-tracking
-            browse-url-transform-url)))
+  (setq eww-url-transformers ; `setopt' causes a warning about custom-type
+        '(eww-remove-tracking
+          browse-url-transform-url)))
 
 ;; External browsers: firefox > chromium > chrome
 (setq browse-url-firefox-program
@@ -1347,6 +1484,36 @@ disconnect first."
             (browse-url-chrome-program #'browse-url-chrome)
             (t #'browse-url-default-browser)))
 
+(defmacro open-url-with (commandline &optional buffer error-buffer)
+  (let ((buffer (or buffer " *open-url-with*"))
+        (error-buffer (or error-buffer " *open-url-with/errors*")))
+    `(lambda (url &rest _)
+       (cl-letf (((alist-get ,buffer
+                             display-buffer-alist
+                             nil nil #'equal)
+                  '(display-buffer-no-window)))
+         (async-shell-command (format ,commandline url)
+                              ,buffer
+                              ,error-buffer)))))
+
+(defun add-browse-url-handler (regexp opener)
+  "Add OPENER to open REGEXP urls."
+  (setf/assoc browse-url-handlers
+              regexp
+              opener))
+
+(add-browse-url-handler (rx (or (: ".pdf" eos)
+                                (: ".PDF" eos)))
+                        (open-url-with "zathura %s"))
+(add-browse-url-handler (rx (or (: ".mp4" eos)
+                                "youtube.com"
+                                "piped.kavin.rocks"))
+                        (open-url-with "mpv %s"))
+
+(when (package-ensure 'elpher)
+  (add-browse-url-handler (rx bos "gemini:")
+                          #'elpher-browse-url-elpher))
+
 ;; Hinting at links
 (when (package-ensure 'link-hint)
   (setopt link-hint-avy-style 'at-full)
@@ -1428,7 +1595,7 @@ NEW is passed to `eshell'."
         (pop-to-buffer buf)
       (eshell arg))
     ;; In the eshell buffer
-    (unless (equal default-directory dir)
+    (unless (file-equal-p default-directory dir)
       (eshell/cd dir)
       (eshell-send-input)
       (goto-char (point-max)))))
@@ -1438,7 +1605,9 @@ NEW is passed to `eshell'."
   (keymap-set eshell-mode-map "C-z" #'quit-window))
 
 (when (package-ensure 'eat)
-  (add-hook 'eshell-first-time-mode-hook #'eat-eshell-mode))
+  (add-hook 'eshell-first-time-mode-hook #'eat-eshell-mode)
+  (with-eval-after-load 'eat
+    (keymap-unset eat-eshell-semi-char-mode-map "M-o" t)))
 
 (when (package-ensure 'wiki-abbrev t)
   (wiki-abbrev-insinuate)
@@ -1448,7 +1617,8 @@ NEW is passed to `eshell'."
 ;;; Dinghie
 
 (add-to-list 'mode-line-misc-info
-             '(buffer-ding-cookie buffer-ding-cookie)
+             '(buffer-ding-cookie (:propertize buffer-ding-cookie
+                                               face error))
              :append)
 
 (defvar buffer-ding-timer nil
@@ -1462,7 +1632,7 @@ NEW is passed to `eshell'."
   "Unflash the buffer after done `ding'ing."
   ;; (face-remap-remove-relative buffer-ding-cookie)
   (setq buffer-ding-cookie nil)
-  (force-mode-line-update))
+  (force-mode-line-update t))
 
 (defun buffer-ding ()
   "Flash the buffer for `ding'."
@@ -1481,6 +1651,9 @@ NEW is passed to `eshell'."
     (force-mode-line-update)
     (run-with-timer buffer-ding-timeout nil #'buffer-unding))))
 
+;; (setopt ring-bell-function (lambda () (pulse-momentary-highlight-region
+;; (window-start) (window-end))))
+
 (setopt ring-bell-function #'buffer-ding)
 (add-hook 'isearch-mode-end-hook #'buffer-unding)
 
@@ -1490,3 +1663,186 @@ NEW is passed to `eshell'."
                 (when (or (null modes)
                           (apply #'derived-mode-p modes))
                   (funcall fn)))))
+
+;;; Flash!
+
+(defun flash-region@ (orig start end &rest args)
+  (apply orig start end args)
+  (pulse-momentary-highlight-region start end))
+
+(advice-add 'eval-region :around #'flash-region@)
+(with-eval-after-load 'geiser
+  (advice-add 'geiser-eval-region :around #'flash-region@))
+
+;;; KeepassXC Integration
+
+(when (package-ensure 'keepassxc-shim t)
+  (keepassxc-shim-activate))
+
+;;; RCIRC
+
+(when (require 'rcirc)
+  (setopt rcirc-default-full-name user-full-name)
+  (setopt rcirc-default-user-name user-login-name)
+  (setopt rcirc-authenticate-before-join t)
+  (setopt rcirc-display-server-buffer nil)
+  (setopt rcirc-buffer-maximum-lines 1000)
+  (setopt rcirc-kill-channel-buffers t)
+  (setopt rcirc-track-ignore-server-buffer-flag t)
+
+  ;; Theming
+  (setopt rcirc-prompt "%t> ")
+  (setopt rcirc-default-part-reason "See You Space Cowboy . . .")
+  (setopt rcirc-default-quit-reason "(TLS connection improperly terminated)")
+  (setopt rcirc-url-max-length 24)
+  (setopt rcirc-response-formats
+          '(("PRIVMSG" . "<%N> %m")
+            ("NOTICE" . "-%N- %m")
+            ("ACTION" . "* %N %m")
+            ("COMMAND" . "%fs%m%f-")
+            ("ERROR" . "%fw!!! %m")
+            ("FAIL" . "(%fwFAIL%f-) %m")
+            ("WARN" . "(%fwWARN%f-) %m")
+            ("NOTE" . "(%fwNOTE%f-) %m")
+            (t . "%fp*** %fs%n %r %m")))
+
+  (face-spec-set 'rcirc-nick-in-message-full-line
+                 '((t :foreground unspecified
+                      :background unspecified
+                      :weight unspecified
+                      :inherit nil)))
+
+  (add-to-list 'rcirc-omit-responses "NAMES")
+
+  (defun chat/setup ()
+    (whitespace-mode -1)
+    (electric-pair-local-mode -1)
+    ;; IDK what's the deal with this
+    (olivetti-mode +1)
+    (visual-line-mode -1)
+    (word-wrap-whitespace-mode +1))
+
+  (setq rcirc-debug-flag t)
+
+  (advice-add 'rcirc :after
+              (defun enable-rcirc-track-minor-mode (&rest _)
+                (rcirc-track-minor-mode 1)))
+
+  (add-hook 'rcirc-mode-hook #'chat/setup)
+  (add-hook 'rcirc-mode-hook #'rcirc-omit-mode)
+
+  ;; "Fix" some things
+  (setf rcirc-implemented-capabilities
+        ;; I don't use these, and they mess up display in a few of my chats
+        (delete "message-tags" rcirc-implemented-capabilities))
+
+  ;; Adding servers more better-er
+  (defun rcirc-add-server (name &rest spec)
+    "Add a server to `rcirc-server-alist' and `rcirc-authinfo' at once.
+TODO: fully document"
+    (let ((name* (if (plist-get spec :host)
+                     (plist-get spec :host)
+                   name))
+          (nick (or (plist-get spec :nick)
+                    (bound-and-true-p rcirc-default-nick)
+                    (bound-and-true-p user-login-name)))
+          (user-name (or (plist-get spec :user-name)
+                         (plist-get spec :user)
+                         (plist-get spec :nick)
+                         (bound-and-true-p rcirc-default-user-name)
+                         (bound-and-true-p rcirc-default-nick)
+                         (bound-and-true-p user-login-name)))
+          (password (let ((password (or (plist-get spec :password)
+                                        (plist-get spec :pass))))
+                      ;; (cond
+                      ;;  ((functionp password) (funcall password))
+                      ;;  ((stringp password) password))
+                      password
+                      )))
+      ;; Add the server to `rcirc-server-alist'
+      (setf (alist-get name* rcirc-server-alist nil nil #'equal)
+            (append
+             (list :nick nick
+                   :user-name user-name)
+             (when password (list :password password))
+             (when-let ((full-name (plist-get spec :full-name)))
+               (list :full-name full-name))
+             (when-let ((channels (plist-get spec :channels)))
+               (list :channels channels))
+             (when-let ((port (plist-get spec :port)))
+               (list :port port))
+             (when-let ((encryption (plist-get spec :encryption)))
+               (list :encryption encryption))
+             (when-let ((server-alias (or (plist-get spec :server-alias)
+                                          (and (plist-get spec :host)
+                                               name))))
+               (list :server-alias server-alias))))
+      ;; Add it to `rcirc-authinfo'
+      (when-let ((auth (plist-get spec :auth)))
+        (unless password (user-error "Trying to auth without a password"))
+        (setf (alist-get name* rcirc-authinfo nil nil #'equal)
+              (cl-case auth
+                (nickserv (list 'nickserv nick password))
+                (bitlbee (list 'bitlbee nick password))
+                (quakenet (list 'quakenet user-name password))
+                (sasl (list 'sasl user-name password))
+                ;; (chanserv)  ; These two aren't supported.
+                ;; (certfp)
+                (t (user-error "Unsupported :auth type `%s'"
+                               (plist-get plist :auth))))))
+      ;; Return the server's name so that we don't leak authinfo
+      name))
+
+  (defun rcirc-resolve-passwords (&rest _)
+    (dolist-with-progress-reporter (s rcirc-server-alist)
+        "Resolving lambda passwords in `rcirc-server-alist...'"
+      (let ((pw (plist-get (cdr s) :password)))
+        (setf (plist-get (cdr s) :password)
+              (if (functionp pw) (funcall pw) pw))))
+    (dolist-with-progress-reporter (i rcirc-authinfo)
+        "Resolving lambda passwords in `rcirc-authinfo...'"
+      (let ((pw (cadddr i)))
+        (setf (cadddr i)
+              (if-let ((s (assoc (car i) rcirc-server-alist)))
+                  (plist-get (cdr s) :password)
+                (if (functionp pw) (funcall pw) pw))))))
+
+  (advice-add 'rcirc :before #'rcirc-resolve-passwords)
+
+  (defun rcirc/password (&rest spec)
+    (lambda () (auth-info-password (car (apply #'auth-source-search spec)))))
+
+  (setq rcirc-server-alist nil)
+
+  (rcirc-add-server "tilde.town"
+                    :host "localhost" :port 6969
+                    :channels '("#tildetown" "#newbirc")
+                    :auth 'sasl
+                    :password
+                    (rcirc/password :host "localhost:6969" :user "acdw"))
+  ;; (rcirc-add-server "43beans.casa"
+  ;;                   :host "localhost" :port 6970
+  ;;                   :channels '("#beans")
+  ;;                   :auth nil
+  ;;                   :password nil)
+  (rcirc-add-server "tilde.chat"
+                    :host "irc.tilde.chat" :port 6697 :encryption 'tls
+                    ;; :channels left blank.  There's some kind of race
+                    ;; condition in SASL and identd that means I authenticate
+                    ;; before being fully authenticated?  Or something.
+                    ;; Tilde.chat's NickServ does autojoin, though, so that
+                    ;; works out without an afternoon of debugging.
+                    :auth 'sasl
+                    :password (rcirc/password :host "tilde.chat" :user "acdw"))
+  (rcirc-add-server "m455.casa"
+                    :port 6697 :encryption 'tls
+                    :channels '("#basement" "#43beans")
+                    :auth 'sasl
+                    :password (rcirc/password :host "m455.casa" :user "acdw"))
+  (rcirc-add-server "libera.chat"
+                    :host "irc.libera.chat" :port 6697 :encryption 'tls
+                    :channels '("#emacs" "#rcirc")
+                    :auth 'sasl
+                    :password (rcirc/password :host "libera.chat" :user "acdw"))
+  ;; End of rcirc configuration.
+  )
diff --git a/user-dirs.dirs b/user-dirs.dirs
index 385533d..55d1c70 100644
--- a/user-dirs.dirs
+++ b/user-dirs.dirs
@@ -1,16 +1,15 @@
-# -*- sh -*-
 # This file is written by xdg-user-dirs-update
 # If you want to change or add directories, just edit the line you're
 # interested in. All local changes will be retained on the next run.
 # Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped
 # homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an
 # absolute path. No other format is supported.
-#
+# 
 XDG_DESKTOP_DIR="$HOME/var/desk"
 XDG_DOCUMENTS_DIR="$HOME/var/doc"
 XDG_DOWNLOAD_DIR="$HOME/var/download"
 XDG_MUSIC_DIR="$HOME/var/music"
 XDG_PICTURES_DIR="$HOME/var/img"
-XDG_PUBLICSHARE_DIR="$HOME/var/public"
-XDG_TEMPLATES_DIR="$HOME/var/templ"
+XDG_PUBLICSHARE_DIR="$HOME/"
+XDG_TEMPLATES_DIR="$HOME/"
 XDG_VIDEOS_DIR="$HOME/var/video"
-- 
cgit 1.4.1-21-gabe81