~thecatster/.emacs.d

f2fdce0dcdb1a4b29f6a8c46e6f00ca50e4969e2 — Daniil Rose 6 months ago 6d27ceb
Reimagine keybindings, modeline, and more
2 files changed, 535 insertions(+), 184 deletions(-)

M emacs.org
M init.el
M emacs.org => emacs.org +313 -110
@@ 334,6 334,13 @@ Add programs to path on macOS.
      (exec-path-from-shell-initialize)))
#+END_SRC

Highlight selected regions ala Vim.

#+BEGIN_SRC emacs-lisp
(use-package volatile-highlights
  :hook (after-init . volatile-highlights-mode))
#+END_SRC

The most common protocol I use TRAMP for is ssh, so might as well make
that default. Also allow me to reopen a file as root automatically.



@@ 459,7 466,7 @@ emojis.
Also, set the default Emacs window to the size I like on my MacBook.

#+BEGIN_SRC emacs-lisp
(add-to-list 'default-frame-alist '((font . "JetBrainsMono Nerd Font 12") (height . 45) (width . 120)))
(add-to-list 'default-frame-alist '(font . "JetBrainsMono Nerd Font"))
(use-package emojify
  :hook (after-init . global-emojify-mode)
  :custom


@@ 576,19 583,37 @@ readability.
(use-package all-the-icons)
#+END_SRC

I'm still not sold on the Doom modeline. I've gone back to using the
smart modeline.
I'm still not sold on the Doom modeline, but I'm willing to try it
again.

#+BEGIN_SRC emacs-lisp
(use-package smart-mode-line-atom-one-dark-theme)
(setq catster/use-doom-ml t)

(when catster/use-doom-ml
  (use-package doom-modeline
    :custom
    (doom-modeline-major-mode-icon t)
    (doom-modeline-minor-modes nil)
    :hook (after-init . doom-modeline-mode)))

(unless catster/use-doom-ml
  (use-package smart-mode-line-atom-one-dark-theme)
  (use-package smart-mode-line
    :after smart-mode-line-atom-one-dark-theme
    :init
    (setq sml/theme 'atom-one-dark)
    (setq sml/no-confirm-load-theme t)
    :config
    (sml/setup)))
#+END_SRC

(use-package smart-mode-line
  :after smart-mode-line-atom-one-dark-theme
Anzu shows you what result you are on out of n when searching, ala
Vim. Not the most useful since I use Consult and friends.

#+BEGIN_SRC emacs-lisp
(use-package anzu
  :init
  (setq sml/theme 'atom-one-dark)
  (setq sml/no-confirm-load-theme t)
  :config
  (sml/setup))
  (global-anzu-mode))
#+END_SRC

** PGP


@@ 986,22 1011,17 @@ What in the world are those default buffer popup locations?

(shackle-mode)
#+END_SRC
** Yasnippet
Still trying to get use to this one, my ultisnips in Neovim are just
unstoppable. Porting my snippets over is also a pain, so once that is
done I should be more used to this.
** Undo Fu
A powerful, linear undo system.

#+BEGIN_SRC emacs-lisp
(use-package yasnippet-snippets)

(use-package yasnippet
  :after yasnippet-snippets
  :diminish yas-minor-mode
  :hook ((prog-mode text-mode) . yas-minor-mode)
(use-package undo-fu
  :config
  (add-to-list 'yas-snippet-dirs "~/.emacs.d/snippets")
  (yas-reload-all))
  (global-unset-key (kbd "C-/"))
  (global-set-key (kbd "C-/")   'undo-fu-only-undo)
  (global-set-key (kbd "C-S-/") 'undo-fu-only-redo))
#+END_SRC

** Helpful
An even more /helpful/ way to understand Emacs. A better alternative
to `describe-function` and the rest of those commands.


@@ 1033,6 1053,132 @@ to `describe-function` and the rest of those commands.
  ;; look at interactive functions.
  (global-set-key (kbd "C-h C") #'helpful-command))
#+END_SRC
** TeX
How I work with TeX in Emacs. Inspired largely by Karthinks.

AucTeX settings.

#+BEGIN_SRC emacs-lisp
(use-package latex
  :straight nil
  :defer t
  :ensure auctex
  :hook ((LaTeX-mode . prettify-symbols-mode))
  :bind (:map LaTeX-mode-map
         ("C-S-e" . latex-math-from-calc))
  :config
  ;; Format math as a Latex string with Calc
  (defun latex-math-from-calc ()
    "Evaluate `calc' on the contents of line at point."
    (interactive)
    (cond ((region-active-p)
           (let* ((beg (region-beginning))
                  (end (region-end))
                  (string (buffer-substring-no-properties beg end)))
             (kill-region beg end)
             (insert (calc-eval `(,string calc-language latex
                                          calc-prefer-frac t
                                          calc-angle-mode rad)))))
          (t (let ((l (thing-at-point 'line)))
               (end-of-line 1) (kill-line 0)
               (insert (calc-eval `(,l
                                    calc-language latex
                                    calc-prefer-frac t
                                    calc-angle-mode rad))))))))

(use-package preview
  :straight nil
  :after latex
  :hook ((LaTeX-mode . preview-larger-previews))
  :config
  (defun preview-larger-previews ()
    (setq preview-scale-function
          (lambda () (* 1.25
                   (funcall (preview-scale-from-face)))))))
#+END_SRC

CDLaTeX settings.

#+BEGIN_SRC emacs-lisp
(use-package cdlatex
  :ensure t
  :hook (LaTeX-mode . turn-on-cdlatex)
  :bind (:map cdlatex-mode-map
              ("<tab>" . cdlatex-tab)))
#+END_SRC

** Yasnippet
Still trying to get use to this one, my ultisnips in Neovim are just
unstoppable. Porting my snippets over is also a pain, so once that is
done I should be more used to this.

#+BEGIN_SRC emacs-lisp
(use-package yasnippet-snippets)

(use-package yasnippet
  :hook ((LaTeX-mode . yas-minor-mode)
         (post-self-insert . my/yas-try-expanding-auto-snippets))
  :after yasnippet-snippets
  :diminish yas-minor-mode
  :hook ((prog-mode text-mode) . yas-minor-mode)
  :config
  (add-to-list 'yas-snippet-dirs "~/.emacs.d/snippets")
  (yas-reload-all)
  (use-package warnings
    :config
    (cl-pushnew '(yasnippet backquote-change)
                warning-suppress-types
                :test 'equal))
  (setq yas-triggers-in-field t)
  ;; Function that tries to autoexpand YaSnippets
  ;; The double quoting is NOT a typo!
  (defun my/yas-try-expanding-auto-snippets ()
    (when (and (boundp 'yas-minor-mode) yas-minor-mode)
      (let ((yas-buffer-local-condition ''(require-snippet-condition . auto)))
        (yas-expand)))))
#+END_SRC
** CDLaTeX Again
In order to make the fast snippets work, I need another block for
TeX. CDLatex integration with YaSnippet: Allow cdlatex tab to work
inside Yas fields

#+BEGIN_SRC emacs-lisp
(use-package cdlatex
  :hook ((cdlatex-tab . yas-expand)
         (cdlatex-tab . cdlatex-in-yas-field))
  :config
  (use-package yasnippet
    :bind (:map yas-keymap
           ("<tab>" . yas-next-field-or-cdlatex)
           ("TAB" . yas-next-field-or-cdlatex))
    :config
    (defun cdlatex-in-yas-field ()
      ;; Check if we're at the end of the Yas field
      (when-let* ((_ (overlayp yas--active-field-overlay))
                  (end (overlay-end yas--active-field-overlay)))
        (if (>= (point) end)
            ;; Call yas-next-field if cdlatex can't expand here
            (let ((s (thing-at-point 'sexp)))
              (unless (and s (assoc (substring-no-properties s)
                                    cdlatex-command-alist-comb))
                (yas-next-field-or-maybe-expand)
                t))
          ;; otherwise expand and jump to the correct location
          (let (cdlatex-tab-hook minp)
            (setq minp
                  (min (save-excursion (cdlatex-tab)
                                       (point))
                       (overlay-end yas--active-field-overlay)))
            (goto-char minp) t))))

    (defun yas-next-field-or-cdlatex ()
      (interactive)
      "Jump to the next Yas field correctly with cdlatex active."
      (if (bound-and-true-p cdlatex-mode)
          (cdlatex-tab)
        (yas-next-field-or-maybe-expand)))))
#+END_SRC

** Magit
The one, the only. I used CLI git only (still do often) but now I've learned to love magit.



@@ 1069,7 1215,7 @@ The ultimate incarnation of Doc View, that allows you to read (and
modify) PDFs in Emacs.

#+BEGIN_SRC emacs-lisp
(setq catster/use-pdf-view nil)
(setq catster/use-pdf-view t)

(when catster/use-pdf-view
  ;; wrapper for save-buffer ignoring arguments


@@ 1133,15 1279,42 @@ I often want to write and/or edit Dockerfiles and docker-compose.yml's
for my server or development. Having the ability to seamlessly do this
in Emacs is awesome (especially in combination with TRAMP!)

Easier to edit Dockerfiles now.

#+BEGIN_SRC emacs-lisp
(use-package dockerfile-mode
  :mode "Dockerfile\\'")
#+END_SRC

Check out docker containers in Emacs.

#+BEGIN_SRC emacs-lisp
(use-package docker
  :bind ("C-c d" . docker))
#+END_SRC

Edit docker-compose files in Emacs.

#+BEGIN_SRC emacs-lisp
(use-package docker-compose-mode)
#+END_SRC

Work in a docker container through Docker TRAMP.

#+BEGIN_SRC emacs-lisp
(use-package docker-tramp)
#+END_SRC

** Hydra
A cool concept that I severely under use.

#+BEGIN_SRC emacs-lisp
(use-package hydra)

(setq lv-use-separator t)
#+END_SRC
** Caddy
Caddy is my favourite HTTP(S) Server/Reverse Proxy. Remote editing my
My favourite HTTP(S) Server/Reverse Proxy. Remote editing my
Caddyfile through TRAMP in Emacs is awesome!

#+BEGIN_SRC emacs-lisp


@@ 1250,6 1423,38 @@ erc is a cool irc client for emacs
  (erc-update-modules))
#+END_SRC

** Flycheck
Who doesn't like Flycheck? :)

#+BEGIN_SRC emacs-lisp
(use-package flycheck
  :hook ((lsp-mode ledger-mode org-mode) . flycheck-mode)
  :config
  (setq-default flycheck-temp-prefix ".flycheck"))
#+END_SRC

And flyspell is great too.

#+BEGIN_SRC emacs-lisp
(add-hook 'text-mode-hook 'flyspell-mode)
(add-hook 'org-mode-hook 'flyspell-mode)
#+END_SRC

Check my writing style as I go. Thanks to Aaron Jacobs for writing the
flychecker.

#+BEGIN_SRC emacs-lisp
(flycheck-define-checker proselint
  "A linter for prose."
  :command ("proselint" source-inplace)
  :error-patterns
  ((warning line-start (file-name) ":" line ":" column ": "
	    (id (one-or-more (not (any " "))))
	    (message) line-end))
  :modes (text-mode markdown-mode gfm-mode org-mode))

(add-to-list 'flycheck-checkers 'proselint)
#+END_SRC
** Treemacs
I used to be opposed to using Treemacs, but have learned to appreciate
it over time.


@@ 1274,62 1479,31 @@ it over time.
#+END_SRC

** Screenshot
Sharing pictures of code is useful, why not build that into Emacs.
Sharing pictures of code is useful, why not build that into
Emacs. This isn't currently working on macOS.

#+BEGIN_SRC emacs-lisp
;; (use-package screenshot
;;   :straight (:host github :repo "tecosaur/screenshot"))
(use-package screenshot
  :config
  (load-file (locate-library "screenshot.el")))
#+END_SRC

** Ledger
By keeping my finances in (encrypted) plain text, I can ensure they
are always accessible, even offline (as opposed to my previous
self-hosted solution, SilverStrike).
** EditorConfig
This is nice, since I use Emacs, and nobody else I work with does.

#+BEGIN_SRC emacs-lisp
(use-package ledger-mode)

(use-package flycheck-ledger
  :after ledger-mode)
(use-package editorconfig
  :config
  (editorconfig-mode 1))
#+END_SRC

** Elfeed
I use miniflux as a self-hosted RSS reader/aggregator, and use elfeed
as a client.
** Quick Run
Quick Run is similar to the run feature in VSC, and allows me to
quickly evaluate the code I'm writing. Neat!

#+BEGIN_SRC emacs-lisp
(use-package elfeed
  :config
  (setq elfeed-use-curl t))

(use-package elfeed-protocol
  :after elfeed
  :config
  (setq elfeed-protocol-fever-maxsize 50)
  (setq elfeed-feeds
        (list (list "fever+https://thecatster@rss.danielr.xyz/"
                    :api-url "https://rss.danielr.xyz/fever/"
                    :use-authinfo t
                    :autotags '(("www.cnx-software.com" embedded)))))
  (elfeed-protocol-enable))

(use-package elfeed-goodies
  :after elfeed
  :config
  (setq elfeed-goodies/entry-pane-position 'bottom)
  (elfeed-goodies/setup))

(use-package elfeed-dashboard
  :config
  (setq elfeed-dashboard-file "~/.emacs.d/elfeed-dashboard.org")
  (advice-add 'elfeed-search-quit-window :after #'elfeed-dashboard-update-links))

(use-package elfeed-autotag
  :config
  (setq elfeed-autotag-files '("~/Nextcloud/org/elfeed.org"))
  (elfeed-autotag))
(use-package quickrun)
#+END_SRC

** OpenSCAD
OpenSCAD has modes for files and previews in Emacs!



@@ 1338,18 1512,6 @@ OpenSCAD has modes for files and previews in Emacs!
(use-package scad-preview)
#+END_SRC

** Web Server
I always have Python installed on my machines for work and side
projects, so I usually use my terminal and ~python3 -m
http.server~. However, it would be awesome to have this functionality
in Emacs! Using web-server and a function I found written by somebody
on GitHub Gists (I promise that I understand what it does and didn't
just copy it,) I can now do that.

#+BEGIN_SRC emacs-lisp
(use-package simple-httpd)
#+END_SRC

** Email
Now, let's add mu4e. I keep this account file in a different location,
but you can easily learn to do this with the great Reddit post "mu4e


@@ 1375,6 1537,13 @@ flycheck to lsp.
** Convenient Features
Things that are really nice to have, but I'm not sure which category they would go in.

Format on save is awesome!

#+BEGIN_SRC emacs-lisp
(use-package format-all
  :hook (prog-mode . format-all-mode))
#+END_SRC

Smartparens is great, and helps me realise I didn't forget (that (one (parentheses)))

#+BEGIN_SRC emacs-lisp


@@ 1382,7 1551,7 @@ Smartparens is great, and helps me realise I didn't forget (that (one (parenthes
  (use-package smartparens
    :hook (prog-mode . smartparens-mode)
    :config
    (setq sp-highlight-pair-overlay nil)
    (setq sp-highlight-pair-overlay t)
    (setq sp-autoskip-closing-pair 'always)
    (setq sp-cancel-autoskip-on-backward-movement nil))
#+END_SRC


@@ 1395,17 1564,6 @@ Compile various code and scroll output.
  (compilation-scroll-output t))
#+END_SRC

Does this work in all modes? Yes.  Is this literally a saving grace in
Lisp modes? Yes.

#+BEGIN_SRC emacs-lisp
  (use-package parinfer-rust-mode
    :hook ((emacs-lisp-mode clojure-mode lisp-mode hy-mode racket-mode). parinfer-rust-mode)
    :init
    (setq parinfer-rust-auto-download t)
    (setq parinfer-rust-preferred-mode 'paren))
#+END_SRC

Makes code easier to read, and specifically on these, as I do not want rainbow to conflict with parinfer in Lisp

#+BEGIN_SRC emacs-lisp


@@ 1424,6 1582,12 @@ See colors easily!
  (setq rainbow-x-colors nil))
#+END_SRC

And edit them easily too!

#+BEGIN_SRC emacs-lisp
(use-package kurecolor)
#+END_SRC

No commentary needed

#+BEGIN_SRC emacs-lisp


@@ 1436,14 1600,36 @@ RIP grep
(use-package deadgrep)
#+END_SRC

** Flycheck
Who doesn't like Flycheck? :)
Highlight TODO and various such comments, great for quickly reading
through in-progress code.

#+BEGIN_SRC emacs-lisp
(use-package flycheck
  :hook ((lsp-mode ledger-mode) . flycheck-mode)
  :config
  (setq-default flycheck-temp-prefix ".flycheck"))
(use-package hl-todo
  :hook (prog-mode . hl-todo-mode)
  :hook (yaml-mode . hl-todo-mode)
  :custom
  (hl-todo-highlight-punctuation ":")
  (hl-todo-keyword-faces
        `(;; For things that need to be done, just not today.
          ("TODO" warning bold)
          ;; For problems that will become bigger problems later if not
          ;; fixed ASAP.
          ("FIXME" error bold)
          ;; For tidbits that are unconventional and not intended uses of the
          ;; constituent parts, and may break in a future update.
          ("HACK" font-lock-constant-face bold)
          ;; For things that were done hastily and/or hasn't been thoroughly
          ;; tested. It may not even be necessary!
          ("REVIEW" font-lock-keyword-face bold)
          ;; For especially important gotchas with a given implementation,
          ;; directed at another user other than the author.
          ("NOTE" success bold)
          ;; For things that just gotta go and will soon be gone.
          ("DEPRECATED" font-lock-doc-face bold)
          ;; For a known bug that needs a workaround
          ("BUG" error bold)
          ;; For warning about a problematic or misguiding code
          ("XXX" font-lock-constant-face bold))))
#+END_SRC

** LSP


@@ 1747,10 1933,8 @@ These are defaults that I have found make Org mode more enjoyable to use.
#+BEGIN_SRC emacs-lisp
  (defun +org|setup-ui ()
    "Configures the UI for `org-mode'."
    (org-indent-mode)
    (auto-fill-mode 0)
    (visual-line-mode 1)
    (diminish org-indent-mode)
    (setq-default org-adapt-indentation nil
                  org-cycle-include-plain-lists t
                  org-eldoc-breadcrumb-separator " → "


@@ 1879,7 2063,8 @@ F**K YEAH Radians over Degrees.
Properly indent headings in org mode.

#+BEGIN_SRC emacs-lisp
(org-indent-mode 1)
(with-eval-after-load 'org-indent
  (add-hook 'org-mode-hook 'org-indent-mode))
#+END_SRC

** Blog, Agenda, and Capture


@@ 1909,7 2094,6 @@ my Org agenda and capture more pleasant.
        (tags priority-down category-keep)
        (search category-keep))))
#+END_SRC

** Org Journal
In combination with Org Roam, this makes for an amazing method to keep
my (often racing) thoughts organized and written in a neat way. I


@@ 1964,13 2148,6 @@ often!
      (org-roam-v2-ack t)
      (org-roam-db-gc-threshold most-positive-fixnum)
      (org-roam-directory (file-truename "~/Nextcloud/org/org-roam"))
      :bind (("C-c n l" . org-roam-buffer-toggle)
             ("C-c n f" . org-roam-node-find)
             ("C-c n g" . org-roam-graph)
             ("C-c n i" . org-roam-node-insert)
             ("C-c n c" . org-roam-capture)
             ;; Dailies
             ("C-c n j" . org-roam-dailies-capture-today))
      :config
      (org-roam-setup)
      (require 'org-roam-protocol))


@@ 2082,3 2259,29 @@ wasn't sure what section to put this in.
I like the Doom idea of binding keybindings in a unified way, however
I dislike the way Doom actually binds them. This is my version,
tailored to my needs.

#+BEGIN_SRC emacs-lisp
(use-package general
  :init
  ;; My Caps Lock is bound to escape, so this is always close.
  (defconst my-leader "<escape>")
  (general-create-definer my-leader-def :prefix my-leader)
  (general-auto-unbind-keys)
  :config
  (my-leader-def
    "" '(:ignore t :wk "personal keybindings"))
  ;; Org Agenda
  (my-leader-def
    "a" '(:ignore t :wk "org")
    "aa" '(org-agenda :wk "agenda"))
  ;; Org Roam
  (my-leader-def
    "n" '(:ignore t :wk "org roam")
    "nl" '(org-roam-buffer-toggle :wk "buffer toggle")
    "nf" '(org-roam-node-find :wk "find node")
    "ng" '(org-roam-graph :wk "graph")
    "ni" '(org-roam-node-insert :wk "insert node")
    "nc" '(org-roam-capture :wk "capture")
    "nj" '(org-roam-dailies-capture-today :wk "daily capture")
    "nu" '(org-roam-ui-open :wk "ui")))
#+END_SRC

M init.el => init.el +222 -74
@@ 198,6 198,9 @@
    :init
    (exec-path-from-shell-initialize)))

(use-package volatile-highlights
  :hook (after-init . volatile-highlights-mode))

(setq tramp-default-method "ssh")

(use-package auto-sudoedit


@@ 252,7 255,7 @@

(add-hook 'before-save-hook 'delete-trailing-whitespace)

(add-to-list 'default-frame-alist '((font . "JetBrainsMono Nerd Font 12") (height . 45) (width . 120)))
(add-to-list 'default-frame-alist '(font . "JetBrainsMono Nerd Font"))
(use-package emojify
  :hook (after-init . global-emojify-mode)
  :custom


@@ 313,15 316,28 @@
  (load-theme 'atom-one-dark t))
(use-package all-the-icons)

(use-package smart-mode-line-atom-one-dark-theme)
(setq catster/use-doom-ml t)

(when catster/use-doom-ml
  (use-package doom-modeline
    :custom
    (doom-modeline-major-mode-icon t)
    (doom-modeline-minor-modes nil)
    :hook (after-init . doom-modeline-mode)))

(unless catster/use-doom-ml
  (use-package smart-mode-line-atom-one-dark-theme)
  (use-package smart-mode-line
    :after smart-mode-line-atom-one-dark-theme
    :init
    (setq sml/theme 'atom-one-dark)
    (setq sml/no-confirm-load-theme t)
    :config
    (sml/setup)))

(use-package smart-mode-line
  :after smart-mode-line-atom-one-dark-theme
(use-package anzu
  :init
  (setq sml/theme 'atom-one-dark)
  (setq sml/no-confirm-load-theme t)
  :config
  (sml/setup))
  (global-anzu-mode))

;; Don't bring up key recipient dialogue.
(require 'epa-file)


@@ 646,15 662,11 @@

(shackle-mode)

(use-package yasnippet-snippets)

(use-package yasnippet
  :after yasnippet-snippets
  :diminish yas-minor-mode
  :hook ((prog-mode text-mode) . yas-minor-mode)
(use-package undo-fu
  :config
  (add-to-list 'yas-snippet-dirs "~/.emacs.d/snippets")
  (yas-reload-all))
  (global-unset-key (kbd "C-/"))
  (global-set-key (kbd "C-/")   'undo-fu-only-undo)
  (global-set-key (kbd "C-S-/") 'undo-fu-only-redo))

(use-package helpful
  :config


@@ 682,6 694,108 @@
  ;; look at interactive functions.
  (global-set-key (kbd "C-h C") #'helpful-command))

(use-package latex
  :straight nil
  :defer t
  :ensure auctex
  :hook ((LaTeX-mode . prettify-symbols-mode))
  :bind (:map LaTeX-mode-map
         ("C-S-e" . latex-math-from-calc))
  :config
  ;; Format math as a Latex string with Calc
  (defun latex-math-from-calc ()
    "Evaluate `calc' on the contents of line at point."
    (interactive)
    (cond ((region-active-p)
           (let* ((beg (region-beginning))
                  (end (region-end))
                  (string (buffer-substring-no-properties beg end)))
             (kill-region beg end)
             (insert (calc-eval `(,string calc-language latex
                                          calc-prefer-frac t
                                          calc-angle-mode rad)))))
          (t (let ((l (thing-at-point 'line)))
               (end-of-line 1) (kill-line 0)
               (insert (calc-eval `(,l
                                    calc-language latex
                                    calc-prefer-frac t
                                    calc-angle-mode rad))))))))

(use-package preview
  :straight nil
  :after latex
  :hook ((LaTeX-mode . preview-larger-previews))
  :config
  (defun preview-larger-previews ()
    (setq preview-scale-function
          (lambda () (* 1.25
                   (funcall (preview-scale-from-face)))))))

(use-package cdlatex
  :ensure t
  :hook (LaTeX-mode . turn-on-cdlatex)
  :bind (:map cdlatex-mode-map
              ("<tab>" . cdlatex-tab)))

(use-package yasnippet-snippets)

(use-package yasnippet
  :hook ((LaTeX-mode . yas-minor-mode)
         (post-self-insert . my/yas-try-expanding-auto-snippets))
  :after yasnippet-snippets
  :diminish yas-minor-mode
  :hook ((prog-mode text-mode) . yas-minor-mode)
  :config
  (add-to-list 'yas-snippet-dirs "~/.emacs.d/snippets")
  (yas-reload-all)
  (use-package warnings
    :config
    (cl-pushnew '(yasnippet backquote-change)
                warning-suppress-types
                :test 'equal))
  (setq yas-triggers-in-field t)
  ;; Function that tries to autoexpand YaSnippets
  ;; The double quoting is NOT a typo!
  (defun my/yas-try-expanding-auto-snippets ()
    (when (and (boundp 'yas-minor-mode) yas-minor-mode)
      (let ((yas-buffer-local-condition ''(require-snippet-condition . auto)))
        (yas-expand)))))

(use-package cdlatex
  :hook ((cdlatex-tab . yas-expand)
         (cdlatex-tab . cdlatex-in-yas-field))
  :config
  (use-package yasnippet
    :bind (:map yas-keymap
           ("<tab>" . yas-next-field-or-cdlatex)
           ("TAB" . yas-next-field-or-cdlatex))
    :config
    (defun cdlatex-in-yas-field ()
      ;; Check if we're at the end of the Yas field
      (when-let* ((_ (overlayp yas--active-field-overlay))
                  (end (overlay-end yas--active-field-overlay)))
        (if (>= (point) end)
            ;; Call yas-next-field if cdlatex can't expand here
            (let ((s (thing-at-point 'sexp)))
              (unless (and s (assoc (substring-no-properties s)
                                    cdlatex-command-alist-comb))
                (yas-next-field-or-maybe-expand)
                t))
          ;; otherwise expand and jump to the correct location
          (let (cdlatex-tab-hook minp)
            (setq minp
                  (min (save-excursion (cdlatex-tab)
                                       (point))
                       (overlay-end yas--active-field-overlay)))
            (goto-char minp) t))))

    (defun yas-next-field-or-cdlatex ()
      (interactive)
      "Jump to the next Yas field correctly with cdlatex active."
      (if (bound-and-true-p cdlatex-mode)
          (cdlatex-tab)
        (yas-next-field-or-maybe-expand)))))

(use-package magit
  :commands (magit-status magit-get-current-branch)
  :custom


@@ 705,7 819,7 @@
(winner-mode)
(add-hook 'ediff-after-quit-hook-internal 'winner-undo)

(setq catster/use-pdf-view nil)
(setq catster/use-pdf-view t)

(when catster/use-pdf-view
  ;; wrapper for save-buffer ignoring arguments


@@ 760,8 874,17 @@
(use-package dockerfile-mode
  :mode "Dockerfile\\'")

(use-package docker
  :bind ("C-c d" . docker))

(use-package docker-compose-mode)

(use-package docker-tramp)

(use-package hydra)

(setq lv-use-separator t)

(use-package caddyfile-mode)

(use-package erc-hl-nicks


@@ 861,6 984,25 @@
  (erc-services-mode 1)
  (erc-update-modules))

(use-package flycheck
  :hook ((lsp-mode ledger-mode org-mode) . flycheck-mode)
  :config
  (setq-default flycheck-temp-prefix ".flycheck"))

(add-hook 'text-mode-hook 'flyspell-mode)
(add-hook 'org-mode-hook 'flyspell-mode)

(flycheck-define-checker proselint
  "A linter for prose."
  :command ("proselint" source-inplace)
  :error-patterns
  ((warning line-start (file-name) ":" line ":" column ": "
	    (id (one-or-more (not (any " "))))
	    (message) line-end))
  :modes (text-mode markdown-mode gfm-mode org-mode))

(add-to-list 'flycheck-checkers 'proselint)

(use-package treemacs
  :defer t
  :config


@@ 878,61 1020,33 @@
(use-package treemacs-magit
  :after (treemacs magit))

;; (use-package screenshot
;;   :straight (:host github :repo "tecosaur/screenshot"))

(use-package ledger-mode)

(use-package flycheck-ledger
  :after ledger-mode)

(use-package elfeed
(use-package screenshot
  :config
  (setq elfeed-use-curl t))
  (load-file (locate-library "screenshot.el")))

(use-package elfeed-protocol
  :after elfeed
  :config
  (setq elfeed-protocol-fever-maxsize 50)
  (setq elfeed-feeds
        (list (list "fever+https://thecatster@rss.danielr.xyz/"
                    :api-url "https://rss.danielr.xyz/fever/"
                    :use-authinfo t
                    :autotags '(("www.cnx-software.com" embedded)))))
  (elfeed-protocol-enable))

(use-package elfeed-goodies
  :after elfeed
(use-package editorconfig
  :config
  (setq elfeed-goodies/entry-pane-position 'bottom)
  (elfeed-goodies/setup))
  (editorconfig-mode 1))

(use-package elfeed-dashboard
  :config
  (setq elfeed-dashboard-file "~/.emacs.d/elfeed-dashboard.org")
  (advice-add 'elfeed-search-quit-window :after #'elfeed-dashboard-update-links))

(use-package elfeed-autotag
  :config
  (setq elfeed-autotag-files '("~/Nextcloud/org/elfeed.org"))
  (elfeed-autotag))
(use-package quickrun)

(use-package scad-mode)
(use-package scad-preview)

(use-package simple-httpd)

(setq catster/use-mail nil)

(when catster/use-mail
  (add-to-list 'load-path "~/.emacs.d/mu4e/")
  (require 'catsters-mail))

(use-package format-all
  :hook (prog-mode . format-all-mode))

(show-paren-mode 1)
  (use-package smartparens
    :hook (prog-mode . smartparens-mode)
    :config
    (setq sp-highlight-pair-overlay nil)
    (setq sp-highlight-pair-overlay t)
    (setq sp-autoskip-closing-pair 'always)
    (setq sp-cancel-autoskip-on-backward-movement nil))



@@ 940,12 1054,6 @@
  :custom
  (compilation-scroll-output t))

(use-package parinfer-rust-mode
  :hook ((emacs-lisp-mode clojure-mode lisp-mode hy-mode racket-mode). parinfer-rust-mode)
  :init
  (setq parinfer-rust-auto-download t)
  (setq parinfer-rust-preferred-mode 'paren))

(use-package rainbow-delimiters
  :diminish rainbow-delimiters-mode
  :hook ((hy-mode python-mode rustic-mode c-mode js-mode rjsx-mode web-mode css-mode html-mode) . rainbow-delimiters-mode))


@@ 956,14 1064,38 @@
  :config
  (setq rainbow-x-colors nil))

(use-package kurecolor)

(use-package fzf)

(use-package deadgrep)

(use-package flycheck
  :hook ((lsp-mode ledger-mode) . flycheck-mode)
  :config
  (setq-default flycheck-temp-prefix ".flycheck"))
(use-package hl-todo
  :hook (prog-mode . hl-todo-mode)
  :hook (yaml-mode . hl-todo-mode)
  :custom
  (hl-todo-highlight-punctuation ":")
  (hl-todo-keyword-faces
        `(;; For things that need to be done, just not today.
          ("TODO" warning bold)
          ;; For problems that will become bigger problems later if not
          ;; fixed ASAP.
          ("FIXME" error bold)
          ;; For tidbits that are unconventional and not intended uses of the
          ;; constituent parts, and may break in a future update.
          ("HACK" font-lock-constant-face bold)
          ;; For things that were done hastily and/or hasn't been thoroughly
          ;; tested. It may not even be necessary!
          ("REVIEW" font-lock-keyword-face bold)
          ;; For especially important gotchas with a given implementation,
          ;; directed at another user other than the author.
          ("NOTE" success bold)
          ;; For things that just gotta go and will soon be gone.
          ("DEPRECATED" font-lock-doc-face bold)
          ;; For a known bug that needs a workaround
          ("BUG" error bold)
          ;; For warning about a problematic or misguiding code
          ("XXX" font-lock-constant-face bold))))

(use-package lsp-mode
  :defer t


@@ 1174,10 1306,8 @@

(defun +org|setup-ui ()
  "Configures the UI for `org-mode'."
  (org-indent-mode)
  (auto-fill-mode 0)
  (visual-line-mode 1)
  (diminish org-indent-mode)
  (setq-default org-adapt-indentation nil
                org-cycle-include-plain-lists t
                org-eldoc-breadcrumb-separator " → "


@@ 1285,7 1415,8 @@
(setq calc-angle-mode 'rad  ; radians are rad, screw degrees
      calc-symbolic-mode t) ; keeps expressions like \sqrt{2} irrational for as long as possible

(org-indent-mode 1)
(with-eval-after-load 'org-indent
  (add-hook 'org-mode-hook 'org-indent-mode))

;; Word choice and such
(use-package writegood-mode


@@ 1339,13 1470,6 @@
      (org-roam-v2-ack t)
      (org-roam-db-gc-threshold most-positive-fixnum)
      (org-roam-directory (file-truename "~/Nextcloud/org/org-roam"))
      :bind (("C-c n l" . org-roam-buffer-toggle)
             ("C-c n f" . org-roam-node-find)
             ("C-c n g" . org-roam-graph)
             ("C-c n i" . org-roam-node-insert)
             ("C-c n c" . org-roam-capture)
             ;; Dailies
             ("C-c n j" . org-roam-dailies-capture-today))
      :config
      (org-roam-setup)
      (require 'org-roam-protocol))


@@ 1422,3 1546,27 @@
        (if b (setq e (re-search-forward end-regexp nil t))))
      (if (and b e (< (point) e)) (setq rlt nil)))
    (setq ad-return-value rlt)))

(use-package general
  :init
  ;; My Caps Lock is bound to escape, so this is always close.
  (defconst my-leader "<escape>")
  (general-create-definer my-leader-def :prefix my-leader)
  (general-auto-unbind-keys)
  :config
  (my-leader-def
    "" '(:ignore t :wk "personal keybindings"))
  ;; Org Agenda
  (my-leader-def
    "a" '(:ignore t :wk "org")
    "aa" '(org-agenda :wk "agenda"))
  ;; Org Roam
  (my-leader-def
    "n" '(:ignore t :wk "org roam")
    "nl" '(org-roam-buffer-toggle :wk "buffer toggle")
    "nf" '(org-roam-node-find :wk "find node")
    "ng" '(org-roam-graph :wk "graph")
    "ni" '(org-roam-node-insert :wk "insert node")
    "nc" '(org-roam-capture :wk "capture")
    "nj" '(org-roam-dailies-capture-today :wk "daily capture")
    "nu" '(org-roam-ui-open :wk "ui")))