Skip to content

Ametsuchi is the universe — It encompasses (almost) everything that forms my ideal Emacs workstation, a living cosmos where creativity, logic, and intuition intertwine.

Notifications You must be signed in to change notification settings

brklntmhwk/ametsuchi

Repository files navigation

Ametsuchi 卍 天地

Ametsuchi is the universe ー It encompasses (almost) everything that forms my ideal Emacs workstation, a living cosmos where creativity, logic, and intuition intertwine.

Table of Contents (auto-generated using org-make-toc):

Overview

This repository is my Emacs configuration suite built using emacs-twist, powered by Nix and Nix Flakes. Therefore, by its nature, this configuration is not compatible with Windows OS.
NameAlternatives
Emacs installationemacs-overlayDirect use of Nixpkgs
Package buildtwist.nixpackage-build
Package managertwist.elpackage.el, straight.el, elpaca, etc.
Configuration Macrouse-packageleaf.el, setup.el, etc.
Project’s frameworkflake-partsflake-utils, snowfall, denix, etc.

Cosmological Principle

Reproducibility

Reproducibility is a software design concept, where an operation for the same inputs yields the same output. [fn:1]

Unlike the conventional approach where Emacs users install pre-built Emacs Lisp packages from package archive repositories (e.g., ELPA, MELPA, etc.), Ametsuchi builds packages directly from upstream sources and manages their versions via a lockfile machanism provided by twist.nix, which in turn leverages the reproducibility of Nix builds.

This Nix-based approach achieves:

  • More secure package installation
  • Greater stability in Emacs
  • More consistent and deliberate version management

Big Bang!

NOTE: This section is still a work in progress.

Initialization

;;; init.el -*- lexical-binding: t; -*-

Emacs packages and built-in features are hereafter categorized according to the realms in which they operate. That said, the categorization is not mutually exclusive; some items may belong to multiple categories. In the event of duplication, the following rules apply:

For simplicity, assume that there are only two sets, 𝐀 and 𝐁, where 𝐀 ≠ 𝐁. For every package 𝓧, 𝓧 is an element of at least one of them. Now, let package 𝓨 be an element of 𝐀. With that in mind, 𝓨 shall be considered a member of 𝐀 if any of the following propositions hold:

  • “𝐀 is a proper subset of 𝐁 (𝐀 ⊂ 𝐁)”
  • “𝐀 is not a proper subset of 𝐁 (𝐀 ⊄ 𝐁), and 𝓨 is not in the intersection of 𝐀 and 𝐁”
  • “𝐀 is not a proper subset of 𝐁 (𝐀 ⊄ 𝐁), 𝓨 is in the intersection of 𝐀 and 𝐁, and you feel that 𝓨 is relatively closer to 𝐀”

Configuration Macro

use-package

A configuration macro for simplifying your .emacs

(eval-when-compile
  (require 'use-package))

(eval-and-compile
  (setq-default use-package-ensure-function #'(lambda (&rest args) t)
                use-package-always-defer t
                use-package-hook-name-suffix nil
                use-package-verbose t
                use-package-expand-minimally nil))

(if init-file-debug
    (setq-default use-package-verbose t
                  use-package-expand-minimally nil
                  use-package-compute-statistics t)
  (setq-default use-package-verbose nil
                use-package-expand-minimally t))

Package Manager

twist

Hot-reload Emacs Lisp packages configured with twist.nix

(use-package twist
  :ensure t
  :hook (emacs-startup-hook . twist-watch-mode)
  :bind
  (("<f12>" . twist-update)))

Library

cl-lib

Common Lisp extensions for Emacs

;; Use macros only.
(eval-when-compile
  (require 'cl-lib))

System

mule-cmds

commands for multilingual environment

(use-package mule-cmds
  :config
  (set-language-environment "UTF-8"))

mwheel

Mouse wheel support

(use-package mwheel
  :custom
  (mouse-wheel-tilt-scroll t))

Custom Keymaps

bindings

define standard key bindings and some variables

(use-package bindings
  :config
  ;; Enable repetitive execution of `undo' by pressing slash key.
  (keymap-set undo-repeat-map "/" #'undo))

system-meta-map

(defvar system-meta-prefix "C-z"
  "Key prefix for `system-meta-map'.")

(defvar-keymap system-meta-map
  :doc "Keymap for system-related or meta actions."
  :prefix 'system-meta-map-prefix)

(keymap-global-set system-meta-prefix 'system-meta-map-prefix)

toggle-map

Eight looks like going back and forth between two states as in its shape,”8”.

(defvar toggle-prefix "<f8>"
  "Key prefix for `toggle-map'.")

(defvar-keymap toggle-map
  :doc "Keymap for common toggle actions."
  :prefix 'toggle-map-prefix
  "*" '("Light/dark theme" . modus-themes-toggle)
  "=" '("Calculator" . calc)
  "b" '("Blamer" . blamer-mode)
  "d" '("Debug on error" . toggle-debug-on-error)
  "f" '("Fill column indicator" . display-fill-column-indicator-mode)
  "h" '("Line highlight" . hl-line-mode)
  "l" '("Line numbers" . global-display-line-numbers-mode)
  "t" '("Truncate lines" . toggle-truncate-lines)
  "v" '("Variable pitch" . variable-pitch-mode)
  "w" '("Whitespace" . whitespace-mode)
  "x" '("Syntax checker" . flymake-mode))

(keymap-global-set toggle-prefix 'toggle-map-prefix)

repeat

convenient way to repeat the previous command

(use-package repeat
  :hook (after-init-hook . repeat-mode))

Customization

custom

tools for declaring and initializing options

(use-package custom
  :custom
  (custom-file (locate-user-emacs-file "custom.el"))
  :bind
  (:map system-meta-map
        :prefix-map custom-prefix-map
        :prefix "c"
        ("v" . customize-variable)
        ("V" . customize-variable-other-window)
        ("g" . customize-group)
        ("G" . customize-group-other-window)))

Data Management

Directory

(require 'xdg)

(defvar emacs-config-home
  (concat (xdg-config-home) "/emacs/"))

(defvar emacs-cache-home
  (concat (xdg-cache-home) "/emacs/"))

(defvar emacs-data-home
  (concat (xdg-data-home) "/emacs/"))

(defvar emacs-state-home
  (concat (xdg-state-home) "/emacs/"))

(defvar user-documents-dir
  (or (xdg-user-dir "DOCUMENTS")
      "~/Documents/"))

(defvar user-downloads-dir
  (or (xdg-user-dir "DOWNLOADS")
      "~/Downloads/"))

(defvar user-pictures-dir
  (or (xdg-user-dir "PICTURES")
      "~/Pictures/"))

no-littering

Help keeping ~/.config/emacs clean

(use-package no-littering
  :ensure t
  :custom
  (no-littering-var-directory emacs-cache-home)
  (no-littering-etc-directory emacs-data-home))

Performance Enhancement

banchmark-init

Benchmarks for require and load calls

(use-package benchmark-init
  :ensure t
  :hook (after-init-hook . benchmark-init/deactivate))

edebug

a source-level debugger for Emacs Lisp

(use-package edebug
  :config
  ;; Prevent `edebug' default bindings from interfering with those of `activities-map'.
  (setq edebug-inhibit-emacs-lisp-mode-bindings t))

gcmh

the Garbage Collector Magic Hack

(use-package gcmh
  :ensure t
  :custom
  (gcmh-idle-delay 'auto)
  (gcmh-high-cons-threshold (* 128 1024 1024))
  (gcmh-verbose init-file-debug)
  :hook
  (after-init-hook . gcmh-mode))

Help

casual

Transient user interfaces for various modes

(use-package casual
  :ensure t
  :after transient
  :config
  (require 'casual-image)
  :bind
  ((:map calc-mode-map
         ("C-:" . casual-calc-tmenu))
   (:map dired-mode-map
         ("C-:" . casual-dired-tmenu))
   (:map image-mode-map
         ("C-:" . casual-image-tmenu)))
  :config
  (with-eval-after-load 'dired
    (transient-replace-suffix 'casual-dired-tmenu "F"
      '("N" "File" dired-create-empty-file))))

help

help commands for Emacs

(use-package help
  :custom
  (help-window-keep-selected t)
  :hook
  (help-mode-hook . (lambda () (setq-local line-spacing 0.4))))

helpful

A better help buffer

(use-package helpful
  :ensure t
  :defer 1
  :hook
  (helpful-mode-hook . (lambda () (setq-local line-spacing 0.4)))
  :bind
  (([remap describe-function] . helpful-callable)
   ([remap describe-command] . helpful-command)
   ([remap describe-key] . helpful-key)
   ([remap describe-variable] . helpful-variable)
   ([remap Info-goto-emacs-command-node] . helpful-function)
   :map mode-specific-map
   ("h" .  helpful-at-point)))

transient

Transient commands

(use-package transient
  :defer 1
  :custom
  (transient-history-file (concat emacs-state-home "transient/history.el"))
  (transient-values-file (concat emacs-data-home "transient/values.el"))
  (transient-levels-file (concat emacs-data-home "transient/levels.el"))
  :config
  (transient-define-prefix my/toggle-transient ()
    "Prefix for `toggle-map'"
    [("d" "Debug on error" toggle-debug-on-error)
     ("f" "Fill column indicator" display-fill-column-indicator-mode)
     ("h" "Line highlight" hl-line-mode)
     ("l" "Line numbers" global-display-line-numbers-mode)
     ("t" "Truncate lines" toggle-truncate-lines)
     ("v" "Variable pitch" variable-pitch-mode)
     ("w" "Whitespace" whitespace-mode)
     ("x" "Syntax checker" flymake-mode)
     ("*" "Light/dark theme" modus-themes-toggle)])
  (keymap-set toggle-map "?" '("Transient help" . my/toggle-transient)))
transient-posframe

Using posframe to show transient

;; (use-package transient-posframe
;;      :ensure t
;;      :after transient
;;      :custom
;;      (transient-posframe-border-width 3)
;;      :config
;;      (transient-posframe-mode 1))

woman

browse UN*X manual pages `wo (without) man’

(use-package woman
  :custom
  (woman-fill-column 82)
  (woman-cache-filename (concat emacs-cache-home ".wmncach.el"))
  :bind
  (("<f1> M-m" . woman)))

Window Management

ace-window

Quickly switch windows.

(use-package ace-window
  :ensure t
  :custom
  (aw-keys '(?e ?i ?a ?o ?k ?t ?n ?s ?h))
  (aw-scope 'frame)
  (aw-dispatch-when-more-than 1)
  :bind
  (("M-o" . ace-window)
   (:map window-prefix-map
         ("o" . ace-swap-window)))
  :config
  ;; Use `setq' here because `aw-dispatch-alist' is implemented with `defvar' as of Jul 2025.
  (setq aw-dispatch-alist
        '((?b aw-switch-buffer-in-window "Select buffer")
          (?c aw-copy-window "Copy Window")
          (?f aw-split-window-vert "Split window fairly")
          (?j aw-switch-buffer-other-window "Select buffer in other window")
          (?m aw-move-window "Move window")
          (?v aw-split-window-vert "Split window vertically")
          (?w aw-swap-window "Swap windows")
          (?x aw-execute-command-other-window "Execute command in other window")
          (?z aw-split-window-horz "Split window horizontally")
          (?0 aw-delete-window "Delete window")
          (?1 delete-other-windows "Delete other windows")
          (?~ aw-transpose-frame "Transpose frame")
          (?? aw-show-dispatch-help))))

popper

Summon and dismiss buffers as popups

(use-package popper
  :ensure t
  :custom
  (popper-window-height 0.333)
  (popper-display-function #'popper-display-popup-at-bottom)
  (popper-mode-line '(:eval (propertize " POP ")))
  (popper-reference-buffers
   '("Output\\*$"
     "\\*Backtrace\\*"
     "\\*Messages\\*$"
     "^\\*Async Shell Command\\*$"
     "^\\*Apropos\\*$"
     "^\\*Compile-Log\\*$"
     "^\\*eat.\\*$" eat-mode
     "^\\*envrc\\*"
     "^\\*eshell.*\\*$" eshell-mode
     "^\\*Flymake diagnostics"
     "^\\*Help.*\\*$" help-mode
     "^\\*helpful.*\\*$" helpful-mode
     "^\\*Shell Command Output\\*"
     "^\\*Warnings\\*$"))
  :hook
  (after-init-hook . popper-mode)
  (popper-mode-hook . popper-echo-mode)
  :bind
  ((:map window-prefix-map
         :prefix-map popper-prefix-map
         :prefix "p"
         ("t" . popper-toggle)
         ("@" . popper-cycle)
         ("~" . popper-toggle-type))
   (:repeat-map popper-repeat-map
                ("t" . popper-toggle)
                ("@" . popper-cycle)
                ("~" . popper-toggle-type))))

tab-bar

frame-local tabs with named persistent window configurations

(use-package tab-bar
  :custom
  (tab-bar-auto-width-max '(320 25))
  (tab-bar-new-tab-choice "*scratch*")
  :bind
  ((:map tab-prefix-map
         ("=" . tab-bar-move-window-to-tab))
   (:map tab-bar-history-mode-map
         :map tab-prefix-map
         (">" . tab-bar-history-forward)
         ("<" . tab-bar-history-back)))
  :hook (after-init-hook . tab-bar-history-mode)
  :config
  (advice-add 'tab-new :after #'find-file))

window

GNU Emacs window commands aside from those written in C

(use-package window
  :custom
  (recenter-positions '(top middle bottom))
  (switch-to-buffer-obey-display-actions t)
  :bind
  ([remap scroll-up-command] . my/scroll-half-window-height-forward)
  ([remap scroll-down-command] . my/scroll-half-window-height-backward)
  :config
  (defun scroll-half-window-height ()
    (/ (window-body-height) 2))
  (defun my/scroll-half-window-height-forward (&optional arg)
    (interactive "P")
    (if (numberp arg)
        (pixel-scroll-up arg)
      (pixel-scroll-up (scroll-half-window-height))))
  (defun my/scroll-half-window-height-backward (&optional arg)
    (interactive "P")
    (if (numberp arg)
        (pixel-scroll-down arg)
      (pixel-scroll-down (scroll-half-window-height)))))

winner

Restore old window configurations

(use-package winner
  :custom
  (winner-dont-bind-my-keys t)
  :hook (window-setup-hook . winner-mode)
  :bind
  (:map window-prefix-map
        ("<" . winner-undo)
        (">" . winner-redo))
  (:repeat-map winner-repeat-map
               ("<" . winner-undo)
               (">" . winner-redo)))

Appearance

buffer.c

Buffer manipulation primitives for GNU Emacs.

(setq-default buffer-file-coding-system 'utf-8 ; `undecided-unix' by default
              cursor-type 'bar ; t by default
              fill-column 85 ; 70 by default
              line-spacing 2  ; 1 by default
              tab-width 2 ; 8 by default
              indicate-empty-lines t ; nil by default
              indicate-buffer-boundaries 'left ; nil by default
              left-fringe-width 2 ; nil by default
              right-fringe-width 2 ; nil by default
              left-margin-width 2 ; 0 by default
              right-margin-width 2 ; 0 by default
              )

fontset.c

Fontset handler.

Fontset allows you to flexibly specify which font to be active for a specific target: Character, charset, or script.

;; fontaine does not seem to support fontset configuration, so implement it on your own.
;; https://github.com/protesilaos/fontaine/commit/bf2a37b5cc7448d05f77a23879436b0f94eb29ff
(defun my--apply-fontset (characters fontset family &optional add-method)
  "Apply fontset configuration with strict type validation.
CHARACTERS is either a list of symbols (scripts/charsets) or a list of (FROM . TO) cons ranges."
  (let ((font-spec (font-spec :family family)))
    (unless (listp characters)
      (error "Characters must be a list: %s" characters))

    (when (null characters)
      (message "Empty character list for font: %s" family)
      (cl-return-from my--apply-fontset))

    (let ((first (car characters)))
      (cond
       ((symbolp first)
        (dolist (sym characters)
          (unless (symbolp sym)
            (error "Expected symbol in character list, got %S (type: %s)"
                   sym (type-of sym)))
          (set-fontset-font fontset sym font-spec nil add-method)))
       ((and (consp first) (integerp (car first)) (integerp (cdr first)))
        (dolist (range characters)
          (unless (and (consp range)
                       (integerp (car range))
                       (integerp (cdr range)))
            (error "Expected (FROM . TO) cons pair, got %S" range))
          (let ((from (car range))
                (to (cdr range)))
            (when (> from to)
              (error "Invalid range order: %d > %d" from to))
            (set-fontset-font fontset range font-spec nil add-method))))
       (t
        (error "Invalid character specification. Expected symbol or cons, got: %S (%s)"
               first (type-of first)))))))

(defun my/apply-fontset-config (&optional fontsets skip-check)
  "Apply font configuration.
FONTSETS defaults to `my/fontset-config-alist'.
SKIP-CHECK bypasses font availability checking."
  (let ((available-fonts (font-family-list))
        (fontsets (or fontsets my/fontset-config-alist)))
    (cl-loop for (characters . plist) in fontsets
             for family = (plist-get plist :family)
             for fontset = (plist-get plist :fontset)
             for add-method = (plist-get plist :add)

             when (or skip-check
                      (member family available-fonts))
             do (my--apply-fontset characters fontset family add-method)
             else collect family into missing-fonts
             finally (when missing-fonts
                       (message "Missing fonts: %s"
                                (string-join missing-fonts ", "))))))

(defcustom my/fontset-config-alist
  '(((emoji)
     :family "Noto Color Emoji"
     :fontset t
     :add prepend)
    ((han)
     :family "Sarasa Mono SC"
     :fontset t)
    ((hangul)
     :family "Sarasa Mono K"
     :fontset t)
    ((kana)
     :family "Sarasa Mono J"
     :fontset t)
    ((symbol)
     :family "Symbola"
     :fontset t
     :add append))
  "Alist of fontset configuration."
  :type '(alist
          :key-type (choice (repeat symbol)
                            (repeat (cons integer integer)))
          :value-type (plist
                       :options ((string
                                  :tag "Name of a font family"
                                  :family)
                                 ((choice
                                   (const :tag "Default fontset" t)
                                   (string :tag "Name of a fontset"))
                                  :fontset)
                                 ((choice
                                   (const nil)
                                   (const prepend)
                                   (const append))
                                  :add))))
  :set (lambda (symbol value)
         (set symbol value)
         (when (or window-system (daemonp))
           (my/apply-fontset-config value (daemonp)))))

(when (daemonp)
  (add-hook 'server-after-make-frame-hook
            (defun my/server-setup-fontsets ()
              (my/apply-fontset-config nil t)
              (remove-hook 'server-after-make-frame-hook
                           #'my/server-setup-fontsets))))

frame.c

Generic frame functions.

(cl-pushnew '(internal-border-width . 16) default-frame-alist :test #'equal)

xdisp.c

Display generation from window structure and buffer text.

(defconst my/base-frame-title-format
  '(" - GNU Emacs"
    (emacs-version (" " emacs-version))
    (system-name (" on " system-name))))

(defconst my/default-frame-title-format
  (cons '("%b")
        my/base-frame-title-format))

(setq-default bidi-inhibit-bpa t
              bidi-display-reordering 'left-to-right
              bidi-paragraph-direction 'left-to-right
              display-line-numbers-width 4
              frame-title-format my/default-frame-title-format
              scroll-conservatively 1)

fontaine

Set Emacs font configurations using presets

(use-package fontaine
  :ensure t
  :custom
  (fontaine-presets
   '((regular
      :default-family "Moralerspace Neon HWNF"
      :default-height 130
      :fixed-pitch-family "Moralerspace Neon HWNF"
      :fixed-pitch-height 1.0
      :variable-pitch-family "Sarasa Mono"
      :variable-pitch-height 1.0
      :line-spacing 1)
     (medium
      :inherit regular
      :default-height 140)
     (large
      :inherit regular
      :default-height 150)))
  :hook
  (after-init-hook . fontaine-mode)
  :config
  (fontaine-set-preset (or (fontaine-restore-latest-preset) 'regular))
  (add-hook 'kill-emacs-hook #'fontaine-store-latest-preset))

frame

multi-frame management independent of window systems

(use-package frame
  :custom
  (window-divider-default-places t)
  (window-divider-default-bottom-width 5)
  (window-divider-default-right-width 5)
  :config
  (blink-cursor-mode -1))

modus-themes

Highly accessible themes for GNU Emacs, conforming with the highest standard for colour contrast between background and foreground values (WCAG AAA).

All faces from both built-in features and external packages are centrally managed and styled within this configuration. After all, that is precisely what a “theme” is meant to accomplish.

(use-package modus-themes
  :ensure t
  :demand t
  :custom
  (modus-themes-headings
   '((1 . (variable-pitch bold 1.7))
     (2 . (variable-pitch rainbow bold 1.6))
     (3 . (variable-pitch rainbow bold 1.5))
     (4 . (variable-pitch rainbow semibold 1.4))
     (5 . (variable-pitch rainbow semibold 1.3))
     (6 . (variable-pitch rainbow semibold 1.2))
     (t . (1.1))))
  (modus-themes-common-palette-overrides
   '((border-mode-line-active unspecified)
     (border-mode-line-inactive unspecified)
     (bg-mode-line-inactive bg-inactive)))
  (modus-vivendi-tinted-palette-overrides
   '((bg-mode-line-active bg-lavender)))
  (modus-operandi-tinted-palette-overrides
   '((bg-mode-line-active bg-magenta-nuanced)))
  (modus-themes-to-toggle '(modus-operandi-tinted modus-vivendi-tinted))
  :init
  (defun my/modus-themes-custom-face ()
    (modus-themes-with-colors
      (custom-set-faces
       ;; ace-window
       `(aw-leading-char-face ((,c :height 2.0 :foreground ,blue-warmer)))
       `(aw-minibuffer-leading-char-face ((,c :height 1.1 :foreground ,blue-warmer)))
       ;; blamer
       `(blamer-face ((,c :height default :background ,bg-hl-line :foreground ,fg-lavender :italic t)))
       ;; dired-filter
       `(‎dired-filter-group-header‎ ((,c :background ,bg-lavender :box(:line-width 2 :color ,bg-lavender))))
       ;; goggles
       `(goggles-added ((,c :background ,bg-added-refine)))
       `(goggles-changed ((,c :background ,bg-changed-refine)))
       `(goggles-removed ((,c :background ,bg-removed-refine)))
       ;; vertico-posframe
       `(vertico-posframe-border-2 ((,c :background ,bg-added-refine)))
       `(vertico-posframe-border-3 ((,c :background ,bg-added-fringe)))
       ;; vundo
       `(vundo-saved ((,c :foreground ,blue)))
       `(vundo-last-saved ((,c :foreground ,blue-intense)))
       `(vundo-highlight ((,c :foreground ,fg-changed)))
       ;; Built-ins
       `(header-line ((,c :background ,bg-dim :box (:line-width 4 :color ,bg-dim))))
       `(mode-line-active ((,c :overline ,bg-lavender
                               :underline (:color ,bg-lavender :position t))))
       `(mode-line-inactive ((,c :overline ,bg-inactive
                                 :underline (:color ,bg-inactive :position t))))
       `(tab-bar-tab ((,c :background ,bg-active :box (:line-width 5 :color ,bg-active))))
       `(tab-bar-tab-inactive ((,c :background ,bg-inactive :box (:line-width 5 :color ,bg-inactive))))
       `(scroll-bar ((,c :foreground ,border :background ,bg-dim)))
       `(whitespace-line ((,c :background ,slate :foreground ,fg-main)))
       `(whitespace-missing-newline-at-eof ((,c :background ,slate :foreground ,fg-main)))
       `(whitespace-trailing ((,c :background ,slate :foreground ,fg-main))))))
  (add-hook 'modus-themes-after-load-theme-hook #'my/modus-themes-custom-face)
  :config
  (modus-themes-load-theme 'modus-vivendi-tinted))

nerd-icons

Emacs Nerd Font Icons Library

(use-package nerd-icons :ensure t)
nerd-icons-completion

Icons for completion via nerd-icons

(use-package nerd-icons-completion
  :ensure t
  :after marginalia
  :config
  (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))
nerd-icons-corfu

Icons for corfu via nerd-icons

(use-package nerd-icons-corfu
  :ensure t
  :after corfu
  :config
  (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
nerd-icons-dired

Icons for dired via nerd-icons

(use-package nerd-icons-dired
  :ensure t
  :hook
  (dired-mode-hook . nerd-icons-dired-mode))

olivetti

Emacs minor mode to automatically balance window margins

(use-package olivetti
  :ensure t
  :custom
  (olivetti-body-width 82)
  :hook
  ((markdown-mode
    org-mode) . olivetti-mode))

page-break-lines

Emacs: display ugly ^L page breaks as tidy horizontal lines

(use-package page-break-lines
  :ensure t
  ;; :hook (after-init-hook . global-page-break-lines-mode)
  :init (global-page-break-lines-mode 1)
  :config
  (dolist (mode '(compilation-mode-hook
                  dashboard-mode-hook
                  doc-mode-hook
                  haskell-mode-hook
                  help-mode-hook
                  magit-mode-hook))
    (add-to-list 'page-break-lines-modes mode)))

show-font

Show font features in an Emacs buffer

(use-package show-font :ensure t)

Lines

buffer.c

Buffer manipulation primitives for GNU Emacs.

(setq-default header-line-format
              '("" header-line-indent
                (:eval (breadcrumb--header-line))
                " "
                (mode-line-misc-info mode-line-misc-info)))

(setq-default mode-line-format
              '("%e"
                mode-line-front-space
                mode-line-mule-info
                mode-line-modified
                "  "
                mode-line-buffer-identification
                (vc-mode vc-mode)
                "  "
                mode-line-modes
                "  "
                (mode-line-process ("  " mode-line-process))
                (current-input-method-title
                 (current-input-method-title " "))
                (global-mode-string global-mode-string)
                (mode-line-client mode-line-client)
                mode-line-position
                mode-line-end-spaces))

breadcrumb

project and imenu-based breadcrumb paths

(use-package breadcrumb
  :ensure t
  :custom
  (breadcrumb-project-crumb-separator " > ")
  :hook (after-init-hook . breadcrumb-mode))

hide-mode-line

minor mode that hides/masks your modeline

(use-package hide-mode-line
  :ensure t
  :commands
  (hide-mode-line-mode
   ‎turn-on-hide-mode-line-mode‎
   ‎turn-off-hide-mode-line-mode‎))

minions

A minor-mode menu for the mode line

(use-package minions
  :ensure t
  :custom
  (minions-mode-line-lighter "[...]")
  :bind
  ("<f7>" . minions-minor-modes-menu)
  :hook (after-init-hook . minions-mode))

mlscroll

A scroll bar for the modeline

(use-package mlscroll
  :ensure t
  :custom
  (mlscroll-right-align nil)
  (mlscroll-alter-percent-position 'replace)
  (mlscroll-minimum-current-width 5)
  :init
  ;; https://apribase.net/2024/06/20/emacs-as-daemon/
  (if (daemonp)
      (add-hook 'server-after-make-frame-hook #'mlscroll-mode)
    (mlscroll-mode 1)))

moody

Tabs and ribbons for the mode-line

(use-package moody
  :ensure t
  :custom
  (moody-mode-line-height 25)
  ;; Make it align with the colors of mode-line-active and mode-line-inactive.
  (moody-ribbon-background '(base :background))
  :hook
  (after-init-hook . (lambda ()
                       (moody-replace-mode-line-front-space)
                       (moody-replace-mode-line-buffer-identification)
                       (moody-replace-vc-mode))))

which-func

print current function in mode line

(use-package which-func
  :custom
  (which-func-unknown "")
  (which-func-non-auto-modes
   '(fundamental-mode
     help-mode
     org-mode
     markdown-mode
     nov-mode
     pdf-view-mode
     minibuffer-mode))
  :hook (after-init-hook . which-function-mode))

Completion

cape

Completion At Point Extensions

(use-package cape
  :ensure t
  :custom
  (cape-dict-file
   (concat emacs-data-home "cape/dict"))
  :functions
  (cape-capf-buster
   cape-capf-super)
  :bind
  ((:prefix-map cape-capf-prefix-map :prefix "M-p"
                ("a" . cape-abbrev)
                ("d" . cape-dabbrev)
                ("f" . cape-file)
                ("h" . cape-history)
                ("k" . cape-keyword)
                ("l" . cape-line)
                ("r" . cape-rfc1345)
                ("s" . cape-sgml)
                ("w" . cape-dict)
                ("&" . cape-sgml)
                ("\\" . cape-tex)))
  :hook
  (eglot-managed-mode-hook . my/setup-cape-eglot-capf)
  (text-mode-hook . my/setup-cape-text-mode-capf)
  (prog-mode-hook . my/setup-cape-prog-mode-capf)
  :config
  (setq-default completion-at-point-functions
                (append (default-value 'completion-at-point-functions)
                        (list #'cape-file #'cape-dabbrev)))
  (defun my/setup-cape-eglot-capf()
    (setq-local completion-at-point-functions
                (list (cape-capf-super
                       #'cape-file
                       (cape-capf-buster #'eglot-completion-at-point #'string-prefix-p)
                       #'cape-keyword
                       :with #'tempel-complete))))
  (defun my/setup-cape-prog-mode-capf()
    (add-hook 'completion-at-point-functions #'cape-file nil t))
  (defun my/setup-cape-text-mode-capf()
    (add-hook 'completion-at-point-functions #'cape-file nil t)
    (add-hook 'completion-at-point-functions #'cape-dict 10 t))
  (with-eval-after-load 'transient
    (transient-define-prefix my/cape-capf-transient ()
      "Prefix for cape capfs."
      [("a" "abbrev" cape-abbrev)
       ("d" "dabbrev" cape-dabbrev)
       ("f" "file" cape-file)
       ("h" "history" cape-history)
       ("k" "keyword" cape-keyword)
       ("l" "line" cape-line)
       ("r" "rfc1345" cape-rfc1345)
       ("s" "elisp symbol" cape-elisp-symbol)
       ("w" "dict" cape-dict)
       ("&" "sgml" cape-sgml)
       ("\\" "tex" cape-tex)])
    (keymap-set cape-capf-prefix-map "?" #'my/cape-capf-transient)))

completion-preview

Preview completion with inline overlay

(use-package completion-preview
  :hook
  (corfu-mode-hook . completion-preview-mode)
  :bind
  (:map completion-preview-active-mode-map
        ("TAB" . completion-preview-complete)
        ("C-e" . completions-preview-insert)))

consult

Consulting completing-read

(use-package consult
  :ensure t
  :custom
  (consult-bookmark-narrow
   '((?e "Eww" eww-bookmark-jump)
     (?f "File" bookmark-default-handler)
     (?h "Help" help-bookmark-jump)
     (?i "Info" Info-bookmark-jump)
     (?o "Org headings" org-bookmark-heading-jump)
     (?w "Woman" woman-bookmark-jump)))
  (consult-buffer-sources
   `(consult--source-project-buffer
     consult--source-project-recent-file
     consult--source-buffer
     consult--source-recent-file))
  (consult-narrow-key "<")
  :bind
  (([remap bookmark-jump] . consult-bookmark)
   ([remap goto-line] . consult-goto-line)
   ([remap switch-to-buffer] . consult-buffer)
   ([remap project-switch-to-buffer] . consult-project-buffer)
   ([remap yank-pop] . consult-yank-pop)
   (:map goto-map
         ("m" . consult-mark)
         ("M" . consult-global-mark)
         ("o" . consult-outline))
   (:map search-map
         ("f" . consult-fd)
         ("g" . consult-git-grep)
         ("k" . consult-keep-lines)
         ("l" . consult-line)
         ("L" . consult-line-multi)
         ("r" . consult-ripgrep)
         ("u" . consult-focus-lines))
   (:map isearch-mode-map
         ("M-e" . consult-isearch-history)
         ("M-s e" . consult-isearch-history))
   (:map mode-specific-map
         ("k" . consult-kmacro)))
  :hook (completion-list-mode-hook . consult-preview-at-point-mode))
consult-dir

Insert paths into the minibuffer prompt in Emacs

(use-package consult-dir
  :ensure t
  :after vertico
  :bind
  ((:map ctl-x-map
         ("C-d" . consult-dir))
   (:map vertico-map
         ("C-x C-d" . consult-dir)
         ("C-x C-j" . consult-dir-jump-file)))
  :config
  (add-to-list 'consult-dir-sources 'consult-dir--source-tramp-ssh t))
consult-gh

An Interactive interface for “GitHub CLI” client inside GNU Emacs using Consult

(use-package consult-gh
  :ensure t
  :if (executable-find "gh")
  :after consult
  :custom
  (consult-gh-default-clone-directory (concat user-documents-dir "projects/"))
  (consult-gh-issue-maxnum 50)
  (consult-gh-repo-maxnum 50)
  (consult-gh-show-preview t)
  (consult-gh-preview-key "C-o")
  (consult-gh-prioritize-local-folder 'suggest)
  (consult-gh-default-interactive-command #'consult-gh-transient)
  :bind
  (:map ctl-x-map
        ("M-g" . consult-gh))
  :config
  (add-to-list 'savehist-additional-variables 'consult-gh--known-orgs-list)
  (add-to-list 'savehist-additional-variables 'consult-gh--known-repos-list)
  (consult-gh-enable-default-keybindings))
consult-gh-embark

Embark Actions for consult-gh

(use-package consult-gh-embark
  :ensure t
  :after consult-gh
  :config
  (consult-gh-embark-mode 1))
consult-gh-transient

Transient Menu for consult-gh

(use-package consult-gh-transient
  :after consult-gh
  :commands consult-gh-transient
  :custom
  (consult-gh-default-interactive-command #'consult-gh-transient))
consult-imenu

Consult commands for imenu

(use-package consult-imenu
  :after consult
  :bind
  (([remap imenu] . consult-imenu))
  (:map goto-map
        ("I" . consult-imenu-multi)))
consult-xref

Xref integration for Consult

(use-package consult-xref
  :after xref
  :functions
  (consult-xref)
  :init
  (setq xref-show-xrefs-function #'consult-xref)
  (setq xref-show-definitions-function #'consult-xref))

corfu

COmpletion in Region FUnction

(use-package corfu
  :ensure t
  :custom
  (corfu-cycle t)
  (corfu-preview-current nil)
  (corfu-min-width 20)
  (corfu-scroll-margin 5)
  (corfu-quit-at-boundary nil)
  :hook
  ((comint-mode-hook
    eshell-mode-hook
    prog-mode-hook
    text-mode-hook) . corfu-mode)
  (minibuffer-setup-hook . my/corfu-enable-in-minibuffer)
  :bind
  (:map corfu-map
        ("SPC" . corfu-insert-separator)
        ("TAB" . corfu-next)
        ([tab] . corfu-next)
        ("S-TAB" . corfu-previous)
        ([backtab] . corfu-previous)
        ("C-e" . corfu-complete))
  :config
  (defun my/corfu-enable-in-minibuffer ()
    "Enable Corfu in the minibuffer if `completion-at-point' is bound."
    (when (where-is-internal #'completion-at-point (list (current-local-map)))
      (corfu-mode 1))))
corfu-history

Sorting by history for Corfu

(use-package corfu-history
  :after corfu
  :hook (corfu-mode-hook . corfu-history-mode)
  :config
  (with-eval-after-load 'savehist
    (add-to-list 'savehist-additional-variables 'corfu-history)))
corfu-popupinfo

Candidate information popup for Corfu

(use-package corfu-popupinfo
  :after corfu
  :custom
  (corfu-popupinfo-delay '(1.5 . 0.5))
  (corfu-popupinfo-max-height 15)
  :hook (corfu-mode-hook . corfu-popupinfo-mode))

embark

Conveniently act on minibuffer completions

(use-package embark
  :ensure t
  :defer 2
  :custom
  (embark-indicators
   '(embark-minimal-indicator
     embark-highlight-indicator
     embark-isearch-highlight-indicator))
  :bind
  ((("C-." . embark-act)
    ("C->" . embark-dwim)
    ("C-*" . embark-act-all))
   (:map minibuffer-mode-map
         ("C-<" . embark-become)
         ("C-SPC" . embark-select))
   (:map help-map
         ("b" . embark-bindings))))
embark-consult

Consult integration for Embark

(use-package embark-consult
  :after (consult embark)
  :hook (embark-collect-mode-hook . consult-preview-at-point-mode))
embark-org

Embark targets and actions for Org Mode

(use-package embark-org
  :bind
  ((:map embark-org-link-map
         ("l" . org-insert-link))
   (:map embark-org-src-block-map
         ("e" . org-edit-special))))

indent

indentation commands for Emacs

(use-package indent
  :custom
  (tab-always-indent 'complete))

marginalia

Enrich existing commands with completion annotations

(use-package marginalia
  :ensure t
  :hook (after-init-hook . marginalia-mode))

minibuffer

Minibuffer and completion functions

(use-package minibuffer
  :custom
  (completion-cycle-threshold 3))

orderless

Completion style for matching regexps in any order

(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-defaults nil)
  (completion-category-overrides nil))

vertico

VERTical Interactive COmpletion

(use-package vertico
  :ensure t
  :custom
  (vertico-count 20)
  (vertico-resize nil)
  :hook (after-init-hook . vertico-mode))
vertico-directory

Ido-like directory navigation for Vertico

(use-package vertico-directory
  :after vertico
  :bind
  (:map vertico-map
        ("RET" . vertico-directory-enter)
        ("DEL" . vertico-directory-delete-char)
        ("M-DEL" . vertico-directory-delete-word))
  :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
vertico-multiform

Configure Vertico in different forms per command

(use-package vertico-multiform
  :after vertico
  :custom
  (vertico-multiform-categories
   '((embark-keybinding grid)
     (jinx grid)))
  (vertico-multiform-commands
   '((consult-buffer (:not posframe))
     (consult-line (:not posframe))
     (consult-ripgrep (:not posframe))
     (t posframe)))
  :config
  (vertico-multiform-mode 1))
vertico-posframe

Using posframe to show Vertico

(use-package vertico-posframe
  :ensure t
  :custom
  (vertico-posframe-border-width 3)
  (vertico-posframe-min-width 80)
  (vertico-posframe-width nil)
  (vertico-posframe-parameters
   '((left-fringe . 10)
     (right-fringe . 10)))
  ;; (vertico-posframe-poshandler 'posframe-poshandler-frame-center)
  :hook (vertico-mode-hook . vertico-posframe-mode))

Editing

fns.c

Random utility Lisp functions.

(setq use-short-answers t)

abbrev

abbrev mode commands for Emacs

(use-package abbrev
  :custom
  (save-abbrevs nil)
  :hook
  ((git-commit-mode-hook
    vc-git-log-edit-mode-hook
    markdown-mode-hook
    org-mode-hook) . abbrev-mode)
  :config
  (define-abbrev-table 'global-abbrev-table
    '(("fixme" "FIXME")
      ("tbd" "TBD")
      ("wip" "WIP")
      ("teh" "the")
      ("afaik" "As far as I know")
      ("btw" "By the way")
      ("imo" "In my opinion")
      ("imho" "In my humble opinion"))))

autoinsert

automatic mode-dependent insertion of text into new files

(use-package autoinsert
  :custom
  (auto-insert 'other)
  (auto-insert-directory (concat emacs-data-home "templates/autoinsert/"))
  (auto-insert-query nil)
  :hook
  (after-init-hook . auto-insert-mode))

avy

Jump to arbitrary positions in visible text and select text quickly.

(use-package avy
  :ensure t
  :custom
  (avy-dispatch-alist
   '((?c . avy-action-copy)
     (?l . avy-action-ispell)
     (?m . avy-action-mark)
     (?r . avy-action-teleport)
     (?w . avy-action-kill-move)
     (?W . avy-action-kill-stay)
     (?y . avy-action-yank)
     (?Y . avy-action-yank-line)
     (?z . avy-action-zap-to-char)))
  (avy-keys '(?e ?i ?a ?o ?k ?t ?n ?s ?h))
  (avy-style 'pre)
  (avy-styles-alist '((avy-goto-char-timer . at-full)))
  (avy-all-windows t)
  (avy-single-candidate-jump nil)
  (avy-timeout-seconds 0.5)
  :bind
  (("M-j" . avy-goto-char-timer)
   ("M-J" . avy-goto-char-in-line)
   (:map goto-map
         ("e" . avy-goto-end-of-line)
         ("j" . avy-goto-char-timer)
         ("J" . avy-goto-char-in-line)
         ("w" . avy-goto-whitespace-end))
   (:map isearch-mode-map
         ("M-j" . avy-isearch)))
  :config
  (with-eval-after-load 'helpful
    ;; https://karthinks.com/software/avy-can-do-anything/#look-up-the-documentation-for-a-symbol
    (defun my/avy-action-helpful (pt)
      (save-excursion
        (goto-char pt)
        (helpful-at-point))
      (select-window
       (cdr (ring-ref avy-ring 0)))
      t)
    (setf (alist-get ?H avy-dispatch-alist) #'my/avy-action-helpful))

  (with-eval-after-load 'embark
    ;; https://karthinks.com/software/avy-can-do-anything/#avy-plus-embark-any-action-anywhere
    (defun my/avy-action-embark (pt)
      (unwind-protect
          (save-excursion
            (goto-char pt)
            (embark-act))
        (select-window
         (cdr (ring-ref avy-ring 0))))
      t)
    (setf (alist-get ?. avy-dispatch-alist) #'my/avy-action-embark)))

deadgrep

fast, friendly searching with ripgrep

(use-package deadgrep
  :ensure t
  :custom
  (deadgrep-display-buffer-function 'pop-to-buffer)
  (deadgrep-extra-arguments
   '("--no-config"
     "--hidden"
     "--ignore-file=.gitignore"
     "--iglob=!.git"
     "--sort=modified"))
  :bind
  ((:map search-map
         ("d" . deadgrep))))

delsel

delete selection if you insert

(use-package delsel
  :hook (after-init-hook . delete-selection-mode))

elec-pair

Automatically insert matching delimiters

(use-package elec-pair
  :hook (after-init-hook . electric-pair-mode))

grugru

Rotate text at point

(use-package grugru
  :ensure t
  :bind
  (:map mode-specific-map
        ("@ <right>" . grugru-forward)
        ("@ <left>" . grugru-backward)
        ("@ >" . grugru-forward)
        ("@ <" . grugru-backward)
        ("@ SPC" . grugru-select))
  (:repeat-map grugru-repeat-map
               ("<right>" . grugru-forward)
               ("<left>" . grugru-backward)
               (">" . grugru-forward)
               ("<" . grugru-backward)
               ("SPC" . grugru-select))
  :config
  (grugru-default-setup)
  (grugru-define-global 'symbol '("yes" "no"))
  (grugru-define-global 'symbol '("true" "false"))
  (grugru-define-multiple
    ((nix-mode rust-mode)
     (non-alphabet "==" "!="))
    (nix-mode
     (symbol "fetchurl" "fetchGit" "fetchTarball" "fetchClosure")
     (symbol "mkShell" "mkShellNoCC"))
    (rust-mode
     (non-alphabet "&&" "||")
     (non-alphabet "+=" "-=")
     (non-alphabet "*=" "/=" "%=")
     (non-alphabet "&=" "|=" "^=")
     (non-alphabet "<" "<=" ">" ">=")
     (non-alphabet ">>=" "<<=")
     (symbol "const" "let" "static"))))

hippie-exp

expand text trying various ways to find its expansion

(use-package hippie-exp
  :custom
  (hippie-expand-try-functions-list
   '(try-complete-file-name-partially
     try-complete-file-name
     try-expand-dabbrev
     try-expand-dabbrev-visible
     try-expand-dabbrev-from-kill
     try-expand-dabbrev-all-buffers))
  :bind
  ([remap dabbrev-expand] . hippie-expand))

isearch

incremental search minor mode

(use-package isearch
  :custom
  (isearch-allow-scroll t)
  (isearch-lazy-count t))

jinx

Enchanted Spell Checker

(use-package jinx
  :ensure t
  :hook
  ((git-commit-mode-hook
    vc-git-log-edit-mode-hook
    markdown-mode-hook
    org-mode-hook) . jinx-mode)
  :bind
  (([remap ispell-word] . jinx-correct)
   ("C-M-$" . jinx-correct-nearest)))

link-hint

Use avy to open, copy, etc. visible links

(use-package link-hint
  :ensure t
  :bind
  ((:map goto-map
         ("l" . link-hint-open-link)
         ("L" . link-hint-copy-link))))

markdown-mode

Major mode for Markdown-formatted text

(use-package markdown-mode
  :ensure t
  :custom
  (markdown-fontify-code-blocks-natively t)
  :mode
  (("\\.markdown\\'"
    "\\.md\\'"
    "\\.mdoc\\'"
    "\\.mdx\\'") . markdown-mode)
  ("README\\.md\\'" . gfm-mode)
  :hook
  (markdown-mode-hook . dprint-on-save-mode)
  (markdown-mode-hook . (lambda () (setq-local line-spacing 0.5)))
  :bind
  (:map markdown-mode-map
        :map mode-specific-map
        ("'" . markdown-edit-code-block)))

misc

some nonstandard editing and utility commands for Emacs

(use-package misc
  :custom
  (duplicate-region-final-position -1)
  :bind
  (:map mode-specific-map
        ("d" . duplicate-dwim)))

move-dup

Eclipse-like moving and duplicating lines or rectangles

(use-package move-dup
  :ensure t
  :bind
  (("M-P" . move-dup-move-lines-up)
   ("M-N" . move-dup-move-lines-down)
   ("C-M-p" . move-dup-duplicate-up)
   ("C-M-n" . move-dup-duplicate-down))
  :hook (after-init-hook . global-move-dup-mode))

pixel-scroll

Scroll a line smoothly

NOTE: Key bindings related to scrolling are defined in the window configuration with some custom commands.

(use-package pixel-scroll
  :if (>= emacs-major-version 29)
  :custom
  (pixel-scroll-precision-interpolate-page t)
  (pixel-scroll-precision-use-momentum t)
  (pixel-scroll-precision-momentum-seconds 0.5)
  (pixel-scroll-precision-initial-velocity-factor 0.000375)
  (pixel-scroll-precision-large-scroll-height 100)
  :hook
  (after-init-hook . pixel-scroll-precision-mode)
  ((eww-mode-hook
    find-file-hook
    help-mode-hook) . pixel-scroll-precision-mode))

puni

Parentheses Universalistic

(use-package puni
  :ensure t
  :hook (after-init-hook . puni-global-mode)
  :bind
  ((:map puni-mode-map
         ([remap mark-sexp] . puni-mark-sexp-at-point)
         ([remap transpose-sexps] . puni-transpose))
   (:map mode-specific-map
         ("SPC" . puni-expand-region)
         ("<" . puni-wrap-angle)
         ("{" . puni-wrap-curly)
         ("^" . puni-splice))
   (:repeat-map puni-region-repeat-map
                ("SPC" . puni-expand-region)
                ("<right>" . puni-expand-region)
                ("<left>" . puni-contract-region)))
  :config
  (mapc (lambda (k) (keymap-unset puni-mode-map k))
        '("C-M-a" "C-M-e" "C-M-f" "C-M-b")))

replace

replace commands for Emacs

(use-package replace
  :bind
  (:map mode-specific-map
        ("o" . occur)))

savehist

Save minibuffer history

(use-package savehist
  :hook (after-init-hook . savehist-mode))

saveplace

automatically save place in files

(use-package saveplace
  :hook (after-init-hook . save-place-mode))

separedit

Edit comment or string/docstring or code block inside them in separate buffer with your favorite mode

(use-package separedit
  :ensure t
  :custom
  (separedit-default-mode 'markdown-mode)
  :bind
  (:map mode-specific-map
        ("'" . separedit)))

simple

basic editing commands for Emacs

(use-package simple
  :custom
  (indent-tabs-mode nil) ;; Use spaces instead of tabs for indentation.
  (kill-whole-line t)
  (line-number-mode nil)
  (read-extended-command-predicate 'command-completion-default-include-p))

string-inflection

foo_bar => FOO_BAR => FooBar => fooBar => foo-bar => Foo_Bar => foo_bar conversion of names

(use-package string-inflection
  :ensure t
  :bind
  ((:map mode-specific-map
         ("-" . string-inflection-all-cycle))
   (:repeat-map string-inflection-repeat-map
                ("-" . string-inflection-all-cycle))))

text-mode

text mode, and its idiosyncratic commands

(use-package text-mode
  :custom
  (text-mode-ispell-word-completion nil)) ; recommended for cape

tempel

Tempo templates/snippets with in-buffer field editing

(use-package tempel
  :ensure t
  :custom
  ;; (tempel-path (concat emacs-data-home "templates/*.eld"))
  (tempel-path (expand-file-name "templates/*.eld" emacs-data-home))
  :bind
  (("M-+" . tempel-complete)
   ("M-*" . tempel-insert)
   (:map tempel-map
         ("TAB" . tempel-next)
         ([tab] . tempel-next)
         ("S-TAB" . tempel-previous)
         ([backtab] . tempel-previous)
         ("M-RET". tempel-done))))

visual-replace

A prompt for replace-string and query-replace

(use-package visual-replace
  :ensure t
  :custom
  (visual-replace-default-to-full-scope t)
  (visual-replace-keep-initial-position t)
  :hook
  (after-init-hook . visual-replace-global-mode)
  :bind
  ([remap query-replace] . visual-replace)
  :config
  (with-eval-after-load 'transient
    (transient-define-prefix my/visual-replace-mode-transient ()
      "Prefix for `visual-replace-mode-map'."
      ["Basic operation"
       ("a" "apply one repeat" visual-replace-apply-one-repeat)
       ("A" "apply one" visual-replace-apply-one)
       ("s" "substring match" visual-replace-substring-match)
       ("u" "undo" visual-replace-undo)
       ("y" "yank" visual-replace-yank)
       ("M-y" "yank-pop" visual-replace-yank-pop)]
      ["Toggle replace mode"
       ("c" "toggle case fold" visual-replace-toggle-case-fold)
       ("e" "toggle regexp" visual-replace-toggle-regexp)
       ("q" "toggle query" visual-replace-toggle-query)
       ("w" "toggle word" visual-replace-toggle-word)]
      ["Change scope"
       ("f" "switch to full scope" visual-replace-switch-to-full-scope)
       ("p" "switch to from-point scope" visual-replace-switch-to-from-point-scope)
       ("r" "switch to region scope" visual-replace-switch-to-region-scope)])
    (keymap-set visual-replace-mode-map "?" #'my/visual-replace-mode-transient)))

vundo

Visual undo tree

(use-package vundo
  :ensure t
  :custom
  (vundo-compact-display t)
  (vundo-glyph-alist vundo-unicode-symbols)
  (vundo-popup-timeout 2.0)
  (vundo-window-max-height 15)
  :bind
  ((:map vundo-mode-map
         ("C-e" . vundo-confirm)))
  :hook (after-init-hook . vundo-popup-mode)
  :config
  (with-eval-after-load 'embark
    (keymap-set embark-general-map "C-/" #'vundo)))

ws-butler

Unobtrusively remove trailing whitespace

(use-package ws-butler
  :ensure t
  :hook
  ((prog-mode-hook
    text-mode-hook) . ws-butler-mode))

Visual Aid

colorful-mode

Preview any color in your buffer in real time

By default, the following major modes are included in `global-colorful-modes`:

  • Prog
  • Help
  • HTML
  • CSS
  • LaTeX
(use-package colorful-mode
  :ensure t
  :custom
  (colorful-use-prefix t)
  (colorful-only-strings 'only-prog)
  (css-fontify-colors nil)
  :config
  (global-colorful-mode 1)
  (add-to-list 'global-colorful-modes 'helpful-mode))

display-fill-column-indicator

interface for display-fill-column-indicator

(use-package display-fill-column-indicator
  :hook
  ((prog-mode-hook
    text-mode-hook) . display-fill-column-indicator-mode))

display-line-numbers

interface for display-line-numbers

(use-package display-line-numbers
  :custom
  (display-line-numbers-type t)
  (display-line-numbers-grow-only t)
  (display-line-numbers-width-start t)
  :hook
  (display-line-numbers-mode-hook . header-line-indent-mode)
  :init
  (global-display-line-numbers-mode 1)
  :config
  (defun my/display-line-numbers-fixed-width ()
    (when (< display-line-numbers-width 5)
      (setq display-line-numbers-width 5)))
  (add-hook 'display-line-numbers-mode-hook #'my/display-line-numbers-fixed-width)
  (dolist (mode '(dashboard-mode-hook
                  dired-mode-hook
                  eat-mode-hook
                  eshell-mode-hook
                  org-mode-hook
                  shell-mode-hook
                  term-mode-hook
                  vterm-mode-hook))
    (add-hook mode (lambda () (display-line-numbers-mode 0)))))

goggles

Pulse modified regions

(use-package goggles
  :ensure t
  :custom
  (goggles-pulse-delay 0.05)
  (goggles-pulse-iterations 15)
  :hook
  ((prog-mode-hook
    text-mode-hook) . goggles-mode))

highlight-indent-guides

Minor mode to highlight indentation

(use-package highlight-indent-guides
  :ensure t
  :custom
  (highlight-indent-guides-method 'character)
  :hook
  ((python-mode-hook
    yaml-mode-hook) . highlight-indent-guides-mode))

hl-line

highlight the current line

(use-package hl-line
  :custom
  (hl-line-sticky-flag nil)
  (global-hl-line-sticky-flag nil)
  :hook
  ((prog-mode-hook
    text-mode-hook
    dired-mode-hook) . hl-line-mode))

hl-todo

Highlight TODO and similar keywords

(use-package hl-todo
  :ensure t
  :custom
  (hl-todo-highlight-punctuation ":")
  :hook
  ((org-mode-hook
    prog-mode-hook) . hl-todo-mode)
  :bind
  ((:map hl-todo-mode-map
         :map mode-specific-map
         ("t <right>" . hl-todo-next)
         ("t <left>" . hl-todo-previous)
         ("t >" . hl-todo-next)
         ("t <" . hl-todo-previous)
         ("t o" . hl-todo-occur))
   (:repeat-map hl-todo-repeat-map
                ("<right>" . hl-todo-next)
                ("<left>" . hl-todo-previous)
                (">" . hl-todo-next)
                ("<" . hl-todo-previous))))

paren

highlight matching paren

(use-package paren
  :custom
  (show-paren-context-when-offscreen t)
  :hook (after-init-hook . show-paren-mode))

rainbow-delimiters

Highlight brackets according to their depth

(use-package rainbow-delimiters
  :ensure t
  :hook
  ((clojure-mode-hook
    emacs-lisp-mode-hook
    haskell-mode-hook
    lisp-mode-hook) . rainbow-delimiters-mode))

shr

Simple HTML Renderer

(use-package shr
  :defer 3
  :custom
  (shr-bullet " - ")
  (shr-use-colors nil)
  (shr-width nil))

shr-tag-pre-highlight

Syntax highlighting code block in HTML

(use-package shr-tag-pre-highlight
  :ensure t
  :after shr
  :config
  (add-to-list 'shr-external-rendering-functions
               '(pre . shr-tag-pre-highlight)))

valign

Visually align tables

(use-package valign
  :ensure t
  :custom
  (valign-fancy-bar t)
  :hook ((markdown-mode-hook org-mode-hook) . valign-mode))

visual-fill-column

fill-column for visual-line-mode

(use-package visual-fill-column
  :ensure t
  :custom
  (visual-fill-column-center-text t)
  (visual-fill-column-extra-text-width '(5 . 0))
  (visual-fill-column-width 100))

whitespace

minor mode to visualize TAB, (HARD) SPACE, NEWLINE

(use-package whitespace
  :custom
  (whitespace-line-column fill-column)
  (whitespace-space-regexp "\\(\u3000+\\)")
  (whitespace-style '(face
                      trailing
                      tabs
                      spaces
                      empty
                      missing-newline-at-eof))
  :config
  (global-whitespace-mode t))

(use-package whitespace-cleanup-mode
  :commands whitespace-cleanup-mode
  :config
  (global-whitespace-cleanup-mode 1))

File and Directory

filelock.c

Lock files for editing.

(setq create-lockfiles nil)

activities

Save/restore sets of windows, tabs/frames, and their buffers

(use-package activities
  :ensure t
  :custom
  (activities-bookmark-warnings t)
  :bind
  ((:map ctl-x-map
         :prefix-map activities-map
         :prefix "C-a"
         ("l" . activities-list)
         ("g" . activities-revert)
         ("RET" . activities-switch)
         ("C-d" . activities-define)
         ("C-k" . activities-kill)
         ("C-n" . activities-new)
         ("C-a" . activities-resume)
         ("C-s" . activities-suspend)))
  :hook (after-init-hook . activities-tabs-mode)
  :config
  (with-eval-after-load 'consult
    (defun my/activities-local-buffer-p (buffer)
      "Returns non-nil if BUFFER is present in `activities-current'."
      (when (activities-current)
        (memq buffer (activities-tabs--tab-parameter 'activities-buffer-list (activities-tabs--tab (activities-current))))))
    (defvar my-consult--source-activities-buffer
      `(:name "Activities Buffers"
              :narrow ?a
              :category buffer
              :face consult-buffer
              :history buffer-name-history
              :default t
              :items ,(lambda () (consult--buffer-query
                                  :predicate #'my/activities-local-buffer-p
                                  :sort 'visibility
                                  :as #'buffer-name))
              :state ,#'consult--buffer-state))
    (add-to-list 'consult-buffer-sources 'my-consult--source-activities-buffer)))

dashboard

A startup screen extracted from Spacemacs

(use-package dashboard
  :ensure t
  :custom
  (dashboard-startup-banner (concat user-pictures-dir "dashboard-banner.png"))
  (dashboard-banner-logo-title "Welcome to Ametsuchi.")
  ;; (dashboard-init-info nil)
  (dashboard-center-content t)
  (dashboard-vertically-center-content t)
  (dashboard-page-separator "\n\f\f\n")
  ;; (dashboard-set-navigator t)
  (dashboard-set-footer nil)
  (dashboard-set-file-icons t)
  (dashboard-set-heading-icons t)
  (dashboard-show-shortcuts t)
  (dashboard-projects-backend 'project-el)
  (dashboard-items
   '((agenda . 10)
     (projects . 5)
     (bookmarks . 10)
     (recents . 15)))
  (dashboard-item-shortcuts
   '((agenda . "a")
     (bookmarks . "s")
     (projects . "j")
     (recents . "r")
     (registers . "e")))
  :bind
  (("<f5>" . my/home)
   (:map dashboard-mode-map
         ("?" . my/dashboard-mode-transient)))
  :hook
  ;; (window-setup-hook . dashboard-open)
  (after-init-hook . dashboard-refresh-buffer)
  (server-after-make-frame-hook . dashboard-refresh-buffer)
  (dashboard-mode-hook . (lambda ()
                           (setq-local frame-title-format nil)))
  :config
  (defun my/home ()
    (interactive)
    (delete-other-windows)
    (dashboard-refresh-buffer))
  (mapc (lambda (k) (keymap-unset dashboard-mode-map k))
        '("j" "k" "{" "}"))
  (with-eval-after-load 'transient
    (transient-define-prefix my/dashboard-mode-transient ()
      "Prefix for dashboard launch menu."
      [("m" "Mastodon" mastodon)
       ("o" "OpenStreetMap" osm)
       ("g" "GitHub CLI" consult-gh)
       ;; ("c" "Calibre" calibredb)
       ("?" "Gptel" gptel-menu)
       ("e" "Mu4e" mu4e)]))
  (dashboard-setup-startup-hook))

dired

directory-browsing commands

(use-package dired
  :commands dired
  :custom
  (dired-auto-revert-buffer t)
  (dired-create-destination-dirs 'ask)
  (dired-recursive-copies 'always)
  (dired-recursive-deletes 'always)
  (delete-by-moving-to-trash t)
  (dired-dwim-target t)
  (dired-listing-switches "-alh --group-directories-first")
  :bind
  ;; replace `dired-do-man' with a more frequently used one.
  ((:map dired-mode-map
         ("N" . dired-create-empty-file)))
  :hook
  (dired-mode-hook . dired-hide-details-mode))
dired-collapse

Collapse unique nested paths in dired listing

(use-package dired-collapse
  :ensure t
  :after dired
  :hook
  (dired-mode-hook . dired-collapse-mode))
dired-filter

Ibuffer-like filtering for dired

(use-package dired-filter
  :ensure t
  :after dired
  :custom
  (dired-filter-group-saved-groups
   '(("default"
      ("General directories"
       (directory . t)
       (name . "^[[:alnum:]]"))
      ("Dot directories"
       (directory . t)
       (name . "^\\."))
      ("Dot or config files"
       (file . t)
       (or (dot-files)
           (extension "conf" "toml" "yaml" "yml")))
      ("Data files"
       (file . t)
       (extension "csv" "json" "jsonc" "lock"))
      ("Code"
       (file . t)
       (extension "astro" "c" "clj" "css" "el" "hs"
                  "html" "js" "jsx" "nix" "py" "rs"
                  "scss" "ts" "tsx" "zig"))
      ("Org"
       (file . t)
       (extension "org" "org_archive"))
      ("Text documents"
       (file . t)
       (or (name . "COPYING")
           (name . "LICENSE")
           (name . "README")
           (name . "TODO")
           (extension "markdown" "md" "mdx" "mkd" "rst" "txt")))
      ("E-books and PDF" (extension "azw" "epub" "mobi"  "pdf"))
      ("Archives" (extension "bz2" "gz" "nar" "rar" "tar" "zip"))
      ("LaTeX" (extension "tex" "bib"))
      ("Executables" (executable))
      ("Images"
       (extension "avif" "bmp" "ico" "jpeg" "jpg" "gif"
                  "png" "raw" "svg" "tiff" "webp" "xcf")))))
  :hook
  ((dired-mode-hook . dired-filter-mode)
   (dired-mode-hook . dired-filter-group-mode)))
dired-hacks-utils

Utilities and helpers for dired-hacks collection

(use-package dired-hacks-utils
  :ensure t
  :after dired
  :bind
  (:map dired-mode-map
        ("n" . dired-hacks-next-file)
        ("p" . dired-hacks-previous-file)))
dired-open-with

And “Open with” dialog for Dired

(use-package dired-open-with
  :ensure t
  :after dired
  :bind
  ((:map dired-mode-map
         ("M-RET" . dired-open-with))))
dired-ranger

Implementation of useful ranger features for dired

(use-package dired-ranger
  :ensure t
  :after dired
  :bind
  ((:map dired-mode-map
         :prefix-map dired-ranger-map
         :prefix "r"
         ("c" . dired-ranger-copy)
         ("x" . dired-ranger-move)
         ("y" . dired-ranger-paste))))
dired-subtree

Insert subdirectories in a tree-like fashion

(use-package dired-subtree
  :ensure t
  :after dired
  :custom
  (dired-subtree-use-backgrounds nil)
  :bind
  (:map dired-mode-map
        ("i" . dired-subtree-insert)
        ("SPC" . dired-subtree-toggle)
        ("b" . dired-subtree-remove)))

envrc

Support for `direnv’ that operates buffer-locally

(use-package envrc
  :ensure t
  :if (executable-find "direnv")
  :hook (after-init-hook . envrc-global-mode))

files

file input and output commands

(use-package files
  :custom
  (auto-mode-case-fold nil)
  (backup-by-copying t)
  (backup-directory-alist
   `(("." . ,(locate-user-emacs-file "backup/"))))
  (delete-old-versions t)
  (require-final-newline t)
  (version-control t)
  (view-read-only t)
  :config
  (with-eval-after-load 'embark
    (defun my/find-file-vertically (file)
      "Open FILE in a new vertically split window."
      (select-window (split-window-right))
      (find-file file))
    (keymap-set embark-file-map "M-RET" #'my/find-file-vertically)))

project

Operations on the current project

(use-package project
  :config
  (defun my/project-try-nix-store (dir)
    (save-match-data
      (when (string-match (rx bol "/nix/store/" (+ (not "/")) "/")
                          dir)
        (list 'nix-store (match-string 0 dir)))))
  (add-hook 'project-find-functions #'my/project-try-nix-store)
  (cl-defmethod project-root ((project (head nix-store)))
    (cadr project)))

recentf

keep track of recently opened files

(use-package recentf
  :custom
  (recentf-max-saved-items 300)
  (recentf-auto-cleanup 'never)
  (recentf-exclude
   '("/tmp/"
     "/nix/store/"))
  :hook
  (after-init-hook . recentf-mode))

startup

process Emacs shell arguments

(use-package startup
  :custom
  (inhibit-default-init t)
  (inhibit-startup-echo-area-message t)
  (inhibit-startup-screen t)
  (initial-buffer-choice
   (lambda () (get-buffer-create "*dashboard*")))
  (initial-scratch-message nil)
  (initial-major-mode 'fundamental-mode))

Development

aggressive-indent-mode

Minor mode to aggressively keep your code always indented

(use-package aggressive-indent
  :ensure t
  :hook (emacs-lisp-mode-hook . aggressive-indent-mode))

compile

run compiler as inferior of Emacs, parse error messages

(use-package compile
  :custom
  (compilation-ask-about-save nil)
  (compilation-scroll-output t)
  :config
  ;; http://stackoverflow.com/a/13408008/1219634
  (require 'ansi-color)
  (defun my/colorize-compilation-buffer ()
    (ansi-color-apply-on-region compilation-filter-start (point)))
  (add-hook 'compilation-filter-hook #'my/colorize-compilation-buffer))

dumb-jump

Jump to definition for 50+ languages without configuration

(use-package dumb-jump
  :ensure t
  :custom
  (dumb-jump-selector 'completing-read)
  :hook
  (xref-backend-functions . dumb-jump-xref-activate))

eglot

The Emacs Client for LSP servers

(use-package eglot
  :defer 3
  :custom
  (eglot-autoshutdown t)
  (eglot-code-action-indications nil)
  (eglot-confirm-server-edits nil)
  (eglot-extend-to-xref t)
  :hook
  (eglot-managed-mode-hook . my/setup-eglot-buffer)
  :bind
  (:map eglot-mode-map
        :map mode-specific-map
        ("L a" . eglot-code-actions)
        ("L i" . eglot-code-actions-inline)
        ("L o" . eglot-code-actions-organize-imports)
        ("L q" . eglot-code-actions-quickfix)
        ("L R" . eglot-reconnect)
        ("L r" . eglot-rename)
        ("L Q" . eglot-shutdown))
  :config
  (defun my/setup-eglot-buffer ()
    (if (eglot-managed-p)
        (add-hook 'before-save-hook #'eglot-format-buffer nil t)
      (remove-hook 'before-save-hook #'eglot-format-buffer t)))

  (dolist (entry '((just-mode . ("just-lsp"))
                   ((nix-ts-mode nix-mode) . ("nil"))
                   (zig-ts-mode . ("zls"))))
    (cl-pushnew entry eglot-server-programs :test #'equal)))
eglot-booster

boost eglot using emacs-lsp-booster

(use-package eglot-booster
  :ensure t
  :if (executable-find "emacs-lsp-booster")
  :after eglot
  :hook (eglot-managed-mode-hook . eglot-booster-mode))
eglot-tempel

bridge for tempel templates with eglot

(use-package eglot-tempel
  :ensure t
  :after (eglot tempel)
  :hook (eglot-managed-mode-hook . eglot-tempel-mode))

eldoc

Show function arglist or variable docstring in echo area

(use-package eldoc
  :custom
  (eldoc-echo-area-use-multiline-p nil)
  :hook (after-init-hook . global-eldoc-mode))

elysium

Automatically apply LLM-created code-suggestions

(use-package elysium
  :ensure t
  :after gptel
  :config
  (with-eval-after-load 'gptel-transient
    (transient-append-suffix 'gptel-menu nil
      ["Elysium"
       ("q" "Elysium query" elysium-query)])))

flymake

a universal on-the-fly syntax checker

(use-package flymake
  :bind
  ((:map flymake-mode-map
         :map goto-map
         ("M-n" . flymake-goto-next-error)
         ("M-p" . flymake-goto-prev-error))
   (:repeat-map flymake-mode-repeat-map
                ("n" . flymake-goto-next-error)
                ("p" . flymake-goto-prev-error))))

reformatter

Define commands which run reformatters on the current Emacs buffer

(use-package reformatter
  :ensure t
  :config
  (reformatter-define dprint
    :program "dprint"
    :args (list "fmt" "--stdin" (buffer-file-name)))
  (reformatter-define stylua
    :program "stylua"
    :args (list "-" "--indent-type=Spaces" "--indent-width=2"))
  (reformatter-define nixfmt
    :program "nixfmt"
    :args (list "-"))
  (reformatter-define yamlfmt
    :program "yamlfmt"
    :args (list "-")))

repl-toggle

Switch to/from repl buffer for current major-mode

(use-package repl-toggle
  :ensure t
  :custom
  (rtog/goto-buffer-fun #'pop-to-buffer))

treesit

tree-sitter utilities

(use-package treesit
  :custom
  (treesit-font-lock-level 4))

Language-specific modes

astro-ts-mode

Major mode for editing Astro templates

(use-package astro-ts-mode
  :ensure t
  :mode "\\.astro\\'"
  :hook (astro-ts-mode-hook . eglot-ensure))
dockerfile-ts-mode

tree-sitter support for Dockerfiles

(use-package dockerfile-ts-mode
  :mode
  "\\.dockerfile\\'"
  "[/\\]\\(?:Containerfile\\|Dockerfile\\)\\(?:\\.[^/\\]*\\)?\\'"
  :hook
  (dockerfile-ts-mode-hook . eglot-ensure)
  (dockerfile-ts-mode-hook . dprint-on-save-mode))
elisp-mode

Emacs Lisp mode

(use-package elisp-mode
  :config
  (add-to-list 'auto-mode-alist
               '("/recipes/[-a-z0-9]+\\'" . lisp-data-mode))
  (define-skeleton elisp-skeleton
    "Insert a header for Emacs Lisp files."
    > ";;; "
    (file-name-nondirectory (or buffer-file-name (buffer-name)))
    " --- " _
    " -*- lexical-binding: t -*-\n"
    "\n\n\n"
    ";;; "
    (file-name-nondirectory (or buffer-file-name (buffer-name)))
    " ends here")
  (with-eval-after-load 'autoinsert
    (dolist (entry (reverse
                    '(("\\.dir-locals\\(?:-2\\)?\\.el\\'" . "dir-locals-insert.el")
                      ("\\.el\\'" . elisp-skeleton))))
      (add-to-list 'auto-insert-alist entry))))
just-mode

Justfile editing mode

(use-package just-mode
  :ensure t
  :mode "/justfile\\'")
lua-ts-mode

Major mode for editing Lua files

(use-package lua-ts-mode
  :mode "\\.lua\\'"
  :hook
  (lua-ts-mode-hook . eglot-ensure)
  (lua-ts-mode-hook . stylua-on-save-mode))
nix-ts-mode

Major mode for Nix expressions, powered by tree-sitter

(use-package nix-ts-mode
  :ensure t
  :mode "\\.nix\\'"
  :hook
  (nix-ts-mode-hook . eglot-ensure)
  (nix-ts-mode-hook . nixfmt-on-save-mode))
nix-mode

An Emacs major mode for editing Nix expressions.

(use-package nix-mode
  :ensure t
  :commands nix-repl)
rust-ts-mode

tree-sitter support for Rust

(use-package rust-ts-mode
  :mode "\\.rs\\'"
  :hook
  (rust-ts-mode-hook . eglot-ensure))
toml-ts-mode

tree-sitter support for TOML

(use-package toml-ts-mode
  :mode "\\.toml\\'"
  :hook
  (toml-ts-mode-hook . eglot-ensure)
  (toml-ts-mode-hook . dprint-on-save-mode))
typescript-ts-mode

tree sitter support for TypeScript

(use-package typescript-ts-mode
  :mode "\\.ts$" "\\.mts\\'"
  :hook (typescript-ts-mode-hook . eglot-ensure))
web-mode

web template editing mode for emacs

(use-package web-mode
  :ensure t
  :custom
  (web-mode-enable-front-matter-block t)
  (web-mode-enable-current-element-highlight t)
  :mode
  "\\.html?\\'"
  "\\.mdx\\'"
  :hook
  (web-mode-hook . eglot-ensure))
yaml-ts-mode

tree-sitter support for YAML

(use-package yaml-ts-mode
  :mode "\\.ya?ml\\'"
  :hook
  (yaml-ts-mode-hook . eglot-ensure)
  (yaml-ts-mode-hook . yamlfmt-on-save-mode))
zig-ts-mode

major mode for editing web templates

(use-package zig-ts-mode
  :ensure t
  :mode "\\(?:\\.z\\(?:ig\\|on\\)\\)\\'"
  :hook
  (zig-ts-mode-hook . eglot-ensure))

Version Control System

blamer

Show git blame info about current line

(use-package blamer
  :ensure t
  :defer 5
  :custom
  (blamer-idle-time 0.5)
  (blamer-max-commit-message-length 50)
  (blamer-max-lines 40)
  (blamer-min-offset 60)
  (blamer-author-formatter "%s ")
  (blamer-commit-formatter "\'%s\'")
  (‎blamer-datetime-formatter‎ "[%s]")
  (blamer-view 'overlay)
  :bind
  ((:map help-map
         ("M-g" . blamer-show-commit-info)))
  :config
  (global-blamer-mode 1))

diff-hl

Highlight uncommitted changes using VC

(use-package diff-hl
  :ensure t
  :custom
  (diff-hl-command-prefix (kbd "C-x v"))
  (diff-hl-draw-borders t)
  :hook
  (after-init-hook . global-diff-hl-mode)
  (dired-mode-hook . diff-hl-dired-mode)
  :config
  (with-eval-after-load 'magit
    (add-hook 'magit-pre-refresh-hook #'diff-hl-magit-pre-refresh)
    (add-hook 'magit-post-refresh-hook #'diff-hl-magit-post-refresh)))

forge

Work with Git forges from the comfort of Magit

(use-package forge
  :ensure t
  :demand t
  :after magit
  :custom
  (forge-database-file (concat emacs-data-home "forge/database.sqlite"))
  (forge-owned-accounts '(("brklntmhwk")))
  (forge-add-pullreq-refspec 'ask))

git-auto-commit-mode

Emacs Minor mode to automatically commit and push

(use-package git-auto-commit-mode
  :ensure t
  :custom
  ;; (gac-default-message "xxx")
  (gac-silent-message-p t))

git-commit

Edit Git commit messages

(use-package git-commit
  :after magit)

magit

A Git porcelain inside Emacs

(use-package magit
  :ensure t
  :custom
  (magit-save-repository-buffers 'dontask)
  (magit-define-global-key-bindings nil)
  (magit-clone-default-directory (concat user-documents-dir "projects/"))
  :bind
  ((:map ctl-x-map
         :prefix-map magit-prefix-map
         :prefix "g"
         ("s" . magit-status)
         ("d" . magit-dispatch)
         ("f" . magit-file-dispatch)))
  :config
  ;; https://www.reddit.com/r/emacs/comments/11auxod/magit_quits_after_a_commit_happen/
  ;; Explicitly set this to prevent the Dashboard buffer from appearing after every commit.
  (add-hook 'git-commit-post-finish-hook #'magit))
magit-delta

Use Delta when displaying diffs in Magit

(use-package magit-delta
  :ensure t
  :if (executable-find "delta")
  :after magit
  :hook (magit-mode-hook . magit-delta-mode))
magit-todos

Show source file TODOs in Magit

(use-package magit-todos
  :ensure t
  :after magit
  :custom
  (magit-todos-exclude-globs '(".git/"))
  :hook (magit-mode-hook . magit-todos-mode))

Browsing

ace-link

Quickly follow links

(use-package ace-link
  :ensure t
  :after avy
  :bind
  ((:map eww-mode-map
         ("o" . ace-link-eww))))

browse-url

pass a URL to a web browser

(use-package browse-url
  :custom
  (browse-url-browser-function 'browse-url-generic)
  ;; (browse-url-browser-function 'eww-browse-url)
  (browse-url-secondary-browser-function 'eww-browse-url)
  (browse-url-generic-program "firefox"))

eww

Emacs Web Wowser

(use-package eww
  :commands (eww eww-search-words)
  :custom
  (eww-auto-rename-buffer 'title)
  ;; (eww-bookmarks-directory "~/")
  ;; (eww-browse-url-new-window-is-tab nil)
  (eww-download-directory user-downloads-dir)
  (eww-history-limit 150)
  :hook
  (eww-after-render-hook . (lambda ()
                             (eww-readable)
                             (visual-line-mode)
                             (setq-local line-spacing 0.4))))

Terminal

eat

Emulate A Terminal, in a region, in a buffer and in Eshell

(use-package eat
  :ensure t
  :custom
  ;; (eat-enable-shell-prompt-annotation nil)
  (eat-kill-buffer-on-exit t)
  :bind
  ((:map project-prefix-map
         ("t" . eat-preject)))
  :config
  (mapc (lambda (k) (keymap-unset eat-semi-char-mode-map k))
        '("M-g" "M-o" "M-s")))

exec-path-from-shell

Get environment variables such as $PATH from the shell

(use-package exec-path-from-shell
  :ensure t
  :if (eq system-type 'darwin)
  :config
  (when (or window-system
            (daemonp))
    (exec-path-from-shell-initialize)))

Email

mu4e

Mu-based mua for emacs

;; (use-package mu4e
;;      :ensure t)

Org Mode

org

Outline-based notes management and organizer

(use-package org
  :defer 5
  :custom
  ;; Org files management
  (org-default-notes-file (concat user-documents-dir "inbox.org"))
  ;; Agenda-related stuff
  (org-enforce-todo-dependencies t)
  (org-extend-today-until 4)
  (org-log-done 'time)
  (org-tags-exclude-from-inheritance '("crypt"))
  (org-todo-keywords
   '((sequence
      "PENDING(t)"
      "READY(r!)"
      "ONGOING(o!)"
      "|"
      "COMPLETED(x)"
      "CANCELLED(c@)")
     (type
      "PAUSED(p@/!)"
      "WAITING(w@/!)")))
  (org-track-ordered-property-with-tag t)
  (org-use-effective-time t)
  ;; General workflow
  (org-cycle-separator-lines 0)
  (org-imenu-depth 6)
  (org-special-ctrl-a/e t)
  (org-special-ctrl-k t)
  (org-use-speed-commands t)
  ;; Appearance
  (org-ellipsis "")
  (org-fontify-done-headline t)
  (org-fontify-quote-and-verse-blocks t)
  (org-fontify-whole-heading-line t)
  (org-image-actual-width t)
  (org-pretty-entities t)
  (org-startup-folded 'content)
  (org-startup-indented nil)
  (org-startup-truncated nil)
  (org-tags-column -80)
  ;; Misc
  (org-bookmark-names-plist nil)
  :hook (org-mode-hook . my/org-mode-setup)
  :config
  (defun my/org-mode-setup ()
    (setq-local tab-width 8)
    (setq-local line-spacing 0.5)))

dslide

Domain Specific sLIDEs. Programmable Presentation

(use-package dslide
  :ensure t
  :after org
  :custom
  (dslide-header nil)
  (dslide-header-author nil)
  (dslide-header-date nil)
  (dslide-header-email nil)
  (dslide-breadcrumb-separator nil)
  :hook
  (dslide-start-hook . hide-mode-line-mode))

org-agenda

Dynamic task and appointment lists for Org

(use-package org-agenda
  :after org
  :custom
  ;; (org-agenda-compact-blocks t)
  ;; (org-agenda-custom-commands
  ;;  '(("n" "Agenda and all TODOs" ((agenda "") (alltodo "")))))
  ;; (org-agenda-dim-blocked-tasks nil)
  (org-agenda-files (list user-documents-dir))
  (org-agenda-inhibit-startup t)
  (org-agenda-restore-windows-after-quit t)
  (org-agenda-start-on-weekday 1)
  (org-agenda-use-tag-inheritance '(todo search agenda))
  (org-agenda-window-setup 'current-window)
  :bind
  (:map mode-specific-map
        ("a" . org-agenda))
  :hook (org-agenda-finalize-hook . hl-line-mode)
  :config
  ;; Unset `org-agenda-goto' because it is confusing.
  (mapc (lambda (k) (keymap-unset org-agenda-mode-map k))
        '("TAB" "<tab>"))
  ;; Then override `delete-other-windows' because I do not use it.
  (keymap-set org-agenda-mode-map "o" #'org-agenda-goto))
org-super-agenda

Supercharge your Org daily/weekly agenda by grouping items

(use-package org-super-agenda
  :ensure t
  :after org-agenda
  :custom
  (org-super-agenda-groups
   '((:name "Timeline"
            :time-grid t)))
  :config
  (org-super-agenda-mode 1))

org-anki

Synchronize org-mode entries to Anki

(use-package org-anki
  :ensure t
  :after org
  :custom
  (org-anki-default-deck "Default")
  (org-anki-default-note-type "Basic")
  (org-anki-inherit-tags nil)
  :bind
  (:map org-mode-map
        :prefix-map org-anki-map
        :prefix "C-c C-x k"
        ("b" . org-anki-browse-entry)
        ("s" . org-anki-sync-entry)
        ("S" . org-anki-sync-all)
        ("u" . org-anki-update-all)
        ("U" . org-anki-update-dir)))

org-appear

Auto-toggle Org elements

(use-package org-appear
  :ensure t
  :hook (org-mode-hook . org-appear-mode))

org-autolist

Improved list management in org-mode

(use-package org-autolist
  :ensure t
  :hook (org-mode-hook . org-autolist-mode))

org-babel(ob)

Working with Code Blocks in Org

(use-package ob
  :after org
  :custom
  (org-confirm-babel-evaluate nil)
  (org-babel-load-languages
   '((clojure . t)
     (emacs-lisp . t)
     (haskell . t)
     (julia . t)
     (latex . t)
     (lua . t)
     (python . t)
     (ocaml . t)
     (shell . t)
     (sql . t)
     (sqlite . t))))

org-bookmark-heading

Emacs bookmark support for Org mode

(use-package org-bookmark-heading
  :ensure t
  :after org
  :custom
  (org-bookmark-heading-make-ids t))

org-capture

Fast note taking in Org

(use-package org-capture
  :after org
  :custom
  (org-capture-templates
   `(("i" "Inbox" entry
      (file "")
      "* %?\n%U\n\n  %i")))
  :bind
  (:map mode-specific-map
        ("c" . org-capture)))

org-clock

The time clocking code for Org mode

(use-package org-clock
  :after org
  :custom
  (org-clock-auto-clockout-timer (* 60 20))
  (org-clock-history-length 30)
  (org-clock-in-resume t)
  (org-clock-mode-line-total 'today)
  (org-clock-out-remove-zero-time-clocks t)
  (org-clock-persist t)
  (org-clock-persist-query-resume t)
  (org-clock-persist-query-save t))

org-clock-convenience

Convenience functions to work with emacs org mode clocking from the agenda view

(use-package org-clock-convenience
  :ensure t
  :bind
  (:map org-agenda-mode-map
        ("M-]" . org-clock-convenience-timestamp-up)
        ("M-[" . org-clock-convenience-timestamp-down)))

org-crypt

Public Key Encryption for Org Entries

(use-package org-crypt
  :custom
  (org-crypt-key nil)
  :hook (org-mode-hook . my/org-encrypt-entries)
  :config
  (defun my/org-encrypt-entries ()
    (add-hook 'before-save-hook #'org-encrypt-entries nil t)))

org-download

Image drag-and-drop for Org-mode.

(use-package org-download
  :ensure t
  :after org
  :custom
  (org-download-image-dir user-pictures-dir)
  ;; (org-download-edit-cmd "swappy %s")
  ;; (org-download-screenshot-method "grimblast copysave")
  (org-download-timestamp "%Y%m%d_%H%M%S_")
  :hook (dired-mode-hook . org-download-enable))

org-element

Parser for Org Syntax

(use-package org-element
  :after org
  :init
  (setq org-element-cache-persistent nil))

org-habit

The habit tracking code for Org

(use-package org-habit
  :after org-agenda
  :custom
  (org-habit-graph-column 35)
  (org-habit-following-days 7)
  (org-habit-preceding-days 14)
  (org-habit-show-done-always-green t))

org-id

Global identifiers for Org entries

(use-package org-id
  :after org
  :custom
  (org-id-locations-file (concat emacs-cache-home "org-id-locations"))
  (org-id-link-to-org-use-id t)
  (org-id-search-archives nil))

org-indent

Dynamic indentation for Org

(use-package org-indent
  :custom
  (org-indent-mode-turns-on-hiding-stars t))

org-journal

a simple org-mode based journaling mode

(use-package org-journal
  :ensure t
  :after org
  :custom
  (org-journal-dir (concat user-documents-dir "journal/"))
  (org-journal-prefix-key nil)
  (org-journal-date-format "%a, %d %b")
  (org-journal-time-format "")
  (org-journal-time-prefix "")
  (org-journal-file-format "%Y.org")
  (org-journal-enable-agenda-integration t)
  ;; (org-journal-enable-encryption t)
  (org-journal-file-type 'yearly)
  (org-journal-file-header "#+TITLE: %Y Journal\n\n")
  :bind
  ((:map mode-specific-map
         ("j" . org-journal-new-entry))
   (:map org-journal-mode-map
         :map mode-specific-map
         ("n" . org-journal-next-entry)
         ("p" . org-journal-previous-entry)
         ("j" . org-journal-new-entry)
         ("s" . org-journal-search))))

org-link(ol)

Org links library

(use-package ol
  :custom
  (org-link-keep-stored-after-insertion t)
  :bind
  (:map mode-specific-map
        ("l" . org-store-link)))

org-make-toc

Automatic tables of contents for Org-mode files

(use-package org-make-toc
  :ensure t
  :custom
  (org-make-toc-insert-custom-ids t)
  :hook (org-mode-hook . org-make-toc-mode))

org-modern

Modern looks for Org

(use-package org-modern
  :ensure t
  :after org
  :custom
  (org-modern-hide-stars 'leading)
  (org-modern-star 'replace)
  ;; Use chess pieces as bullets, reflecting piece hierarchy.
  (org-modern-replace-stars
   (concat (string #x265a) ; King
           (string #x265b) ; Queen
           (string #x265c) ; Rook
           (string #x265d) ; Bishop
           (string #x265e) ; Knight
           (string #x265f))) ; Pawn
  :hook
  (org-mode-hook . org-modern-mode)
  (org-agenda-finalize . org-modern-agenda))

org-nix-shell

Org local nix-shell

(use-package org-nix-shell
  :ensure t
  :hook (org-mode-hook . org-nix-shell-mode))

org-pomodoro

Pomodoro implementation for org-mode.

(use-package org-pomodoro
  :ensure t
  :after org-agenda
  :commands (org-pomodoro)
  :custom
  (org-pomodoro-length 25)
  (org-pomodoro-short-break-length 5)
  (org-pomodoro-long-break-length 20))

org-ql

Org Query Language, search command, and agenda-like view

(use-package org-ql
  :ensure t
  :after org
  :bind
  (:map org-mode-map
        ("C-c C-x /" . org-ql-sparse-tree)))

org-recur

Recurring org-mode tasks

(use-package org-recur
  :ensure t
  :hook
  ((org-mode-hook . org-recur-mode)
   (org-agenda-mode-hook . org-recur-agenda-mode)))

org-refile

Refile Org Subtrees

(use-package org-refile
  :after org
  :custom
  (org-log-refile nil)
  (org-outline-path-complete-in-steps nil)
  (org-refile-allow-creating-parent-nodes 'confirm)
  ;; Set the maxlevel to 99 to be able to refile to everywhere in the targeted file.
  (org-refile-targets
   '((nil :maxlevel . 99)
     (org-agenda-files :maxlevel . 99)))
  (org-refile-use-outline-path 'file))

org-src

Source code examples in Org

(use-package org-src
  :custom
  (org-src-tab-acts-natively t)
  (org-src-window-setup 'split-window-below)
  (org-src-preserve-indentation nil)
  (org-edit-src-content-indentation 0))

org-super-links

Make super links

(use-package org-super-links
  :ensure t
  :bind
  ((:map org-mode-map
         :prefix-map org-super-links-map
         :prefix "C-c C-x s"
         ;; ("d" . org-super-links-delete-link)
         ("l" . org-super-links-insert-link)
         ("s" . org-super-links-store-link))))

org-transclusion

Transclude text content via links

(use-package org-transclusion
  :ensure t
  :after org
  ;; :custom
  ;; (org-transclusion-add-all-on-activate t)
  :hook (org-mode-hook . org-transclusion-mode))

org-web-tools

Display and capture web content with Org-mode

(use-package org-web-tools
  :ensure t
  :after org
  :bind
  ((:map org-mode-map
         :prefix-map org-web-tools-map
         :prefix "C-c C-x w"
         ("y" . org-web-tools-insert-link-for-url)
         ("Y" . org-web-tools-insert-web-page-as-entry))))

Miscellaneous

keyboard.c

Keyboard and mouse input; editor command loop.

;; Fix the copy issue on WSL with WSLg.
(setq select-active-regions nil)

terminal.c

Functions related to terminal devices.

(setq ring-bell-function 'ignore)

calc

the GNU Emacs calculator

(use-package calc
  :custom
  (calc-kill-line-numbering nil))

calendar

calendar functions

(use-package calendar
  :custom
  (calendar-mark-holidays-flag t)
  (calendar-date-style 'european))

calibredb

Yet another calibre client

(use-package calibredb
  :ensure t
  :custom
  (calibredb-root-dir (concat user-documents-dir "calibre/"))
  (calibredb-db-dir (expand-file-name "metadata.db" calibredb-root-dir))
  ;; (calibredb-device-dir "/TODO")
  (calibredb-download-dir nil)
  (calibredb-format-nerd-icons t)
  (calibredb-library-alist
   '((calibredb-root-dir (name . "Calibre"))))
  (calibredb-virtual-library-default-name "Library")
  (calibredb-virtual-library-alist nil))

epkg

Browse the Emacsmirror package database

(use-package epkg
  :custom
  (epkg-repository (concat emacs-data-home "epkgs/")))
epkg-marginalia

Show Epkg information in completion annotations

(use-package epkg-marginalia
  :ensure t
  :after (epkg marginalia)
  :config
  (cl-pushnew 'epkg-marginalia-annotate-package
              (alist-get 'package marginalia-annotator-registry)))

gt

Translation framework, configurable and scalable

(use-package gt
  :ensure t
  :custom
  (gt-langs '(en es ja))
  (gt-polyglot-p t)
  (gt-default-translator
   (gt-translator
    :taker (list
            (gt-taker :pick nil :if 'selection)
            ;; (gt-taker :text 'buffer :pick 'paragraph)
            (gt-taker :text 'word))
    :engines (gt-google-engine)
    ;; :engines (list
    ;;                                  (gt-google-engine :if 'word)
    ;;                                  (gt-deepl-engine :if 'not-word))
    :render (gt-buffer-render)))
  :bind
  ((:map mode-specific-map
         ("q" . gt-do-translate))))

gptel

Interact with ChatGPT or other LLMs

(use-package gptel
  :ensure t
  :custom
  (gptel-default-mode 'org-mode)
  (gptel-use-header-line t)
  (gptel-log-level 'info)
  :bind
  (:map mode-specific-map
        ("\\" . gptel-menu))
  :config
  (setq gptel-model 'gemma3:4b
        gptel-backend (gptel-make-ollama "Ollama"
                        :host "localhost:11434"
                        :stream t
                        :models '(deepseek-r1:8b
                                  gemma3:4b
                                  llama3.2:3b
                                  mistral:7b
                                  phi4:14b
                                  qwen3:4b))))
gptel-org

Org functions for gptel

(use-package gptel-org
  :after gptel
  :bind
  (:map org-mode-map
        ("C-c C-x `" . gptel-org-set-topic)
        ("C-c C-x =" . gptel-org-set-properties)))
gptel-quick

Quick LLM lookups in Emacs

(use-package gptel-quick
  :after (gptel)
  :config
  (with-eval-after-load 'embark
    (keymap-set embark-general-map "?" #'gptel-quick)))
gptel-rewrite

Refactoring functions for gptel

(use-package gptel-rewrite
  :after gptel
  :custom
  (‎gptel-rewrite-default-action‎ 'dispatch)
  :config
  (with-eval-after-load 'embark
    (keymap-set embark-region-map "!" #'gptel-rewrite)))

mastodon

Client for fediverse services using the Mastodon API

(use-package mastodon
  :ensure t)

nov

Featureful EPUB reader mode

(use-package nov
  :ensure t
  :mode ("\\.epub\\'" . nov-mode)
  :custom
  (nov-text-width 82)
  ;; File name where last reading places are saved to and restored from.
  (nov-save-place-file (concat emacs-cache-home "nov-places"))
  :hook (nov-mode-hook . my/nov-mode-setup)
  :config
  ;; https://github.com/akirak/emacs-config?tab=readme-ov-file#nov
  (defun my/nov-mode-setup ()
    (setq-local line-spacing 0.4)
    (when (require 'olivetti nil t)
      (olivetti-mode 1)
      (setq-local nov-text-width nil)
      (add-hook 'olivetti-expand-hook
                #'nov-render-document
                nil t))))

osm

OpenStreetMap viewer

(use-package osm
  :ensure t
  :custom
  (osm-search-language "en,ja")
  (osm-tile-directory emacs-cache-home)
  :bind
  (("<f6>" . osm)
   (:map osm-mode-map
         ([remap previous-line] . osm-up)
         ([remap next-line] . osm-down)
         ([remap backward-char] . osm-left)
         ([remap forward-char] . osm-right)
         ("g" . osm-goto)
         ("h" . osm-home)
         ("j" . osm-jump)
         ("s" . osm-search)
         ("v" . osm-server)
         ("x" . osm-gpx-show)
         ("X" . osm-gpx-hide))))

pdf-tools

Support library for PDF documents.

(use-package pdf-tools
  :ensure t
  :magic ("%PDF" . pdf-view-mode))

prodigy

Manage external services

(use-package prodigy
  :ensure t)

Personal

Make sure that customizable variables whose values should preferably be kept private are added to the custom file. (e.g., auth-sources)

;; Load `custom-file' if you have created one.
(when (and custom-file (file-readable-p custom-file))
  (load custom-file))

License

This project is licensed under the terms of the MIT license. It adopts and follows the REUSE Specification Version 3.3; therefore the license files are stored under LICENSES directory, and each file contains an SPDX license identifier.

Acknowledgments

This project stands on the shoulders of great pioneers from all walks of life. Heartfelt thanks to all the developers involved in the Nix and Emacs communities, package development, and beyond.

Below are some of the resources I frequently consulted:

Footnotes

[fn:1] https://zero-to-nix.com/concepts/reproducibility/

About

Ametsuchi is the universe — It encompasses (almost) everything that forms my ideal Emacs workstation, a living cosmos where creativity, logic, and intuition intertwine.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published