A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/terlar/emacs-config below:

GitHub - terlar/emacs-config: GNU Emacs configuration

Terje’s GNU Emacs configuration.

This configuration is making a lot of assumptions as it is built as a package with Nix. This means that all packages are expected to be on the load-path already and compatibility is only guaranteed with the GNU Emacs version that is part of this package. Currently GNU Emacs 31.0.50.

The rough details:

themes
readable-typo-theme and readable-mono-theme
fonts
Iosevka Curly Slab, Iosevka Aile, Iosevka Etoile
buffer completion
corfu, completion-preview
minibuffer completion
vertico
package configuration
use-package
key definitions
keymap, repeat
code navigation
xref, dumb-jump, imenu-anywhere
syntax checker
flymake
persistence
desktop
language server integration
eglot
structured editing
puni

Nix:

;;; early-init.el --- Early Initialization -*- lexical-binding: t; -*-

Provide an easy way to toggle debug mode which will set certain variables to produce more informative output. It can be set either by providing the environment variable DEBUG or start Emacs with --debug-init.

(when (getenv "DEBUG") (setq init-file-debug t))
(setq debug-on-error (and (not noninteractive) init-file-debug))

Time the startup and display the startup time after completed.

(add-hook 'emacs-startup-hook
          (lambda ()
            (message "Loaded Emacs in %.03fs"
                     (float-time (time-subtract after-init-time before-init-time)))))

Temporarily reduce garbage collection to gain some performance boost during startup.

(let ((normal-gc-cons-threshold gc-cons-threshold)
      (normal-gc-cons-percentage gc-cons-percentage)
      (normal-file-name-handler-alist file-name-handler-alist)
      (init-gc-cons-threshold most-positive-fixnum)
      (init-gc-cons-percentage 0.6))
  (setq gc-cons-threshold init-gc-cons-threshold
        gc-cons-percentage init-gc-cons-percentage
        file-name-handler-alist nil)
  (add-hook 'after-init-hook
            `(lambda ()
               (setq gc-cons-threshold ,normal-gc-cons-threshold
                     gc-cons-percentage ,normal-gc-cons-percentage
                     file-name-handler-alist ',normal-file-name-handler-alist))))

Inhibit startup screen and messages. If you are new to Emacs it is recommended to not disable the startup screen as it has great content to get you going.

(setq inhibit-startup-echo-area-message t)
(setq inhibit-startup-screen t)
(setq initial-scratch-message nil)

Performance tweaks. Don’t load default library and use fundamental-mode to reduce amount of hooks.

(setq inhibit-default-init t)
(setq initial-major-mode 'fundamental-mode)

Disable package.el support. Packages are managed via Nix and disabling this gives a slight performance boost.

(setq package-enable-at-startup nil)

Disable GUI components.

(setq use-dialog-box nil)
(push '(undecorated . t) default-frame-alist)
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)

Don’t implicitly resize frames when changing various settings.

(setq frame-inhibit-implied-resize t)
(defvar global-text-scale-adjust-resizes-frames t)

Allow resizing by dragging internal border.

(push '(drag-internal-border . t) default-frame-alist)

Ignore X resources.

(advice-add #'x-apply-session-resources :override #'ignore)
;;; init.el --- Initialization -*- lexical-binding: t; -*-

A macro for package customization, see use-package for further details.

This configuration is intended to support byte-compiling and is compiling with the strict option byte-compile-error-on-warn t. See the section about byte-compiling with information on how to support this use case.

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

(eval-and-compile
  (defun use-package-ensure-ignore (&rest _args) t)
  (setq use-package-ensure-function #'use-package-ensure-ignore)

  (setq use-package-always-defer t)
  (setq use-package-hook-name-suffix nil))

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

Provide a location where Emacs can store data and cache.

(defvar data-dir
  (if (getenv "XDG_DATA_HOME")
      (concat (getenv "XDG_DATA_HOME") "/emacs/")
    (expand-file-name "~/.local/share/emacs/"))
  "Directory for data.")

(defvar cache-dir
  (if (getenv "XDG_CACHE_HOME")
      (concat (getenv "XDG_CACHE_HOME") "/emacs/")
    (expand-file-name "~/.cache/emacs/"))
  "Directory for cache.")

(defvar pictures-dir
  (or (getenv "XDG_PICTURES_DIR")
      (expand-file-name "~/Pictures/"))
  "Directory for pictures.")

Put custom definitions in a temporary file so it doesn’t grow over time. This means all customization will disappear upon reboot and instead needs to be managed via the initialization file.

(setq custom-file (expand-file-name "custom.el" temporary-file-directory))

Help keeping user-emacs-directory clean.

(use-package no-littering
  :ensure t
  :demand t
  :init
  (setq no-littering-etc-directory data-dir)
  (setq no-littering-var-directory cache-dir))

No second pass of case-insensitive search over auto-mode-alist.

(setq auto-mode-case-fold nil)

Give up some bidirectional functionality for slightly faster re-display.

(setq bidi-inhibit-bpa t)
(setq-default bidi-display-reordering 'left-to-right
              bidi-paragraph-direction 'left-to-right)

Defer processing font faces while scrolling and typing.

(setq fast-but-imprecise-scrolling t)
(setq jit-lock-defer-time 0)

Adjust Garbage Collector threshold depending on activity and try to run garbage collection during idle instead.

(use-package gcmh
  :ensure t
  :hook
  (after-init-hook . gcmh-mode)
  :init
  (setq gcmh-idle-delay 5)
  (setq gcmh-high-cons-threshold (* 16 1024 1024)) ; 16MB
  (setq gcmh-verbose init-file-debug))

Track how much time is spent in each function and present a view to investigate this data.

(use-package explain-pause-mode
  :ensure t
  :commands
  (explain-pause-mode)
  :init
  (when init-file-debug
    (explain-pause-mode 1)))

Large file support. This can view/edit/search and compare large files.

(use-package vlf :ensure t)

Library for displaying icons. I am trying to use icons where possible.

(use-package all-the-icons
  :ensure t
  :commands
  (all-the-icons-faicon all-the-icons-octicon))

Library providing functions inspired by Common Lisp. In many cases these functions feel more natural to use.

(require 'cl-lib)
(require 'cl-extra)

Prevent forms from producing output or other noise.

(defmacro quiet! (&rest forms)
  "Run FORMS without making any noise."
  `(if init-file-debug
       (progn ,@forms)
     (let ((message-log-max nil))
       (with-temp-message (or (current-message) "") ,@forms))))

(defun quiet-function-advice (orig-fn &rest args)
  "Advice used to make a function quiet.
Call ORIG-FN with ARGS and suppress the output.  Usage:

  (advice-add \\='orig-fn :around #\\='quiet-function-advice)"
  (quiet! (apply orig-fn args)))

Easily define REPL functions.

(defmacro define-repl (fn-name buffer-name command &rest args)
  "Define a REPL function named FN-NAME running COMMAND inside BUFFER-NAME."
  (let ((repl-buffer (concat "*" buffer-name "*")))
    `(defun ,fn-name ()
       ,(format "Run an inferior instance of %s inside Emacs." command)
       (interactive)
       (let ((buffer (get-buffer-create ,repl-buffer)))
         (unless (comint-check-proc ,repl-buffer)
           (apply 'make-comint-in-buffer ,buffer-name buffer ,command nil ,args))
         (pop-to-buffer buffer)))))
(defun display-ctrl-M-as-newline ()
  "Display `^M' as newline."
  (interactive)
  (setq buffer-display-table (make-display-table))
  (aset buffer-display-table ?\^M [?\n]))

Screenshot current frame in .svg or .png format.

(defun screenshot (type)
  "Save a screenshot of the current frame as an image in TYPE format.
Saves to a temp file and puts the filename in the kill ring."
  (let* ((ext (concat "." (symbol-name type)))
         (filename (make-temp-file "Emacs-" nil ext))
         (data (x-export-frames nil type)))
    (with-temp-file filename
      (insert data))
    (kill-new filename)
    (message filename)))

(defun screenshot-svg ()
  "Save a screenshot of the current frame as an SVG image.
Saves to a temp file and puts the filename in the kill ring."
  (interactive)
  (screenshot 'svg))

(defun screenshot-png ()
  "Save a screenshot of the current frame as an PNG image.
Saves to a temp file and puts the filename in the kill ring."
  (interactive)
  (screenshot 'png))
(defun send-buffer-to-ssh ()
  "Send the whole buffer to the *ssh* process."
  (interactive)
  (process-send-region "*ssh*" (point-min) (point-max)))

(defun send-to-ssh ()
  "Send selected region or current line to the *ssh* process."
  (interactive)
  (let ((procbuf "*ssh*"))
    (if (use-region-p)
        (process-send-region procbuf (region-beginning) (region-end))
      (process-send-string procbuf (thing-at-point 'line t)))))

Fringe control:

(define-minor-mode hide-fringes-mode
  "Toggle hiding of fringes."
  :group 'fringe
  (if hide-fringes-mode
      (set-window-fringes nil 0 0 nil)
    (set-window-fringes nil left-fringe-width right-fringe-width t)))

(define-minor-mode global-hide-fringes-mode
  "Toggle hiding of fringes globally."
  :global t
  :group 'fringe
  (if global-hide-fringes-mode
        (set-fringe-style 0)
      (set-fringe-style nil)))
(setq-default calendar-week-start-day 1)

Set shell to bash as fish is not compatible with all packages using the shell.

(setq shell-file-name "bash")

Fix WSL/WSLg copy issue.

(setq select-active-regions nil)

Disable bell (both visual and audible).

(setq ring-bell-function #'ignore)
(setq visible-bell nil)

Use y / n instead of yes / no.

(setq confirm-kill-emacs #'y-or-n-p)
(fset #'yes-or-no-p #'y-or-n-p)

Hide M-x commands which does not work in the current buffer.

(setq read-extended-command-predicate #'command-completion-default-include-p)
(defvar init-line-spacing 0.25
  "Spacing between lines.")

(defvar init-default-font-height 105
  "Default font height.")
(defvar init-fixed-pitch-font "Iosevka Curly Slab"
  "Font used for fixed-pitch faces.")

(defvar init-variable-pitch-font "Iosevka Aile"
  "Font used for variable-pitch faces.")

(defvar init-serif-font "Iosevka Etoile"
  "Font used for serif faces.")

(defvar init-unicode-font "Noto Sans Mono"
  "Fallback font used for unicode glyphs.")

(defvar init-symbol-fonts '("Noto Emoji" "Symbola")
  "Fonts used for symbol/emoji faces.")

Setup symbol fonts.

(dolist (font init-symbol-fonts)
  (set-fontset-font t 'symbol font nil 'append))
(setq-default fill-column 110)

Underline line at descent position, not baseline position.

(setq x-underline-at-descent-line t)

Use a bar cursor by default.

(setq-default cursor-type 'bar)
(use-package readable-typo-theme
  :ensure t
  :demand t
  :init
  (setq readable-typo-theme-default-font-height init-default-font-height)
  (setq readable-typo-theme-line-spacing init-line-spacing)
  (setq readable-typo-theme-fixed-pitch-font init-fixed-pitch-font)
  (setq readable-typo-theme-fixed-pitch-serif-font init-fixed-pitch-font)
  (setq readable-typo-theme-variable-pitch-font init-variable-pitch-font)
  (setq readable-typo-theme-serif-font init-serif-font)
  :config
  (load-theme 'readable-typo t))
(use-package readable-mono-theme
  :ensure t
  :demand t
  :config
  (load-theme 'readable-mono t))

Attach a face to the echo area in order to style it differently.

(dolist (buffer-name '(" *Echo Area 0*"
                       " *Echo Area 1*"))
  (with-current-buffer (get-buffer-create buffer-name)
    (setq-local face-remapping-alist
                '((default readable-typo-theme-echo-area)))))
(defun toggle-theme-mode ()
  "Toggle dark/light `background-mode' and reload all loaded themes."
  (interactive)
  (customize-set-variable
   'frame-background-mode
   (if (eq 'light (frame-parameter nil 'background-mode)) 'dark 'light))
  (customize-set-variable 'custom-enabled-themes custom-enabled-themes))

(defun reload-themes ()
  "Reload all loaded themes."
  (interactive)
  (customize-set-variable 'custom-enabled-themes custom-enabled-themes))

See Frame Layout for details and terminology.

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

Setup fringes on both sides and display an indicator for buffer boundaries on the right side. Display fringes outside margins to have the padding on the inside.

(setq-default fringes-outside-margins t
              left-fringe-width 8
              right-fringe-width 8
              indicate-buffer-boundaries 'right)

Add margins inside windows to make text feel less crowded. Padding around the frame is configured via the internal-border-width in the Frame section.

(setq-default left-margin-width 1
              right-margin-width 1)

Add window dividers, mainly to add a border below the mode line.

(use-package frame
  :hook
  ((after-make-frame-functions
    server-after-make-frame-hook) . window-divider-mode)
  :init
  (setq window-divider-default-places t)
  (setq window-divider-default-bottom-width 1)
  (setq window-divider-default-right-width 1))

I try to retain functionality from the original mode line as much as possible, but I also want to simplify it slightly and separate into two parts; left side and right side mode line. There is a helper function in order to fill up the space needed to make the mode line appear on the right side. Also the coding system related information will be hidden if using utf-8-unix. I am also not displaying any minor mode lighters.

Define a variable to conveniently access only the major mode part of mode-line-modes.

(defvar mode-line-major-mode
  `(:propertize ("" mode-name)
                help-echo "Major mode\n\
mouse-1: Display major mode menu\n\
mouse-2: Show help for major mode\n\
mouse-3: Toggle minor modes"
                mouse-face mode-line-highlight
                local-map ,mode-line-major-mode-keymap))

Configure the order and components of the mode line.

(setq-default mode-line-format
              '("%e" mode-line-front-space
                mode-line-misc-info
                (vc-mode vc-mode)
                "  "
                mode-line-modified
                mode-line-remote
                mode-line-buffer-identification
                mode-line-position
                (:eval (mode-line-right))
                mode-line-end-spaces))

Setup the right aligned mode line and helper function to display it.

(defvar mode-line-right-format nil
  "The mode line to display on the right side.")

(defun mode-line-right ()
  "Render the `mode-line-right-format'."
  (let ((formatted-line (format-mode-line mode-line-right-format)))
    (list
     (propertize
      " "
      'display
      `(space :align-to (- (+ right right-fringe right-margin) ,(string-width formatted-line))))
     formatted-line)))

Move default components to the right side of the mode line.

(setq mode-line-right-format
      (list '(:eval mode-line-mule-info)
            "  "
            mode-line-major-mode))

Add position information including column and line number but skip the percentage.

(setq mode-line-position-column-line-format '(" L%l:C%C"))
(setq mode-line-percent-position nil)
(column-number-mode 1)
(line-number-mode 1)

To reduce unnecessary information coding system will not be shown by default if the file is UTF-8 with UNIX end-of-line.

(setq eol-mnemonic-unix ""
      eol-mnemonic-dos (propertize "[CR+LF]" 'face 'warning)
      eol-mnemonic-mac (propertize "[CR]" 'face 'warning)
      eol-mnemonic-undecided (propertize "[?]" 'face 'error))

(let ((coding (nthcdr 2 mode-line-mule-info)))
  (setcar coding '(:eval (if (string-equal "U" (format-mode-line "%z"))
                             ""
                           (propertize "[%z]" 'face 'warning))))
  coding)

Display information about the current indentation settings.

(use-package indent-info
  :ensure t
  :hook
  (after-init-hook . global-indent-info-mode)
  :init
  (setq indent-info-display-change-message-p nil)
  (setq indent-info-insert-target 'mode-line-mule-info)
  (setq indent-info-space-format "Spaces: %s")
  (setq indent-info-tab-format "Tab Size: %s"))

Support hiding the mode line, this can be useful for different modes displaying documents or presentation.

(use-package hide-mode-line
  :ensure t
  :commands
  (hide-mode-line-mode
   turn-on-hide-mode-line-mode
   turn-off-hide-mode-line-mode))
(defun mode-line-modified-icons ()
  "Icon representation of `mode-line-modified'."
  (cond (buffer-read-only
         (concat (all-the-icons-octicon "lock" :v-adjust -0.05) " "))
        ((buffer-modified-p)
         (concat (all-the-icons-faicon "floppy-o" :v-adjust -0.05) " "))
        ((and buffer-file-name
              (not (file-exists-p buffer-file-name)))
         (concat (all-the-icons-octicon "circle-slash" :v-adjust -0.05) " "))))

(setq-default mode-line-modified '((:eval (mode-line-modified-icons))))
(defun mode-line-remote-icons ()
  "Icon representation of `mode-line-remote'."
  (when (and buffer-file-name
             (file-remote-p buffer-file-name))
    (concat (all-the-icons-octicon "radio-tower" :v-adjust -0.02) " ")))

(setq-default mode-line-remote   '((:eval (mode-line-remote-icons))))

Shorten long Git branch names as well as replace Git prefix with a nice icon.

(defun vc-git-mode-line-shorten (string)
  "Shorten `version-control' STRING in mode-line and add icon."
  (cond
   ((string-prefix-p "Git" string)
    (concat (all-the-icons-octicon "git-branch" :v-adjust -0.05)
            " "
            (if (> (length string) 30)
                (concat (substring-no-properties string 4 30) "")
              (substring-no-properties string 4))))
   (t
    string)))
(advice-add 'vc-git-mode-line-string :filter-return #'vc-git-mode-line-shorten)
(defvar leader-key "C-,"
  "The key used for most custom operations.")
(defvar local-leader-key "C-."
  "The key used for major mode operations.")
(defvar toggle-prefix "C-'"
  "Key prefix for commands related to toggling.")
(defvar next-prefix "M-]"
  "Key prefix used for commands doing a next operation.")
(defvar prev-prefix "M-["
  "Key prefix used for commands doing a previous operation.")
(use-package repeat
  :hook
  (after-init-hook . repeat-mode))
;; Editing
(keymap-global-set "<XF86Tools>" #'just-one-space)
(keymap-global-set "C-M-y" #'duplicate-dwim)
(keymap-global-set "C-x C-/" #'revert-buffer)
(keymap-global-set "C-z" #'zap-up-to-char)
(keymap-global-set "<remap> <upcase-word>" #'upcase-dwim)
(keymap-global-set "<remap> <downcase-word>" #'downcase-dwim)
(keymap-global-set "<remap> <capitalize-word>" #'capitalize-dwim)
;; Files
(keymap-global-set "C-x j" #'find-sibling-file)
;; Region
(keymap-global-set "C-x r S" #'sort-lines)
(keymap-set goto-map "k" #'eldoc-doc-buffer)
(use-package window
  :bind
  ((:map window-prefix-map
         ("d" . toggle-dedicated-window)
         ("m" . maximize-window)
         ("r" . window-configuration-to-register)
         ("w" . window-toggle-side-windows))
   (:repeat-map resize-window-repeat-map
                ("+" . balance-windows)
                ("-" . fit-window-to-buffer)
                ("m" . maximize-window))
   (:repeat-map buffer-repeat-map
                ("b" . next-buffer)
                ("B" . previous-buffer)
                ("[" . previous-buffer)
                ("]" . next-buffer))
   (:repeat-map other-window-repeat-map
                ("o" . other-window)
                ("O" . other-window-reverse-repeat)))
  :config
  (defun toggle-dedicated-window ()
    "Toggle selected window as dedicated window."
    (interactive)
    (set-window-dedicated-p (selected-window)
                            (not (window-dedicated-p (selected-window)))))

  (defun other-window-reverse-repeat ()
    (interactive)
    (setq repeat-map 'other-window-repeat-map)
    (other-window -1)))
(defvar-keymap next-map
  :doc "Keymap for the next key sequences."
  :prefix 'next-map-prefix
  "b" '("Buffer" . next-buffer))
(keymap-global-set next-prefix 'next-map-prefix)

(defvar-keymap prev-map
  :doc "Keymap for the prev key sequences."
  :prefix 'prev-map-prefix
  "b" '("Buffer" . previous-buffer))
(keymap-global-set prev-prefix 'prev-map-prefix)
(keymap-global-set toggle-prefix 'toggle-map-prefix)
(defvar-keymap toggle-map
  :doc "Keymap for toggle key sequences."
  :prefix 'toggle-map-prefix
  "*" '("Light/Dark theme" . toggle-theme-mode)
  "c" '("Changes" . highlight-changes-mode)
  "d" '("Debug on error" . toggle-debug-on-error)
  "f" '("Code folding" . hs-minor-mode)
  "F" '("Follow" . follow-mode)
  ;; Group together as one mode?
  "g" '("Sub-word" . subword-mode)
  "G" '("Readable camelCase" . glasses-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" '("White-space" . whitespace-mode)
  "x" '("Syntax checker" . flymake-mode))
(keymap-global-set leader-key 'leader-map-prefix)
(defvar-keymap leader-map
  :doc "Keymap for leader key sequences."
  :prefix 'leader-map-prefix
  "m" 'gnus
  "P" 'list-processes
  "s" 'screenshot-svg
  "S" 'screenshot-png
  "x" 'regexp-builder
  "w" 'eww)

(keymap-global-set local-leader-key 'local-leader-map-prefix)
(defvar-keymap local-leader-map
  :doc "Keymap for leader key sequences."
  :prefix 'local-leader-map-prefix)

Enable indentation and completion with the TAB key.

(setq tab-always-indent 'complete)

Cycle with the TAB key if there are only few candidates.

(setq completion-cycle-threshold 3)

Completion preview inline, with quick completion key.

(use-package completion-preview
  :hook
  ((comint-mode-hook
    eshell-mode-hook
    prog-mode-hook
    text-mode-hook) . completion-preview-mode)
  (minibuffer-setup-hook . completion-preview-enable-in-minibuffer)
  :bind
  (:map completion-preview-active-mode-map
        ("TAB" . completion-preview-complete)
        ("C-e" . completion-preview-insert))
  :init
  (setq completion-preview-adapt-background-color nil)
  (setq completion-preview-minimum-symbol-length 2)
  :config
  (defun completion-preview-enable-in-minibuffer ()
    "Enable Corfu completion in the minibuffer, e.g., `eval-expression'."
    (when (where-is-internal #'completion-at-point (list (current-local-map)))
      (completion-preview-mode 1)))

  (cl-pushnew 'org-self-insert-command completion-preview-commands :test #'equal))

Space-separated matching components matching in any order.

(use-package orderless
  :ensure t
  :init
  (setq completion-styles '(substring orderless))
  (setq completion-category-defaults nil)
  (setq completion-category-overrides '((file (styles partial-completion)))))

Completion Overlay Region FUnction.

(use-package corfu
  :ensure t
  :commands
  (corfu-mode
   corfu-indexed-mode
   global-corfu-mode)
  :hook
  (minibuffer-setup-hook . corfu-enable-in-minibuffer)
  (corfu-mode-hook . corfu-popupinfo-mode)
  :bind
  (:map corfu-map
        ([return] . nil)
        ("RET" . nil)
        ("TAB" . corfu-next)
        ([tab] . corfu-next)
        ("S-TAB" . corfu-previous)
        ([backtab] . corfu-previous)
        ("C-e" . corfu-complete))
  :init
  (setq corfu-cycle t)
  (setq corfu-preselect 'first)
  (global-corfu-mode 1)
  (corfu-indexed-mode 1)
  :config
  (defun corfu-enable-in-minibuffer ()
    "Enable Corfu completion in the minibuffer, e.g., `eval-expression'."
    (when (where-is-internal #'completion-at-point (list (current-local-map)))
      (corfu-mode 1))))

Vertical interactive completion UI.

(use-package vertico
  :ensure t
  :commands
  (vertico-insert
   vertico-exit)
  :hook
  (after-init-hook . vertico-mode)
  :bind
  (:map vertico-map
        ("C-e" . vertico-move-end-of-line-or-insert))
  :init
  (defun vertico-move-end-of-line-or-insert (arg)
    "Move to end of line or insert current candidate.
   ARG lines can be used.

   When only one candidate exists exit input after insert."
    (interactive "p")
    (if (eolp)
        (progn
          (vertico-insert)
          (when (= vertico--total 1)
            (vertico-exit)))
      (move-end-of-line arg))))
(use-package all-the-icons-completion
  :ensure t
  :hook
  (marginalia-mode-hook . all-the-icons-completion-marginalia-setup))

Completion At Point Extensions.

(use-package cape
  :ensure t
  :commands
  (cape-wrap-silent
   cape-wrap-purify)
  :functions
  (cape-capf-buster
   cape-capf-super)
  :hook
  ((comint-mode-hook
    eshell-mode-hook) . init-cape-comint-capf)
  (eglot-managed-mode-hook . init-cape-eglot-capf)
  (prog-mode-hook . init-cape-prog-capf)
  (text-mode-hook . init-cape-text-capf)
  :bind
  (([remap dabbrev-expand] . cape-dabbrev)
   (:prefix-map completion-prefix-map :prefix "M-p"
                ("d" . cape-dabbrev)
                ("h" . cape-history)
                ("f" . cape-file)
                ("k" . cape-keyword)
                ("M-p" . completion-at-point)
                ("p" . cape-pcomplete)
                ("s" . cape-elisp-symbol)
                ("a" . cape-abbrev)
                ("l" . cape-line)
                ("w" . cape-dict)
                ("\\" . cape-tex)
                ("&" . cape-sgml)
                ("r" . cape-rfc1345))
   (:map corfu-map
         ("C-x C-f" . cape-file)))
  :init
  ;; Use cape-dict for dictionary completion.
  (setq cape-dict-file (getenv "WORDLIST"))
  (setq text-mode-ispell-word-completion nil)
  :config
  (defun init-cape-comint-capf ()
    (setq-local completion-at-point-functions
                (list (apply #'cape-capf-super
                             #'cape-history
                             (cl-remove-if-not #'functionp completion-at-point-functions)))))

  (defun init-cape-eglot-capf ()
    (setq-local completion-at-point-functions
                (list #'cape-file
                      (cape-capf-super (cape-capf-buster #'eglot-completion-at-point #'string-prefix-p)
                                       :with #'tempel-complete))))

  (defun init-cape-prog-capf ()
    (add-hook 'completion-at-point-functions #'cape-file nil t))

  (defun init-cape-text-capf ()
    (add-hook 'completion-at-point-functions #'cape-file nil t)
    (add-hook 'completion-at-point-functions #'cape-dict 10 t))

  (setq-default completion-at-point-functions
                (list #'cape-file #'cape-dabbrev))

  (setf (symbol-function 'cape-pcomplete) (cape-capf-interactive #'pcomplete-completions-at-point))
  (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
  (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify))

Commands compatible with completing-read.

(use-package consult
  :ensure t
  :bind
  (([remap bookmark-jump] . consult-bookmark)
   ([remap goto-line] . consult-goto-line)
   ([remap imenu] . consult-imenu)
   ([remap jump-to-register] . consult-register)
   ([remap point-to-register] . consult-register-store)
   ([remap switch-to-buffer] . consult-buffer)
   ([remap yank-pop] . consult-yank-pop)
   ("C-c k" . consult-kmacro)
   ("C-x C-r" . consult-recent-file)
   (:map search-map
         ("g" . consult-ripgrep)
         ("m" . consult-mark)
         ("M-m" . consult-global-mark)))
  :init
  (setq consult-preview-key "M-RET"))

(use-package consult-xref
  :after xref
  :functions
  (consult-xref)
  :init
  (setq xref-show-xrefs-function #'consult-xref)
  (setq xref-show-definitions-function #'consult-xref))
(use-package dabbrev
  :init
  (setq dabbrev-case-replace nil)
  (setq dabbrev-ignored-buffer-regexps '("\\.\\(?:pdf\\|jpe?g\\|png\\)\\'")))

Icons for buffer completions.

(use-package kind-icon
  :ensure t
  :after corfu
  :commands
  (kind-icon-margin-formatter)
  :init
  (cl-pushnew #'kind-icon-margin-formatter corfu-margin-formatters :test #'equal))

Annotations for completion candidates.

(use-package marginalia
  :ensure t
  :defer 2
  :commands
  (marginalia-mode)
  :config
  (marginalia-mode 1))
(use-package help
  :bind
  (:map help-map
        ("B" . find-library)
        ("u" . describe-face)
        ("U" . list-faces-display)
        ("'" . describe-char)))

(use-package help-at-pt
  :init
  (setq help-at-pt-timer-delay 0.1)
  (setq help-at-pt-display-when-idle '(flymake-diagnostic)))

Generic help system.

(use-package ghelp
  :ensure t
  :bind
  ((:map help-map
         ("A" . ghelp-describe-elisp)
         ("f" . ghelp-describe-function)
         ("k" . ghelp-describe-key)
         ("v" . ghelp-describe-variable))
   (:map goto-map
         ("h" . ghelp-describe-at-point))))

Better *help* buffer.

(use-package helpful
  :ensure t
  :bind
  (:map help-map
        ("C" . helpful-command)
        ("M" . helpful-macro)))

Favor horizontal splits.

(setq split-width-threshold nil)

Respect display actions for both automatic and manual window switching.

(setq switch-to-buffer-obey-display-actions t)

Resize pixelwise.

(setq window-resize-pixelwise t)

Hide asynchronous shell command buffers.

(cl-pushnew '("^*Async Shell Command*" . (display-buffer-no-window))
            display-buffer-alist
            :test #'equal)

Undo/redo between window layouts.

(use-package winner
  :hook
  (window-setup-hook . winner-mode)
  :bind
  (:repeat-map winner-repeat-map
               ("[" . winner-undo)
               ("]" . winner-redo)
               ("M-[" . winner-undo)
               ("M-]" . winner-redo))
  :init
  (setq winner-dont-bind-my-keys t)
  (keymap-set next-map next-prefix '("Window History" . winner-redo))
  (keymap-set prev-map prev-prefix '("Window History" . winner-undo)))

Transpose window arrangement.

(use-package transpose-frame
  :ensure t
  :bind
  ((:map window-prefix-map
         ("t" . transpose-frame)
         ("f" . flip-frame)
         ("F" . flop-frame))
   (:repeat-map window-arrangement-repeat-map
                ("t" . transpose-frame)
                ("f" . flip-frame)
                ("F" . flop-frame))))

Manage “popups”.

(use-package popper
  :ensure t
  :commands
  (popper-display-popup-at-bottom)
  :hook
  (after-init-hook . popper-mode)
  (popper-mode-hook . popper-echo-mode)
  :bind
  (("C-`" . popper-toggle)
   ("C-M-`" . popper-cycle)
   (:map window-prefix-map
        ("p" . popper-toggle-type)))
  :init
  (setq popper-display-function #'popper-display-popup-at-bottom)
  (setq popper-reference-buffers
        '("Output\\*$"
          "\\*Messages\\*"
          "\\*Warnings\\*"
          "\\*devdocs\\*"
          "\\*envrc\\*"
          "^\\*eldoc"
          elisp-refs-mode
          flymake-diagnostics-buffer-mode
          ghelp-page-mode
          (lambda (buf)
            (with-current-buffer buf
              (derived-mode-p '(compilation-mode
                                comint-mode
                                help-mode)))))))
(define-minor-mode hide-cursor-mode
    "Toggle hiding of the cursor."
    :lighter " Hide Cursor"
    (if hide-cursor-mode
        (setq cursor-type nil)
      (kill-local-variable 'cursor-type)))

Buttonize URLs and e-mail addresses in the current buffer.

(use-package goto-addr
  :hook
  (text-mode-hook . goto-address-mode)
  (prog-mode-hook . goto-address-prog-mode))

Disabled by default. When enabled, only highlight in the selected window.

(use-package hl-line
  :hook
  (hl-line-mode-hook . hl-line-number-mode)
  (global-hl-line-mode-hook . global-hl-line-number-mode)
  :init
  (setq hl-line-sticky-flag nil)
  (setq global-hl-line-sticky-flag nil)
  :preface
  (autoload 'face-remap-add-relative "face-remap")
  (autoload 'face-remap-remove-relative "face-remap")

  (defvar-local hl-line-number--current-line-remap nil
    "Face remapping cookie for `line-number-current-line' to `hl-line'.")

  (define-global-minor-mode global-hl-line-number-mode hl-line-number-mode hl-line-number-mode
    :group 'hl-line)

  (define-minor-mode hl-line-number-mode
    "Toggle highlighting of the current line number."
    :group 'hl-line
    (if (or (bound-and-true-p global-hl-line-mode) (bound-and-true-p hl-line-mode))
        (setq hl-line-number--current-line-remap
              (face-remap-add-relative 'line-number-current-line 'hl-line))
      (face-remap-remove-relative hl-line-number--current-line-remap)
      (setq hl-line-number--current-line-remap nil))))
(use-package adaptive-wrap
  :ensure t
  :hook
  (prog-mode-hook . adaptive-wrap-prefix-mode))

Soft wrap lines according to fill-column in visual-line-mode.

(use-package visual-fill-column
  :ensure t
  :init
  (setq visual-fill-column-center-text t))

(use-package virtual-auto-fill
  :ensure t
  :commands
  (virtual-auto-fill-mode)
  :init
  (keymap-set toggle-map "SPC" '("Virtual auto fill" . virtual-auto-fill-mode)))

Display page breaks as a horizontal line.

(use-package page-break-lines
  :ensure t
  :defer 3
  :commands
  (global-page-break-lines-mode)
  :config
  (global-page-break-lines-mode 1))
(use-package valign
  :ensure t
  :hook
  ((markdown-mode-hook
    org-mode-hook) . valign-mode)
  :init
  (setq valign-fancy-bar t))

Truncate large tables.

(use-package lte
  :ensure t
  :hook
  ((markdown-mode-hook
    org-mode-hook) . lte-truncate-table-mode))

Making invisible text temporarily visible.

(use-package simple
  :commands
  (visible-mode)
  :init
  (keymap-set toggle-map "v" '("Visibility" . visible-mode)))

Display whitespace.

(use-package whitespace
  :init
  (setq whitespace-line-column fill-column)
  (setq whitespace-style
        '(face tabs tab-mark spaces space-mark trailing lines-tail))
  (setq whitespace-display-mappings
        '((tab-mark 9 [8250 9])
          (newline-mark 10 [172 10])
          (space-mark 32 [183] [46]))))

Convert between tabs and spaces (only tabify initial white-space).

(setq-default tabify-regexp "^\t* [ \t]+")

Wrap at words.

(setq-default word-wrap t)

Save clipboard contents into kill-ring before replacing them.

(setq save-interprogram-paste-before-kill t)
(setq kill-ring-max 30)

Automatic parenthesis pairing and highlighting.

(electric-pair-mode 1)
(show-paren-mode 1)
(setq show-paren-context-when-offscreen t)
(use-package tempel
  :ensure t
  :commands
  (tempel-expand)
  :bind
  (("M-+" . tempel-complete)
   ("M-*" . tempel-insert))
  :config
  (setq tempel-path (concat user-emacs-directory "templates")))

Guess indentation offset and adjust the corresponding setting.

(use-package dtrt-indent
  :ensure t
  :hook
  ((prog-mode-hook
    text-mode-hook) . dtrt-indent-mode)
  :init
  (setq dtrt-indent-ignore-single-chars-flag t)
  (setq dtrt-indent-run-after-smie t)
  (setq dtrt-indent-verbosity 0)
  :config
  (cl-pushnew '(default default (standard-indent tab-width)) dtrt-indent-hook-mapping-list :test #'equal)
  (cl-pushnew '(groovy-mode default tab-width) dtrt-indent-hook-mapping-list :test #'equal)
  (cl-pushnew '(js-ts-mode javascript js-indent-level) dtrt-indent-hook-mapping-list :test #'equal))

Cycle through words, symbols and patterns.

(use-package grugru
  :ensure t
  :commands
  (grugru-forward
   grugru-backward)
  :functions
  (grugru-define-global
   grugru-define-on-major-mode)
  :bind
  (:repeat-map grugru-repeat-map
               ("r" . grugru-forward)
               ("R" . grugru-backward)
               ("SPC" . grugru-select)
               ("[" . grugru-backward)
               ("]" . grugru-forward))
  :init
  (keymap-set next-map "r" '("Rotate text" . grugru-forward))
  (keymap-set prev-map "r" '("Rotate text" . grugru-backward))
  :config
  (grugru-define-global 'symbol '("assert" "refute"))
  (grugru-define-global 'symbol '("true" "false"))
  (grugru-define-global 'symbol '("yes" "no")))

(use-package grugru-default
  :after grugru
  :functions grugru-default-setup
  :init (grugru-default-setup))

Structured editing with soft deletion and balanced expressions.

(use-package puni
  :ensure t
  :commands
  (puni-mode
   puni-contract-region
   puni-expand-region
   puni-kill-line
   puni-kill-active-region
   puni-mark-list-around-point)
  :hook
  (after-init-hook . puni-global-mode)
  :bind
  ((:map puni-mode-map
         ([remap transpose-sexps] . puni-transpose)
         ("M-W" . puni-kill-ring-save-line)
         ("M-'" . puni-kill-list-around-point)
         ("M-D" . puni-splice)
         ("M-R" . puni-squeeze)
         ("M-S <" . puni-wrap-angle)
         ("M-S {" . puni-wrap-curly)
         ("M-S (" . puni-wrap-round)
         ("M-S [" . puni-wrap-square)
         ("C-w" . puni-whole-line-or-region-kill)
         ("M-w" . puni-whole-line-or-region-kill-ring-save)
         ("M-;" . puni-comment-line))
   (:repeat-map puni-region-repeat-map
                ("SPC" . puni-expand-region)
                ("[" . puni-contract-region)
                ("]" . puni-expand-region)))
  :init
  (keymap-set toggle-map toggle-prefix '("Structured editing" . puni-mode))
  (keymap-set next-map "SPC" '("Expand region" . puni-expand-region))
  (keymap-set prev-map "SPC" '("Contract region" . puni-contract-region))
  :config
  (defun puni-comment-line (arg)
    "Comment whole structured line(s) based on ARG or active region."
    (interactive "P")
    (cl-letf (((symbol-function 'kill-region) #'comment-region))
      (puni-kill-line arg)))

  (defun puni-kill-ring-save-line (arg)
    "Save whole structured line(s) based on ARG or active region."
    (interactive "P")
    (cl-letf (((symbol-function 'kill-region) #'kill-ring-save))
      (puni-kill-line arg)))

  (defun puni-whole-line-or-region-kill (arg)
    "Kill whole structured line(s) based on ARG or active region."
    (interactive "P")
    (if (use-region-p)
        (puni-kill-active-region)
      (let ((kill-whole-line t))
        (if (and (looking-at-p "^$") (= (or arg 1) 1))
            (kill-line)
          (save-excursion
            (beginning-of-line)
            (puni-kill-line arg))))))

  (defun puni-whole-line-or-region-kill-ring-save (arg)
    "Save whole structured line(s) based on ARG or active region."
    (interactive "P")
    (cl-letf (((symbol-function 'kill-region) #'kill-ring-save))
      (puni-whole-line-or-region-kill arg)))

  (defun puni-kill-list-around-point ()
    (interactive)
    (puni-mark-list-around-point)
    (kill-region nil nil t)))
(use-package separedit
  :ensure t
  :bind
  (:map prog-mode-map ("C-c '" . separedit))
  :init
  (setq separedit-preserve-string-indentation t))

Conversion between different variable naming conventions. Toggle between snake/pascal/camel/up/kebab-case or capital underscore.

(use-package string-inflection
  :ensure t
  :bind
  ("M-_" . string-inflection-all-cycle))

Visually indicate what will be modified in a search and replace as you type.

(use-package visual-replace
  :ensure t
  :hook
  (after-init-hook . visual-replace-global-mode)
  :bind
  ([remap query-replace-regexp] . visual-replace-regexp)
  :config
  (defun visual-replace-regexp ()
    (interactive)
    (let ((visual-replace-defaults-hook 'visual-replace-toggle-regexp))
      (call-interactively 'visual-replace))))

Prevent generation of useless lock and backup files.

(setq create-lockfiles nil)
(setq make-backup-files nil)

Don’t require confirmation when opening a new buffer.

(setq confirm-nonexistent-file-or-buffer t)

Remove visual indicators from non-selected windows

(setq highlight-nonselected-windows nil)
(setq-default cursor-in-non-selected-windows nil)
(use-package files
  :hook
  (after-init-hook . auto-save-visited-mode)
  :init
  (setq auto-save-no-message t)
  (setq save-abbrevs 'silently))
(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)

Enable recursive minibuffers.

(setq enable-recursive-minibuffers t)

Do not allow the cursor in the minibuffer prompt.

(setq minibuffer-prompt-properties
      '(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)

Give some more room to the minbuffer.

(setq max-mini-window-height 0.3)
(setq resize-mini-windows 'grow-only)

Don’t show fringes in the minibuffer.

(defun disable-minibuffer-window-fringes (&rest _)
  "Disable the window fringes for minibuffer window."
  (set-window-fringes (minibuffer-window) 0 0 nil))
(add-hook 'minibuffer-setup-hook #'disable-minibuffer-window-fringes)

Track minibuffer history

(setq history-delete-duplicates t)
(setq history-length 500)
(use-package embark
  :ensure t
  :commands
  (embark-prefix-help-command)
  :bind
  (("C-h B" . embark-bindings)
   ("M-o" . embark-dwim)
   ("M-O" . embark-act)
   (:map vertico-map ("C-SPC" . embark-select)))
  :init
  (setq prefix-help-command #'embark-prefix-help-command)
  (setq embark-indicators
        '(embark-minimal-indicator
          embark-highlight-indicator
          embark-isearch-highlight-indicator)))

(use-package embark-consult :ensure t)

Edit minibuffer in a new temporary buffer by pressing C-c '.

(use-package miniedit
  :ensure t
  :bind
  (:map minibuffer-local-map ("C-c '" . miniedit))
  :init
  (setq miniedit-show-help-p nil))
(setq scroll-conservatively 101)
(setq scroll-preserve-screen-position t)
(use-package ultra-scroll
  :ensure t
  :hook
  (after-init-hook . ultra-scroll-mode))

Revert buffers when underlying files change.

(use-package autorevert
  :hook
  (image-mode-hook . auto-revert-mode)
  :init
  (setq auto-revert-verbose nil))
(use-package eldoc
  :hook
  (after-init-hook . global-eldoc-mode))

Descriptive buffer names or project relative paths for buffer names.

(use-package epithet
  :ensure t
  :functions
  (epithet-relative-project-name)
  :hook
  ((eww-after-render-hook
    help-mode-hook
    Info-selection-hook
    occur-mode-hook
    prog-mode-hook
    shell-mode-hook
    text-mode-hook) . epithet-rename-buffer)
  :config
  (defun epithet-relative-project-name ()
    (when-let* ((project (project-current))
                (buffer-file-name (buffer-file-name)))
      (let* ((project-root (expand-file-name (project-root project)))
             (prefix (file-name-directory (directory-file-name project-root)))
             (buffer (expand-file-name buffer-file-name)))
        (string-trim buffer prefix))))

  (cl-pushnew #'epithet-relative-project-name epithet-suggesters :test #'equal))
(use-package pairable
  :ensure t
  :init
  (keymap-set toggle-map "p" '("Pair-programming" . pairable-mode)))
(use-package readable
  :ensure t
  :hook
  ((eww-mode-hook
    Info-mode-hook
    nov-mode-hook
    text-mode-hook) . readable-mode))

Allow repeated mark popping. This behavior is similar to Vim’s C-o. With this configuration you can press C-u and continuously C-SPC to jump to previous entries in the mark ring.

(setq set-mark-command-repeat-pop t)
(use-package dired
  :hook
  (dired-mode-hook . auto-revert-mode)
  (dired-mode-hook . hl-line-mode)
  (dired-mode-hook . dired-hide-details-mode)
  :init
  (setq dired-listing-switches "-al --group-directories-first")
  ;; Always copy/delete recursively
  (setq dired-recursive-copies  'always)
  (setq dired-recursive-deletes 'top))
(use-package wdired
  :after dired
  :bind
  (:map dired-mode-map ("C-c '" . wdired-change-to-wdired-mode)))
(use-package find-dired
  :bind
  ("C-x D" . find-dired)
  :init
  (setq find-ls-option '("-print0 | xargs -0 ls -ld" . "-ld")))
(use-package dired-sidebar
  :ensure t
  :hook
  (dired-sidebar-mode-hook . hide-mode-line-mode)
  (dired-sidebar-mode-hook . hl-line-mode)
  (dired-sidebar-mode-hook . variable-pitch-mode)
  (dired-sidebar-mode-hook . hide-cursor-mode)
  :bind
  (:map leader-map ("n" . dired-sidebar-toggle-sidebar)))

Display subtrees in dired view.

(use-package dired-subtree
  :ensure t
  :init
  (setq dired-subtree-use-backgrounds nil)
  (setq dired-subtree-line-prefix "     "))

Striped dired buffers.

(use-package stripe-buffer
  :ensure t
  :commands (stripe-buffer-mode)
  :functions (stripe-buffer-maybe-enable-for-dired)
  :hook
  (dired-after-readin-hook . stripe-buffer-maybe-enable-for-dired)
  :config
  (defun stripe-buffer-maybe-enable-for-dired ()
    (unless (derived-mode-p 'dired-sidebar-mode)
      (stripe-buffer-mode 1))))
(use-package all-the-icons-dired
  :ensure t
  :hook
  (dired-mode-hook . all-the-icons-dired-mode))
(use-package dired-git-info
  :ensure t
  :bind
  (:map dired-mode-map (")" . dired-git-info-mode)))
(use-package isearch
  :init
  (setq isearch-lazy-count t))
(use-package replace
  :bind
  (:map occur-mode-map ("C-c '" . occur-edit-mode)))

(use-package noccur
  :ensure t
  :bind
  (:map goto-map ("O" . noccur-project)))

Jump to …

(use-package avy
  :ensure t
  :bind
  (:map goto-map ("C" . avy-goto-char-in-line)))

Keep track of bookmarks

(use-package bookmark
  :init
  (setq bookmark-save-flag 1))

URL handling.

(use-package browse-url
  :bind
  (:map goto-map
        ("u" . browse-url-at-point)
        ("U" . browse-url)))
(use-package deadgrep
  :ensure t
  :bind
  ((:map search-map ("G" . deadgrep))
   (:map deadgrep-mode-map ("C-c '" . deadgrep-edit-mode))
   (:map deadgrep-edit-mode-map ("C-c C-c" . deadgrep-mode))))
(use-package find-file
  :init
  (setq-default ff-quiet-mode t)
  (put 'ff-search-directories
       'safe-local-variable
       (lambda (x) (cl-every #'stringp x))))

Move point through buffer-undo-list positions.

(use-package goto-chg
  :ensure t
  :bind
  ((:map goto-map ("SPC" . goto-last-change))
   (:repeat-map goto-chg-repeat-map
                ("SPC" . goto-last-change)
                ("[" . goto-last-change)
                ("]" . goto-last-change-reverse))))

Hint mode for links.

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

Keep track of recently opened files.

(use-package recentf
  :defer 1
  :init
  (setq recentf-exclude
        (list "/tmp/"                        ; Temp-files
              "/dev/shm"                     ; Potential secrets
              "/ssh:"                        ; Files over SSH
              "/nix/store"                   ; Files in Nix store
              "/TAGS$"                       ; Tag files
              "^/\\.git/.+$"                 ; Git contents
              "\\.?ido\\.last$"
              "\\.revive$"
              "^/var/folders/.+$"
              (concat "^" cache-dir ".+$")
              (concat "^" data-dir ".+$")))
  (setq recentf-filename-handlers '(abbreviate-file-name))
  (setq recentf-max-menu-items 0)
  (setq recentf-max-saved-items 300)
  (setq recentf-auto-cleanup 'never)
  :config
  (quiet! (recentf-mode 1)))

Keep track of last point place to resume editing in the same file.

(use-package saveplace
  :defer 2
  :config
  (save-place-mode 1))

Retrieve project list via ghq.

(use-package project
  :commands
  (project-read-project-list-from-ghq)
  :config
  (defun project-read-project-list-from-ghq ()
    "Initialize `project--list' using contents of command ghq output."
    (interactive)
    (with-temp-buffer
      (call-process "ghq" nil t nil "list" "--full-path")
      (goto-char (point-min))
      (while (not (eobp))
        (cl-pushnew
         (list (buffer-substring-no-properties (line-beginning-position) (line-end-position)))
         project--list
         :test #'equal)
        (forward-line 1))))

  (advice-add 'project--read-project-list :after #'project-read-project-list-from-ghq))

Reduce scroll margin.

(defun prog-scroll-margin-setup ()
  "Setup `scroll-margin' for `prog-mode'."
  (setq-local scroll-margin 3))
(add-hook 'prog-mode-hook #'prog-scroll-margin-setup)

Kill compilation process before starting another and save all buffers on compile. Also there is compile-on-save-mode that will compile when files are saved, compilation buffer will only be displayed on error.

(use-package compile
  :functions
  (compilation-find-buffer
   compilation-finish-handle-buffer-display
   recompile)
  :bind
  (:map local-leader-map
        ("a" . compile-on-save-mode)
        ("c" . recompile)
        ("C" . compile))
  :preface
  (define-minor-mode compile-on-save-mode
    "Minor mode to automatically call `recompile' whenever the
current buffer is saved. When there is ongoing compilation,
nothing happens."
    :lighter " CoS"
    (if compile-on-save-mode
        (progn  (make-local-variable 'after-save-hook)
                (add-hook 'after-save-hook 'compile-on-save-start nil t))
      (remove-hook 'after-save-hook 'compile-on-save-start t)))

  (make-variable-buffer-local 'compile-command)
  :init
  (setq compilation-always-kill t)
  (setq compilation-ask-about-save nil)
  (setq compilation-scroll-output t)

  (put 'compile-command 'safe-local-variable 'stringp)
  :config
  (defun compile-on-save-start ()
    (let ((compile-buffer (compilation-find-buffer)))
      (unless (get-buffer-process compile-buffer)
        (let ((display-buffer-alist '(("^*compilation*" . (display-buffer-no-window)))))
          (recompile)))))

  (defun compilation-finish-handle-buffer-display (buffer outstr)
    "Display failed compilation buffer or burry finished ones."
    (let ((compilation-window (get-buffer-window buffer)))
      (cond
       ;; If compilation failed and compilation buffer is not visible,
       ((and (not (string-match "finished" outstr))
             (not compilation-window))
        ;; display that buffer.
        (display-buffer (compilation-find-buffer)))
       ;; If compilation succeeded and compilation buffer is visible,
       ((and (string-match "finished" outstr)
             compilation-window)
        ;; bury that buffer.
        (with-selected-window compilation-window
          (bury-buffer))))))

  (cl-pushnew #'compilation-finish-handle-buffer-display compilation-finish-functions :test #'equal))
(use-package ansi-color
  :hook
  (compilation-filter-hook . ansi-color-compilation-filter))
(use-package docker
  :ensure t
  :bind
  (:map leader-map
        ("d" . docker)
        ("c" . docker-compose))
  :init
  (setq docker-command "podman"))

Support for Docker related files.

(use-package dockerfile-ts-mode
  :mode
  "Dockerfile\\'"
  "\\.dockerfile\\'")
(use-package kubernetes :ensure t)
(use-package cov
  :ensure t
  :commands
  (cov-mode
   cov-mode-toggle)
  :bind
  (:map prog-mode-map ("C-. v" . cov-mode-toggle))
  :init
  (setq cov-coverage-mode t)
  :config
  (defun cov-mode-toggle ()
    "Turn on `cov-mode'."
    (interactive)
    (require 'cov)
    (if (bound-and-true-p cov-mode)
        (cov-mode 0)
      (unless cov-lcov-file-name
        (setq cov-lcov-file-name (expand-file-name "lcov.info" (project-root (project-current)))))
      (cov-mode 1))))

Lookup documentation via DevDocs.

(use-package devdocs
  :ensure t
  :bind
  (:map goto-map ("K" . devdocs-lookup)))

Code folding.

(use-package hideshow
  :functions
  (hs-fold-overlay-ellipsis)
  :hook
  (prog-mode-hook . hs-minor-mode)
  :bind
  (:map leader-map :prefix-map hs-prefix-map :prefix "z"
        ("c" . hs-hide-block)
        ("o" . hs-show-block)
        ("C" . hs-hide-all)
        ("O" . hs-show-all)
        ("l" . hs-hide-level)
        ("z" . hs-toggle-hiding)
        ("<tab>" . hs-toggle-hiding))
  :init
  (setq hs-hide-comments-when-hiding-all nil)
  (setq hs-allow-nesting t)
  (setq hs-set-up-overlay #'hs-fold-overlay-ellipsis)
  :config
  (defun hs-fold-overlay-ellipsis (ov)
    (when (eq 'code (overlay-get ov 'hs))
      (overlay-put
       ov 'display (propertize "" 'face 'font-lock-comment-face)))))

Reformat buffer without moving point.

(use-package apheleia
  :ensure t
  :hook
  (prog-mode-hook . apheleia-mode)
  :bind
  (:map local-leader-map ("f" . apheleia-format-buffer))
  :config
  (dolist (formatter '((nix . ("nix" "fmt" "--" "-"))
                       (rufo . ("rufo" "--simple-exit"))))
    (cl-pushnew formatter apheleia-formatters :test #'equal)))

Jump to definition is really useful and I prefer doing so without TAGS which is pretty much the default for most modes. I am using the excellent package dumb-jump to jump via grep tools e.g. (grep, rx, ag)

Don’t ask about keeping current list of tags tables.

(use-package etags
  :init
  (setq tags-add-tables nil))
(use-package xref
  :commands
  (xref-show-definitions-completing-read)
  :bind
  (:map goto-map ("o" . xref-find-definitions-other-window))
  :config
  (remove-hook 'xref-backend-functions #'etags--xref-backend))
(use-package dumb-jump
  :ensure t
  :hook
  (xref-backend-functions . dumb-jump-xref-activate)
  :init
  (setq dumb-jump-default-project user-emacs-directory)
  (setq dumb-jump-selector 'completing-read))
(use-package comint
  :bind
  (:map comint-mode-map ("C-c C-k" . term-char-mode))
  :init
  (setq comint-use-prompt-regexp t))
(use-package repl-toggle
  :ensure t
  :bind
  (:map local-leader-map ("r" . rtog/toggle-repl))
  :init
  (setq rtog/goto-buffer-fun 'pop-to-buffer)
  (setq rtog/mode-repl-alist
        '((emacs-lisp-mode . ielm)
          (org-mode . ielm))))
Persistent history in comint
(use-package comint
  :functions
  (comint-read-input-ring
   comint-write-input-ring
   comint-history-enable
   comint-history-write-on-exit)
  :config
  (defun comint-history-write-on-exit (process event)
    "Write `comint' history on exit.
Receives PROCESS and EVENT."
    (comint-write-input-ring)
    (let ((buf (process-buffer process)))
      (when (buffer-live-p buf)
        (with-current-buffer buf
          (insert (format "\nProcess %s %s" process event))))))

  (defun comint-history-enable ()
    "Enable `comint' history."
    (let ((process (get-buffer-process (current-buffer))))
      (when process
        (setq comint-input-ring-file-name
              (expand-file-name
               (format "comint-%s-history" (process-name process))
               cache-dir))
        (comint-read-input-ring)
        (set-process-sentinel process #'comint-history-write-on-exit)))))

Silence next/previous error, by default it produces a message every time.

(advice-add 'next-error :around #'quiet-function-advice)
(advice-add 'previous-error :around #'quiet-function-advice)

Connect flymake to next-error-function and add some navigation bindings. Disable the legacy diagnostic functions as some of them have bugs and cause instability (mainly the Haskell one).

(use-package flymake
  :hook
  (flymake-mode-hook . flymake-setup-next-error-function)
  :commands
  (flymake-show-diagnostic
   flymake-goto-next-error)
  :bind
  ((:map flymake-mode-map
         ("C-. !" . flymake-show-buffer-diagnostics)
         ("M-] E" . flymake-goto-next-error)
         ("M-[ E" . flymake-goto-prev-error))
   (:map flymake-diagnostics-buffer-mode-map
         ("n" . flymake-diagnostics-next-error)
         ("p" . flymake-diagnostics-prev-error)
         ("j" . flymake-diagnostics-next-error)
         ("k" . flymake-diagnostics-prev-error)
         ("TAB" . flymake-show-diagnostic))
   (:repeat-map flymake-mode-repeat-map
               ("e" . flymake-goto-next-error)
               ("E" . flymake-goto-prev-error)
               ("[" . flymake-goto-prev-error)
               ("]" . flymake-goto-next-error)))
  :config
  (defun flymake-setup-next-error-function ()
    (setq next-error-function 'flymake-next-error-compat))

  (defun flymake-next-error-compat (&optional n _)
    (flymake-goto-next-error n))

  (defun flymake-diagnostics-next-error ()
    (interactive)
    (forward-line)
    (when (eobp) (forward-line -1))
    (flymake-show-diagnostic (point)))

  (defun flymake-diagnostics-prev-error ()
    (interactive)
    (forward-line -1)
    (flymake-show-diagnostic (point))))

(use-package flymake-proc
  :config
  (setq flymake-proc-ignored-file-name-regexps '("\\.l?hs\\'"))
  (remove-hook 'flymake-diagnostic-functions 'flymake-proc-legacy-flymake))
(setq vc-follow-symlinks t)
(setq vc-make-backup-files nil)

Open link to files in the web UI connected to a repository.

(use-package browse-at-remote
  :ensure t
  :bind
  (:map vc-prefix-map ("SPC" . browse-at-remote-kill)))
(use-package smerge-mode
  :bind
  (:repeat-map smerge-repeat-map
               ("[" . smerge-prev)
               ("]" . smerge-next)
               ("n" . smerge-next)
               ("p" . smerge-prev)

               ("RET" . smerge-keep-current)
               ("a" . smerge-keep-all)
               ("b" . smerge-keep-base)
               ("l" . smerge-keep-lower)
               ("u" . smerge-keep-upper)

               ("E" . smerge-ediff)
               ("r" . smerge-resolve)
               ("R" . smerge-refine))
  :init
  (setq smerge-command-prefix (kbd "C-x c"))
  (keymap-set toggle-map "m" '("Merging" . smerge-mode)))
(use-package diff
  :init
  (setq diff-font-lock-prettify t))
(use-package ediff
  :commands
  (ediff-copy-both-to-C)
  :preface
  (autoload 'ediff-copy-diff "ediff-util")
  (autoload 'ediff-get-region-contents "ediff-util")
  (autoload 'ediff-setup-windows-plain "ediff-wind")
  :hook
  (ediff-quit-hook . winner-undo)
  (ediff-keymap-setup-hook . init-ediff-keys)
  :init
  (setq ediff-diff-options "-w")
  (setq ediff-merge-split-window-function #'split-window-horizontally)
  (setq ediff-split-window-function #'split-window-horizontally)
  (setq ediff-window-setup-function #'ediff-setup-windows-plain)
  :config
  (defun ediff-copy-both-to-C ()
    "Copy change from both A and B to C."
    (interactive)
    (ediff-copy-diff
     ediff-current-difference nil 'C nil
     (concat
      (ediff-get-region-contents ediff-current-difference 'A ediff-control-buffer)
      (ediff-get-region-contents ediff-current-difference 'B ediff-control-buffer))))

  (defun init-ediff-keys ()
    "Setup keybindings for `ediff-mode'."
    (keymap-set ediff-mode-map "d" '("Copy both to C" . ediff-copy-both-to-C))
    (keymap-set ediff-mode-map "j" '("Next difference" . ediff-next-difference))
    (keymap-set ediff-mode-map "k" '("Previous difference" . ediff-previous-difference))))

Diff indicators in fringe

(use-package diff-hl
  :ensure t
  :defer 2
  :commands
  (global-diff-hl-mode)
  :preface
  (autoload 'diff-hl-flydiff-mode "diff-hl-flydiff" nil t)
  (autoload 'diff-hl-dired-mode "diff-hl-dired" nil t)
  :hook
  (dired-mode-hook . diff-hl-dired-mode)
  (magit-post-refresh-hook . diff-hl-magit-post-refresh)
  :init
  (setq diff-hl-ask-before-revert-hunk nil)
  (setq diff-hl-update-async t)
  :config
  (global-diff-hl-mode 1)
  (diff-hl-flydiff-mode 1))

Enhanced git related views and commands.

(use-package magit
  :ensure t
  :defer 2
  :functions
  (magit-process-ask-create-pull-request)
  :preface
  (autoload 'magit-show-commit "magit-diff" nil t)
  :hook
  (git-commit-mode-hook . git-commit-set-fill-column)
  :bind
  ("C-x g" . magit)
  :init
  (setq magit-log-buffer-file-locked t)
  (setq magit-refs-show-commit-count 'all)
  (setq magit-save-repository-buffers 'dontask)
  (setq magit-process-prompt-functions #'magit-process-ask-create-pull-request)
  :config
  (defun git-commit-set-fill-column ()
    "Set `fill-column' for git commit."
    (setq fill-column 72))

  (defvar magit-process-create-pull-request-regexp
    "remote: Create pull request for.*\nremote: +\\(?1:[^ ]+\\)[^\n]*"
    "Regular expression detecting PR.")

  (defun magit-process-ask-create-pull-request (_process string)
    "Detect pull request STRING and ask to create PR."
    (when (string-match magit-process-create-pull-request-regexp string)
      (let ((url (match-string 1 string))
            (inhibit-message t))
        (if (y-or-n-p "Create PR? ")
            (browse-url (url-encode-url url))))))

  ;; Unset pager as it is not supported properly inside emacs.
  (setenv "GIT_PAGER" ""))

Project-specific environment variables via direnv.

(use-package envrc
  :ensure t
  :if (executable-find "direnv")
  :defer 1
  :commands
  (envrc-global-mode)
  :bind
  (:map envrc-mode-map ("C-c e" . envrc-command-map))
  :config
  (envrc-global-mode 1))

Generic Language Server Protocol integration via eglot.

(use-package eglot
  :defer 3
  :bind
  ((:map eglot-mode-map ("C-. C-." . eglot-code-actions))
   (:map eglot-mode-map :prefix-map eglot-prefix-map :prefix "C-. e"
         ("a" . eglot-code-actions)
         ("f" . eglot-format)
         ("r" . eglot-rename)
         ("q" . eglot-reconnect)
         ("Q" . eglot-shutdown)))
  :init
  (setq eglot-autoshutdown t)
  (setq eglot-code-action-indications nil)
  (setq eglot-confirm-server-edits nil)
  (setq eglot-sync-connect nil)
  :config
  (cl-pushnew '((elixir-mode elixir-ts-mode heex-ts-mode) . ("elixir-ls"))
              eglot-server-programs
              :test #'equal))

Highlight TODO inside comments and strings.

(use-package hl-todo
  :ensure t
  :hook
  (prog-mode-hook . hl-todo-mode)
  :bind
  (:repeat-map hl-todo-repeat-map
               ("t" . hl-todo-next)
               ("T" . hl-todo-previous)
               ("[" . hl-todo-previous)
               ("]" . hl-todo-next))
  :init
  (keymap-set next-map "t" '("Todo" . hl-todo-next))
  (keymap-set prev-map "t" '("Todo" . hl-todo-previous)))

Highlight symbol at point on idle.

(use-package idle-highlight-mode
  :ensure t
  :hook
  (prog-mode-hook . idle-highlight-mode)
  :init
  (setq idle-highlight-exclude-point t))

Jump to document locations in current buffer

(use-package imenu-anywhere
  :ensure t
  :bind
  (:map search-map
        ("i" . imenu)
        ("I" . imenu-anywhere)))

Easily add document locations via regular expressions.

(use-package imenu-extra
  :ensure t
  :functions (imenu-extra-auto-setup))

Document locations in a sidebar.

(use-package imenu-list
  :ensure t
  :hook
  (imenu-list-major-mode-hook . hide-mode-line-mode)
  (imenu-list-major-mode-hook . hide-cursor-mode)
  :bind
  (:map leader-map ("i" . imenu-list-smart-toggle)))

Delete trailing white-space before save, but only for edited lines.

(use-package ws-butler
  :ensure t
  :commands
  (ws-butler-mode)
  :hook
  ((prog-mode-hook
    text-mode-hook) . ws-butler-mode)
  :init
  (setq ws-butler-convert-leading-tabs-or-spaces t))

Visually separate delimiter pairs.

(use-package rainbow-delimiters
  :ensure t
  :hook
  ((clojure-mode-hook
    emacs-lisp-mode-hook
    ielm-mode-hook
    lisp-mode-hook
    racket-mode-hook) . rainbow-delimiters-mode)
  :init
  (setq rainbow-delimiters-max-face-count 3))

Highlight source code identifiers based on their name.

(use-package color-identifiers-mode :ensure t)
(use-package ligature
  :ensure t
  :commands
  (ligature-set-ligatures)
  :hook
  (prog-mode-hook . ligature-mode)
  :config
  (ligature-set-ligatures
   'prog-mode
   '("-<<" "-<" "-<-" "<--" "<---" "<<-" "<-" "->" "->>" "-->" "--->" "->-" ">-" ">>-" "<->" "<-->" "<--->" "<---->" "<!--"
     "=<<" "=<" "=<=" "<==" "<===" "<<=" "<=" "=>" "=>>" "==>" "===>" "=>=" ">=" ">>=" "<=>" "<==>" "<===>" "<====>" "<!---"
     "<------" "------>" "<=====>" "<~~" "<~" "~>" "~~>" "::" ":::" "\\/" "/\\" "==" "!=" "/=" "~=" "<>" "===" "!==" "=/=" "=!="
     ":=" ":-" ":+" "<*" "<*>" "*>" "<|" "<|>" "|>" "<." "<.>" ".>" "+:" "-:" "=:" "<******>" "(*" "*)" "++" "+++" "|-" "-|"
     "&&" "||")))

(use-package prog-mode
  :init
  (setq prettify-symbols-unprettify-at-point t))
(use-package elisp-mode
  :hook
  (emacs-lisp-mode-hook . flymake-mode)
  (emacs-lisp-mode-hook . outline-minor-mode)
  :bind
  (:map emacs-lisp-mode-map
        ("C-. c" . emacs-lisp-byte-compile)
        ("C-. C" . emacs-lisp-byte-compile-and-load)
        ("C-. d" . checkdoc)
        ("C-. l" . emacs-lisp-load-buffer-file)
        ("C-. L" . eval-buffer)
        ("C-. p" . package-lint-current-buffer)
        ("C-. t" . ert))
  :config
  (defun emacs-lisp-load-buffer-file ()
    "Load the Lisp file associated with current buffer."
    (interactive)
    (load-file (buffer-file-name))))

(custom-set-variables
 '(ad-redefinition-action 'accept)
 '(apropos-do-all t)
 '(enable-local-eval 'maybe)
 '(enable-local-variables :safe))

Specific safe local code can be specified via:

(use-package package-lint-flymake
  :ensure t
  :commands (package-lint-flymake-setup)
  :preface
  (autoload 'package-lint--provided-feature "package-lint")
  :hook
  (emacs-lisp-mode-hook . package-lint-flymake-setup-when-package)
  :config
  (defun package-lint-flymake-setup-when-package ()
    "Enable `package-lint-flymake' when buffer seems to be a package."
    (when (package-lint--provided-feature)
      (package-lint-flymake-setup))))
Regular expression escapes

Improve readability of escape characters in regular expressions.

(use-package easy-escape
  :ensure t
  :hook
  (emacs-lisp-mode-hook . easy-escape-minor-mode))
(use-package erc
  :init
  (setq erc-hide-list '("JOIN" "PART" "QUIT"))
  (setq erc-prompt-for-password nil))
(use-package org
  :defer 5
  :preface
  (autoload 'org-get-outline-path "org-refile" nil t)
  :hook
  (org-mode-hook . auto-fill-mode)
  (org-mode-hook . org-mode-init)
  :bind
  (("C-c a" . org-agenda)
   (:map org-mode-map
         ("C-'" . nil)
         ("C-," . nil)))
  :init
  (setq org-agenda-files
        '("~/org/Personal.org" "~/org/Work.org"))
  (setq org-insert-heading-respect-content t)
  (setq org-log-done 'time)
  (setq org-modules '(ol-info))
  (setq org-special-ctrl-a/e t)

  (setq org-confirm-babel-evaluate nil)
  (setq org-edit-src-content-indentation 0)
  (setq org-src-preserve-indentation nil)
  (setq org-src-tab-acts-natively t)
  (setq org-src-window-setup 'current-window)

  (setq org-startup-truncated nil)

  (setq org-auto-align-tags nil)
  (setq org-tags-column 0)
  (setq org-tag-alist
        '(("@work"  . ?w)
          ("@home"  . ?h)
          ("laptop" . ?l)))

  (setq org-imenu-depth 3)
  :config
  (defun org-mode-init ()
    (setq tab-width 8))

  (dolist (lang '("emacs-lisp" "elisp"))
    (cl-pushnew (cons lang 'lisp-interaction) org-src-lang-modes :test #'equal)))

(use-package ob-plantuml
  :init
  (setq org-plantuml-exec-mode 'plantuml))

Presentation mode.

(use-package dslide
  :ensure t
  :functions
  (dslide-stop-restore-modes)
  :hook
  (dslide-start-hook . hide-cursor-mode)
  (dslide-start-hook . global-hide-fringes-mode)
  (dslide-start-hook . hide-mode-line-mode)
  (dslide-stop-hook . dslide-stop-restore-modes)
  :bind
  (:map org-mode-map ("C-. p" . dslide-deck-start))
  :init
  (setq dslide-header nil)
  :config
  (defun dslide-stop-restore-modes ()
    (global-hide-fringes-mode 0)))

Unmaintained add-ons for org-mode, in this configuration org-eldoc is used.

(use-package org-contrib :ensure t)

Paste links from clipboard and automatically fetch title.

(use-package org-cliplink
  :ensure t
  :bind
  (:map org-mode-map ("C-. l" . org-cliplink)))

Eldoc support, showing path to current section.

(use-package org-eldoc
  :after eldoc
  :functions
  (org-eldoc-get-breadcrumb-no-properties)
  :hook
  (org-mode-hook . org-eldoc-load)
  :config
  (defun org-eldoc-get-breadcrumb-no-properties (string)
    "Remove properties from STRING."
    (when string (substring-no-properties string)))

  (advice-add 'org-eldoc-get-breadcrumb :filter-return #'org-eldoc-get-breadcrumb-no-properties))
(use-package org-limit-image-size
  :ensure t
  :after org
  :commands
  (org-limit-image-size-activate
   org-limit-image-size-deactivate)
  :init
  (org-limit-image-size-activate)
  (setq org-limit-image-size '(0.48 . 0.8)))

Annotate documents with org-mode.

(use-package org-noter :ensure t
  :bind
  (:map leader-map ("o" . org-noter)))
(use-package ob-http :ensure t)

This sections makes org-mode look more beautiful and appealing.

(use-package org
  :hook
  (org-babel-after-execute-hook . org-redisplay-inline-images)
  :init
  (setq org-fold-catch-invisible-edits 'show-and-error)
  (setq org-fontify-quote-and-verse-blocks t)
  (setq org-hide-emphasis-markers t)
  (setq org-pretty-entities t)
  (setq org-src-fontify-natively t)
  (setq org-startup-with-inline-images t))

(use-package org-modern
  :ensure t
  :hook
  (org-mode-hook . org-modern-mode)
  :init
  (setq org-modern-hide-stars t)
  (setq org-modern-table nil))

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

Allow more newlines (1 to 4) for emphasized text, useful when filling long text.

(use-package org
  :preface
  (autoload 'org-set-emph-re "org")
  :config
  (setcar (nthcdr 4 org-emphasis-regexp-components) 4)
  (org-set-emph-re 'org-emphasis-regexp-components org-emphasis-regexp-components))
(use-package org
  :init
  (setq org-ellipsis "")
  (setq org-fontify-whole-heading-line t)
  (setq org-fontify-todo-headline t)
  (setq org-fontify-done-headline t))
(use-package ox-epub :ensure t)
(use-package ox-html
  :init
  (setq org-html-postamble nil)
  (setq org-html-validation-link nil))

Disable link colors.

(use-package ox-latex
  :init
  (setq org-latex-hyperref-template
        (mapconcat
         'identity
         '("\\hypersetup{"
           "pdfauthor={%a},"
           "pdftitle={%t},"
           "pdfkeywords={%k},"
           "pdfsubject={%d},"
           "pdfcreator={%c},"
           "pdflang={%L},"
           "pdfborder=0 0 0}")
         "\n")))

Add links in footnotes.

(autoload 'org-export-derived-backend-p "ox")

(defvar org-export-latex-add-link-footnotes t
  "If non-nil links will be added as footnotes if exported to latex.")

(defun org-export-latex-link-footnote (text backend _info)
  "Create a footnote for each link to retain this information for print.
If there is a URL and the export BACKEND is latex, then extract
URL into footnote from TEXT."
  (when (and org-export-latex-add-link-footnotes
             (org-export-derived-backend-p backend 'latex)
             (string-match "\\\\href{\\(.*\\)}{\\(.*\\)}" text))
    (when (cl-some (lambda (type)
                     (string-prefix-p type (match-string 1 text)))
                   '("http" "https" "ftp" "mailto" "doi"))
      (format "%s \\footnote{\\url{%s}} " text (match-string 1 text)))))

(with-eval-after-load 'ox
  (cl-pushnew #'org-export-latex-link-footnote org-export-filter-link-functions :test #'equal))

Display outlines in text like files or use it in conjunction with other major modes via outline-minor-mode.

Add faces to outline-minor-mode in order to make the headings stand out.

(use-package outline-minor-faces
  :ensure t
  :after outline
  :hook
  (outline-minor-mode-hook . outline-minor-faces-mode))
(use-package clojure-mode
  :ensure t
  :mode
  "\\.\\(clj\\|dtm\\|edn\\)\\'"
  "\\(?:build\\|profile\\)\\.boot\\'"
  ("\\.cljc\\'" . clojurec-mode)
  ("\\.cljs\\'" . clojurescript-mode)
  :config
  (cl-pushnew '("src/\\([^/]+\\)\\.clj\\'" "test/\\1_test.clj") find-sibling-rules :test #'equal)
  (cl-pushnew '("test/\\([^/]+\\)_test\\.clj\\'" "src/\\1.clj") find-sibling-rules :test #'equal))
(use-package cider
  :ensure t
  :commands
  (cider-current-repl
   cider-jack-in-clj)
  :hook
  (clojure-mode-hook . cider-mode)
  (cider-mode-hook . cider-auto-test-mode)
  :bind
  ((:map cider-mode-map
         ("C-. R" . cider-jack-in)
         ("C-. c" . cider-ns-refresh)
         ("C-. l" . cider-load-buffer)
         ("C-. t a" . cider-test-run-project-tests)
         ("C-. t n" . cider-test-run-ns-tests)
         ("C-. t t" . cider-test-run-test)
         ("C-. t w" . cider-auto-test-mode)))
  :init
  (setq cider-prompt-for-symbol nil)
  (setq cider-repl-display-help-banner nil)
  (setq cider-repl-history-file (concat data-dir "cider-history"))

  (with-eval-after-load 'popper
    (cl-pushnew 'cider-test-report-mode popper-reference-buffers :test #'equal))
  :config
  (defun clojure-repl ()
    "Open a Clojure REPL."
    (interactive)
    (if-let* ((repl-buffer (cider-current-repl)))
        (pop-to-buffer repl-buffer)
      (cider-jack-in-clj nil)))

  (with-eval-after-load 'repl-toggle
    (cl-pushnew '(clojure-mode . clojure-repl) rtog/mode-repl-alist :test #'equal)))
(use-package cobol-mode
  :ensure t
  :mode "\\.\\(cob\\|cbl\\|cpy\\)\\'")
(use-package crystal-mode
  :ensure t
  :mode "\\(?:\\.cr\\)\\'"
  :bind
  ((:map crystal-mode-map
         ("C-. t a" . crystal-spec-all)
         ("C-. t f" . crystal-spec-buffer)
         ("C-. t t" . crystal-spec-line))))
(use-package inf-crystal
  :ensure t
  :commands
  (inf-crystal)
  :hook
  (crystal-mode-hook . inf-crystal-minor-mode)
  :config
  (defun crystal-repl ()
    "Open a Crystal REPL."
    (inf-crystal inf-crystal-interpreter))

  (with-eval-after-load 'repl-toggle
    (cl-pushnew '(crystal-mode . crystal-repl) rtog/mode-repl-alist :test #'equal)))
(use-package csv-mode
  :ensure t
  :mode
  "\\.[Cc][Ss][Vv]\\'"
  ("\\.tsv\\'" . tsv-mode)
  :init
  (setq csv-separators '("," "\t" ";")))
(use-package d2-mode
  :ensure t
  :mode "\\.d2\\'"
  :hook
  (d2-mode-hook . d2-mode-set-compile-command)
  (d2-mode-hook . compile-on-save-mode)
  :init
  (setq d2-flags '("--layout" "elk" "--sketch" "--theme" "1"))
  :config
  (defun d2-mode-set-compile-command ()
    "Configure compile command for d2-mode."
    (set (make-local-variable 'compile-command)
         (mapconcat #'shell-quote-argument (append (list d2-location buffer-file-name) d2-flags)
                    " "))))
(use-package elixir-ts-mode
  :mode
  "\\.elixir\\'"
  "\\.ex\\'"
  "\\.exs\\'"
  :hook
  (elixir-ts-mode-hook . eglot-ensure)
  :init
  (cl-pushnew '("lib/\\([^/]+\\)\\.ex\\'" "test/\\1_test.exs") find-sibling-rules :test #'equal)
  (cl-pushnew '("test/\\([^/]+\\)_test\\.exs\\'" "lib/\\1.ex") find-sibling-rules :test #'equal))

(cl-pushnew '(elixir-mode . elixir-ts-mode) major-mode-remap-alist :test #'equal)

Elm and elm-mode seems unmaintained at the moment, so I disable this.

(use-package elm-mode
  :ensure t
  :mode "\\.elm\\'"
  :bind
  (:map elm-mode-map ("C-. t" . elm-test-project))
  :init
  (setq elm-format-on-save t)
  (setq elm-package-json "elm.json")
  (setq elm-tags-exclude-elm-stuff nil)
  (setq elm-tags-on-save t)
  :config
  (with-eval-after-load 'repl-toggle
    (cl-pushnew '(elm-mode . elm-repl-load) rtog/mode-repl-alist :test #'equal)))
(use-package nov
  :ensure t
  :mode
  ("\\.epub\\'" . nov-mode)
  :hook
  (nov-mode-hook . init-nov-delayed-render)
  (nov-mode-hook . hide-fringes-mode)
  :init
  (setq nov-save-place-file (concat data-dir "nov-places"))
  :config
  (defun init-nov-delayed-render ()
    (run-with-idle-timer 0.2 nil 'nov-render-document)))
(use-package erlang
  :ensure t
  :mode
  ("\\.\\(e\\|h\\|x\\|y\\)rl$" . erlang-mode)
  ("\\.escript" . erlang-mode)
  ("\\.app\\.src$" . erlang-mode)
  ("/ebin/.+\\.app" . erlang-mode)
  :hook
  (erlang-mode-hook . init-erlang-eunit)
  (erlang-mode-hook . init-erlang-flymake)
  :bind
  (:map erlang-mode-map ("M-g k" . erlang-man-function))
  :init
  (cl-pushnew '("src/\\([^/]+\\)\\.erl\\'" "test/\\1_tests.erl") find-sibling-rules :test #'equal)
  (cl-pushnew '("test/\\([^/]+\\)_tests\\.erl\\'" "src/\\1.erl") find-sibling-rules :test #'equal)
  :config
  (defun init-erlang-eunit ()
    "Setup EUnit support for `erlang-mode'."
    (require 'erlang-eunit))

  (defun init-erlang-flymake ()
    "Setup `flymake' support for `erlang-mode'."
    (require 'erlang-flymake)
    (flymake-mode 1))

  (with-eval-after-load 'repl-toggle
    (cl-pushnew '(erlang-mode . erlang-shell-display) rtog/mode-repl-alist :test #'equal)))

(use-package erlang-eunit
  :bind
  (:map erlang-mode-map
        ("C-. t t" . erlang-eunit-compile-and-run-current-test)
        ("C-. t m" . erlang-eunit-compile-and-run-module-tests)))
(use-package git-modes
  :ensure t
  :mode
  ("/\\.dockerignore\\'" . gitignore-mode))
(use-package go-ts-mode
  :mode
  "\\.go\\'"
  ("go\\.mod\\'" . go-mod-ts-mode)
  :hook
  (go-ts-mode-hook . eglot-ensure)
  (go-ts-mode-hook . go-ts-mode-set-devdocs)
  :preface
  (define-repl go-repl "Go REPL" "gore")
  :config
  (defun go-ts-mode-set-devdocs ()
    (setq-local devdocs-current-docs '("go")))

  (cl-pushnew '(go-mode . go-ts-mode) major-mode-remap-alist :test #'equal)

  (with-eval-after-load 'apheleia
    (cl-pushnew '(go-ts-mode . goimports) apheleia-mode-alist :test #'equal))

  (with-eval-after-load 'repl-toggle
    (cl-pushnew '(go-ts-mode . go-repl) rtog/mode-repl-alist :test #'equal))

  (cl-pushnew '("\\([^/]+\\)\\.go\\'" "\\1_test.go") find-sibling-rules :test #'equal)
  (cl-pushnew '("\\([^/]+\\)_test\\.go\\'" "\\1.go") find-sibling-rules :test #'equal))
(use-package gotest
  :ensure t
  :bind
  (:map go-ts-mode-map
        ("C-. l" . go-run)
        ("C-. t a" . go-test-current-project)
        ("C-. t f" . go-test-current-file)
        ("C-. t t" . go-test-current-test)))
(use-package groovy-mode
  :ensure t
  :mode
  "\\.g\\(?:ant\\|roovy\\|radle\\)\\'"
  "Jenkinsfile")
(use-package fish-mode
  :ensure t
  :mode
  "\\.fish\\'"
  "/fish_funced\\..*\\'")
(use-package haskell-mode
  :ensure t
  :preface
  (eval-when-compile
    (require 'haskell-commands))
  :mode
  "\\.[gh]s\\'"
  "\\.hsig\\'"
  "\\.hsc\\'"
  ("\\.cabal\\'\\|/cabal\\.project\\|/\\.cabal/config\\'" . haskell-cabal-mode)
  ("\\.l[gh]s\\'" . haskell-literate-mode)
  :hook
  (haskell-mode-hook . eglot-ensure)
  :preface
  (autoload 'interactive-haskell-mode-map "haskell" nil t)
  :bind
  (:map haskell-mode-map
        ("C-. r" . haskell-interactive-switch)
        ("C-. R" . haskell-session-change-target))
  :init
  (setq haskell-font-lock-symbols t)
  (setq haskell-process-auto-import-loaded-modules t)
  (setq haskell-process-log t)
  (setq haskell-process-show-debug-tips nil)
  (setq haskell-process-use-presentation-mode t)
  (setq haskell-stylish-on-save t)
  (setq haskell-mode-stylish-haskell-path "brittany")

  ;; Allow configuring project local cabal repl commands.
  (put 'haskell-process-args-cabal-repl
       'safe-local-variable
       (lambda (x) (cl-every #'stringp x))))

(use-package haskell
  :hook
  (haskell-mode-hook . interactive-haskell-mode)
  :bind
  (:map interactive-haskell-mode-map ("M-." . nil)))
(use-package java-ts-mode
  :preface
  (cl-pushnew '(java-mode . java-ts-mode) major-mode-remap-alist :test #'equal)
  :hook
  (java-ts-mode-hook . eglot-ensure))
(use-package gradle-mode
  :ensure t
  :hook
  ((java-mode-hook java-ts-mode-hook kotlin-mode-hook) . gradle-mode)
  :bind
  (:map gradle-mode-map ("C-. t" . gradle-test))
  :init
  (setq gradle-executable-path "gradle"))
(use-package js
  :mode
  ("\\.js[mx]?\\'" . js-ts-mode)
  ("\\.har\\'" . js-ts-mode)
  :hook
  (js-ts-mode-hook . eglot-ensure)
  :init
  (cl-pushnew '("\\([^/]+\\)\\.js\\'" "\\1.spec.js") find-sibling-rules :test #'equal)
  (cl-pushnew '("\\([^/]+\\).spec\\.js\\'" "\\1.js") find-sibling-rules :test #'equal))

(cl-pushnew '(js-mode . js-ts-mode) major-mode-remap-alist :test #'equal)
(use-package json-ts-mode
  :mode
  "\\(?:\\(?:\\.json\\|\\.jsonld\\|\\.babelrc\\|\\.bowerrc\\|composer\\.lock\\)\\'\\)")

(cl-pushnew '(json-mode . json-ts-mode) major-mode-remap-alist :test #'equal)
(use-package json-navigator
  :ensure t
  :bind
  (:map json-ts-mode-map ("C-. n" . json-navigator-navigate-region)))
(use-package kotlin-mode :ensure t)
(use-package inf-lisp
  :init
  (setq inferior-lisp-program "sbcl"))
(use-package sly
  :ensure t
  :bind
  (:map sly-mode-map
        ("M-g k" . sly-describe-symbol)
        ("C-. o" . sly)))

(use-package sly-quicklisp :ensure t)
(use-package lua-ts-mode
  :mode "\\.lua\\'"
  :config
  (with-eval-after-load 'repl-toggle
    (cl-pushnew '(lua-ts-mode . lua-ts-inferior-lua) rtog/mode-repl-alist :test #'equal)))
(use-package markdown-mode
  :ensure t
  :mode
  "\\.markdown\\'"
  "\\.md\\'"
  :hook
  (markdown-mode-hook . markdown-display-inline-images)
  :bind
  (:map markdown-mode-map
        ("C-. i" . markdown-toggle-inline-images)
        ("C-. v" . markdown-toggle-markup-hiding))
  :init
  (setq markdown-enable-wiki-links t)
  (setq markdown-fontify-code-blocks-natively t)
  (setq markdown-header-scaling t)
  (setq markdown-hide-markup t)
  (setq markdown-italic-underscore t)
  (setq markdown-blockquote-display-char '("" ">"))
  (setq markdown-list-item-bullets '("" ""))
  (setq markdown-make-gfm-checkboxes-buttons t)
  (setq markdown-max-image-size '(1024 . 1024)))

Edit regions in separate buffers.

(use-package edit-indirect :ensure t)

Generate Table of Contents.

(use-package markdown-toc :ensure t)

Use variable-pitch font but still make sure everything aligns.

(font-lock-add-keywords
 'markdown-mode
 '(("^[[:space:]-*+>]+" 0 'fixed-pitch append))
 'append)

Pretty check-boxes

(font-lock-add-keywords
 'markdown-mode
 '(("^ *[-*+] \\[\\([Xx]\\)\\] "
    (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) ""))))))
(use-package mermaid-mode
  :ensure t
  :mode "\\.\\(mmd|mermaid\\)\\'"
  :hook
  (mermaid-mode-hook . mermaid-mode-set-compile-command)
  (mermaid-mode-hook . compile-on-save-mode)
  :init
  (setq mermaid-flags "--backgroundColor transparent")
  :config
  (defun mermaid-mode-set-compile-command ()
    "Configure compile command for mermaid-mode."
    (set (make-local-variable 'compile-command)
         (concat (mapconcat #'shell-quote-argument
                            (list
                             mermaid-mmdc-location
                             "-i" buffer-file-name
                             "-o" (concat (file-name-sans-extension buffer-file-name) mermaid-output-format)) " ")
                 " "
                 mermaid-flags))))
(use-package message
  :init
  (setq message-expand-name-standard-ui t))
(use-package nginx-mode
  :ensure t
  :mode
  "/nginx/.+\\.conf\\'"
  "nginx\\.conf\\'")
(use-package nix-ts-mode
  :ensure t
  :mode "\\.nix\\'"
  :hook
  (nix-ts-mode-hook . eglot-ensure)
  (nix-ts-mode-hook . nix-ts-mode-set-devdocs)
  :init
  (with-eval-after-load 'apheleia
    (cl-pushnew '(nix-ts-mode . nix) apheleia-mode-alist :test #'equal))
  (with-eval-after-load 'grugru
    (grugru-define-on-major-mode 'nix-ts-mode 'symbol '("true" "false")))
  (with-eval-after-load 'repl-toggle
    (cl-pushnew '(nix-ts-mode . nix-repl) rtog/mode-repl-alist :test #'equal))
  :config
  (defun nix-ts-mode-set-devdocs ()
    (setq-local devdocs-current-docs '("nix"))))

(use-package nix-mode
  :ensure t
  :commands
  (nix-repl)
  :bind
  (:map leader-map ("f" . nix-flake)))
(use-package nushell-ts-mode
  :ensure t
  :mode "\\.nu\\'")
(use-package nxml-mode
  :mode "\\.plist\\'"
  :init
  (setq nxml-slash-auto-complete-flag t))
(use-package caml :ensure t)

(use-package tuareg
  :ensure t
  :bind
  ((:map tuareg-mode-map
         ("C-x C-e" . tuareg-eval-phrase)
         ("C-. r" . run-ocaml))))
(use-package pdf-tools
  :ensure t
  :mode ("\\.pdf\\'" . pdf-view-mode))
(use-package plantuml-mode
  :ensure t
  :mode "\\.\\(plantuml\\|pum\\|plu\\)\\'"
  :init
  (setq plantuml-default-exec-mode 'executable))
(use-package python
  :hook
  (python-ts-mode-hook . eglot-ensure)
  (python-ts-mode-hook . indent-bars-mode)
  :bind
  (:map python-ts-mode-map ("C-. r" . run-python))
  :init
  (cl-pushnew '("\\([^/]+\\)\\.py\\'" "\\1_test.py") find-sibling-rules :test #'equal)
  (cl-pushnew '("\\([^/]+\\)_test\\.py\\'" "\\1.py") find-sibling-rules :test #'equal)
  (cl-pushnew '("src/\\(\\(?:[s][r][^c]\\|[^s][^r][^c]\\|$\\)./\\)+\\([^/]+\\)\\.py\\'" "tests/\\1test_\\2.py") find-sibling-rules :test #'equal)
  (cl-pushnew '("tests/\\(.+/\\)test_\\([^/]+\\)\\.py\\'" "src/\\1\\2.py") find-sibling-rules :test #'equal)
  :config
  (put 'python-shell-interpreter 'safe-local-variable #'(lambda (x) (member x '("python" "ipython")))))

(cl-pushnew '(python-mode . python-ts-mode) major-mode-remap-alist :test #'equal)
(use-package python-test
  :ensure t
  :bind
  (:map python-ts-mode-map
        ("C-. t a" . python-test-project)
        ("C-. t f" . python-test-file)
        ("C-. t t" . python-test-function))
  :init
  (setq python-test-backend 'pytest)
  :config
  (setq python-test-project-root-files
        (append '("README.md") python-test-project-root-files)))
(use-package racket-mode
  :ensure t
  :mode "\\.rkt[dl]?\\'"
  :bind
  (:map racket-mode-map
        ("M-g k" . racket-doc)
        ("C-. t" . racket-test))
  :config
  (with-eval-after-load 'repl-toggle
    (cl-pushnew '(racket-mode . racket-repl) rtog/mode-repl-alist :test #'equal)))
(use-package flymake-racket
  :ensure t
  :hook
  (racket-mode-hook . flymake-racket-add-hook))

Disabled due to currently not working with rego.

(use-package rego-mode :ensure t)
(use-package rst
  :hook
  (rst-mode-hook . auto-fill-mode))

Use variable-pitch font but still make sure everything aligns.

(font-lock-add-keywords
 'rst-mode
 '(("^[[:space:]-*+]+\\(\\[.\\]\\)?" 0 'fixed-pitch append))
 'append)

Pretty check-boxes as well as bullet lists.

(font-lock-add-keywords
 'rst-mode
 '(("^ *\\([-*+]\\) "
    (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) ""))))
   ("^ *[-*+] \\[\\([Xx]\\)\\] "
    (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) ""))))))
(use-package ruby-ts-mode
  :mode
  "\\.\\(rbw?\\|ru\\|rake\\|thor\\|jbuilder\\|rabl\\|gemspec\\|podspec\\)\\'"
  "\\(Gem\\|Rake\\|Cap\\|Thor\\|Puppet\\|Berks\\|Brew\\|Vagrant\\|Guard\\|Pod\\)file"
  :hook
  (ruby-ts-mode-hook . eglot-ensure)
  :init
  (setq ruby-align-chained-calls t)

  (with-eval-after-load 'apheleia
    (cl-pushnew '(ruby-ts-mode . rufo) apheleia-mode-alist :test #'equal))

  (cl-pushnew '("\\([^/]+\\)\\.rb\\'" "\\1_test.rb") find-sibling-rules :test #'equal)
  (cl-pushnew '("\\([^/]+\\)_test\\.rb\\'" "\\1.rb") find-sibling-rules :test #'equal)
  :config
  (with-eval-after-load 'hideshow
    (cl-pushnew `(ruby-ts-mode
                  ,(rx (or "def" "class" "module" "do" "{" "[")) ; Block start
                  ,(rx (or "}" "]" "end"))                       ; Block end
                  ,(rx bol
                       (or (+ (zero-or-more blank) "#") "=begin")) ; Comment start
                  ruby-forward-sexp nil)
                hs-special-modes-alist
                :test #'equal)))
(use-package inf-ruby
  :ensure t
  :hook
  (ruby-ts-mode-hook . inf-ruby-minor-mode)
  ;; Auto breakpoint
  (compilation-filter-hook . inf-ruby-auto-enter)
  :init
  (setq inf-ruby-default-implementation "pry")

  (with-eval-after-load 'repl-toggle
    (cl-pushnew '(ruby-ts-mode . inf-ruby) rtog/mode-repl-alist :test #'equal)))
(use-package minitest
  :ensure t
  :hook
  (ruby-ts-mode-hook . minitest-enable-appropriate-mode)
  :bind
  (:map minitest-mode-map
        ("C-. t a" . minitest-verify-all)
        ("C-. t f" . minitest-verify)
        ("C-. t t" . minitest-verify-single))
  :init
  (put 'minitest-use-bundler 'safe-local-variable 'booleanp))
(use-package rust-ts-mode
  :mode "\\.rs\\'"
  :hook
  (rust-ts-mode-hook . eglot-ensure)
  :init
  (with-eval-after-load 'org
    (cl-pushnew '("rust" . rust-ts-mode) org-src-lang-modes :test #'equal)))
(use-package scala-mode
  :ensure t
  :mode "\\.\\(scala\\|sbt\\)\\'"
  :hook
  (scala-mode-hook . init-scala-prettify-symbols)
  :init
  (setq scala-indent:align-parameters t)
  :config
  (defun init-scala-prettify-symbols ()
    (setq prettify-symbols-alist scala-prettify-symbols-alist)
    (prettify-symbols-mode 1)))
(use-package sh-script
  :hook
  (sh-mode-hook . flymake-mode)
  :bind
  (:map sh-mode-map ("M-g k" . man))
  :init
  ;; Use regular indentation for line-continuation
  (setq sh-indent-after-continuation 'always)

  (cl-pushnew '("\\([^/]+\\)\\.sh\\'" "\\1.bats") find-sibling-rules :test #'equal)
  (cl-pushnew '("\\([^/]+\\)\\.bats\\'" "\\1.sh") find-sibling-rules :test #'equal)

  (with-eval-after-load 'apheleia
    (cl-pushnew '(sh-mode . shfmt) apheleia-mode-alist :test #'equal)))
(use-package sql
  :init
  (setq sql-mysql-options '("--protocol=tcp" "--prompt=" "--disable-pager")))
(use-package terraform-mode
  :ensure t
  :mode "\\.tf$"
  :hook
  (terraform-mode-hook . terraform-mode-set-devdocs)
  :config
  (defun terraform-mode-set-devdocs ()
    (setq-local devdocs-current-docs '("terraform"))))
(use-package typescript-ts-mode
  :mode "\\.ts$"
  :hook
  (typescript-ts-mode-hook . eglot-ensure)
  :init
  (cl-pushnew '("\\([^/]+\\)\\.ts\\'" "\\1.test.ts") find-sibling-rules :test #'equal)
  (cl-pushnew '("\\([^/]+\\).test\\.ts\\'" "\\1.ts") find-sibling-rules :test #'equal))

Display current path for HTML/XML/CSS.

(use-package cakecrumbs
  :ensure t
  :defer 3
  :commands
  (cakecrumbs-auto-setup)
  :config
  (cakecrumbs-auto-setup))
(use-package web-mode
  :ensure t
  :mode "\\.\\(phtml\\|php\\|[agj]sp\\|as[cp]x\\|erb\\|djhtml\\|html?\\|hbs\\|ejs\\|jade\\|swig\\|tmpl\\)\\'"
  :init
  (setq web-mode-enable-html-entities-fontification t)
  ;; Highlight enclosing tags of the element under cursor
  (setq web-mode-enable-current-element-highlight t)
  ;; No extra indentation for blocks.
  (setq web-mode-script-padding 0)
  (setq web-mode-style-padding 0))
(use-package yaml-ts-mode
  :mode "\\.\\(e?ya?\\|ra\\)ml\\'"
  :hook
  (yaml-ts-mode-hook . apheleia-mode)
  (yaml-ts-mode-hook . indent-bars-mode)
  (yaml-ts-mode-hook . (lambda () (variable-pitch-mode 0))))

Dim out the surrounding text except the current focused paragraph or expression.

(use-package focus :ensure t)
(use-package indent-bars
  :ensure t
  :init
  (setq indent-bars-width-frac 0.2))
(use-package pomm
  :ensure t
  :commands (pomm pomm-third-time)
  :bind
  (:map leader-map ("p" . pomm-third-time)))

Support for restoring previous session on Emacs restart. This adds a few tweaks that makes it really useful.

(use-package desktop
  :hook
  (server-after-make-frame-hook . desktop-read)
  (server-after-make-frame-hook . desktop-save-mode)
  :init
  (setq desktop-save t)
  (setq desktop-files-not-to-save "\\(\\`/[^/:]*:\\|(ftp)\\|\\.gz\\'\\)")

  (setq desktop-load-locked-desktop t)
  (setq desktop-restore-eager 0)
  (setq desktop-restore-frames nil)

  (desktop-save-mode 1)
  :config
  (dolist (var '(compile-history
                 extended-command-history
                 grep-history
                 minibuffer-history
                 query-replace-history
                 read-expression-history
                 shell-command-history))
    (cl-pushnew var desktop-globals-to-save :test #'equal))
  (dolist (var '(apheleia-formatter buffer-undo-list comint-input-ring))
    (cl-pushnew var desktop-locals-to-save :test #'equal)))
(use-package spray
  :ensure t
  :init
  (setq spray-height 500)
  (setq spray-margin-left 2)

  (keymap-set toggle-map "s" '("Speed reading" . spray-mode))
  :config
  (setq spray-unsupported-minor-modes
        (append '(beacon-mode centered-window-mode visual-fill-column-mode)
                spray-unsupported-minor-modes)))
(setq ispell-alternate-dictionary (getenv "WORDLIST"))

(use-package jinx
  :ensure t
  :hook
  ((prog-mode-hook
    text-mode-hook) . jinx-mode)
  :bind
  (([remap ispell-word] . jinx-correct)
   (:repeat-map jinx-repeat-map
                ("s" . jinx-next)
                ("S" . jinx-previous)
                ("[" . jinx-previous)
                ("]" . jinx-next)))
  :init
  (keymap-set next-map "s" '("Misspelling" . jinx-next))
  (keymap-set prev-map "s" '("Misspelling" . jinx-previous)))

Automatic language detection that updates the spell checker.

(use-package guess-language
  :ensure t
  :commands
  (guess-language-mode))

Avoid color when possible.

(use-package eshell
  :preface
  (eval-when-compile
    (require 'em-hist)
    (require 'em-term))
  (defvar eshell-visual-commands)
  :hook
  (eshell-mode-hook . abbrev-mode)
  (eshell-mode-hook . init-eshell-define-keys)
  (eshell-mode-hook . init-eshell-set-visual-commands)
  :bind
  (("C-!" . eshell)
   (:map leader-map ("t" . eshell)))
  :init
  (setq eshell-buffer-maximum-lines 20000)
  (setq eshell-history-size 10000)
  (setq eshell-hist-ignoredups t)
  (setq eshell-save-history-on-exit t)
  (setq eshell-error-if-no-glob t)
  (setq eshell-destroy-buffer-when-process-dies t)
  (autoload 'eshell-smart-initialize "em-smart")
  :config
  (defun init-eshell-define-keys ()
    (keymap-set eshell-mode-map "RET" '+eshell-expand-abbrev-and-send-input))

  (defun init-eshell-set-visual-commands ()
    (setq eshell-visual-commands
          (append
           '("fish" "ghcid" "jshell" "most" "ssh" "tail" "tsun" "watch")
           eshell-visual-commands))))

Fish-like abbreviations that expand on space or enter.

(use-package eshell
  :functions
  (+eshell-abbrev-expand-p)
  :preface
  (autoload 'eshell-parse-arguments "esh-arg")
  (autoload 'eshell-send-input "esh-mode")
  :init
  (define-abbrev-table 'eshell-mode-abbrev-table
    '(("base64" "base64 -w0")
      ("e" "find-file-other-window")
      ("E" "dired")
      ("gco" "git checkout")
      ("gd" "magit-diff-unstaged")
      ("gds" "magit-diff-staged")
      ("gs" "magit-status")
      ("time" "time -p")
      ("tree" "tree -a")
      ("week" "date '+%V'"))
    :enable-function #'+eshell-abbrev-expand-p)
  :config
  (defun +eshell-expand-abbrev-and-send-input ()
    "Expand abbreviation and send input to `eshell'."
    (interactive)
    (expand-abbrev)
    (call-interactively #'eshell-send-input))

  (defun +eshell-abbrev-expand-p ()
    "Return t if abbreviation should be expanded.
Expansion should happen when abbreviation is at the beginning of
the line or after an eshell operator."
    (let* ((end (point-marker))
           (begin (save-excursion (beginning-of-line) (point)))
           (args (catch 'eshell-incomplete (eshell-parse-arguments begin end))))
      (or (= 1 (length args))
          (let ((last-two-args (last args 2)))
            (and (consp (car last-two-args))
                 (eq (caar last-two-args)
                     'eshell-operator)))))))

Command execution status indicator in the fringe.

(use-package eshell-fringe-status
  :ensure t
  :hook
  (eshell-mode-hook . eshell-fringe-status-mode))

Fast terminal emulator utilizing libvterm.

(use-package vterm
  :ensure t
  :bind
  (:map leader-map ("T" . vterm))
  :init
  (setq vterm-max-scrollback 100000)
  (setq vterm-shell "fish"))
(use-package vterm-toggle
  :ensure t
  :bind
  (("C-M-!" . vterm-toggle)
   (:map vterm-mode-map ("C-<return>" . vterm-toggle-insert-cd))))

Increase undo limit.

(setq undo-limit 1000000)
(setq undo-strong-limit (* 2 undo-limit))

Visual undo history navigation.

(use-package vundo
  :ensure t
  :bind
  (:map leader-map ("u" . vundo)))
(use-package gptel
  :ensure t
  :functions
  (gptel-make-ollama)
  :bind
  (:map leader-map
        ("g" . gptel)
        ("G" . gptel-menu))
  :config
  (setq gptel-model 'gemma3)
  (setq gptel-backend (gptel-make-ollama "Ollama"
                                         :host "localhost:11434"
                                         :stream t
                                         :models '("gemma3"
                                                   "qwen3"
                                                   "llama3.2"
                                                   "deepseek-r1"
                                                   "deepcoder")))
  (setq gptel-default-mode 'org-mode)

  (cl-pushnew
   '(cli . "You are a large language model and a correct command line helper. Provide commands and only commands as output without any additional text, prompt or note.")
   gptel-directives
   :test #'equal)

  (cl-pushnew
   '(regex . "You are a large language model and regular expression expert. Respond with pure regular expressions without involvement of other programming languages.")
   gptel-directives
   :test #'equal))

(use-package gptel-quick
  :ensure t
  :bind
  (:map help-map ("," . gptel-quick)))
(use-package elysium
  :ensure t
  :bind
  (:map leader-map
        ("q" . elysium-query))
  :config
  (with-eval-after-load 'popper
    (cl-pushnew "\\*elysium\\*" popper-reference-buffers :test #'equal)))

Packages that I am currently testing or evaluating.

(use-package annotate
  :ensure t
  :commands
  (annotate-mode)
  :init
  (keymap-set toggle-map "a" '("Annotate" . annotate-mode)))
(use-package consult-git-log-grep
  :ensure t
  :after magit
  :init
  (setq consult-git-log-grep-open-function #'magit-show-commit))
(use-package dape :ensure t)
(use-package elfeed :ensure t)
(use-package freeze-it :ensure t)
(use-package minuet :ensure t)
(use-package copilot
  :ensure t
  :bind
  (:map copilot-completion-map
        ("C-e" . 'copilot-accept-completion)
        ("TAB" . 'copilot-accept-completion-by-word))
  :preface
  (defun copilot-turn-on-when-prog-mode ()
    "Turn on `copilot-mode' if the buffer mode is derived from `prog-mode'."
    (when (derived-mode-p 'prog-mode)
      (copilot-mode 1)))

  (define-global-minor-mode global-copilot-prog-mode copilot-mode copilot-turn-on-when-prog-mode
    :group 'copilot))
(use-package copilot-chat
  :ensure t)
(use-package gptel-aibo :ensure t)

I am trying to reduce the amount of custom keybindings, therefore I present a table of default keybindings in case I would forget them.

Keybinding Alternative M- C-[ TAB C-i RET C-m Keybinding Function Description C-o open-line Open line above C-j electric-newline-and-maybe-indent Add newline and indent if needed M-SPC just-one-space Ensures just one space M-\ delete-horizontal-space Delete all space M-^ delete-indentation Join current line with previous line M-z zap-to-char Delete until character C-S-backspace kill-whole-line Kill entire lines, can be used to move several lines at once M-/ dabbrev-expand Abbreviation completion M-tab / C-[ C-i completion-at-point More context aware completion M-s . isearch-forward-symbol-at-point Search for the symbol at point C-w kill-region Cut M-w kill-ring-save Copy C-y yank Paste M-y yank-next Paste (next item) C-x SPC rectangle-mark-mode Rectangular selection C-x r t string-rectangle Insert string in beginning of rectangular selection (C-t in rectangle-mark-mode) C-M-f forward-sexp Move forward inside a balanced expression C-M-b backward-sexp Move backward inside a balanced expression C-M-n forward-list Move forward across one balanced group of parenthesis C-M-p backward-list Move backward across one balanced group of parenthesis M-m back-to-indentation Move to the first non-whitespace character M-e forward-sentence End of sentence M-a backward-sentence Start of sentence C-M-d down-list Move forward down one level of parenthesis C-M-u backward-up-list Move backward out of one level of parenthesis C-u C-x $ set-selective-display Hide/show indentation level C-x r w <reg> window-configuration-to-register Store the window configuration of the selected frame in REGISTER C-x r j jump-to-register Go to location stored in REGISTER, or restore configuration stored there C-x C-M-0 global-text-scale-adjust Change font size of all faces M-h mark-paragraph Mark paragraph C-SPC set-mark-command Set a mark C-u C-SPC pop-to-mark-command Pop a mark C-x $ set-selective-display Code-folding via indentation C-x p ! project-shell-command Run shell command in the current project’s root directory C-x p & project-async-shell-command Run shell command asynchronously in the current project’s root directory Keybinding Function Description L gnus-group-list-all-groups List all groups (works together with prefix to provide level) RET gnus-topic-select-group List group mails (works together with prefix to see all) g gnus-group-get-new-news Refresh groups list G G gnus-group-make-nnir-group Search mails at server side # gnus-group-mark-group Mark M-# gnus-group-unmark-group Un-mark R gnus-summary-reply-with-original Reply w/ quoted text r gnus-summary-reply Reploy w/o quoted text S W gnus-summary-wide-reply-with-original Reply all w/ quoted text S w gnus-summary-wide-reply Reply all w/o quoted text m / C-x m gnus-new-mail Compose new mail S D e gnus-summary-resend-message-edit Re-send a mail in Draft folder C-c C-a mml-attach-file Attach a file o gnus-mime-save-part Save attachment C-c C-f gnus-summary-mail-forward Forward mail c gnus-group-catchup-current Mark mails as read Keybinding Function Description C-c C-w org-refile Move headline under another top level headline <S-right> org-shiftright Cycle through todo keywords (right) <S-left> org-shiftleft Cycle through todo keywords (left) C-c C-c org-ctrl-c-ctrl-c Set tags for an item C-c C-t org-todo Set tags for an item (via menu) C-c C-s org-schedule Schedule an item C-c C-d org-deadline Set a deadline C-c C-q org-set-tags-command Attach tags to item Split theme into several parts Extract history persistence code (persistory) Use vc-mode commands more C-x v g, C-x v v and C-x v =. Use ChangeLog entries C-x 4 a Create macros via checking C-h l (view-lossage) then it can be used together with edit-last-kbd-macro. Is it useful to use highlight-regexp? Prefix function that overrides kill-region as kill-ring-save for next command Function to jump to file under point, preferably with support for : line number Function to load theme defined in current file Split configuration into essential and full feature

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4