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):
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.Name | Alternatives | |
---|---|---|
Emacs installation | emacs-overlay | Direct use of Nixpkgs |
Package build | twist.nix | package-build |
Package manager | twist.el | package.el, straight.el, elpaca, etc. |
Configuration Macro | use-package | leaf.el, setup.el, etc. |
Project’s framework | flake-parts | flake-utils, snowfall, denix, etc. |
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
NOTE: This section is still a work in progress.
;;; 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 𝐀”
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))
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)))
Common Lisp extensions for Emacs
;; Use macros only.
(eval-when-compile
(require 'cl-lib))
commands for multilingual environment
(use-package mule-cmds
:config
(set-language-environment "UTF-8"))
Mouse wheel support
(use-package mwheel
:custom
(mouse-wheel-tilt-scroll t))
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))
(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)
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)
convenient way to repeat the previous command
(use-package repeat
:hook (after-init-hook . repeat-mode))
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)))
(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/"))
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))
Benchmarks for require and load calls
(use-package benchmark-init
:ensure t
:hook (after-init-hook . benchmark-init/deactivate))
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))
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))
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 commands for Emacs
(use-package help
:custom
(help-window-keep-selected t)
:hook
(help-mode-hook . (lambda () (setq-local line-spacing 0.4))))
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 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)))
Using posframe to show transient
;; (use-package transient-posframe
;; :ensure t
;; :after transient
;; :custom
;; (transient-posframe-border-width 3)
;; :config
;; (transient-posframe-mode 1))
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)))
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))))
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))))
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))
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)))))
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)))
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 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))))
Generic frame functions.
(cl-pushnew '(internal-border-width . 16) default-frame-alist :test #'equal)
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)
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))
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))
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))
Emacs Nerd Font Icons Library
(use-package nerd-icons :ensure t)
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))
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))
Icons for dired via nerd-icons
(use-package nerd-icons-dired
:ensure t
:hook
(dired-mode-hook . nerd-icons-dired-mode))
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))
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 features in an Emacs buffer
(use-package show-font :ensure t)
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))
project and imenu-based breadcrumb paths
(use-package breadcrumb
:ensure t
:custom
(breadcrumb-project-crumb-separator " > ")
:hook (after-init-hook . breadcrumb-mode))
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))
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))
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)))
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))))
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 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)))
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)))
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))
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))
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))
Embark Actions for consult-gh
(use-package consult-gh-embark
:ensure t
:after consult-gh
:config
(consult-gh-embark-mode 1))
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 commands for imenu
(use-package consult-imenu
:after consult
:bind
(([remap imenu] . consult-imenu))
(:map goto-map
("I" . consult-imenu-multi)))
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))
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))))
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)))
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))
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))))
Consult integration for Embark
(use-package embark-consult
:after (consult embark)
:hook (embark-collect-mode-hook . consult-preview-at-point-mode))
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))))
indentation commands for Emacs
(use-package indent
:custom
(tab-always-indent 'complete))
Enrich existing commands with completion annotations
(use-package marginalia
:ensure t
:hook (after-init-hook . marginalia-mode))
Minibuffer and completion functions
(use-package minibuffer
:custom
(completion-cycle-threshold 3))
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))
VERTical Interactive COmpletion
(use-package vertico
:ensure t
:custom
(vertico-count 20)
(vertico-resize nil)
:hook (after-init-hook . vertico-mode))
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))
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))
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))
Random utility Lisp functions.
(setq use-short-answers t)
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"))))
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))
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)))
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))))
delete selection if you insert
(use-package delsel
:hook (after-init-hook . delete-selection-mode))
Automatically insert matching delimiters
(use-package elec-pair
:hook (after-init-hook . electric-pair-mode))
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"))))
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))
incremental search minor mode
(use-package isearch
:custom
(isearch-allow-scroll t)
(isearch-lazy-count t))
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)))
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))))
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)))
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)))
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))
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))
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 commands for Emacs
(use-package replace
:bind
(:map mode-specific-map
("o" . occur)))
Save minibuffer history
(use-package savehist
:hook (after-init-hook . savehist-mode))
automatically save place in files
(use-package saveplace
:hook (after-init-hook . save-place-mode))
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)))
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))
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, and its idiosyncratic commands
(use-package text-mode
:custom
(text-mode-ispell-word-completion nil)) ; recommended for cape
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))))
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)))
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)))
Unobtrusively remove trailing whitespace
(use-package ws-butler
:ensure t
:hook
((prog-mode-hook
text-mode-hook) . ws-butler-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))
interface for display-fill-column-indicator
(use-package display-fill-column-indicator
:hook
((prog-mode-hook
text-mode-hook) . display-fill-column-indicator-mode))
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)))))
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))
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))
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))
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))))
highlight matching paren
(use-package paren
:custom
(show-paren-context-when-offscreen t)
:hook (after-init-hook . show-paren-mode))
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))
Simple HTML Renderer
(use-package shr
:defer 3
:custom
(shr-bullet " - ")
(shr-use-colors nil)
(shr-width nil))
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)))
Visually align tables
(use-package valign
:ensure t
:custom
(valign-fancy-bar t)
:hook ((markdown-mode-hook org-mode-hook) . valign-mode))
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))
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))
Lock files for editing.
(setq create-lockfiles nil)
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)))
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))
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))
Collapse unique nested paths in dired listing
(use-package dired-collapse
:ensure t
:after dired
:hook
(dired-mode-hook . dired-collapse-mode))
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)))
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)))
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))))
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))))
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)))
Support for `direnv’ that operates buffer-locally
(use-package envrc
:ensure t
:if (executable-find "direnv")
:hook (after-init-hook . envrc-global-mode))
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)))
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)))
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))
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))
Minor mode to aggressively keep your code always indented
(use-package aggressive-indent
:ensure t
:hook (emacs-lisp-mode-hook . aggressive-indent-mode))
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))
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))
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)))
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))
bridge for tempel templates with eglot
(use-package eglot-tempel
:ensure t
:after (eglot tempel)
:hook (eglot-managed-mode-hook . eglot-tempel-mode))
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))
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)])))
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))))
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 "-")))
Switch to/from repl buffer for current major-mode
(use-package repl-toggle
:ensure t
:custom
(rtog/goto-buffer-fun #'pop-to-buffer))
tree-sitter utilities
(use-package treesit
:custom
(treesit-font-lock-level 4))
Major mode for editing Astro templates
(use-package astro-ts-mode
:ensure t
:mode "\\.astro\\'"
:hook (astro-ts-mode-hook . eglot-ensure))
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))
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))))
Justfile editing mode
(use-package just-mode
:ensure t
:mode "/justfile\\'")
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))
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))
An Emacs major mode for editing Nix expressions.
(use-package nix-mode
:ensure t
:commands nix-repl)
tree-sitter support for Rust
(use-package rust-ts-mode
:mode "\\.rs\\'"
:hook
(rust-ts-mode-hook . eglot-ensure))
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))
tree sitter support for TypeScript
(use-package typescript-ts-mode
:mode "\\.ts$" "\\.mts\\'"
:hook (typescript-ts-mode-hook . eglot-ensure))
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))
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))
major mode for editing web templates
(use-package zig-ts-mode
:ensure t
:mode "\\(?:\\.z\\(?:ig\\|on\\)\\)\\'"
:hook
(zig-ts-mode-hook . eglot-ensure))
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))
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)))
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))
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))
Edit Git commit messages
(use-package git-commit
:after 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))
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))
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))
Quickly follow links
(use-package ace-link
:ensure t
:after avy
:bind
((:map eww-mode-map
("o" . ace-link-eww))))
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"))
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))))
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")))
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)))
Mu-based mua for emacs
;; (use-package mu4e
;; :ensure t)
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)))
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))
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))
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))
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)))
Auto-toggle Org elements
(use-package org-appear
:ensure t
:hook (org-mode-hook . org-appear-mode))
Improved list management in org-mode
(use-package org-autolist
:ensure t
:hook (org-mode-hook . org-autolist-mode))
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))))
Emacs bookmark support for Org mode
(use-package org-bookmark-heading
:ensure t
:after org
:custom
(org-bookmark-heading-make-ids t))
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)))
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))
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)))
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)))
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))
Parser for Org Syntax
(use-package org-element
:after org
:init
(setq org-element-cache-persistent nil))
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))
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))
Dynamic indentation for Org
(use-package org-indent
:custom
(org-indent-mode-turns-on-hiding-stars t))
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 links library
(use-package ol
:custom
(org-link-keep-stored-after-insertion t)
:bind
(:map mode-specific-map
("l" . org-store-link)))
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))
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 local nix-shell
(use-package org-nix-shell
:ensure t
:hook (org-mode-hook . org-nix-shell-mode))
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 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)))
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)))
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))
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))
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))))
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))
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))))
Keyboard and mouse input; editor command loop.
;; Fix the copy issue on WSL with WSLg.
(setq select-active-regions nil)
Functions related to terminal devices.
(setq ring-bell-function 'ignore)
the GNU Emacs calculator
(use-package calc
:custom
(calc-kill-line-numbering nil))
calendar functions
(use-package calendar
:custom
(calendar-mark-holidays-flag t)
(calendar-date-style 'european))
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))
Browse the Emacsmirror package database
(use-package epkg
:custom
(epkg-repository (concat emacs-data-home "epkgs/")))
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)))
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))))
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))))
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)))
Quick LLM lookups in Emacs
(use-package gptel-quick
:after (gptel)
:config
(with-eval-after-load 'embark
(keymap-set embark-general-map "?" #'gptel-quick)))
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)))
Client for fediverse services using the Mastodon API
(use-package mastodon
:ensure t)
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))))
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))))
Support library for PDF documents.
(use-package pdf-tools
:ensure t
:magic ("%PDF" . pdf-view-mode))
Manage external services
(use-package prodigy
:ensure t)
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))
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.
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: