From df207947bae8f29dce49815587436cde9f49ebed Mon Sep 17 00:00:00 2001
From: Case Duckworth
Date: Thu, 23 Sep 2021 17:11:30 -0500
Subject: blehhaheoi

---
 init.el      | 540 ++++++++++++++++++++++++-----------------------------------
 lisp/acdw.el | 132 ++++++++++++++-
 2 files changed, 348 insertions(+), 324 deletions(-)

diff --git a/init.el b/init.el
index 48f3d39..d8e9bf0 100644
--- a/init.el
+++ b/init.el
@@ -21,7 +21,10 @@
 ;; NOTE that some of the names in `setup' forms are arbitrary.
 
 (setup (:require auth-source)
-  (:option auth-sources '("~/.authinfo" "~/.authinfo.gpg")))
+  (:option auth-sources (list (acdw/sync-dir "authinfo")
+                              (acdw/sync-dir "authinfo.gpg")
+                              "~/.authinfo"
+                              "~/.authinfo.gpg")))
 
 (setup (:require goto-addr)
   (if (fboundp #'global-goto-address-mode)
@@ -181,7 +184,25 @@ In short, DO NOT USE THIS FUNCTION!!!"
   (acdw/add-button-url-regexp-protocol "gemini"))
 
 (setup buffers
-  (:global "C-x k" #'acdw/kill-a-buffer))
+  (:global "C-x k" #'acdw/kill-a-buffer)
+  (defun buffer-list-update@set-major-mode ()
+    "Set `major-mode' from buffer name, even when not visiting a file."
+    (let ((name (buffer-name)))
+      (unless (or (active-minibuffer-window)
+                  (string-prefix-p "*" name)
+                  (not (eq major-mode 'fundamental-mode)))
+        (catch 'done
+          (dolist (cell auto-mode-alist)
+            (let ((regexp (car cell))
+                  (mode (cdr cell)))
+              (when (string-match regexp name)
+                (let ((major-mode mode))
+                  (funcall mode))
+                (throw 'done mode))))))))
+
+  ;; TODO: more testing, just in case.
+  ;;(add-hook 'buffer-list-update-hook #'buffer-list-update@set-major-mode)
+  )
 
 (setup calendar
   (:option calendar-week-start-day 1))
@@ -189,35 +210,24 @@ In short, DO NOT USE THIS FUNCTION!!!"
 (setup (:straight circe)
   (require 'circe)
   (require 'acdw-irc)
-  
-  (:option acdw-irc/left-margin 12
+
+  (:option acdw-irc/left-margin 20
            acdw-irc/post-my-nick "-> "
            circe-channel-killed-confirmation nil
            circe-color-nicks-everywhere t
            circe-default-nick "acdw"
            circe-default-part-message "See You, Space Cowpokes . . ."
            circe-default-user "acdw"
-           circe-format-action
-           (lambda (&rest plist)
-             (concat
-              (acdw-irc/margin-format "" "*" "*" t)
-              " " (plist-get plist :nick) " " (plist-get plist :body)))
-           circe-format-say
-           (lambda (&rest plist)
-             (concat
-              (acdw-irc/margin-format (plist-get plist :nick) "" " |" t)
-              " " (plist-get plist :body)))
-           circe-format-self-action
-           (lambda (&rest plist)
-             (concat
-              (acdw-irc/margin-format "" "-*" " *" t)
-              " " (plist-get plist :nick) " " (plist-get plist :body)))
-           circe-format-self-say
-           (lambda (&rest plist)
-             (concat
-              (acdw-irc/margin-format (plist-get plist :nick) "-" " >" t)
-              " " (plist-get plist :body)))
-           ;; circe-highlight-nick-type 'message
+           circe-format-action (format
+                                (format "%%%ds* {nick} {body}"
+                                        (- acdw-irc/left-margin 2)) " ")
+           circe-format-say (format
+                             "{nick:%1$d.%1$ds} | {body}"
+                             (- acdw-irc/left-margin 3))
+           circe-format-self-action circe-format-action
+           circe-format-self-say (format
+                                  "{nick:%1$d.%1$ds} > {body}"
+                                  (- acdw-irc/left-margin 3))
            circe-network-options
            `(("Libera Chat"
               :channels ("#emacs" "#systemcrafters" "##webpals")
@@ -226,7 +236,7 @@ In short, DO NOT USE THIS FUNCTION!!!"
                                :host "libera.chat"))
              ("Tilde Chat" :host "irc.tilde.chat" :port 6697 :use-tls t
               :channels ("#meta" "#bread" "#dadjokes" "#team"
-                         "#emacs")
+                         "#emacs" "#nsfw")
               :sasl-username ,circe-default-nick
               :sasl-password ,(acdw/make-password-fetcher
                                :host "tilde.chat"))
@@ -247,9 +257,12 @@ In short, DO NOT USE THIS FUNCTION!!!"
            circe-server-buffer-action (lambda (buf)
                                         (message "Connected to %s" buf)))
 
-  ;; (:face circe-nick-highlight-face
-  ;;        ((t (:inherit (modus-themes-hl-line)))))
-
+  (with-eval-after-load 'circe
+    (:face circe-nick-highlight-face
+           ((t (:inherit (modus-themes-hl-line modus-themes-bold))))
+           circe-my-message-face
+           ((t (:inherit (modus-themes-slant))))))
+  
   (:bind "C-c C-p" #'circe-command-PART
          "C-l" #'lui-track-jump-to-indicator)
 
@@ -280,7 +293,8 @@ In short, DO NOT USE THIS FUNCTION!!!"
                  (with-current-buffer buf
                    (dolist (buf (circe-server-chat-buffers))
                      (let ((circe-channel-killed-confirmation nil))
-                       (kill-buffer buf)))
+                       (kill-buffer buf))
+                     (cancel-timer 'irc-send--queue))
                    (message "%s: %s" buf circe-server-killed-confirmation)
                    (kill-buffer))))))
 
@@ -312,12 +326,13 @@ In short, DO NOT USE THIS FUNCTION!!!"
             #'circe-nick-color-reset)
 
   (:with-mode lui-mode
-    (:option lui-fill-column fill-column
+    (:option lui-fill-column (+ fill-column acdw-irc/left-margin)
              lui-fill-type (repeat-string acdw-irc/left-margin " ")
              lui-time-stamp-position 'right-margin
              lui-time-stamp-format "%H:%M"
              lui-track-behavior 'before-switch-to-buffer
-             lui-track-indicator 'fringe)
+             lui-track-indicator 'fringe
+             lui-fill-remove-face-from-newline nil)
 
     (:local-set fringes-outside-margins t
                 right-margin-width 5
@@ -374,8 +389,9 @@ In short, DO NOT USE THIS FUNCTION!!!"
              dired-collapse
              dired-git-info)
   
-  (:option dired-recursive-copies 'always
-           dired-recursive-deletes 'always
+  (:option dired-recursive-copies 'top
+           dired-recursive-deletes 'top
+           dired-create-destination-dirs 'ask
            delete-by-moving-to-trash t
            dired-listing-switches "-Al"
            ls-lisp-dirs-first t
@@ -433,24 +449,7 @@ In short, DO NOT USE THIS FUNCTION!!!"
   
   ;; And set the disabled function to something better than the default.
   ;; Now, I can run any disabled command, but I have to use M-x to do it.
-  (setq disabled-command-function
-        (defun acdw/disabled-command-function (&optional cmd keys)
-          (let ((cmd (or cmd this-command))
-                (keys (or keys (this-command-keys))))
-            ;; this logic stolen from original `disabled-command-function'
-            (if (or (eq (aref keys 0) (if (stringp keys)
-                                          (aref "\M-x" 0)
-                                        ?\M-x))
-                    (and (>= (length keys) 2)
-                         (eq (aref keys 0) meta-prefix-char)
-                         (eq (aref keys 1) ?x)))
-                ;; it's been run as an M-x command, we want to do it
-                (call-interactively cmd)
-              ;; else, tell the user it's disabled.
-              (message (substitute-command-keys
-                        (concat "Command `%s' has been disabled.  "
-                                "Run with \\[execute-extended-command]."))
-                       cmd))))))
+  (:option disabled-command-function #'acdw/disabled-command-function))
 
 (setup ediff
   (:option ediff-diff-options "-w" ; ignore whitespace
@@ -459,8 +458,6 @@ In short, DO NOT USE THIS FUNCTION!!!"
   ;; https://oremacs.com/2015/01/17/setting-up-ediff/
   (add-hook 'ediff-after-quit-hook-internal #'winner-undo))
 
-(setup (:straight edit-indirect))
-
 ;; requires extension:
 ;; https://addons.mozilla.org/en-US/firefox/addon/edit-with-emacs1/
 (setup (:straight edit-server)
@@ -487,6 +484,8 @@ In short, DO NOT USE THIS FUNCTION!!!"
   (:with-mode emacs-lisp-mode ;; -_-
     (:option eval-expression-print-length nil
              eval-expression-print-level nil
+             print-length nil
+             print-level nil
              lisp-indent-function #'lisp-indent-function)
 
     (:local-set (append imenu-generic-expression)
@@ -494,7 +493,7 @@ In short, DO NOT USE THIS FUNCTION!!!"
                   ,(rx (seq
                         (group bol (* space) "(setup" (+ space))
                         (? (group "(:" (+ graph) (* space) (? "(")))
-                        (group (+ (any word ?-)))))
+                        (group (+ (any word ?+ ?-)))))
                   3))
 
     (:hook #'checkdoc-minor-mode
@@ -522,6 +521,7 @@ In short, DO NOT USE THIS FUNCTION!!!"
   ;; else /should/ go there.
   (:option
    attempt-orderly-shutdown-on-fatal-signal nil
+   auto-hscroll-mode 'current-line
    attempt-stack-overflow-recovery nil
    echo-keystrokes 0.01
    find-function-C-source-directory (acdw/find-emacs-source)
@@ -544,10 +544,6 @@ In short, DO NOT USE THIS FUNCTION!!!"
     "A keymap for looking up things.")
   (global-set-key (kbd "C-c l") lookup-map)
 
-  (defvar toggle-map (make-sparse-keymap)
-    "A keymap for toggling!")
-  (global-set-key (kbd "C-c t") toggle-map)
-
   (:global "M-=" #'count-words
            "C-w" #'kill-region-or-backward-word
            "C-c d" #'acdw/insert-iso-date
@@ -557,11 +553,26 @@ In short, DO NOT USE THIS FUNCTION!!!"
            "C-c _" #'add-file-local-variable
            "C-x C-c" #'acdw/fat-finger-exit)
 
+  ;; inspo: https://github.com/zaeph/.emacs.d/blob/master/init.el#L479
+  (defvar toggle-map (make-sparse-keymap)
+    "A keymap for toggling!")
+  (global-set-key (kbd "C-c t") toggle-map)
+
   (:with-map toggle-map
     (:bind "c" #'column-number-mode
            "l" #'display-line-numbers-mode
-           "d" #'toggle-debug-on-error))
+           "d" #'toggle-debug-on-error
+           "s" #'so-long-mode
+           "S" #'scroll-bar-mode))
+
+  ;; Toggle
+  (:with-map toggle-map
+    (:bind "b" (defun acdw/toggle-lexical-binding ()
+                 "Toggle `lexical-binding' in the current buffer."
+                 (interactive)
+                 (setq lexical-binding (not lexical-binding)))))
 
+  
   (:with-map case-map
     (require 'titlecase)
     (:bind "c" #'capitalize-dwim
@@ -796,7 +807,7 @@ specific to most general, they are these:
            word-wrap t
            truncate-lines nil)
 
-  (global-display-fill-column-indicator-mode +1)
+  (global-display-fill-column-indicator-mode -1)
   (global-so-long-mode +1)
 
   (add-hook 'visual-line-mode-hook
@@ -837,6 +848,17 @@ specific to most general, they are these:
       (fset 'yes-or-no-p #'y-or-n-p)
     (setq use-short-answers t)))
 
+(setup mouse
+  ;; Unconditionally follow links when clicked.
+  ;; This is because mouse-1 usually sets point.
+  ;; Other options:
+  ;; +[ms] -> perform mouse-2 until held for [ms], then mouse-1
+  ;; -[ms] -> perform mouse-1 until held for [ms], then mouse-2
+  ;; 'double -> mouse-2 on double click
+  ;; nil -> mouse-1 never follows link
+  ;; <anything> -> mouse-1 /always/ follows link
+  (:option mouse-1-click-follows-link t))
+
 (setup mouse-avoidance
   (mouse-avoidance-mode 'exile))
 
@@ -869,24 +891,6 @@ specific to most general, they are these:
   ;; (put 'backward-page 'repeat-map 'page-navigation-repeat-map)
   )
 
-(setup prog
-  (:option show-paren-delay 0
-           show-paren-style 'mixed
-           show-paren-when-point-inside-paren t
-           show-paren-when-point-in-periphery t
-           smie-indent-basic tab-width)
-  
-  (:hook show-paren-mode
-         electric-pair-local-mode
-         acdw/setup-fringes       
-
-         (defun prog-mode@auto-fill ()
-           (setq-local comment-auto-fill-only-comments t)
-           (turn-on-auto-fill)))
-
-  (add-hook 'after-save-hook
-            #'executable-make-buffer-file-executable-if-script-p))
-
 (setup repeat
   ;; new for Emacs 28!
   (:only-if (fboundp #'repeat-mode))
@@ -1153,146 +1157,6 @@ specific to most general, they are these:
   (:with-feature isearch
     (:bind "C-'" #'avy-isearch)))
 
-(setup (:straight circe)
-  (require 'circe)
-  (require 'acdw-irc)
-  
-  (:option acdw-irc/left-margin 12
-           acdw-irc/post-my-nick "-> "
-           circe-channel-killed-confirmation nil
-           circe-color-nicks-everywhere t
-           circe-default-nick "acdw"
-           circe-default-part-message "See You, Space Cowpokes . . ."
-           circe-default-user "acdw"
-           circe-format-action
-           (lambda (&rest plist)
-             (concat
-              (acdw-irc/margin-format "" "*" "*" t)
-              " " (plist-get plist :nick) " " (plist-get plist :body)))
-           circe-format-say
-           (lambda (&rest plist)
-             (concat
-              (acdw-irc/margin-format (plist-get plist :nick) "" " |" t)
-              " " (plist-get plist :body)))
-           circe-format-self-action
-           (lambda (&rest plist)
-             (concat
-              (acdw-irc/margin-format "" "-*" " *" t)
-              " " (plist-get plist :nick) " " (plist-get plist :body)))
-           circe-format-self-say
-           (lambda (&rest plist)
-             (concat
-              (acdw-irc/margin-format (plist-get plist :nick) "-" " >" t)
-              " " (plist-get plist :body)))
-           ;; circe-highlight-nick-type 'message
-           circe-network-options
-           `(("Libera Chat"
-              :channels ("#emacs" "#systemcrafters" "##webpals")
-              :sasl-username ,circe-default-nick
-              :sasl-password ,(acdw/make-password-fetcher
-                               :host "libera.chat"))
-             ("Tilde Chat" :host "irc.tilde.chat" :port 6697 :use-tls t
-              :channels ("#meta" "#bread" "#dadjokes" "#team"
-                         "#emacs")
-              :sasl-username ,circe-default-nick
-              :sasl-password ,(acdw/make-password-fetcher
-                               :host "tilde.chat"))
-             ("Casa" :host "m455.casa" :port 6697 :use-tls t
-              :channels ("#basement")
-              :sasl-username ,circe-default-nick
-              :sasl-password ,(acdw/make-password-fetcher
-                               :host "m455.casa"))
-             ("Pissnet" :host "piss.hmm.st" :port 6697 :use-tls t
-              :channels ("#i-just-peed")
-              :sasl-username ,circe-default-nick
-              :sasl-password ,(acdw/make-password-fetcher
-                               :host "piss.hmm.st"))
-             ;; TODO: irc.chat.twitch.tv
-             )
-           circe-reduce-lurker-spam t
-           circe-server-auto-join-default-type :after-auth)
-
-  ;; (:face circe-nick-highlight-face
-  ;;        ((t (:inherit (modus-themes-hl-line)))))
-
-  (:bind "C-c C-p" #'circe-command-PART
-         "C-l" #'lui-track-jump-to-indicator)
-
-  (:advise circe-command-PART :after
-           (defun circe-part@kill-buffer (&rest _)
-             (let ((circe-channel-killed-confirmation nil))
-               (kill-buffer)))
-
-           circe-command-QUIT :after
-           (defun circe-quit@kill-buffer (&rest _)
-             ;; `circe-server-killed-confirmation' set to nil, and manually
-             ;; deleting all chat buffers, pending Github issue #402
-             ;; (https://github.com/emacs-circe/circe/issues/402)
-             (let ((circe-server-killed-confirmation nil))
-               (with-circe-server-buffer
-                 (dolist (buf (circe-server-chat-buffers))
-                   (let ((circe-channel-killed-confirmation nil))
-                     (kill-buffer buf)))
-                 (kill-buffer))))
-
-           circe-command-GQUIT :after
-           (defun circe-gquit@kill-buffer (&rest _)
-             ;; `circe-server-killed-confirmation' set to nil, and manually
-             ;; deleting all chat buffers, pending Github issue #402
-             ;; (https://github.com/emacs-circe/circe/issues/402)
-             (let ((circe-server-killed-confirmation nil))
-               (dolist (buf (circe-server-buffers))
-                 (with-current-buffer buf
-                   (dolist (buf (circe-server-chat-buffers))
-                     (let ((circe-channel-killed-confirmation nil))
-                       (kill-buffer buf)))
-                   (message "%s: %s" buf circe-server-killed-confirmation)
-                   (kill-buffer))))))
-
-  (defun circe-command-SHORTEN (url)
-    "Shorten URL using `0x0-shorten-uri'."
-    (interactive "sURL to shorten: ")
-    ;; TODO: enable /shorten URL comment syntax
-    (let ((short-url (0x0-shorten-uri (0x0--choose-server) url)))
-      (circe-command-SAY short-url)))
-
-  (:with-mode circe-chat-mode
-    (:hook  #'acdw/stop-paren-annoyances
-            #'enable-circe-color-nicks
-            #'enable-circe-display-images
-            #'enable-circe-new-day-notifier
-            (defun circe-chat@set-prompt ()
-              (lui-set-prompt
-               (concat
-                (propertize
-                 (acdw-irc/margin-format (buffer-name) "" ">")
-                 'face 'circe-prompt-face
-                 'read-only t
-                 'intangible t
-                 'cursor-intangible t)
-                " ")))))
-
-  (autoload 'circe-nick-color-reset "circe-color-nicks")
-  (add-hook 'modus-themes-after-load-theme-hook
-            #'circe-nick-color-reset)
-
-  (:with-mode lui-mode
-    (:option lui-fill-column fill-column
-             lui-fill-type (repeat-string acdw-irc/left-margin " ")
-             lui-time-stamp-position 'right-margin
-             lui-time-stamp-format "%H:%M"
-             lui-track-behavior 'before-switch-to-buffer
-             lui-track-indicator 'fringe)
-
-    (:local-set fringes-outside-margins t
-                right-margin-width 5
-                scroll-margin 0
-                word-wrap t
-                wrap-prefix (repeat-string acdw-irc/left-margin " ")
-                line-number-mode nil)
-    
-    (:hook #'enable-lui-track)))
-
 (setup (:straight (consult
                    :host github
                    :repo "minad/consult"))
@@ -1437,24 +1301,6 @@ specific to most general, they are these:
 
 (setup (:straight edit-indirect))
 
-;; requires extension:
-;; https://addons.mozilla.org/en-US/firefox/addon/edit-with-emacs1/
-(setup (:straight edit-server)
-  (:require edit-server)
-  (edit-server-start)
-
-  (:option edit-server-default-major-mode 'text-mode
-           edit-server-url-major-mode-alist
-           (list (cons (rx (| "reddit.com"
-                              "tildes.net"))
-                       'markdown-mode)
-                 (cons (rx "github.com")
-                       'gfm-mode)))
-
-  (:advise edit-server-make-frame :before
-           (defun edit-server@set-a-variable (&rest _)
-             (setq-local edit-server-frame-p t))))
-
 (setup (:straight (electric-cursor
                    :host github
                    :repo "duckwork/electric-cursor"))
@@ -1688,28 +1534,14 @@ specific to most general, they are these:
   (defvar helpful-pre-windows nil
     "Window configuration /before/ helpful was called.")
   
-  (:option helpful-switch-buffer-function
-           (defun helpful-pop-to-buffer (&rest args)
-             (if (eq major-mode 'helpful-mode)
-                 (apply #'pop-to-buffer-same-window args)
-               (require 'winner)
-               (setq helpful-pre-windows (winner-conf))
-               (apply #'pop-to-buffer args))))
+  (:option helpful-switch-buffer-function #'pop-to-buffer)
   
   (:global "<help> f" #'helpful-callable
            "<help> v" #'helpful-variable
            "<help> k" #'helpful-key
            "<help> o" #'helpful-symbol)
 
-  (:bind "q" (defun helpful-quit ()
-               (interactive)
-               (when (eq major-mode 'helpful-mode)
-                 (quit-window)
-                 (unless (or (= 1 (count-windows))
-                             (eq major-mode 'helpful-mode))
-                   (delete-window)
-                   (ignore-errors
-                     (winner-set helpful-pre-windows)))))))
+  (:bind "q" #'quit-window))
 
 (setup (:straight hungry-delete)
   (:option hungry-delete-chars-to-skip " \t"
@@ -1849,11 +1681,12 @@ browser defined in `browse-url-secondary-browser-function'."
 
 (setup (:straight (mastodon
                    :host github
-                   :repo "mooseyboots/mastodon.el")
-                  request)
+                   :repo "mooseyboots/mastodon.el"))
   (:option mastodon-instance-url "https://writing.exchange"
            mastodon-auth-source-file (car auth-sources)
-           mastodon-client--token-file (acdw/dir "mastodon.plstore"))
+           mastodon-client--token-file (acdw/dir "mastodon.plstore")
+           mastodon-tl--enable-proportional-fonts t
+           mastodon-tl--enable-relative-timestamps nil)
 
   (:hook #'hl-line-mode
          #'reading-mode))
@@ -1870,7 +1703,14 @@ browser defined in `browse-url-secondary-browser-function'."
            modus-themes-mode-line nil)
   
   (acdw/sunrise-sunset #'modus-themes-load-operandi
-                       #'modus-themes-load-vivendi))
+                       #'modus-themes-load-vivendi)
+
+  (add-hook 'modus-themes-after-load-theme-hook
+            (defun modus-themes@customize-faces ()
+              "Customize faces of modus-themes."
+              (custom-set-faces
+               '(org-tag
+                 ((t (:height 90 :slant italic :inherit org-tag))))))))
 
 (setup (:straight mwim)
   (:global "C-a" #'mwim-beginning
@@ -1949,13 +1789,16 @@ browser defined in `browse-url-secondary-browser-function'."
 
 (setup (:straight org
                   org-contrib)
-  (:also-load acdw-org)                 ; so I don't clutter up init.el
+  (:also-load acdw-org                 ; so I don't clutter up init.el
+              chd)
   (:option
    org-adapt-indentation nil
    org-agenda-files nil                 ; only until I set this up
    org-catch-invisible-edits 'show-and-error
-   org-clock-clocked-in-display 'mode-line
-   org-clock-string-limit 7             ; gives time and not title
+   org-clock-clocked-in-display 'frame-title
+   org-clock-frame-title-format (cons '(t org-mode-line-string)
+                                      (cons " --- " frame-title-format))
+   ;;org-clock-string-limit 7             ; gives time and not title
    org-confirm-babel-evaluate nil
    org-cycle-separator-lines 0
    org-directory "~/org"
@@ -1976,6 +1819,7 @@ browser defined in `browse-url-secondary-browser-function'."
    org-list-demote-modify-bullet '(("-" . "+")
                                    ("+" . "*")
                                    ("*" . "-"))
+   org-log-into-drawer t
    org-outline-path-complete-in-steps nil
    org-pretty-entities t
    org-refile-use-outline-path 'file
@@ -1993,7 +1837,7 @@ browser defined in `browse-url-secondary-browser-function'."
          "<S-return>" #'acdw-org/org-table-copy-down
          "M-SPC M-SPC" #'insert-zero-width-space
          "C-c C-l" #'org-insert-link-dwim
-         "M-w" #'acdw/copy-region-plain
+         "C-c w" #'chd/do-the-thing
          "C-c C-n" #'acdw/org-next-heading-widen
          "C-c C-p" #'acdw/org-previous-heading-widen)
 
@@ -2026,9 +1870,50 @@ browser defined in `browse-url-secondary-browser-function'."
                                              end
                                              999)))))
   
-  (:advise org-delete-backward-char :override #'acdw-org/delete-backward-char))
+  (:advise org-delete-backward-char :override #'acdw-org/delete-backward-char)
+
+  (el-patch-feature org)
+  (with-eval-after-load 'org
+    (el-patch-defun org-format-outline-path (path &optional width prefix separator)
+      "Format the outline path PATH for display.
+WIDTH is the maximum number of characters that is available.
+PREFIX is a prefix to be included in the returned string,
+such as the file name.
+SEPARATOR is inserted between the different parts of the path,
+the default is \"/\"."
+      (setq width (or width 79))
+      (setq path (delq nil path))
+      (unless (> width 0)
+        (user-error "Argument `width' must be positive"))
+      (setq separator (or separator "/"))
+      (let* ((org-odd-levels-only nil)
+	         (fpath (concat
+		             prefix (and prefix path separator)
+		             (mapconcat
+		              (lambda (s) (replace-regexp-in-string "[ \t]+\\'" "" s))
+		              (cl-loop for head in path
+			                   for n from 0
+			                   collect (el-patch-swap
+                                         (org-add-props
+				                             head nil '`face
+				                             (nth (% n org-n-level-faces) org-level-faces))
+                                         head))
+		              separator))))
+        (when (> (length fpath) width)
+          (if (< width 7)
+	          ;; It's unlikely that `width' will be this small, but don't
+	          ;; waste characters by adding ".." if it is.
+	          (setq fpath (substring fpath 0 width))
+	        (setf (substring fpath (- width 2)) "..")))
+        fpath))))
 
 (setup (:straight org-appear)
+  (:option org-appear-autoemphasis t
+           org-appear-autoentities t
+           org-appear-autokeywords t
+           org-appear-autolinks nil
+           org-appear-autosubmarkers t
+           org-appear-delay 0)
   (:hook-into org-mode))
 
 (setup (:straight package-lint))
@@ -2047,7 +1932,8 @@ browser defined in `browse-url-secondary-browser-function'."
     (:with-map lisp-mode-shared-map
       (:bind "DEL" #'paredit-backward-delete
              "C-M-;" #'comment-or-uncomment-sexp
-             "C-<backspace>" #'paredit-backward-kill-word))
+             "C-<backspace>" #'paredit-backward-kill-word
+             "M-w" #'paredit-copy-as-kill))
     (paredit-mode +1))
 
   (dolist (mode lispy-modes)
@@ -2078,20 +1964,8 @@ browser defined in `browse-url-secondary-browser-function'."
           (with-current-buffer buf
             (when (funcall persistent-scratch-scratch-buffer-p-function)
               (persistent-scratch-mode +1))))
-
         (buffer-list)))
 
-(setup (:straight-if pkgbuild-mode
-                     (executable-find "makepkg"))
-  (:file-match "PKGBUILD"))
-
-(setup (:straight powerthesaurus)
-  (:global "C-c l t" #'powerthesaurus-lookup-word-dwim))
-
-;; (setup (:straight prism)
-;;   (dolist (mode lispy-modes)
-;;     (add-hook (intern (format "%s-hook" mode)) #'prism-mode)))
-
 (setup prog
   (:option show-paren-delay 0
            show-paren-style 'mixed
@@ -2107,12 +1981,8 @@ browser defined in `browse-url-secondary-browser-function'."
            (setq-local comment-auto-fill-only-comments t)
            (turn-on-auto-fill)))
 
-  (mapc (lambda (buf)
-          (with-current-buffer buf
-            (when (funcall persistent-scratch-scratch-buffer-p-function)
-              (persistent-scratch-mode +1))))
-
-        (buffer-list)))
+  (add-hook 'after-save-hook
+            #'executable-make-buffer-file-executable-if-script-p))
 
 (setup (:straight-if pkgbuild-mode
                      (executable-find "makepkg"))
@@ -2121,19 +1991,15 @@ browser defined in `browse-url-secondary-browser-function'."
 (setup (:straight powerthesaurus)
   (:global "C-c l t" #'powerthesaurus-lookup-word-dwim))
 
-(setup (:straight prism)
-  (dolist (mode lispy-modes)
-    (add-hook (intern (format "%s-hook" mode)) #'prism-mode)))
-
-(setup (:straight restart-emacs)
-  (defun emacs-upgrade (&optional update-packages)
-    "Pull config, upgrade packages, restart Emacs."
-    (interactive "P")
-    (emacs-git-pull-config)
-    (when update-packages
-      (require 'straight-x)
-      (straight-x-pull-all))
-    (restart-emacs)))
+1(setup (:straight restart-emacs)
+   (defun emacs-upgrade (&optional update-packages)
+     "Pull config, upgrade packages, restart Emacs."
+     (interactive "P")
+     (emacs-git-pull-config)
+     (when update-packages
+       (require 'straight-x)
+       (straight-x-pull-all))
+     (restart-emacs)))
 
 (setup (:straight (shell-command+
                    :host nil
@@ -2169,21 +2035,22 @@ browser defined in `browse-url-secondary-browser-function'."
            tab-bar-show 1)
 
   ;; I've put in a pull request to add the (- 0 right-margin) bit here.
-  (:advise simple-modeline--format :override
-           (defun simple-modeline@format (lefts rights)
-             (let* ((left (simple-modeline--format-segments lefts))
-                    (right (simple-modeline--format-segments rights))
-                    (reserve (length right)))
-               (concat
-                left
-                (propertize " "
-                            'display `((space :align-to
-                                              (- right
-                                                 (- 0 right-margin)
-                                                 ,reserve)))
-                            'face '(:inherit simple-modeline-space))
-                right))))
-
+  (el-patch-feature simple-modeline)
+  (with-eval-after-load 'simple-modeline
+    (el-patch-defun simple-modeline--format (left-segments right-segments)
+      "Return a string of `window-width' length containing LEFT-SEGMENTS and RIGHT-SEGMENTS, aligned respectively."
+      (let* ((left (simple-modeline--format-segments left-segments))
+             (right (simple-modeline--format-segments right-segments))
+             (reserve (length right)))
+        (concat
+         left
+         (propertize " "
+                     'display (el-patch-swap
+                                `(space :align-to (- right ,reserve))
+                                `(space :align-to (- right (- 0 right-margin) ,reserve)))
+                     'face '(:inherit simple-modeline-space))
+         right))))
+  
   (simple-modeline-mode +1))
 
 (setup (:straight-if sly
@@ -2304,14 +2171,14 @@ If used with a numeric prefix argument N, N backticks will be inserted."
            vertico-count-format nil
            vertico-cycle t)
   
-  (:with-map vertico-map
-    (:bind "<C-backspace>"
-           (defun up-directory (arg)
-             "Move up a directory (delete backwards to /)."
-             (interactive "p")
-             (if (string-match-p "/." (minibuffer-contents))
-                 (zap-up-to-char (- arg) ?/)
-               (backward-kill-word arg)))))
+  ;; (:with-map vertico-map
+  ;;   (:bind "<C-backspace>"
+  ;;          (defun up-directory (arg)
+  ;;            "Move up a directory (delete backwards to /)."
+  ;;            (interactive "p")
+  ;;            (if (string-match-p "/." (minibuffer-contents))
+  ;;                (zap-up-to-char (- arg) ?/)
+  ;;              (backward-kill-word arg)))))
 
   (when (boundp 'native-comp-deferred-compilation-deny-list)
     (add-to-list 'native-comp-deferred-compilation-deny-list "vertico"))
@@ -2319,9 +2186,15 @@ If used with a numeric prefix argument N, N backticks will be inserted."
   (vertico-mode +1)
 
   ;; Extensions!
-  (:also-load vertico-mouse)
+  (:also-load vertico-mouse
+              vertico-directory)
   (vertico-mouse-mode +1)
-
+  (:with-map vertico-map
+    (:bind "RET" #'vertico-directory-enter
+           "DEL" #'vertico-directory-delete-char
+           "M-DEL" #'vertico-directory-delete-word))
+  (add-hook 'rfn-eshadow-update-overlay-hook #'vertico-directory-tidy)
+  
   ;; Prefix the current candidate with "> ".  From Vertico wiki.
   (:advise vertico--format-candidate :around
            (defun vertico-format@add-arrow (orig cand pref suf index start)
@@ -2345,7 +2218,12 @@ If used with a numeric prefix argument N, N backticks will be inserted."
 (setup (:straight wc-mode)
   (:option wc-modeline-format "[%tww]"
            wc-idle-wait 2)
-  (:hook-into text-mode))
+  (:hook-into text-mode)
+  (:unbind "C-c C-w a"
+           "C-c C-w c"
+           "C-c C-w l"
+           "C-c C-w w"
+           "C-c C-w"))
 
 (setup (:straight web-mode)
   (:option css-level-offset 2
@@ -2413,5 +2291,27 @@ If used with a numeric prefix argument N, N backticks will be inserted."
                  (call-interactively #'zzz-to-char)
                (call-interactively #'zzz-up-to-char)))))
 
+(setup (:straight dictionary)
+  (:option dictionary-use-single-buffer t)
+  
+  (autoload 'dictionary-search "dictionary"
+    "Ask for a word and search it in all dictionaries" t)
+  (autoload 'dictionary-match-words "dictionary"
+    "Ask for a word and search all matching words in the dictionaries" t)
+  (autoload 'dictionary-lookup-definition "dictionary"
+    "Unconditionally lookup the word at point." t)
+  (autoload 'dictionary "dictionary"
+    "Create a new dictionary buffer" t)
+  (autoload 'dictionary-mouse-popup-matching-words "dictionary"
+    "Display entries matching the word at the cursor" t)
+  (autoload 'dictionary-popup-matching-words "dictionary"
+    "Display entries matching the word at the point" t)
+  (autoload 'dictionary-tooltip-mode "dictionary"
+    "Display tooltips for the current word" t)
+  (autoload 'global-dictionary-tooltip-mode "dictionary"
+    "Enable/disable dictionary-tooltip-mode for all buffers" t)
+  
+  (:with-map lookup-map
+    (:bind "d" #'dictionary-search)))
 
 ;;; init.el ends here
diff --git a/lisp/acdw.el b/lisp/acdw.el
index dcf7b19..b146f58 100644
--- a/lisp/acdw.el
+++ b/lisp/acdw.el
@@ -323,6 +323,43 @@ with `string<' starting with the key determined by KEY-FN."
                         (insert-before-markers real)
                         (delete-region (point) (marker-position end)))))))))
 
+(defun acdw/sort-setups ()
+  "Sort `setup' forms in the current buffer.
+Actually sorts all forms, but based on the logic of `setup'.
+In short, DO NOT USE THIS FUNCTION!!!"
+  (save-excursion
+    (sort-sexps
+     (point-min) (point-max)
+     (lambda (sexp)
+       (format "%S" (cadr sexp)))
+     (lambda (s1 s2)                  ; oh god, this is worse.
+       (let* ((s1 (cdr s1)) (s2 (cdr s2)) ; for the strings themselves
+              (s1-require (string-match ":require" s1))
+              (s2-require (string-match ":require" s2))
+              (s1-straight (string-match ":straight" s1))
+              (s2-straight (string-match ":straight" s2))
+              (s1-bare (not (or s1-require s1-straight)))
+              (s2-bare (not (or s2-require s2-straight))))
+         (cond
+          ;; if both are the same, sort regular style
+          ((or (and s1-require s2-require)
+               (and s1-bare s2-bare))
+           (string< s1 s2))
+          ((and s1-straight s2-straight)
+           (let* ((r (rx ":straight" (? "-if") (* space) (? "(")))
+                  (s1 (replace-regexp-in-string r "" s1))
+                  (s2 (replace-regexp-in-string r "" s2)))
+             (message "'%S' '%S'" s1 s2)
+             (string< s1 s2)))
+          ;; requires should go first
+          ((and s1-require (not s2-require)) t)
+          ((and (not s1-require) s2-require) nil)
+          ;; straights should go last
+          ((and s1-straight (not s2-straight)) nil)
+          ((and (not s1-straight) s2-straight) t)
+          ;; else, just sort em.
+          (t (string< s1 s2))))))))
+
 
 ;;; Emacs configuration functions
 
@@ -402,6 +439,59 @@ first."
   (setq deactivate-mark t)
   nil)
 
+;; https://emacs.stackexchange.com/questions/36366/
+(defun html-body-id-filter (output backend info)
+  "Remove random ID attributes generated by Org."
+  (when (eq backend 'html)
+    (replace-regexp-in-string
+     " id=\"[[:alpha:]-]*org[[:alnum:]]\\{7\\}\""
+     ""
+     output t)))
+
+(defun html-body-div-filter (output backend info)
+  "Remove wrapping divs generated by Org."
+  (when (eq backend 'html)
+    (replace-regexp-in-string
+     "</?div[^>]*>\n*" ""
+     output t)))
+
+(defun org-demote-headings (backend)
+  (while (/= (point) (point-max))
+    (org-next-visible-heading 1)
+    (org-demote-subtree)))
+
+(defun acdw/org-export-copy-html ()
+  "Copy a tree as HTML."
+  (interactive)
+  (require 'ox-html)
+  (org-export-with-buffer-copy
+   ;; (add-hook 'org-export-before-parsing-hook #'org-demote-headings nil t)
+   (let ((extracted-heading (acdw/org-extract-heading-text))
+         (org-export-show-temporary-export-buffer nil)
+         (org-export-filter-final-output-functions
+          '(html-body-id-filter html-body-div-filter))
+         (org-export-with-smart-quotes nil)
+         (org-export-smart-quotes-alist nil))
+     (insert "* ORG IS STUPID SOMETIMES\n")
+     (goto-char (point-min))
+     (org-html-export-as-html nil t nil t)
+     (with-current-buffer "*Org HTML Export*"
+       (goto-char (point-min))
+       (replace-regexp "<h2>.*</h2>" "")
+       (insert "<h2>" extracted-heading "</h2>")
+       (flush-lines "^$" (point-min) (point-max))
+       (let ((sentence-end-double-space nil))
+         (unfill-region (point-min) (point-max)))
+       (replace-regexp "<h" "\n<h" nil (1+ (point-min)) (point-max))
+       (replace-regexp "<p" "\n<p" nil (point-min) (point-max))
+       (replace-regexp "<p> +" "<p>" nil (point-min) (point-max))
+       (replace-regexp " +</p>" "</p>" nil (point-min) (point-max))
+       (copy-region-as-kill (point-min) (point-max)))))
+  (when (called-interactively-p 'interactive)
+    (indicate-copied-region))
+  (setq deactivate-mark t)
+  nil)
+
 (defun acdw/org-export-copy ()
   "copy a tree"
   (interactive)
@@ -409,14 +499,17 @@ first."
   (let ((extracted-heading (acdw/org-extract-heading-text)))
     ;; Export to ASCII - not async, subtree only, visible-only, body-only
     (let ((org-export-show-temporary-export-buffer nil))
-      (org-ascii-export-as-ascii nil t t t))
+      (org-ascii-export-as-ascii nil t nil t))
     (with-current-buffer "*Org ASCII Export*"
       (goto-char (point-min))
       (insert extracted-heading)
-      (newline)
-      (newline)
+      (newline 2)
 
-      (unfill-region (point-min) (point-max))
+      (replace-regexp org-list-full-item-re "
+\4")
+      
+      (let ((sentence-end-double-space nil))
+        (unfill-region (point-min) (point-max)))
       (flush-lines "^$" (point-min) (point-max))
       
       (copy-region-as-kill (point-min) (point-max)))
@@ -435,6 +528,19 @@ first."
                                  (match-string-no-properties 2 match))
                                heading))))
 
+(defun acdw/sync-dir (&optional file make-directory)
+  "Return FILE from ~/Sync.
+Optional argument MAKE-DIRECTORY makes the directory.
+Logic is as in `acdw/dir', which see."
+  (let ((dir (expand-file-name (convert-standard-filename "~/Sync/"))))
+    (if file
+        (let ((file-name (expand-file-name (convert-standard-filename file)
+                                           dir)))
+          (when make-directory
+            (make-directory (file-name-directory file-name) 'parents))
+          file-name)
+      dir)))
+
 (defun acdw/dir (&optional file make-directory)
   "Place Emacs files in one place.
 
@@ -695,6 +801,24 @@ When called with PREFIX, just kill Emacs without confirmation."
     (ignore-errors
       (delete-frame))))
 
+(defun acdw/disabled-command-function (&optional cmd keys)
+  (let ((cmd (or cmd this-command))
+        (keys (or keys (this-command-keys))))
+    ;; this logic stolen from original `disabled-command-function'
+    (if (or (eq (aref keys 0) (if (stringp keys)
+                                  (aref "\M-x" 0)
+                                ?\M-x))
+            (and (>= (length keys) 2)
+                 (eq (aref keys 0) meta-prefix-char)
+                 (eq (aref keys 1) ?x)))
+        ;; it's been run as an M-x command, we want to do it
+        (call-interactively cmd)
+      ;; else, tell the user it's disabled.
+      (message (substitute-command-keys
+                (concat "Command `%s' has been disabled.  "
+                        "Run with \\[execute-extended-command]."))
+               cmd))))
+
 
 ;;; cribbed
 
-- 
cgit 1.4.1-21-gabe81