Skip to content

Latest commit

 

History

History
916 lines (854 loc) · 38.5 KB

config.org

File metadata and controls

916 lines (854 loc) · 38.5 KB

Literate Config

Contents

UI

General appearance/display

Misc. & popups

When I split windows, I usually want to go to that window immediately afterwards. I like the defaults from the popups module except for the size, which cuts things off a little short.

Also, disable line numbers since I never use them for movement commands; text objects/avy/ snipe is usually faster

(setq which-key-side-window-location 'bottom
      which-key-sort-order 'which-key-key-order-alpha
      which-key-max-description-length nil

      display-line-numbers-type 'relative
      evil-split-window-below t
      evil-vsplit-window-right t

      doom-modeline-persp-name t
      doom-modeline-major-mode-icon t)

;; (global-display-fill-column-indicator-mode)

(after! ivy-posframe
  (setf (alist-get t ivy-posframe-display-functions-alist)
        #'ivy-posframe-display-at-frame-top-center))


(setq! +popup-defaults
       (list :side   'bottom
             :height .25 ;; 0.16
             :width  40
             :quit   t
             :select #'ignore
             :ttl    5))

package: solaire-mode

Note: currently disabled in packages.el

;; (use-package! solaire-mode
;;   :init
;;   (setq solaire-mode-auto-swap-bg t
;;         solaire-mode-remap-line-numbers t)
;;   (solaire-global-mode -1))

Frame setup

Surprisingly tricky to get emacs to start in fullscreen, but this works (and doesn’t do anything weird if tiling fullscreen emacs to left or right on macOS)

(setq frame-title-format '("%b – Emacs")
      icon-title-format frame-title-format)
;; (when IS-MAC
;;   (modify-frame-parameters nil '((fullscreen . fullboth)))
;;   (when EMACS28+
;;     (modify-frame-parameters nil '((fullscreen . nil)))
;;     (add-to-list 'default-frame-alist '(height . 59))
;;     (add-to-list 'default-frame-alist '(width . 238))))
 ;; (modify-frame-parameters nil '((fullscreen . fullboth)))
(when IS-MAC
  (set-frame-parameter nil 'fullscreen 'maximized)
  ;; (set-frame-parameter nil 'undecorated t)
  )

Theme

Set theme

changing +override-theme to nil will have this snippet will choose randomly from a selection of light themes or dark themes, depending on the time of day. Usually I just stick with one of the gruvboxes though.

(let* ((+override-theme 'doom-gruvbox)
       (hour (caddr (decode-time nil))))
  (setq! ;doom-gruvbox-dark-variant 'soft
         ;doom-gruvbox-light-variant 'soft
         doom-theme                (or +override-theme
                                       (if (<= 8 hour 16) 'doom-gruvbox-light
                                         'doom-gruvbox))))

Disable embedded block background

I don’t love the way that embedded blocks look in e.g. this config.

(doom-themes-set-faces nil
  '(org-block-begin-line :background nil)
  '(org-quote :background nil)
  '(org-block :background nil)
  '(org-block-end-line :background nil))

Set theme across system

Only for linux, Requires a pip install pywal and imagemagick. When theme changes, update the theme of terminals etc.

(unless IS-MAC
  (use-package! theme-magic
    :init
    (add-hook! 'doom-load-theme-hook (theme-magic-from-emacs))))

Font

I like the iosevka font family for programming, and I like the ‘quasi-spaced’ options like Etoile/Sparkle/Aile for variable pitch stuff – real variable pitch fonts are a little jarring imo when switching between buffers or embedding something monospaced (like in this config). A mostly monospaced font is more readable without obviously being a totally different font at a glance.

(setq doom-font                       (font-spec
                                       :family "Iosevka Extended"
                                       :size 12)
      doom-variable-pitch-font        (font-spec
                                       :family "Iosevka Etoile"
                                       :size 12)

      +zen-text-scale                 0
      +ligatures-extras-in-modes '(org-mode)
      +ligatures-in-modes      '(org-mode))
(set-ligatures! 'python-mode nil)
(set-ligatures! 'tuareg-mode nil)

package: mixed-pitch-mode

(if (modulep! :ui zen)
    (use-package! mixed-pitch
      :hook (text-mode . mixed-pitch-mode)
      :config
      (pushnew! mixed-pitch-fixed-pitch-faces
                'org-date
                'org-special-keyword
                'org-property-value
                'org-ref-cite-face
                'org-tag
                'org-todo-keyword-todo
                'org-todo-keyword-habt
                'org-todo-keyword-done
                'org-todo-keyword-wait
                'org-todo-keyword-kill
                'org-todo-keyword-outd
                'org-todo
                'org-done
                'font-lock-comment-face
                'line-number
                'line-number-current-line)))

Dashboard

Modifications to the doom-emacs home/fallback buffer.

ASCII-art (terminal only)

When starting up in a terminal: Modified `doom-dashboard-widget-banner’ with ascii art modified from https://github.com/plexus/chemacs. It looks better without all the escaped \\’s.

(defun +my/doom-dashboard-widget-banner ()
  (let ((point (point)))
    (mapc (lambda (line)
            (insert (propertize (+doom-dashboard--center +doom-dashboard--width line)
                                'face 'doom-dashboard-banner) " ")
            (insert "\n"))
          '(""
            "       ___           ___           ___           ___           ___      "
            "      /  /\\         /__/\\         /  /\\         /  /\\         /  /\\     "
            "     /  /:/_       |  |::\\       /  /::\\       /  /:/        /  /:/_    "
            "    /  /:/ /\\      |  |:|:\\     /  /:/\\:\\     /  /:/        /  /:/ /\\   "
            "   /  /:/ /:/_   __|__|:|\\:\\   /  /:/ /::\\   /  /:/  ___   /  /:/ /::\\  "
            "  /__/:/ /:/ /\\ /__/::::| \\:\\ /__/:/ /:/\\:\\ /__/:/  /  /\\ /__/:/ /:/\\:\\ "
            "  \\  \\:\\/:/ /:/ \\  \\:\\     \\/ \\  \\:\\/:/__\\/ \\  \\:\\ /  /:/ \\  \\:\\/:/ /:/ "
            "   \\  \\::/ /:/   \\  \\:\\        \\  \\::/       \\  \\:\\  /:/   \\  \\::/ /:/  "
            "    \\  \\:\\/:/     \\  \\:\\        \\  \\:\\        \\  \\:\\/:/     \\__\\/ /:/   "
            "     \\  \\::/       \\  \\:\\        \\  \\:\\        \\  \\::/        /__/:/    "
            "      \\__\\/         \\__\\/         \\__\\/         \\__\\/         \\__\\/     "
            ""
            ""
            ""
            ""))
    (when (and (display-graphic-p)
               (not EMACS28+)
               (stringp fancy-splash-image)
               (file-readable-p fancy-splash-image))
      (let ((image (create-image (fancy-splash-image-file))))
        (add-text-properties
         point (point) `(display ,image rear-nonsticky (display)))
        (save-excursion
          (goto-char point)
          (insert (make-string
                   (truncate
                    (max 0 (+ 1 (/ (- +doom-dashboard--width (car (image-size image nil)))
                                   2)))) 32))))
      (insert (make-string (or (cdr +doom-dashboard-banner-padding) 0) 10)))
    ))

Splash image

Lifted nearly verbatim from https://tecosaur.github.io/emacs-config/config.html#splash-screen

(defvar fancy-splash-image-template
  (expand-file-name "img/blackhole-lines-template.svg" doom-private-dir)
  "Default template svg used for the splash image, with substitutions from ")
(defvar fancy-splash-image-nil
  (expand-file-name "img/transparent-pixel.png" doom-private-dir)
  "An image to use at minimum size, usually a transparent pixel")

(setq fancy-splash-sizes
      `((:height 500 :min-height 50 :padding (0 . 2) :template ,(expand-file-name "img/blackhole-lines-0.svg" doom-private-dir))
        (:height 440 :min-height 42 :padding (1 . 2) :template ,(expand-file-name "img/blackhole-lines-0.svg" doom-private-dir))
        (:height 400 :min-height 38 :padding (1 . 3) :template ,(expand-file-name "img/blackhole-lines-0.svg" doom-private-dir))
        (:height 350 :min-height 36 :padding (1 . 1) :template ,(expand-file-name "img/blackhole-lines-0.svg" doom-private-dir))
        (:height 300 :min-height 34 :padding (1 . 1) :template ,(expand-file-name "img/blackhole-lines-0.svg" doom-private-dir))
        (:height 250 :min-height 32 :padding (1 . 1) :template ,(expand-file-name "img/blackhole-lines-0.svg" doom-private-dir))
        (:height 200 :min-height 30 :padding (1 . 1) :template ,(expand-file-name "img/blackhole-lines-0.svg" doom-private-dir))
        (:height 100 :min-height 24 :padding (1 . 1) :template ,(expand-file-name "img/emacs-e-template.svg" doom-private-dir))
        (:height 0   :min-height 0  :padding (0 . 0) :file ,fancy-splash-image-nil)))

(defvar fancy-splash-sizes
  `((:height 500 :min-height 50 :padding (0 . 2))
    (:height 440 :min-height 42 :padding (1 . 4))
    (:height 330 :min-height 35 :padding (1 . 3))
    (:height 200 :min-height 30 :padding (1 . 2))
    (:height 0   :min-height 0  :padding (0 . 0) :file ,fancy-splash-image-nil))
  "list of plists with the following properties
  :height the height of the image
  :min-height minimum `frame-height' for image
  :padding `+doom-dashboard-banner-padding' to apply
  :template non-default template file
  :file file to use instead of template")

(defvar fancy-splash-template-colours
  '(("$colour1" . keywords) ("$colour2" . type) ("$colour3" . base5) ("$colour4" . base8))
  "list of colour-replacement alists of the form (\"$placeholder\" . 'theme-colour) which applied the template")

(unless (file-exists-p (expand-file-name "theme-splashes" doom-cache-dir))
  (make-directory (expand-file-name "theme-splashes" doom-cache-dir) t))

(defun fancy-splash-filename (theme-name height)
  (expand-file-name (concat (file-name-as-directory "theme-splashes")
                            (symbol-name doom-theme)
                            "-" (number-to-string height) ".svg")
                    doom-cache-dir))

(defun fancy-splash-clear-cache ()
  "Delete all cached fancy splash images"
  (interactive)
  (delete-directory (expand-file-name "theme-splashes" doom-cache-dir) t)
  (message "Cache cleared!"))

(defun fancy-splash-generate-image (template height)
  "Read TEMPLATE and create an image if HEIGHT with colour substitutions as  ;described by `fancy-splash-template-colours' for the current theme"
  (with-temp-buffer
    (insert-file-contents template)
    (re-search-forward "$height" nil t)
    (replace-match (number-to-string height) nil nil)
    (dolist (substitution fancy-splash-template-colours)
      (beginning-of-buffer)
      (while (re-search-forward (car substitution) nil t)
        (replace-match (doom-color (cdr substitution)) nil nil)))
    (write-region nil nil
                  (fancy-splash-filename (symbol-name doom-theme) height) nil nil)))

(defun fancy-splash-generate-images ()
  "Perform `fancy-splash-generate-image' in bulk"
  (dolist (size fancy-splash-sizes)
    (unless (plist-get size :file)
      (fancy-splash-generate-image (or (plist-get size :file)
                                       (plist-get size :template)
                                       fancy-splash-image-template)
                                   (plist-get size :height)))))

(defun ensure-theme-splash-images-exist (&optional height)
  (unless (file-exists-p (fancy-splash-filename
                          (symbol-name doom-theme)
                          (or height
                              (plist-get (car fancy-splash-sizes) :height))))
    (fancy-splash-generate-images)))

(defun get-appropriate-splash ()
  (let ((height (frame-height)))
    (cl-some (lambda (size) (when (>= height (plist-get size :min-height)) size))
             fancy-splash-sizes)))

(setq fancy-splash-last-size nil)
(setq fancy-splash-last-theme nil)
(defun set-appropriate-splash (&optional frame)
  (let ((appropriate-image (get-appropriate-splash)))
    (unless (and (equal appropriate-image fancy-splash-last-size)
                 (equal doom-theme fancy-splash-last-theme)))
    (unless (plist-get appropriate-image :file)
      (ensure-theme-splash-images-exist (plist-get appropriate-image :height)))
    (setq fancy-splash-image
          (or (plist-get appropriate-image :file)
              (fancy-splash-filename (symbol-name doom-theme) (plist-get appropriate-image :height))))
    (setq +doom-dashboard-banner-padding (plist-get appropriate-image :padding))
    (setq fancy-splash-last-size appropriate-image)
    (setq fancy-splash-last-theme doom-theme)
    (+doom-dashboard-reload)))

(add-hook 'window-size-change-functions #'set-appropriate-splash)
(add-hook 'doom-load-theme-hook #'set-appropriate-splash)

Shortcuts, icons

There are only a few shortcuts I’d want to use from the dashboard.

(setq doom--initial-load-path (get 'load-path 'initial-value))
(add-hook! +doom-dashboard-mode (hl-line-mode -1))
(setq! +doom-dashboard-name "*dashboard*" )
(defun +my/doom-dashboard-widget-loaded ()
  (insert
   "\n\n"
   (propertize
    (+doom-dashboard--center
     +doom-dashboard--width
     (+my/doom-display-benchmark-h 'return))
    'face 'doom-dashboard-loaded)
   "\n"))
(defun +my/doom-display-benchmark-h (&optional return-p)
  (funcall (if return-p #'format #'message)
           "Loaded %d packages across %d modules in %.03fs"
           (- (length load-path) (length doom--initial-load-path))
           (if doom-modules (hash-table-count doom-modules) 0)
           (or doom-init-time
               (setq doom-init-time
                     (float-time (time-subtract (current-time) before-init-time))))))
(setq! +doom-dashboard-menu-sections
       '(("Reload last session"
          :icon (all-the-icons-octicon "history" :face 'doom-dashboard-menu-title)
          :when (cond ((require 'persp-mode nil t)
                       (file-exists-p (expand-file-name persp-auto-save-fname persp-save-dir)))
                      ((require 'desktop nil t)
                       (file-exists-p (desktop-full-file-name))))
          :face (:inherit (doom-dashboard-menu-title bold))
          :action doom/quickload-session)
         ("Open random note"
          :icon (all-the-icons-octicon "book" :face 'doom-dashboard-menu-title)
          :action org-roam-random-note)
         ("Recently opened files"
          :icon (all-the-icons-octicon "file-text" :face 'doom-dashboard-menu-title)
          :action recentf-open-files)
         ("Open project"
          :icon (all-the-icons-octicon "repo" :face 'doom-dashboard-menu-title)
          :action projectile-switch-project)
         ("Open private configuration"
          :icon (all-the-icons-octicon "tools" :face 'doom-dashboard-menu-title)
          :when (file-directory-p doom-private-dir)
          :action doom/open-private-config))

       +doom-dashboard-functions '(+my/doom-dashboard-widget-banner
                                   doom-dashboard-widget-shortmenu
                                   +my/doom-dashboard-widget-loaded))

Editor

What I’d call the “editor” stuff could probably use some organizational work; it’s a little broad. I’m also not sure how much I want to keep LSP-related config stuff all together for different languages, and how much I want to keep that code with the config for the respective languages. I find myself fairly frequently changing between LSP frontends (eglot, lsp-mode) as well as backends (for python-mode especially).

General

Miscellaneous variables/ packages that don’t warrant their own section. Completion and the ‘inner/around line’ text objects here.

(setq user-full-name "Owen Price Skelly"
      user-mail-address "Owen.Price.Skelly@gmail.com"
      ;; iedit-occurrence-context-lines 1
      fill-column 100
      +workspaces-on-switch-project-behavior t)

;; (after! evil-multiedit

;;   (map! :map iedit-occurrence-keymap-default
;;         "M-D" nil))

(after! company
  (setq completion-ignore-case t
        company-idle-delay 0.5)
  ;(+company/toggle-auto-completion)
  )
(after! tramp
  (setq password-cache-expiry nil))
(use-package! evil-textobj-line
  :after evil)
(after! vertico
  (setq +vertico-company-completion-styles '(flex orderless basic partial-completion)))
(after! consult
  (consult-customize
   consult-ripgrep consult-git-grep consult-grep
   consult-bookmark consult-recent-file
   +default/search-project +default/search-project-for-symbol-at-point
   +default/search-other-project
   +vertico/search-symbol-at-point +vertico/jump-list
   +default/search-cwd +default/search-other-cwd
   +default/search-notes-for-symbol-at-point consult--source-bookmark
   :preview-key (list (kbd "C-SPC") :debounce 0.5 'any))

  (map! :leader
        (:prefix ("s" . "search")
         :desc "jump to symbol (workspace)" "I" #'consult-imenu-multi)))

Programming

LSP

lsp-mode is noticeably faster (for python, anyways) than eglot as of the most recent release, Haven’t bothered to reconfigure much yet, but holding on to eglot options in case I switch back.

(when (modulep! :tools lsp )
  (if (modulep! :tools lsp +eglot)
      (use-package! eglot
        :commands (eglot eglot-ensure)
        :hook (csharp-mode . eglot-ensure)
        :config
        (setq eglot-send-changes-idle-time 0.01)
        ;; TODO: keybinds for shutdown/reconnect
        ;;(add-to-list 'eglot-ignored-server-capabilites :documentHighlightProvider)
        )
    ;; else
    (use-package lsp-ui
      :commands (lsp-ui-mode)
      :config
      (setq lsp-ui-doc-enable t
            lsp-ui-doc-use-childframe t
            lsp-ui-doc-position 'top
            lsp-ui-doc-include-signature t
            lsp-ui-doc-max-height 32
            lsp-ui-doc-max-width 70
            lsp-ui-sideline-enable nil
            lsp-ui-flycheck-list-position 'right
            lsp-lens-enable nil
            lsp-ui-peek-enable t
            lsp-ui-peek-list-width 60
            lsp-ui-peek-peek-height 25)
      (lsp-ui-doc-enable t))))
  • Note: the highlighting on hover can be too slow sometimes to keep up with some movements and isn’t great. If it doesn’t noticeably hurt performance, leaving it enabled and reducing eglot-send-changes-idle-time to 0 is good, otherwise just disable it. Everything else is solid.

lisp

(after! lispyville
  (setq lispyville-key-theme
        '((operators normal)
          c-w
          text-objects
          commentary
          (prettify insert)
          (atom-movement t)
          slurp/barf-lispy
          additional
          additional-insert))
  (lispyville-set-key-theme))

python

Fix: f-strings in python mode not inserting close quotation mark

(after! python
  (sp-local-pair '(python-mode) "f\"" "\"" :post-handlers '(:add sp-python-fix-tripple-quotes))
  (setq +python-ipython-repl-args '("-i" "--no-color-info" ;; "--simple-prompt"
                                    )))

Python LSP integration

Tbh I’m not super happy with any of the lsp options for python (especially compared to e.g. ccls, which is finicky to set up but extremely slick once it is). Genuinely unsure why the best completion I’ve tried is just out-of-box ipython repl, when all of these are supposedly the same jedi backend.

(after! (python (:or eglot lsp-mode))
  (after! eglot
       (add-to-list 'eglot-server-programs
                    `(python-mode . ("/Users/owen/Library/Python/3.9/bin/pylsp"))) ;; trying https://github.com/python-lsp/python-lsp-server, a fork of the palantir one
    )
  (after! lsp-mode
    (setq! lsp-pyls-plugins-pycodestyle-ignore "E501")
    (add-to-list 'lsp-disabled-clients '(python-mode . '(mspyls pyright jedi)))))

OCaml

(after! utop
  (setq! utop-command "dune utop . -- -emacs"))

For future reference: camlformat mystery error was caused by opam defaulting to a version that wasn’t semver enough

C

Even though I don’t ever actually compile C projects locally when it’s so much less hassle/ more consistent to test with valgrind etc on the linux.cs.uchicago.edu computers, this is necessary for keep ccls from yelling at me about missing headers with OpenMP

;; NOTE: pretty sure this is going to need updating/troubleshooting for M1
;; (after! ccls
;;       (setq ccls-initialization-options
;;             `(:index (:trackDependency 1 :threads 2)
;;               :clang ,(list
;;                        :extraArgs ["-isystem" "-isystem/Library/Developer/CommandLineTools/usr/include/c++/v1" "-isystem/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include" "-isystem/usr/local/include" "-isystem/opt/local/include/libomp" "-L/opt/local/lib/libomp"]
;;                        :resourceDir (cdr (doom-call-process "clang" "-print-resource-dir"))))))
;; (set-eglot-client! 'cc-mode '("ccls" "--init={\"index\": {\"threads\": 3}, \"clang\": {\"extraArgs\": [\"-isystem\", \"-isystem/Library/Developer/CommandLineTools/usr/include/c++/v1\", \"-isystem/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include\", \"-isystem/usr/local/include\", \"-isystem/opt/local/include/libomp\", \"-L/opt/local/lib/libomp\"], \"resourceDir\": \"/Library/Developer/CommandLineTools/usr/lib/clang/12.0.0\"}}"))
;;;
(add-to-list '+format-on-save-enabled-modes 'c-mode :append) ;; this confusingly is needed to disable formatting on save.

Julia

(after! (eglot eglot-jl)
  (setq eglot-jl-language-server-project "~/.julia/environments/v1.7"
        eglot-connect-timeout 60))

(after! (julia-mode lsp-julia)
  (add-hook! 'julia-mode-hook
    (setq-local lsp-enable-folding t
                lsp-folding-range-limit 100)) )

(after! (org emacs-jupyter)
  (setq org-babel-default-header-args:jupyter-julia '((:async . "yes")
                                                      (:session . "jl")
                                                      (:kernel . "julia-1.7"))))
(after! lsp-mode
  (lsp-register-client
   (make-lsp-client :new-connection (lsp-tramp-connection '+my/lsp-julia-tramp-command)
                    :major-modes '(julia-mode ess-julia-mode)
                    :server-id 'julia-ls-remote
                    :remote? t
                    :multi-root t)))

Go

Taken from https://github.com/golang/tools/blob/master/gopls/doc/emacs.md

(after! (go eglot project)
  (defun project-find-go-module (dir)
    (when-let ((root (locate-dominating-file dir "go.mod")))
      (cons 'go-module root)))

  (cl-defmethod project-root ((project (head go-module)))
    (cdr project))

  (add-hook 'project-find-functions #'project-find-go-module)

  (setq-default eglot-workspace-configuration
                '((:gopls .
                   ((staticcheck . t)
                    (matcher . "CaseSensitive"))))))

Plaintext

org

Mostly aesthetic changes to org.

package: org (builtin)

See also: org keybindings

;; has to be loaded ahead of time
(setq org-directory "~/Notes")
(use-package! org
  :defer t
  :hook (org-mode . toc-org-mode)
  :hook (org-mode . +org-pretty-mode)
  ;; :hook (org-mode . writeroom-mode)
  ;; :hook (org-mode . auto-fill-mode)
  :config
  (add-hook! org-mode (hl-line-mode -1))
  (set-company-backend! '(org-mode org-roam-mode)
    'company-capf)
  ;; basic settings
  (setq org-directory            "~/Notes" ;; now symlinked to icloud documents for app on mac
        org-agenda-files         (list org-directory)
        org-src-window-setup     'plain
        org-use-sub-superscripts '{}
        org-export-with-toc      nil
        org-export-with-section-numbers nil
        org-export-with-sub-superscripts '{}
        org-export-with-entities t
        org-imenu-depth          9
        org-startup-folded       'content)  ;; showeverything ;; t ;; nil

  ;; fontifying, keywords
  (setq org-ellipsis                      ""
        org-todo-keywords                 '((sequence "[ ](t)" "[~](p)" "[*](w)" "[!](r)" "|"
                                                      "[X](d)" "[-](k)")
                                            (sequence "TODO(T)" "PROG(P)" "WAIT(W)" "WARN(R)" "|"
                                                      "DONE(D)" "DROP(K)"))
        org-todo-keyword-faces            '(("[~]"   . +org-todo-active)
                                            ("[*]"   . +org-todo-onhold)
                                            ("[!]"   . compilation-error)
                                            ("WARN"  . compilation-error)
                                            ("PROG"  . +org-todo-active)
                                            ("WAIT"  . +org-todo-onhold)))
  ;; inline LaTeX/math-related
  (sp-local-pair '(org-mode) "$" "$")
  (setq org-preview-latex-default-process 'dvisvgm ;'imagemagick ;'dvipng
        org-startup-with-latex-preview nil
        org-highlight-latex-and-related nil
        org-latex-packages-alist  '(("kw" "pseudo" t)
                                    ("" "tabularx" t)
                                    ("margin=2cm" "geometry" nil))
        ;; pseudocode and convenience \mathbb{} macros
        org-format-latex-header (concat org-format-latex-header "\n"
                                        "\\pseudodefinestyle{fullwidth}{begin-tabular=\\tabularx{\\linewidth}{@{} r>{\\pseudosetup} X>{\\leavevmode\\small\\color{black!60}} p{0.45\\linewidth} @{}}, end-tabular=\\endtabularx, setup-append=\\pseudoeq}" "\n"
                                        "\\newcommand{\\R}{\\mathbb{R}}" "\n" "\\newcommand{\\N}{\\mathbb{N}}" "\n" "\\newcommand{\\Z}{\\mathbb{Z}}" "\n" "\\newcommand{\\Q}{\\mathbb{Q}}" "\n")
        org-format-latex-options '(:foreground default
                                   :background default
                                   :scale 1.0
                                   :html-scale 1.0
                                   :html-foreground "Black"
                                   :html-background "Transparent"
                                   :matchers ("begin" "$1" "$" "$$" "\\(" "\\["))))
(after! visual-fill-column
  (setq visual-fill-column-width 100))
package: org-superstar
(use-package! org-superstar ; "prettier" bullets
  :hook (org-mode . org-superstar-mode)
  :config
  (setq org-superstar-headline-bullets-list '("" "" "" "" "" "")  ;; '("#")
        org-superstar-prettify-item-bullets t
        org-superstar-item-bullet-alist
        '((?* . )
          (?+ . )
          (?- . ?›))
        org-superstar-special-todo-items nil))
package: org-noter
(use-package! org-noter
  :defer t
  :config
  (map! :map org-noter-notes-mode-map
        :n [ret] #'org-noter-sync-current-note)
  (map! :map org-noter-doc-mode-map
        :n [ret] #'org-noter-sync-current-page-or-chapter))
package: org-roam

I’m a pretty big fan of this package, though it changes pretty rapidly and think a fair bit of my config is outdated. I really like the [[roam:]] links and the completion at point is excellent, but I’d prefer them to look like regular links. Havent taken the time to figure out the font-lock options or whatever for that. See also: org-roam keybindings

(defun +my/org-init-roam-h ()
    "Setup `org-roam' but don't immediately initialize its database.
Instead, initialize it when it will be actually needed."
    (letf! ((#'org-roam-db-sync #'ignore))
      (org-roam-db-autosync-enable)))
(use-package! org-roam
  :defer t
  ;; :hook (org-load . +my/org-init-roam-h)
  :init
  (setq! org-roam-directory               "~/Notes"
         org-roam-graph-max-title-length  40
         org-roam-completion-everywhere   nil
         org-roam-graph-shorten-titles    'truncate
         org-roam-graph-viewer            (executable-find "open")
         org-roam-graph-executable        "dot")
  ;; (remove-hook 'org-roam-buffer-prepare-hook 'org-roam-buffer--insert-ref-links)
  ;; (add-hook! 'org-roam-buffer-prepare-hook #'outline-hide-body)
  (setq org-roam-capture-ref-templates `(("r" "ref" plain "%?"
                                          :if-new (file+head "%<%Y-%m-%d>-${slug}.org" ,(concat "#+title: ${title}\n"
                                                                                                "#+setupfile: setup.org\n"
                                                                                                "* Notes: \n"
                                                                                                "* Etc: \n"
                                                                                                "  - [[${ref}][link]]\n"))
                                          :unnarrowed t))
        org-roam-capture-templates `(("d" "default" plain "%?"
                                      :if-new (file+head "%<%Y-%m-%d>-${slug}.org" ,(concat "#+title: ${title}\n"
                                                                                            "#+setupfile: setup.org\n"
                                                                                            "* Notes: \n"
                                                                                            "* Etc: \n"))
                                      :unnarrowed t)))
  :config
  (setq org-roam-verbose t
        org-roam-mode-section-functions (list #'org-roam-backlinks-section
                                              ;; #'org-roam-reflinks-section
                                              #'org-roam-unlinked-references-section)))
package: mathpix
(use-package! mathpix
  :commands (mathpix-screenshot)
  :config
  (setq mathpix-app-id            (password-store-get "mathpix.com/app-id")
        mathpix-app-key           (password-store-get "mathpix.com/app-key")
        mathpix-screenshot-method "screencapture -i %s"))
package: org-download
(use-package! org-download
  :commands
  org-download-dnd
  org-download-yank
  org-download-screenshot
  org-download-clipboard
  :config
  (setq org-download-image-org-width 500))

Keybindings

Best-organized section of my config by far. Some of these are from transitioning from spacemacs, but most of them are newer; the map! macro is easily one of my favorite parts about the doom emacs distribution.

Highlights:

  • following a “missed snipe” motion from evil-snipe package, s-; will execute an avy-goto-char-2 with those characters, so you can move where you meant to.
  • Under the SPC t /”toggle” prefix, m/f/d toggle frame maximized/fullscreen/decorated parameters, respectively

leader key / variables

(setq  doom-leader-key "SPC"
       doom-localleader-key ","
       doom-leader-alt-key "C-SPC"
       doom-localleader-alt-key "C-,")
(use-package! expand-region
  :config
  (setq expand-region-contract-fast-key "V"))

evil-snipe/evil-easymotion/avy

(use-package! evil-snipe
  :init
  (setq evil-snipe-scope                     'whole-visible
        evil-snipe-spillover-scope           'whole-buffer
        evil-snipe-repeat-scope              'buffer
        evil-snipe-tab-increment             t
        evil-snipe-repeat-keys               t
        evil-snipe-override-evil-repeat-keys t)
  :config
  ;; when f/t/s searching, interpret open/close square brackets to be any
  ;; open/close delimiters, respectively
  (push '(?\[ "[[{(<]") evil-snipe-aliases)
  (push '(?\] "[]})>]") evil-snipe-aliases)
  ;; "s-;" pre-fills avy-goto-char-2 with most recent snipe
  (map! :map (evil-snipe-parent-transient-map evil-snipe-local-mode-map)
        "s-;" (cmd! (if evil-snipe--last
                        (let ((most-recent-chars (nth 1 evil-snipe--last)))
                          (if (eq 2 (length most-recent-chars))
                              (apply #'avy-goto-char-2 most-recent-chars)
                            (call-interactively #'avy-goto-char-2))))))
  (evil-snipe-override-mode +1))

top-level

[tab] and jump-list

(map! :nv [tab]  #'evil-jump-item
      (:when (modulep! :ui workspaces)
       :g [C-tab] #'+workspace/switch-right)

      :m "C-S-o" #'better-jumper-jump-forward
      :g "C-s-o" #'+vertico/jump-list)

multiedit

(map! :nv "R"  #'evil-multiedit-match-all
      :n "s-d" #'evil-multiedit-match-symbol-and-next
      :n "s-D" #'evil-multiedit-match-symbol-and-prev
      :v "s-d" #'evil-multiedit-match-and-next
      :v "s-D" #'evil-multiedit-match-and-prev
      (:after evil-multiedit
       (:map evil-multiedit-mode-map
        :n "n"    #'evil-multiedit-next
        :n "N"    #'evil-multiedit-prev
        :n "V"    #'iedit-show/hide-context-lines
        "s-d"  #'evil-multiedit-match-and-next
        "s-D"  #'evil-multiedit-match-and-prev)))

leader

(map! :leader
      :desc "Search project" "/" #'+default/search-project
      :desc "Visual expand" "v" #'er/expand-region
      :desc "Switch buffer" "," #'switch-to-buffer

      (:prefix ("w" . "window")
       :desc "Switch to last window" "w"    #'evil-window-mru)

      (:prefix ("b" . "buffer")
       :desc "Fallback buffer"        "h"   #'+doom-dashboard/open
       :desc "Messages buffer"        "m"   #'view-echo-area-messages
       :desc "ibuffer (other window)" "I"   #'ibuffer-other-window)


      (:prefix ("f" . "file")
       :desc "find file new window"   "F"   #'find-file-other-window)

      (:when (modulep! :completion vertico)
       (:prefix ("s" . "search")
        :desc "imenu (multi)" "i" #'consult-imenu-multi))


      (:prefix ("t"  "toggle")
       ;; :desc "toggle writeroom hook"  "W" (cmd! (if (memq 'writeroom-mode org-mode-hook) (add-hook! org-mode :remove #'writeroom-mode) (add-hook! org-mode :append #'writeroom-mode)))

       :desc "toggle fullscreen" "F" #'toggle-frame-fullscreen
       :desc "toggle maximized" "M" #'toggle-frame-maximized
       :desc "toggle hl-line mode" "h" (cmd! (hl-line-mode (if hl-line-mode -1 +1)))
       :desc "toggle decorated"  "d" (cmd! (set-frame-parameter nil 'undecorated (not (frame-parameter nil 'undecorated)))))

      (:when (modulep! :emacs undo +tree)
       :desc "Undo tree"              "U"   #'undo-tree-visualize)

      (:when (modulep! :ui treemacs)
       :desc "Project sidebar"        "0"   #'+treemacs/toggle)

      (:when (modulep! :ui workspaces)
       (:prefix "TAB"
        :desc "Main workspace"       "`"    #'+workspace/switch-to-0
        :desc "Previous workspace"   "TAB"  #'+workspace/other
        :desc "Forward frame"        "f"    #'+evil/next-frame
        :desc "Backward frame"       "F"    #'+evil/previous-frame))

      :desc "M-x"                "SPC" #'execute-extended-command)


(after! evil-easymotion
  (map! :leader
        :desc "jump" "j" evilem-map)
  (map! :leader
        :prefix "j"
        "j" #'evil-avy-goto-char-2
        "m" #'+ivy/jump-list
        "l" #'evil-avy-goto-line
        "i" #'consult-imenu))
(after! lsp-mode
  (map! :leader
        :prefix "j"
        "i" #'lsp-ui-imenu))

local

org

(after! org
  (map! :map org-mode-map
        :localleader
        :desc "Sort"                     "S" #'org-sort
        :desc "preview LaTeX fragments"  "L" #'org-latex-preview
        :desc "toggle pretty-mode"   "p" #'+org-pretty-mode)
  (after! evil-org  ;; HACK - something funny w/ doom electric module, maybe? see org module's evil-org use package map! config
    (map! :map evil-org-mode-map
          :i [return]   #'org-return
          :i "RET"      #'org-return)))

org-roam

(map! :leader
      :prefix ("n" . "notes")
      :desc "roam buffer"        "r"  #'org-roam
      :desc "random note"        "R"  #'org-roam-node-random
      :desc "find"               "n"  #'org-roam-node-find
      :desc "insert"             "i"  #'org-roam-node-insert
      :desc "mathpix screenshot" "m"  #'mathpix-screenshot
      (:prefix ( "g" . "graph")
       ;; :desc "server view"       "s"  (cmd! (unless org-roam-server-mode
       ;;                                        (org-roam-server-mode))
       ;;                                      (browse-url
       ;;                                       (url-recreate-url
       ;;                                        (url-generic-parse-url
       ;;                                         (concat "http://" org-roam-server-host ":" (int-to-string org-roam-server-port))))))
       :desc "graph all"   "g"  #'org-roam-graph
       ;; :desc "graph connected" "c" (cmd!! #'org-roam-graph '(4)) ;; NOTE: C-u SPC n g g does this
       ))
(after! org-roam
  (map!
   :leader
   :prefix ("n" . "notes")
   :desc "daily entries map" "d" 'org-roam-dailies-map))

python

(map! :map python-mode-map
      :localleader
      :desc "ipython repl"         "I" #'+python/open-ipython-repl)
;; see: ccls navigation functions
(map! :map python-mode-map
      :m "C-h" #'evil-backward-section-begin
      :m "C-j" #'+evil/next-beginning-of-method
      :m "C-k" #'+evil/previous-beginning-of-method
      :m "C-l" #'evil-forward-section-begin )