Orchix
by Rhia, the Scheming Eunuch

Table of Contents

make yourself at home, there's cookies and punch by the door.

Bootstrap

~/.emacs.d/early-init.el

Emacs 27 introduced early-init.el, which is run before init.el, before package and UI initialization happens.

See: emacs#Early Init File and https://github.com/mnewt/dotemacs/blob/master/early-init.el

;; If an `.el' file is newer than its corresponding `.elc', load the `.el'.
(setq load-prefer-newer t)

;; Set Garbage Collection threshold to 1GB during startup. `gcmh' will clean
;; things up later.
(setq gc-cons-threshold 1073741824
      gc-cons-percentage 0.6)

;; Write any customizations to a temp file so they are discarded.
;; (setq custom-file (make-temp-file "custom-" nil ".el"))

;; Faster to disable these here (before they've been initialized)
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)

;; Give the frame basic coloring while waiting for the theme to load. The main
;; purpose of this is to not blind me when it's dark by flashing a screen full
;; of white. These colors are from leuven-dark.
(set-face-attribute 'default nil :background "#25202a" :foreground "#cfccd2")
;; Default frame settings. This is actually maximized, not full screen.
(push '(fullscreen . maximized) initial-frame-alist)
(push '(ns-transparent-titlebar . t) default-frame-alist)

;; Resizing the Emacs frame can be a terribly expensive part of changing the
;; font. By inhibiting this, we easily halve startup times with fonts that are
;; larger than the system default.
(setq frame-inhibit-implied-resize t
      frame-resize-pixelwise t)

;; Ignore X resources; its settings would be redundant with the other settings
;; in this file and can conflict with later config (particularly where the
;; cursor color is concerned).
(advice-add #'x-apply-session-resources :override #'ignore)

;; These are good notes on optimizing startup performance:
;; https://github.com/hlissner/doom-emacs/wiki/FAQ#how-is-dooms-startup-so-fast

;; Unset `file-name-handler-alist' too (temporarily). Every file opened and
;; loaded by Emacs will run through this list to check for a proper handler for
;; the file, but during startup, it won’t need any of them.
(defvar file-name-handler-alist-old file-name-handler-alist)
(setq file-name-handler-alist nil)
(add-hook 'emacs-startup-hook
          (lambda ()
            (setq file-name-handler-alist file-name-handler-alist-old)))

;; Disable `package' in favor of `elpaca'.
(setq package-enable-at-startup nil)

;; (menu-bar-mode -1)
;; (tool-bar-mode -1)
;; (scroll-bar-mode -1)
;; (fringe-mode 8)
;; (setq inhibit-startup-screen t)

(provide 'early-init)

;;; early-init.el ends here

~/.emacs.d/init.el

;(let ((gc-cons-percentage .6)
;      (gc-cons-threshold most-positive-fixnum)
;      (read-process-output-max (* 1024 1024)))

  ;; Disable that pesky echo message
  (setq inhibit-startup-echo-area-message (user-login-name))

  ;; Elpaca
  (defvar elpaca-installer-version 0.12)
  (defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
  (defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
  (defvar elpaca-sources-directory (expand-file-name "sources/" elpaca-directory))
  (defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
                                :ref nil :depth 1 :inherit ignore
                                :files (:defaults "elpaca-test.el" (:exclude "extensions"))
                                :build (:not elpaca-activate)))
  (let* ((repo  (expand-file-name "elpaca/" elpaca-sources-directory))
         (build (expand-file-name "elpaca/" elpaca-builds-directory))
         (order (cdr elpaca-order))
         (default-directory repo))
    (add-to-list 'load-path (if (file-exists-p build) build repo))
    (unless (file-exists-p repo)
      (make-directory repo t)
      (when (<= emacs-major-version 28) (require 'subr-x))
      (condition-case-unless-debug err
          (if-let* ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
                    ((zerop (apply #'call-process `("git" nil ,buffer t "clone"
                                                    ,@(when-let* ((depth (plist-get order :depth)))
                                                        (list (format "--depth=%d" depth) "--no-single-branch"))
                                                    ,(plist-get order :repo) ,repo))))
                    ((zerop (call-process "git" nil buffer t "checkout"
                                          (or (plist-get order :ref) "--"))))
                    (emacs (concat invocation-directory invocation-name))
                    ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
                                          "--eval" "(byte-recompile-directory \".\" 0 'force)")))
                    ((require 'elpaca))
                    ((elpaca-generate-autoloads "elpaca" repo)))
              (progn (message "%s" (buffer-string)) (kill-buffer buffer))
            (error "%s" (with-current-buffer buffer (buffer-string))))
        ((error) (warn "%s" err) (delete-directory repo 'recursive))))
    (unless (require 'elpaca-autoloads nil t)
      (require 'elpaca)
      (elpaca-generate-autoloads "elpaca" repo)
      (let ((load-source-file-function nil)) (load "./elpaca-autoloads"))))
  (add-hook 'after-init-hook #'elpaca-process-queues)
  (elpaca `(,@elpaca-order))

  (elpaca elpaca-use-package
    (elpaca-use-package-mode))

(load "~/.emacs.d/orchix.el" t t nil t)
(load "~/.emacs.d/secret.el" t t nil t)
(setq custom-file "~/.emacs.d/custom.el")
;; (load custom-file t)
;)

~/.emacs.d/orchix.el

Core Settings

;; leaves moving with the wind,
;; the defiant tree stands strong
(defalias 'up #'use-package)

(require 'cl-lib)

;;(setq warning-suppress-log-types '((package reinitialization)))

(setq use-package-always-ensure t)


(up emacs
  :ensure nil
  :init
  (scroll-bar-mode -1)
  (menu-bar-mode t)
  (tool-bar-mode -1)
  :custom
  (ring-bell-function #'ignore)
  (garbage-collection-messages t)
  (cursor-type 'bar)
  (blink-cursor-mode nil))

(when window-system
  (setq
   ;; ns-use-proxy-icon nil  ; whoa the icon lets u drag files
   ;; Smoother and nicer scrolling
   scroll-margin 6
   scroll-step 1
   scroll-conservatively 10000
   scroll-preserve-screen-position 1
   auto-window-vscroll nil
   ;; No GUI dialogs
   use-dialog-box nil)
  )

(up gcmh
  :init
  (gcmh-mode 1))

;; for gcl common lisp spec
;; wanna work out quick lookup in lisp-mode
;; for now, "C-c i" works well enough.
;; (add-hook 'Info-mode-hook #'(lambda ()
;;                               (add-to-list 'Info-directory-list
;;                                            (expand-file-name "~/.info"))))

(setf tab-always-indent 'complete)

;; Keep all backup and auto-save files in one directory
(setq backup-directory-alist '(("." . "~/.config/emacs/backups")))
(setq auto-save-file-name-transforms '((".*" "~/.config/emacs/auto-save-list/" t)))

;; UTF-8 please
(setq locale-coding-system 'utf-8) ; pretty
(set-terminal-coding-system 'utf-8) ; pretty
(set-keyboard-coding-system 'utf-8) ; pretty
(set-selection-coding-system 'utf-8) ; please
(prefer-coding-system 'utf-8) ; with sugar on top
(set-language-environment 'utf-8) ; fix mu compose?

;;  (setq confirm-kill-processes nil)
(setq-default
 help-window-select t        ;; Focus new help windows when opened
 ;; debug-on-error t
 ;;   indent-tabs-mode nil        ;; Adjust indent using 'space', not 'tab'
 ;;   jit-lock-defer-time 0       ;; Defer fontification while there is input pending
 window-combination-resize t ;; Resize windows proportionally
 ;;   history-delete-duplicates t
 )

(setf display-time-default-load-average nil)
(setq display-time-day-and-date t)
(display-battery-mode -1)
(display-time-mode 1)

(setq calendar-longitude 115.919)
(setq calendar-latitude -32.013)
(setq calendar-location-name "Boorloo")

;; Maybe I want double spaces, but not right now. Not like this.
(setq sentence-end-double-space nil)

;;  Save recent files list periodically, when emacs has been idle for a while,
;; because it will otherwise not be saved when emacs runs in server mode.
;;  (run-with-idle-timer 600 t (lambda ()
;;                              (let ((save-silently t))
;;                               (recentf-save-list))))

;; (when window-system
;;   ;; wtf nah m8    (blink-cursor-mode 0)       ;; Disable the cursor blinking
;;   (tooltip-mode 0)         ;; Disable the tooltips
;;   )

(xterm-mouse-mode)  ; emacs mouse in terminal mode (emacs -nw)
(tool-bar-mode -1)  (scroll-bar-mode -1)  (display-battery-mode)
;; (setq-default line-spacing '(1 . 1))
(use-package ace-window
  :ensure t  :demand t  :config
  (global-set-key (kbd "M-o") 'ace-window))

;; Project
(setf project-mode-line t)

;; Org Mode
(setq org-babel-python-command "python3")

;; make the up down arrow keys move based on logical lines. logical lines means separated by newline character.
(setq line-move-visual nil)

;; Git
(use-package magit
  :ensure t)

;; Ugh MacOS Env is borked
;; (when (memq window-system '(mac ns x))
;;   (exec-path-from-shell-initialize))

;; (use-package eldoc-mouse :ensure t
;;   :bind (:map eldoc-mouse-mode-map
;;               ("<f1> <f1>" . eldoc-mouse-pop-doc-at-cursor))
;;   :hook (eglot-managed-mode emacs-lisp-mode))

;; ;; Mode Hooks
;; (defvar newcomers-presets-mode-enabled-local-modes
;;   `((prog-mode-hook ;;,#'display-line-numbers-mode
;;      ,#'flymake-mode
;;      ,#'flyspell-prog-mode)

;;     (text-mode-hook ,#'display-line-numbers-mode
;;                     ,#'flyspell-mode))
;;   "Alist mapping hooks to a list of function to add to the hook.
;; The functions are added to the corresponding hooks when enabling
;; `newcomers-presets-mode', and removed when disabling the mode.")
  • TODO Follow Mode is cool

    Can I make it so that New Page characters split the page?

  • System Specific
    (cl-case system-type
      (darwin
       (message "hi"))
      (android
       (message "hello")))
    
    (cond ((eq system-type 'android)
           (setq overriding-text-conversion-style nil  ; fixes lispy not getting input
                 touch-screen-display-keyboard t  ; toucha-toucha-touch screeeeen
                 touch-screen-precision-scroll t))
    
          ((eq system-type 'darwin)  ; MacOS
           ;; (add-to-list 'Info-directory-list "/opt/homebrew/Cellar/gforth/0.7.3_3/share/info")
           (setf ns-use-native-fullscreen nil) ; don't switch to new workspace
           (use-package exec-path-from-shell
             :init
             (exec-path-from-shell-initialize)
             (exec-path-from-shell-copy-envs '("LIBRARY_PATH" "INFOPATH" "CPATH" "MANPATH")))))
    
  • Org Navigation

    with cursor on a * heading:

    • ? help
    • n next
    • p prev
    • s narrow
  • Page based navigation changed my life
  • org-tree-to-indirect-buffer

    Alternatively, if you must use org-tree-to-indirect-buffer, it looks like you could also do this:

    (setq org-indirect-buffer-display 'current-window)

    C-u M-x org-tree-to-indirect-buffer

    Where the normal action is to prevent buffer proliferation, but with the universal arg it will open a 2nd subtree without trashing the previous buffer. Check C-h f org-tree-to-indirect-buffer for full details.

UI & UX

  • Theme

    I like:

    light
    acme silkworm autumn-light
    dark
    modus-vivendi-tinted starlit chocolate farmhouse-dark
    packs
    ef-themes alabaster-themes doric-themes modus-flexoki lambda-themes
    (up ef-themes
      :init
      (load-theme 'ef-fig t))
    
  • Mode Line
    (setf display-time-default-load-average nil)
    (setq display-time-day-and-date nil)
    (display-battery-mode -1)
    (display-time-mode -1)
    
    ;; (use-package hide-mode-line
    ;;   :hook (dashboard-mode . hide-mode-line-mode))
    
      ;; (up mood-line
      ;;   :config (mood-line-mode 1))
    
  • Fonts

    get the facts:

    • Go Mono is a perfect font
    • Ponic Mono is a
    (defun rio/font (&optional font)
      "Pick a default font and it's size for all frames."
      (interactive)
      (modify-all-frames-parameters
       `((font . ,(or font
                      ;; switch to counsel to get completion for fonts
                      ;; other than my besties? (counsel-fonts)
                      (ivy-read "sitelen?  "
                                (list "ponicMono-10"
                                      "Go Mono-10"
                                      "ponicMono-18"
                                      "Go Mono-18")))))))
    ;; (bind-key "C-c f" 'rio/font)
    
    
    ;; Add a font for Japanese characters
    ;; The coverage is weird tho...
    ;; (日本語)        こんにちは / コンニチハ
    (set-fontset-font "fontset-default" 'japanese-jisx0208
                      '("HakusyuGyosyoNenga" . "iso10646-1"))
    
    ;; Finding the Face at Point You can use ` C-u C-x = ' to find out
    ;; which faces are applied to the text at point (under the cursor).
    ;; Alternatively, you can use 'M-x describe-face RET' .
    ;; (set-frame-font "ponicMono-12")
    ;; (set-frame-font "Go Mono-12")
    
    ;; Prolly work out the modus way to do this, incl colour
    ;; (set-face-font 'default "Go Mono-12")
    
    ;; mode-line inactive doesn't inherit this...
    ;; (set-face-font 'mode-line "ponicMono-14")
    
    ;; (set-face-attribute 'default nil :family "Go Mono" :height 142)
    ;; (set-face-attribute 'default nil :family "Aporetic Sans Mono" :height 160)
    ;; (set-face-attribute 'variable-pitch nil :family "Aporetic Sans" :height 1.0)
    ;; (set-face-attribute 'fixed-pitch nil :family "Aporetic Sans Mono" :height 1.0)
    
    ;; (rio/font "PonicMono-12")
    ;; (rio/font "Go Mono-12")
    ;; (setq-default line-spacing '(1 . 1))
    
    (set-face-font 'default "Go Mono-12")
    
    • TODO Add tokipona font.
  • Window Management
    (setq
     kill-buffer-quit-windows t
     quit-window-kill-buffer t)
    
  • Dashboard
    (use-package dashboard
      :config
      (setq
       dashboard-banner-logo-title "Orchix"
       dashboard-items '((agenda    . 5)
                         (recents   . 5)
                         (bookmarks . 5)
                         ;; (registers . 5)
                         (projects  . 5))
       dashboard-startupify-list '(dashboard-insert-banner
                                   dashboard-insert-newline
                                   dashboard-insert-banner-title
                                   ;; dashboard-insert-newline
                                   ;; dashboard-insert-navigator
                                   ;; dashboard-insert-newline
                                   ;; dashboard-insert-init-info
                                   dashboard-insert-items
                                   ;; dashboard-insert-newline
                                   ;; dashboard-insert-footer
                                   )
       dashboard-agenda-sort-strategy '(time-up))
    
      (setq dashboard-icon-type 'all-the-icons)
      (setq dashboard-startup-banner 'logo)
      (add-hook 'elpaca-after-init-hook #'dashboard-insert-startupify-lists)
      (add-hook 'elpaca-after-init-hook #'dashboard-initialize)
      (dashboard-setup-startup-hook)
      (setq initial-buffer-choice 'dashboard-open))
    
  • Windowing and Buffering
    ;;; Emacs X-less Window Manager
    ;; i miss EXWM :c
    ;; should i use frames for multitasking? probably
    (dolist (bind-cons
             '(("M-o"       . ace-window)
               ("C-x o"       . ace-window)
               ("M-<tab>"   . mode-line-other-buffer)
               ("C-x C-b"   . bs-show)))
      (funcall (lambda (cons)
                 (keymap-global-set (car cons) (cdr cons)))
               bind-cons))
    
  • Helpful
    (up helpful
      :config
      ;; Note that the built-in `describe-function' includes both functions
      ;; and macros. `helpful-function' is functions only, so we provide
      ;; `helpful-callable' as a drop-in replacement.
      (global-set-key (kbd "C-h f") #'helpful-callable)
    
      (global-set-key (kbd "C-h v") #'helpful-variable)
      (global-set-key (kbd "C-h k") #'helpful-key)
    
      ;; Lookup the current symbol at point. C-c C-d is a common keybinding
      ;; for this in lisp modes.
      (global-set-key (kbd "C-c C-d") #'helpful-at-point)
    
      ;; Look up *F*unctions (excludes macros).
      ;;
      ;; By default, C-h F is bound to `Info-goto-emacs-command-node'. Helpful
      ;; already links to the manual, if a function is referenced there.
      (global-set-key (kbd "C-h F") #'helpful-function)
    
      ;; Look up *C*ommands.
      ;;
      ;; By default, C-h C is bound to describe `describe-coding-system'. I
      ;; don't find this very useful, but it's frequently useful to only
      ;; look at interactive functions.
      (global-set-key (kbd "C-h C") #'helpful-command))
    
  • Binds

    Should binds be in their use-packages or here?

    ;; for stump xmodmap
    (unbind-key (kbd "<f20>"))
    
    ;; MacBook scroll momentum pain fix
    (unbind-key (kbd "C-<mouse-4>"))
    (unbind-key (kbd "C-<mouse-5>"))
    (unbind-key (kbd "C-<wheel-down>"))
    (unbind-key (kbd "C-<wheel-up>"))
    
    ;;; Org
    (global-set-key (kbd "C-c l") #'org-store-link)
    (global-set-key (kbd "C-c a") #'org-agenda)
    (global-set-key (kbd "C-c c") #'org-capture)
    
    ;; random binds
    (bind-key* "M-o" 'ace-window)
    (bind-key "<f5>"
              (lambda ()
                (interactive)
                (find-file "~/jnl.org")))
    
      ;;(bind-key "<f6>" 'eshell)
    
  • vundo
    (up vundo
      :bind* (("C-x u" . vundo)))
    
  • Tab Navigation

    adapted from https://www.gonsie.com/blorg/tab-bar.html

    ;; (when (< 26 emacs-major-version)  ; do i rly need to support old versions...
    (use-package tab-bar
      :ensure nil
      :demand t
      :custom
      ;; Use package :custom autocomplete variable names?
      (tab-bar-show 1)
      ;; (tab-bar-new-tab-choice "*dashboard*")  ; TODO should this use the function??
      (tab-bar-new-tab-choice 'dashboard-open)
      (tab-bar-close-button-show nil)
      (tab-bar-tab-hints t)
      (tab-bar-auto-width nil)
      (tab-bar-separator " ")
      (tab-bar-format '( ;; tab-bar-format-menu-bar  ; TODO possibly only show on linux
                        ;; (lambda () "Orchix")
                        tab-bar-format-tabs-groups
                        Tab-bar-format-tabs tab-bar-separator
                        tab-bar-format-add-tab
                        tab-bar-format-align-right tab-bar-format-global))
      :init
      (setq display-time-day-and-date t)
      (display-time-mode t)
      (display-battery-mode t)
      (setq mode-line-misc-info nil)
    
      ;; (defun tab-bar-tab-name-format-hints (name _tab i)
      ;;   (if tab-bar-tab-hints (concat (format "(%d) " i) name ".") name))
    
      ;;; --- UTILITIES FUNCTIONS
      (defun emacs-solo/tab-group-from-project ()
        "Call `tab-group` with the current project name as the group."
        (interactive)
        (when-let* ((proj (project-current))
                    (name (file-name-nondirectory
                           (directory-file-name (project-root proj)))))
          (tab-group (format "[%s]" name))))
    
      (defun emacs-solo/tab-switch-to-group ()
        "Prompt for a tab group and switch to its first tab.
    Uses position instead of index field."
        (interactive)
        (let* ((tabs (funcall tab-bar-tabs-function)))
          (let* ((groups (delete-dups (mapcar (lambda (tab)
                                                (funcall tab-bar-tab-group-function tab))
                                              tabs)))
                 (group (completing-read "Switch to group: " groups nil t)))
            (let ((i 1) (found nil))
              (dolist (tab tabs)
                (let ((tab-group (funcall tab-bar-tab-group-function tab)))
                  (when (and (not found)
                             (string= tab-group group))
                    (setq found t)
                    (tab-bar-select-tab i)))
                (setq i (1+ i)))))))
    
      ;;; --- EXTRA KEYBINDINGS
      (global-set-key (kbd "C-x t P") #'emacs-solo/tab-group-from-project)
      (global-set-key (kbd "C-x t g") #'emacs-solo/tab-switch-to-group)
      ;; these mirror "safari" but i wonder how universal they are...
      (global-set-key (kbd "s-{") 'tab-bar-switch-to-prev-tab)
      (global-set-key (kbd "s-}") 'tab-bar-switch-to-next-tab)
      (global-set-key (kbd "s-t") 'tab-bar-new-tab)
      (global-set-key (kbd "s-w") 'tab-bar-close-tab)
      (global-set-key (kbd "s-r") 'tab-bar-rename-tab)
      ;; in ff on mac, these are back and forward
      ;; TODO do buffer walking??
      (global-set-key (kbd "s-[") 'tab-bar-switch-to-prev-tab)
      (global-set-key (kbd "s-]") 'tab-bar-switch-to-next-tab)
      ;; i think these should be bound automagically but they arent.
      (global-set-key (kbd "s-1") 'tab-bar-select-tab)
      (global-set-key (kbd "s-2") 'tab-bar-select-tab)
      (global-set-key (kbd "s-3") 'tab-bar-select-tab)
      (global-set-key (kbd "s-4") 'tab-bar-select-tab)
      (global-set-key (kbd "s-5") 'tab-bar-select-tab)
      (global-set-key (kbd "s-6") 'tab-bar-select-tab)
    
      (tab-bar-mode 1))
    
  • Completion and Minibuffer
      (up vertico
        :custom
        (vertico-scroll-margin 0)
        (vertico-count 10)
        (vertico-resize t)
        (vertico-cycle t)
        :config
        (keymap-set vertico-map "M-q" #'vertico-quick-insert)
        (keymap-set vertico-map "C-q" #'vertico-quick-exit)
        ;; (setq vertico-scroll-margin 0
        ;;  vertico-count 20
        ;;  vertico-resize t
        ;;  vertico-cycle t)
        :init
        (vertico-mode)
        ;; (vertico-reverse-mode)
    
        ;; Enable vertico-multiform
        (vertico-multiform-mode)
    
        ;; Configure the display per command.
        ;; Use a buffer with indices for imenu
        ;; and a flat (Ido-like) menu for M-x.
        (setq vertico-multiform-commands
                    '(
                      ;; (consult-imenu buffer indexed)
                ;; (execute-extended-command unobtrusive)
                      ))
    
        ;; Configure the display per completion category.
        ;; Use the grid display for files and a buffer
        ;; for the consult-grep commands.
        (setq vertico-multiform-categories
                    '(;; (file grid)
                (consult-grep buffer)))
    
        ;; Configure `consult-outline' as a scaled down TOC in a separate buffer
        (setq vertico-multiform-commands
            `((consult-outline ;; buffer
               ,(lambda (_) (text-scale-set -1)))))
    
        ;; Configure the buffer display and the buffer display action
        (setq vertico-multiform-categories
            '((consult-grep
                 buffer
                 (vertico-buffer-display-action display-buffer-in-direction
                                                (direction . above)
                                                (window-height . 20)))))
    
        ;; Disable preview for consult-grep commands
       ;; (consult-customize consult-ripgrep consult-git-grep consult-grep :preview-key nil)
    
        ;; (vertico-mouse-mode)
        )
    
      ;; Configure directory extension.
      (use-package vertico-directory
        :after vertico
        :ensure nil
        ;; More convenient directory navigation commands
        :bind (:map vertico-map
                    ("RET" . vertico-directory-enter)
                    ("DEL" . vertico-directory-delete-char)
                    ("M-DEL" . vertico-directory-delete-word))
        ;; Tidy shadowed file names
        :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
    
      ;; Persist history over Emacs restarts. Vertico sorts by history position.
      (up savehist
        :ensure nil
        :config
        (savehist-mode))
    
      ;; Emacs minibuffer configurations.
      (use-package emacs
        :ensure nil
        :config
        (setq read-file-name-completion-ignore-case t
                    read-buffer-completion-ignore-case t
                    completion-ignore-case t)
    ;;  (setq completion-styles '(basic substring partial-completion flex))
        :custom
        ;; Enable context menu. `vertico-multiform-mode' adds a menu in the minibuffer
        ;; to switch display modes.
        (context-menu-mode t)
        ;; Support opening new minibuffers from inside existing minibuffers.
        (enable-recursive-minibuffers t)
        ;; Hide commands in M-x which do not work in the current mode.  Vertico
        ;; commands are hidden in normal buffers. This setting is useful beyond
        ;; Vertico.
        (read-extended-command-predicate #'command-completion-default-include-p)
        ;; Do not allow the cursor in the minibuffer prompt
        (minibuffer-prompt-properties
         '(read-only t cursor-intangible t face minibuffer-prompt)))
    
      ;; Optionally use the `orderless' completion style.
      (use-package orderless
        :custom
        ;; Configure a custom style dispatcher (see the Consult wiki)
        ;; (orderless-style-dispatchers '(+orderless-consult-dispatch orderless-affix-dispatch))
        ;; (orderless-component-separator #'orderless-escapable-split-on-space)
        (completion-styles '(orderless basic))
        (completion-category-overrides '((file (styles partial-completion))))
        (completion-category-defaults nil) ;; Disable defaults, use our settings
        (completion-pcm-leading-wildcard t)) ;; Emacs 31: partial-completion behaves like substring
    
      ;; Enable rich annotations using the Marginalia package
      (up marginalia
        ;; Bind `marginalia-cycle' locally in the minibuffer.  To make the binding
        ;; available in the *Completions* buffer, add it to the
        ;; `completion-list-mode-map'.
        ;; :bind (:map minibuffer-local-map
        ;;        ("M-A" . marginalia-cycle))
    
        :config
        (marginalia-mode))
    
      ;; A few more useful configurations...
      (use-package emacs
        :ensure nil
        :custom
        ;; TAB cycle if there are only few candidates
        ;; (completion-cycle-threshold 3)
    
        ;; Enable indentation+completion using the TAB key.
        ;; `completion-at-point' is often bound to M-TAB.
        (tab-always-indent 'complete)
    
        ;; Emacs 30 and newer: Disable Ispell completion function.
        ;; Try `cape-dict' as an alternative.
        (text-mode-ispell-word-completion nil)
    
        ;; Hide commands in M-x which do not apply to the current mode.  Corfu
        ;; commands are hidden, since they are not used via M-x. This setting is
        ;; useful beyond Corfu.
        (read-extended-command-predicate #'command-completion-default-include-p))
    
  • Corfu - in-buffer completion
    (use-package corfu
      :after orderless
      :custom
      (corfu-cycle t)       ;; Enable cycling for `corfu-next/previous'
      (corfu-auto t)        ;; Enable auto completion
      (corfu-separator ?\s) ;; Orderless field separator
      (corfu-quit-at-boundary nil) ;; Never quit at completion boundary
      (corfu-quit-no-match nil) ;; Never quit, even if there is no match
      (corfu-preview-current nil) ;; Disable current candidate preview
      ;; (corfu-preselect-first nil)    ;; Disable candidate preselection
      ;; (corfu-on-exact-match nil)     ;; Configure handling of exact matches
      ;; (corfu-echo-documentation nil) ;; Disable documentation in the echo area
      (corfu-scroll-margin 5) ;; Use scroll margin
      ;; Enable Corfu only for certain modes.
      :hook ((prog-mode . corfu-mode)
             (shell-mode . corfu-mode)
             (eshell-mode . corfu-mode))
      ;; Recommended: Enable Corfu globally.
      ;; This is recommended since Dabbrev can be used globally (M-/).
      ;; See also `corfu-excluded-modes'.
      :init
      (global-corfu-mode) ; This does not play well in eshell if you run a repl
      ;;   ;; Enable optional extension modes:
      ;;   ;; (corfu-history-mode)
      ;;   ;; (corfu-popupinfo-mode)
      ;; (setq corfu-auto t)
      )
    
  • Whichkey
    (up which-key
      ;;:diminish which-key-mode
      :config
      (which-key-mode t)
      (setq which-key-idle-delay 0.3))
    
  • Consult
    ;; Example configuration for Consult
    (use-package consult
      ;; Replace bindings. Lazily loaded by `use-package'.
      :bind (;; C-c bindings in `mode-specific-map'
             ("C-c M-x" . consult-mode-command)
             ("C-c h" . consult-history)
             ("C-c k" . consult-kmacro)
             ("C-c m" . consult-man)
             ("C-c i" . consult-info)
             ([remap Info-search] . consult-info)
             ;; C-x bindings in `ctl-x-map'
             ("C-x M-:" . consult-complex-command)     ;; orig. repeat-complex-command
             ("C-x b" . consult-buffer)                ;; orig. switch-to-buffer
             ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
             ("C-x 5 b" . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
             ("C-x t b" . consult-buffer-other-tab)    ;; orig. switch-to-buffer-other-tab
             ("C-x r b" . consult-bookmark)            ;; orig. bookmark-jump
             ("C-x p b" . consult-project-buffer)      ;; orig. project-switch-to-buffer
             ;; Custom M-# bindings for fast register access
             ("M-#" . consult-register-load)
             ("M-'" . consult-register-store)          ;; orig. abbrev-prefix-mark (unrelated)
             ("C-M-#" . consult-register)
             ;; Other custom bindings
             ("M-y" . consult-yank-pop)                ;; orig. yank-pop
             ;; M-g bindings in `goto-map'
             ("M-g e" . consult-compile-error)
             ("M-g r" . consult-grep-match)
             ("M-g f" . consult-flymake)               ;; Alternative: consult-flycheck
             ("M-g g" . consult-goto-line)             ;; orig. goto-line
             ("M-g M-g" . consult-goto-line)           ;; orig. goto-line
             ("M-g o" . consult-outline)               ;; Alternative: consult-org-heading
             ("M-g m" . consult-mark)
             ("M-g k" . consult-global-mark)
             ("M-g i" . consult-imenu)
             ("M-g I" . consult-imenu-multi)
             ;; M-s bindings in `search-map'
             ("M-s d" . consult-find)                  ;; Alternative: consult-fd
             ("M-s c" . consult-locate)
             ("M-s g" . consult-grep)
             ("M-s G" . consult-git-grep)
             ("M-s r" . consult-ripgrep)
             ("M-s l" . consult-line)
             ("M-s L" . consult-line-multi)
             ("M-s k" . consult-keep-lines)
             ("M-s u" . consult-focus-lines)
             ;; Isearch integration
             ("M-s e" . consult-isearch-history)
             :map isearch-mode-map
             ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
             ("M-s e" . consult-isearch-history)       ;; orig. isearch-edit-string
             ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
             ("M-s L" . consult-line-multi)            ;; needed by consult-line to detect isearch
             ;; Minibuffer history
             :map minibuffer-local-map
             ("M-s" . consult-history)                 ;; orig. next-matching-history-element
             ("M-r" . consult-history))                ;; orig. previous-matching-history-element
    
      ;; The :init configuration is always executed (Not lazy)
      :init
    
      ;; Tweak the register preview for `consult-register-load',
      ;; `consult-register-store' and the built-in commands.  This improves the
      ;; register formatting, adds thin separator lines, register sorting and hides
      ;; the window mode line.
      (advice-add #'register-preview :override #'consult-register-window)
      (setq register-preview-delay 0.5)
    
      ;; Use Consult to select xref locations with preview
      (setq xref-show-xrefs-function #'consult-xref
            xref-show-definitions-function #'consult-xref)
    
      ;; Configure other variables and modes in the :config section,
      ;; after lazily loading the package.
      :config
    
      ;; Optionally configure preview. The default value
      ;; is 'any, such that any key triggers the preview.
      ;; (setq consult-preview-key 'any)
      ;; (setq consult-preview-key "M-.")
      ;; (setq consult-preview-key '("S-<down>" "S-<up>"))
      ;; For some commands and buffer sources it is useful to configure the
      ;; :preview-key on a per-command basis using the `consult-customize' macro.
      (consult-customize
       consult-theme :preview-key '(:debounce 0.2 any)
       consult-ripgrep consult-git-grep consult-grep consult-man
       consult-bookmark consult-recent-file consult-xref
       consult-source-bookmark consult-source-file-register
       consult-source-recent-file consult-source-project-recent-file
       ;; :preview-key "M-."
       :preview-key '(:debounce 0.4 any))
    
      ;; Optionally configure the narrowing key.
      ;; Both < and C-+ work reasonably well.
      (setq consult-narrow-key "<") ;; "C-+"
    
      ;; Optionally make narrowing help available in the minibuffer.
      ;; You may want to use `embark-prefix-help-command' or which-key instead.
      ;; (keymap-set consult-narrow-map (concat consult-narrow-key " ?") #'consult-narrow-help)
      )
    
  • Hydra
    (up hydra
      :config
      (global-set-key
       (kbd "C-z")
       (defhydra trambopoline (:color blue)
         ;; "Rhia's Trambopoline"
         ("j" (find-file "~/jnl.org") "jnl" :column "files")
         ("r" (find-file "~/.config/emacs/rio.el") "rio.el")
         ("s" scratch-buffer "*scratch*")
    
         ("h" man "man" :column "search")
         ("i" consult-info "info")
         ("w" (browse-url "http://www.emacswiki.org/") "emacswiki")
    
         ("b" (display-battery-mode 'toggle) "battery" :exit nil :column "visual")
         ("k" text-scale-increase "in" :exit nil)
         ("l" text-scale-decrease "out" :exit nil)
    
         ("e" eshell "eshell" :column "tools")
         ("m" mu4e "mu")
         ("q" nil "cancel")))
    
      (global-set-key
       (kbd "C-c z")
       (defhydra hydra-vi
         (:pre
          (set-cursor-color "#40e0d0")
          :post
          (set-cursor-color "#ffffff")
          :color amaranth)
         "vi"
         ("l" forward-char)
         ("h" backward-char)
         ("j" next-line)
         ("k" previous-line)
         ("q" nil "quit"))))
    

Development

  • Eglot

    Eglot Integrates with core Emacs features better than LSP Mode.

    (up eglot
      :ensure nil
      :config
      (add-to-list 'eglot-server-programs
                   '(python-base-mode . ("rass" "python")) ;; basedruff or python
                   )
      :hook
      (python-base-mode . (lambda ()
                            (eglot-ensure)
                            ;; (add-hook 'after-save-hook 'eglot-format nil t)
                            ))
      (java-mode . eglot-ensure))
    
  • Tree-Sitter

    https://www.masteringemacs.org/article/how-to-get-started-tree-sitter

    (use-package treesit-auto
    :custom
    (treesit-auto-install 'prompt)
    :config
    (treesit-auto-add-to-auto-mode-alist 'all)
    (global-treesit-auto-mode))
    
  • Python

    We're gonna try eglot again..

    ;; (use-package elpy
    ;;   :defer t
    ;;   :init
    ;;   (advice-add 'python-mode :before 'elpy-enable))
    
  • Lisp
    (use-package sly
      :defer t
      :custom
      (inferior-lisp-program "/opt/homebrew/bin/sbcl"))
    
    ;; Lispy
    (use-package lispy
      :config
      (add-hook 'emacs-lisp-mode-hook (lambda () (lispy-mode 1)))
    
      (defun conditionally-enable-lispy ()
        (when (eq this-command 'eval-expression)
          (lispy-mode 1)))
      (add-hook 'minibuffer-setup-hook 'conditionally-enable-lispy))
    
    ;; (use-package paredit)
    
    ;; Smartparents had wonky usage i noticed in python mode.
    ;; Additionally it would corrupt my undo history which is horrifying.
    ;; this could be partially vundo's fault, not sure.
    ;; (up smartparens
    ;;   :hook (prog-mode text-mode markdown-mode)
    ;;   :config
    ;;   (require 'smartparens-config))
    
    ;; (use-package paren-face',
    ;;   :custom
    ;;   (global-paren-face-mode t))
    
    
  • Racket
    (up racket-mode)
    

Applications

  • Terminal Emulators

    Eat, vterm, does comint count here?

    (up eat) ;; Eat didn't work with jshell backspace..
    
    (up vterm)
    
  • Eww
    (setq browse-url-browser-function 'eww-browse-url)
    (use-package eww-lnum
      :bind (:map eww-mode-map
             ("C-c j" . eww-lnum-follow)
             ("C-c C-j" . eww-lnum-universal)))
    
  • wiki-summary
    (use-package wiki-summary)
    
  • Mu!

    TODO: Set up conditional depending on Mu installed

    (if (eq system-type 'darwin) (add-to-list 'load-path "/opt/homebrew/share/emacs/site-lisp/mu/mu4e/"))
    (require 'mu4e)
    (global-set-key (kbd "<f7>") 'mu4e)
    
    (setq
     mu4e-mu-binary "/opt/homebrew/bin/mu"
     mu4e-get-mail-command "mbsync -a"
     mu4e-update-interval 300         ;; update every 5 mins
     mu4e-sent-folder   "/Sent"       ;; folder for sent messages
     mu4e-drafts-folder "/Drafts"     ;; unfinished messages
     mu4e-trash-folder  "/Trash"      ;; trashed messages
     mu4e-refile-folder "/Archive")   ;; saved messages
    
    (setq
     ;; send-mail-function 'smtpmail-send-it       ; Send mail via SMTP
     user-full-name    "Rhia Rokich"                  ; Our full name
     user-mail-address "[email protected]"         ; Our return address
     ;; message-send-mail-function   'smtpmail-send-it
     smtpmail-default-smtp-server "smtp.migadu.com"
     smtpmail-smtp-server         "smtp.migadu.com"
     smtpmail-smtp-user "[email protected]"
     smtpmail-stream-type 'tls
     smtpmail-smtp-service 465)
    (setq send-mail-function 'message-send-mail-with-sendmail
          message-send-mail-function 'message-send-mail-with-sendmail)
    (setq sendmail-program (executable-find "msmtp"))
    (setq message-sendmail-envelope-from 'header)
    
    (setq mu4e-compose-format-flowed t)
    
    ;; (setq
    ;;  ;; The mail URL, specifying a remote mail account
    ;;  ;; (Omit this to read from /var/mail/user)
    ;;  ;; rmail-primary-inbox-list
    ;;  ;; '("pop://me%40example.com:[email protected]")
    
    
    
    ;;  ;; rmail-preserve-inbox 1                     ; Don't delete mail from server
    ;;  ;; rmail-mail-new-frame 1                     ; Compose in a full frame
    ;;  rmail-delete-after-output 1                ; Delete original mail after copying
    ;;  rmail-mime-prefer-html nil                 ; Prefer plaintext when possible
    ;;  rmail-file-name   "~/mail/gmail.mbox"           ; The path to our inbox file
    ;;  rmail-secondary-file-directory "~/mail"    ; The path to our other mbox files
    ;;  ;; message-default-headers "Fcc: ~/mail/sent" ; Copy sent mail to the "sent" file
    ;;  message-signature "-- Rhia :3")              ; A signature
    
    (setq
     ;; mu4e-get-mail-command "mpop -Q"
     ;; mu4e-update-interval 300
     mu4e-view-show-images t
     mu4e-use-fancy-chars t
     message-kill-buffer-on-exit t
     mu4e-headers-precise-alignment t
     ;; mu4e-split-view 'horizontal
     ;; mu4e-headers-visible-columns 80
    
     ;; mail-user-agent 'mu4e-user-agent
     ;; read-mail-command 'mu4e
    
     ;; message-send-mail-function 'message-send-mail-with-sendmail
     ;; sendmail-program "msmtp"
     )
    
    (setq mu4e-bookmarks
          '(( :name "Today's messages"
              :favorite t
              :key ?t
              :query "date:today..now AND NOT flag:trashed AND maildir:/INBOX")
            ( :name "Jess"
              :key  ?j
              :query "from:[email protected]")
            ( :name  "Unread messages"
              :query "flag:unread AND NOT flag:trashed"
              :key ?u)
            ( :name "Messages with images"
              :query "mime:image/*"
              :key ?p)
            ( :name "Delve"
              :query "NOT flag:trashed AND maildir:/"
              :hide-unread t
              :key ?d)
            ( :name "Last 7 days"
              :query "date:7d..now"
              :hide-unread t
              :key ?w)))
    
    (setq mu4e-maildir-shortcuts
          '( (:maildir "/INBOX"     :key  ?i)
             (:maildir "/Archive"   :key  ?a)
             ;; (:maildir "/lists"     :key  ?l)
             ;; (:maildir "/work"      :key  ?w)
             ;; (:maildir "/lists/project/project_X" :key ?x :name "Project X")
             (:maildir "/Drafts"      :key  ?d)
             (:maildir "/Trash"      :key  ?t)
             (:maildir "/Sent"      :key  ?s)))
    
    (setq mu4e-headers-fields
          '((:human-date . 10)
            (:flags . 6)
            (:from-or-to . 18)
            (:subject . nil)))
    
  • TC: LaTeX iS fUcKiN iNsAnE wItH aUcTeX

    live preview and folding wip (more in custom)

      ;(setq TeX-save-query nil)
    
      ;(defun my-TeX-revert-document-buffer (file)
      ;  (TeX-revert-document-buffer file)
      ;  (pdf-outline))
    
      ;(add-hook 'TeX-after-compilation-finished-functions #'my-TeX-revert-document-buffer)
    
      ;    (org-mode)
        (add-hook 'LaTeX-mode-hook (lambda ()
                                     (TeX-fold-mode 1)))
    
    ;    (add-hook 'find-file-hook #'TeX-fold-buffer t)
    
  • Arent u Dired yet?
    (add-hook 'dired-mode-hook 'dired-omit-mode)
    
    (use-package all-the-icons-dired
      :init
      (add-hook 'dired-mode-hook 'all-the-icons-dired-mode))
    
    (use-package dired-sidebar
      :bind (("C-x C-n" . dired-sidebar-toggle-sidebar))
      :commands (dired-sidebar-toggle-sidebar))
    
    (up dired-collapse
      :config
      (global-dired-collapse-mode t))
    
  • Org Mode
    ;; (use-package grove
    ;;   :load-path "~/el/grove"
    ;;   :custom
    ;;   (grove-directory "~/grove")
    ;;   :config
    ;;   (global-set-key (kbd "C-c v") grove-command-map))
    
    (use-package plantuml-mode
      :custom
      (org-plantuml-jar-path (expand-file-name "/Users/rio/java/plantuml.jar"))  ; TODO Move to system independent dir.
      :config
      (add-to-list 'org-src-lang-modes '("plantuml" . plantuml))
      (org-babel-do-load-languages 'org-babel-load-languages '((plantuml . t))))
    
    
    (global-set-key (kbd "C-c l") #'org-store-link)
    (global-set-key (kbd "C-c a") #'org-agenda)
    (global-set-key (kbd "C-c c") #'org-capture)
    
    (setq org-indirect-buffer-display 'current-window
          org-agenda-span 'month)
    
    (up org-modern
      :config
      (set-face-attribute 'default nil :family "Iosevka")
      (set-face-attribute 'default nil :family "PonicMono")
      (set-face-attribute 'variable-pitch nil :family "Iosevka Aile")
      (set-face-attribute 'org-modern-symbol nil :family "Iosevka")
    
      ;; (setq-default line-spacing 0.4)
    
      ;; Add frame borders and window dividers
      ;; (modify-all-frames-parameters
      ;;  '((right-divider-width . 40)
      ;;    (internal-border-width . 40)))
      ;; (dolist (face '(window-divider
      ;;              window-divider-first-pixel
      ;;              window-divider-last-pixel))
      ;;   (face-spec-reset-face face)
      ;;   (set-face-foreground face (face-attribute 'default :background)))
      ;; (set-face-background 'fringe (face-attribute 'default :background))
    
      (setq
       ;; org-auto-align-tags nil
       ;; org-tags-column 0
       ;; org-catch-invisible-edits 'show-and-error
       ;; org-special-ctrl-a/e t
       ;; org-insert-heading-respect-content t
       org-hide-emphasis-markers t
       org-pretty-entities t
       ;; org-agenda-tags-column 0
       org-ellipsis "…")
    
      ;;  (global-org-modern-mode)
      )
    
    ;; (use-package org-modern-indent
    ;;   :straight (org-modern-indent :type git :host github :repo "jdtsmith/org-modern-indent")
    ;;   :config ; add late to hook
    ;;   (add-hook 'org-mode-hook #'org-modern-indent-mode 90))
    
    ;; (use-package ob-hy)
    ;; (load-library "gforth")
    
    (setq org-babel-python-command "python3")
    
    ;; error on load?
    ;; (up ob-racket
    ;;   :vc (:url "https://github.com/xchrishawk/ob-racket"))
    
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((lisp . t)
       (python . t)
       (forth . t)
       (sql . t)
       (sqlite . t)
       (java . t)
       (plantuml . t)
       ;; (racket . t)
       ;; (hy . t)
       ))
    
    ;; (setf org-babel-lisp-eval-fn 'sly-eval)
    
    (setf org-edit-src-persistent-message nil
          org-src-window-setup 'current-window)
    
    ;; Visual display of super- and subscripts
    (setf org-pretty-entities t)
    (setf org-pretty-entities-include-sub-superscripts t)
    
    (setf org-use-speed-commands t)
    
    (use-package htmlize)
    
    (use-package org-auto-tangle
      ;;  :delight
      :config
      (add-hook 'org-mode-hook 'org-auto-tangle-mode))
    
  • PDF Tools
    (use-package pdf-tools)
    (setq pdf-view-midnight-colors ;; '("#839496" . "#002b36")
          '("#e7e7e7" . "#181818"))
    
  • Elfeed
    (up elfeed)
    
    (up elfeed-org
      :config
      (elfeed-org)
      (setq rmh-elfeed-org-files (list "~/.emacs.d/elfeed.org")))
    
    (global-set-key (kbd "<f9>") 'elfeed)
    
  • Calc
    (global-set-key (kbd "<f10>") 'calc)
    
  • Markdown Mode
    (up markdown-mode)
    
  • EMMS
    (use-package emms
      :config
      (emms-all)
      (setq emms-player-list '(emms-player-vlc)
            emms-info-functions '(emms-info-native)))
    

Utils

  • Xah's Novel Mode
    (defun xah-toggle-read-novel-mode ()
      "Setup current frame to be suitable for reading long novel/article text.
    • Set frame width to 70
    • Line wrap at word boundaries.
    • Line spacing is increased.
    • Proportional width font is used.
    Call again to toggle back.
    
    URL `http://xahlee.info/emacs/emacs/emacs_novel_reading_mode.html'
    Created: 2019-01-30
    Version: 2021-01-16"
      (interactive)
      (if (eq (frame-parameter (selected-frame) 'width) 70)
          (progn
            (set-frame-parameter (selected-frame) 'width 106)
            (variable-pitch-mode 0)
            (setq line-spacing nil)
            (setq word-wrap nil))
        (progn
          (set-frame-parameter (selected-frame) 'width 70)
          (variable-pitch-mode 1)
          (setq line-spacing 0.5)
          (setq word-wrap t)))
      (redraw-frame (selected-frame)))
    
  • RSVP - Speed Reading

    https://www.dyerdwelling.family/emacs/20260116182841-emacs--speed-reading-in-emacs-building-an-rsvp-reader/

    (defun rsvp-minibuffer ()
      "Display words from point (or mark to point) in minibuffer using RSVP.
    Use f/s for speed, [/] for size, b/n to skip, SPC to pause, q to quit."
      (interactive)
      (let* ((start (if (region-active-p) (region-beginning) (point)))
             (end (if (region-active-p) (region-end) (point-max)))
             (text (buffer-substring-no-properties start end))
             (wpm 350) (font-size 200) (orp-column 20)
             (word-positions '()) (pos 0) (i 0)
             (message-log-max nil))  ; Disable message logging
        ;; Build word positions list
        (dolist (word (split-string text))
          (unless (string-blank-p word)
            (when-let ((word-start (string-match (regexp-quote word) text pos)))
              (push (cons word (+ start word-start)) word-positions)
              (setq pos (+ word-start (length word))))))
        (setq word-positions (vconcat (nreverse word-positions))) ;; Convert to vector!
        ;; Display loop
        (while (< i (length word-positions))
          (let* ((word-cell (aref word-positions i)) ;; O(1) optimization
                 (word (car word-cell))
                 (word-pos (cdr word-cell))
                 (word-len (length word))
                 (delay (* (/ 60.0 wpm)
                          (cond ((< word-len 3) 0.8) ((> word-len 8) 1.3) (t 1.0))
                          (if (string-match-p "[.!?]$" word) 1.5 1.0)))
                 (orp-pos (/ word-len 3))
                 (face-mono `(:height ,font-size :family "monospace"))
                 (face-orp `(:foreground "red" :weight normal ,@face-mono))
                 (padded-word (concat
                              (propertize (make-string (max 0 (- orp-column orp-pos)) ?\s) 'face face-mono)
                              (propertize (substring word 0 orp-pos) 'face face-mono)
                              (propertize (substring word orp-pos (1+ orp-pos)) 'face face-orp)
                              (propertize (substring word (1+ orp-pos)) 'face face-mono))))
            (goto-char (+ word-pos word-len))
            (message "%s" padded-word)
            (pcase (read-event nil nil delay)
              (?f (setq wpm (min 1000 (+ wpm 50))))
              (?s (setq wpm (max 50 (- wpm 50))))
              (?\[ (setq font-size (max 100 (- font-size 20))))
              (?\] (setq font-size (min 400 (+ font-size 20))))
              (?b (setq i (max 0 (- i 10))))
              (?n (setq i (min (1- (length word-positions)) (+ i 10))))
              (?\s (read-event (format "%s [PAUSED - WPM: %d]" padded-word wpm)))
              (?q (setq i (length word-positions)))
            (_ (setq i (1+ i))))))))
    
  • Unfill
    (defun unfill-paragraph ()
      (interactive)
      (let ((fill-column (point-max)))
        (fill-paragraph nil)))
    
    (defun unfill-region ()
      (interactive)
      (let ((fill-column (point-max)))
        (fill-region (region-beginning) (region-end) nil)))
    

Other Files

~/.emacs.d/secrets.el

Stuff I don't want to share publicly.

  • org-publish-project-alist

~/.emacs.d/custom.el

I use custom a little, I load it after Orchix so I can test new things. Ideally I will go through it periodically and work out what's getting included in Orchix proper.

~/.exwm

-- emacs-lisp -- Emacs as a X11 Window Manager

This file is run by gdm when logging into xsession exwm.desktop. EXWM is very fun, particularly while falling in love with Emacs. It makes it so emacs is always available, and you can access anything you set up.

I'm trying to find a primary window manager… stumpwm is great but i gotta think about wayland at some point! (as of April 2024, mahogany is still very WIP) Wayland would mean being able to use the new alpha-background frame parameter to have beautiful backgrounds for my buffers.

A dork can dream~


  (use-package exwm
;;  :if my-laptop-p
    :init
    (progn
      ;;    (require 'exwm-config)
      ;;    (exwm-config-default)
      ;;    (exwm-enable)
      (exwm-input-set-key (kbd "s-p") 'fhd/toggle-exwm-input-line-mode-passthrough)
      (exwm-input-set-key (kbd "s-i") #'fhd/exwm-input-toggle-mode)))

  (require 'exwm-randr)

  (defun exwm-change-screen-hook ()
    (let ((xrandr-output-regexp "\n\\([^ ]+\\) connected ")
          default-output)
      (with-temp-buffer
        (call-process "xrandr" nil t nil)
        (goto-char (point-min))
        (re-search-forward xrandr-output-regexp nil 'noerror)
        (setq default-output (match-string 1))
        (forward-line)
        (if (not (re-search-forward xrandr-output-regexp nil 'noerror))
            (call-process "xrandr" nil nil nil "--output" default-output "--auto")
          (call-process
           "xrandr" nil nil nil
           "--output" (match-string 1) "--primary" "--auto"
           "--output" default-output "--off")
          (setq exwm-randr-workspace-output-plist (list 0 (match-string 1)))))))

  (setq exwm-randr-workspace-output-plist '(1 "DP-1" 2 "DP-1" 3 "DP-1"))

  (defun rio/screen-change-hook ()
    (start-process-shell-command
     "xrandr" nil (concat
                   "xrandr "
                   "--output LVDS-1 --mode 2560x1440 --scale 0.45 "
                   "--output DP-1 --right-of LVDS-1 --mode 3840x2160 "
                   ;;"--output VGA-1 --left-of LVDS-1 --mode 1024x768 "
                   )))

  (add-hook 'exwm-randr-screen-change-hook
            'rio/screen-change-hook)

  (exwm-randr-enable)


  ;; https://emacs.stackexchange.com/questions/33326/how-do-i-cut-and-paste-effectively-between-applications-while-using-exwm
  (defun fhd/exwm-input-line-mode ()
    "Set exwm window to line-mode and show mode line"
    (call-interactively #'exwm-input-grab-keyboard)
    (exwm-layout-show-mode-line))

  (defun fhd/exwm-input-char-mode ()
    "Set exwm window to char-mode and hide mode line"
    (call-interactively #'exwm-input-release-keyboard)
    (exwm-layout-hide-mode-line))

  (defun fhd/exwm-input-toggle-mode ()
    "Toggle between line- and char-mode"
    (interactive)
    (with-current-buffer (window-buffer)
      (when (eq major-mode 'exwm-mode)
        (if (equal (cl-second (cl-second mode-line-process)) "line")
            (fhd/exwm-input-char-mode)
          (fhd/exwm-input-line-mode)))))

  (defun fhd/toggle-exwm-input-line-mode-passthrough ()
    (interactive)
    (if exwm-input-line-mode-passthrough
        (progn
          (setq exwm-input-line-mode-passthrough nil)
          (message "App receives all the keys now (with some simulation)"))
      (progn
        (setq exwm-input-line-mode-passthrough t)
        (message "emacs receives all the keys now")))
    (force-mode-line-update))

  ;; workspaces[] start from 1
  (setq ;;exwm-workspace-index-map (lambda (i) (number-to-string (1+ i)))
   exwm-workspace-number 4)

  ;; x11 win titles
  (add-hook 'exwm-update-class-hook
            (lambda ()
              (unless (or (string-prefix-p "sun-awt-X11-" exwm-instance-name)
                          (string= "gimp" exwm-instance-name))
                (exwm-workspace-rename-buffer exwm-class-name))))
  (add-hook 'exwm-update-title-hook
            (lambda ()
              (when (or (not exwm-instance-name)
                        (string-prefix-p "sun-awt-X11-" exwm-instance-name)
                        (string-prefix-p "firefox-" exwm-instance-name)
                        (string= "gimp" exwm-instance-name))
                (exwm-workspace-rename-buffer exwm-title))))

  ;; keybinds for the globalist elites
  (setq exwm-input-global-keys
        `(
          ;; Bind "s-r" to exit char-mode and fullscreen mode.
          ([?\s-r] . exwm-reset)

          ;; Bind "s-w" to switch workspace interactively.
          ([?\s-w] . exwm-workspace-switch)

          ;; Bind "s-0" to "s-9" to switch to a workspace by its index.
          ,@(mapcar (lambda (i)
                      `(,(kbd (format "s-%d" i)) .
                        (lambda ()
                          (interactive)
                          (exwm-workspace-switch-create ,i))))
                    (number-sequence 0 9))
          ([?\s-`] . (lambda () (interactive) (exwm-workspace-switch-create 0)))

          ;; Dired File Manager
          ([?\s-d] . (lambda ()
                       (interactive)
                       (dired default-directory)))

          ([menu] . counsel-M-x)
          ([s-menu] . counsel-linux-app)

          ;; Bind "s-&" to launch applications
          ([?\s-&] . (lambda (command)
                       (interactive (list (read-shell-command "==> ")))
                       (start-process-shell-command command nil command)))

          ;; ([?\s-f] . (lambda ()
          ;;              (interactive)
          ;;              (exwm-layout-toggle-mode-line)
          ;;              (exwm-workspace-toggle-minibuffer)))

          ([?\s-b] . exwm-workspace-switch-to-buffer)

          ([?\s-o] . (lambda ()
                       (interactive)
                       (start-process "" nil "firefox")))

          ;; Bind "s-<f2>" to "slock", a simple X display locker.
          ;; ([s-f2] . (lambda ()
          ;;             (interactive)
          ;;             (start-process "" nil "/usr/bin/slock")))
          ))

  ;; line-mode only key bindings
  (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)

  ;; These keys should always pass through to Emacs
  ;; (setq exwm-input-prefix-keys
  ;;       '(?\C-x
  ;;    ?\C-u
  ;;    ?\C-h
  ;;    ?\M-x
  ;;    ?\M-`
  ;;    ?\M-&
  ;;    ?\M-:
  ;;    ?\C-\M-j  ;; Buffer list
  ;;    ?\C-\ ))  ;; File-tree

  ;; The following example demonstrates how to use simulation keys to mimic
  ;; the behavior of Emacs.  The value of `exwm-input-simulation-keys` is a
  ;; list of cons cells (SRC . DEST), where SRC is the key sequence you press
  ;; and DEST is what EXWM actually sends to application.  Note that both SRC
  ;; and DEST should be key sequences (vector or string).
  ;; line mode only
  (setq exwm-input-simulation-keys
        '(
          ;; movement
          ([?\C-b] . [left])
          ([?\M-b] . [C-left])
          ([?\C-f] . [right])
          ([?\M-f] . [C-right])
          ([?\C-p] . [up])
          ([?\C-n] . [down])
          ([?\C-a] . [home])
          ([?\C-e] . [end])
          ([?\M-v] . [prior])
          ([?\C-v] . [next])
          ([?\C-d] . [delete])
          ([?\C-k] . [S-end delete])
          ;; cut/paste.
          ([?\C-w] . [?\C-x])
          ([?\M-w] . [?\C-c])
          ([?\C-y] . [?\C-v])
          ;; search
          ([?\C-s] . [?\C-f])))

  ;; You can hide the minibuffer and echo area when they're not used, by
  ;; uncommenting the following line.
  (setq exwm-workspace-minibuffer-position 'nil)

  (require 'exwm-systemtray)
  (exwm-systemtray-enable)

  ;; I believe this breaks C-c in char mode
  ;;(require 'exwm-edit)

  ;; Do not forget to enable EXWM. It will start by itself when things are
  ;; ready.  You can put it _anywhere_ in your configuration.
  (exwm-enable)

Other Dotfiles

Currently manually copying these to new devices, want to look into GNU Stow.

  • ~/.mbsyncrc Used for IMAP (Getting Email)
  • ~/.msmtprc Used for SMTP (Sending Email)