inhibit-mouse.el – Deactivate mouse input in Emacs (Alternative to disable-mouse)

Build Status MELPA MELPA Stable License

The inhibit-mouse package allows the disabling of mouse input in Emacs using inhibit-mouse-mode.

Instead of modifying the keymap of its own mode as the disable-mouse package does, enabling inhibit-mouse-mode only modifies input-decode-map to disable mouse events, making it more efficient and faster than disable-mouse.

Additionally, the inhibit-mouse package allows for the restoration of mouse input when inhibit-mouse-mode is disabled.

If this enhances your workflow, please show your support by ⭐ starring inhibit-mouse on GitHub to help more Emacs users discover its benefits.

Installation

To install inhibit-mouse from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.
  2. Add the following code to the Emacs init file:
    
    (use-package inhibit-mouse
    :ensure t
    :custom
    ;; Disable highlighting of clickable text such as URLs and hyperlinks when
    ;; hovered by the mouse pointer.
    (inhibit-mouse-adjust-mouse-highlight t)

;; Disables the use of tooltips (show-help-function) during mouse events. (inhibit-mouse-adjust-show-help-function t)

:config (if (daemonp) (add-hook ‘server-after-make-frame-hook #’inhibit-mouse-mode) (inhibit-mouse-mode 1)))


## Customization

### Customizing the mouse buttons disabled by inhibit-mouse?

The *inhibit-mouse* custom variables allow you to fine-tune which mouse interactions are disabled.

You can use the following configuration to specify which mouse buttons and events you want to disable:
``` emacs-lisp
;; This variable specifies which mouse buttons should be inhibited from
;; triggering events.
(setq inhibit-mouse-button-numbers '(1 2 3 4 5))

;; List of mouse button events to be inhibited.
(setq inhibit-mouse-button-events '("mouse"
                                    "up-mouse"
                                    "down-mouse"
                                    "drag-mouse"))

;; List of miscellaneous mouse events to be inhibited.
(setq inhibit-mouse-misc-events '("wheel-up"
                                  "wheel-down"
                                  "wheel-left"
                                  "wheel-right"
                                  "pinch"))

;; List of mouse multiplier events to be inhibited.
(setq inhibit-mouse-multipliers '("double" "triple"))

;; List of key modifier combinations to be inhibited for mouse events.
(setq inhibit-mouse-key-modifiers '((control)
                                    (meta)
                                    (shift)
                                    (control meta shift)
                                    (control meta)
                                    (control shift)
                                    (meta shift)))

Enabling/Disabling the context menu

To enable or disable the context menu based on the state of inhibit-mouse-mode, the following code dynamically toggles context-menu-mode accordingly:

(add-hook 'inhibit-mouse-mode-hook
          #'(lambda()
              ;; Enable or disable the context menu based on the state of
              ;; `inhibit-mouse-mode', the following code dynamically toggles
              ;; `context-menu-mode' accordingly.
              (when (fboundp 'context-menu-mode)
                (if (bound-and-true-p inhibit-mouse-mode)
                    (context-menu-mode -1)
                  (context-menu-mode 1)))))

This ensures that the context menu is disabled when inhibit-mouse-mode is active and enabled when it is inactive.

Enabling/Disabling tooltip-mode

When tooltip-mode is enabled, Emacs displays certain UI hints (e.g., help text and mouse-hover messages) as popup windows near the cursor, instead of in the echo area. This behavior is useful in graphical Emacs sessions.

To toggle tooltip-mode dynamically based on the state of inhibit-mouse-mode, you can use the following hook:

(add-hook 'inhibit-mouse-mode-hook
          #'(lambda()
              ;; Enable or disable `tooltip-mode'. When tooltip-mode is
              ;; enabled, certain UI elements (e.g., help text, mouse-hover
              ;; hints) will appear as native system tooltips (pop-up
              ;; windows), rather than as echo area messages. This is useful
              ;; in graphical Emacs sessions where tooltips can appear near
              ;; the cursor.
              (when (fboundp 'tooltip-mode)
                (if (bound-and-true-p inhibit-mouse-mode)
                    (tooltip-mode -1)
                  (tooltip-mode 1)))))

Enabling/disabling pixel scroll precision mode

The following configuration toggles pixel-scroll-precision-mode based on the state of inhibit-mouse-mode, excluding macOS Carbon environments where pixel scrolling is natively supported and does not require explicit activation.

(add-hook 'inhibit-mouse-mode-hook
          #'(lambda()
              (unless (and
                       ;; Exclude macOS Carbon environments where pixel
                       ;; scrolling is natively supported and does not
                       ;; require explicit activation.
                       (eq window-system 'mac)
                       (bound-and-true-p mac-carbon-version-string))
                (when (fboundp 'pixel-scroll-precision-mode)
                  (if (bound-and-true-p inhibit-mouse-mode)
                      (pixel-scroll-precision-mode -1)
                    (pixel-scroll-precision-mode 1))))))

Frequently Asked Question

What motivates the author to disable the mouse in Emacs?

The author disables the mouse in Emacs:

  • To prevent accidental clicks or cursor movements that can change the cursor position unexpectedly.
  • To reinforce a keyboard-centric workflow, helping to avoid the habit of relying on the mouse for navigation.

Some may suggest that the author could modify the touchpad settings at the OS level. However, he prefers not to disable the touchpad entirely, as it remains useful in other applications, such as web browsers.

Is it not enough to simply avoid touching the mouse?

It is not always as simple as just deciding not to touch the mouse. When transitioning to a fully keyboard-driven workflow, existing habits can be surprisingly persistent.

In the author’s case, he often found himself unconsciously reaching for the mouse, even though they had deliberately chosen to keep his hands on the home row. The home row, the middle row of keys on a standard keyboard layout, is where the fingers rest in the touch typing method. Keeping the hands on the home row minimizes unnecessary hand movement, preserves typing rhythm, and allows immediate access to the majority of keys. In contrast, reaching for the mouse interrupts the workflow, introduces delays, and shifts focus away from the keyboard, reducing overall efficiency.

The inhibit-mouse Emacs package provided a practical solution. By disabling mouse input entirely, it removed the possibility of falling back on that habit. Over time, this enforced constraint trained the author to rely exclusively on the keyboard.

This package acted as a form of behavioral reinforcement for the author: each attempt to use the mouse proved unproductive, gradually reshaping habits until the keyboard-driven workflow became natural and automatic.

What is the difference between the disable-mouse and inhibit-mouse packages?

The inhibit-mouse package is a efficient alternative to the disable-mouse package, as it only modifies input-decode-map to disable mouse events.

In contrast, disable-mouse applies mouse events to its own mode, and sometimes the user has to apply it to other modes that are not affected by the disable-mouse mode using the disable-mouse-in-keymap function (e.g, evil-mode, tab-bar…).

Additionally, inhibit-mouse:

  • Allows re-enabling mouse functionality when the mode is disabled, which is not supported by disable-mouse when the disable-mouse-in-keymap function is used. The disable-mouse-in-keymap function overwrites the key mappings of other modes (e.g., evil, tab-bar), and there is no straightforward way to make disable-mouse restore them.
  • It resolves issues that disable-mouse does not, such as the “C-c C-x is not bound” problem, where the user intended to enter C-c C-x j but accidentally touched the touchpad.

This concept of utilizing input-decode-map to disable the mouse was introduced by Stefan Monnier in an emacs-devel mailing list thread initiated by Daniel Radetsky, who proposed a patch to the Emacs developers. Additionally, here is an interesting discussion on GitHub: Add recipe for inhibit-mouse.

Author and License

The inhibit-mouse Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2024-2025 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

Emacs flymake-bashate.el – A Flymake backend for bashate that provides style checking for Bash shell scripts within Emacs

Build Status MELPA MELPA Stable License

The flymake-bashate Emacs package provides a Flymake backend for bashate, enabling real-time style checking for Bash shell scripts within Emacs.

(This package can also work with Flycheck: simply use the flymake-flycheck package, which allows any Emacs Flymake backend to function as a Flycheck checker.)

If this enhances your workflow, please show your support by ⭐ starring flymake-bashate.el on GitHub to help more Emacs users discover its benefits.

Installation

To install flymake-bashate from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code to your Emacs init file to install flymake-bashate from MELPA:

    (use-package flymake-bashate
    :ensure t
    :commands flymake-bashate-setup
    :hook (((bash-ts-mode sh-mode) . flymake-bashate-setup)
          ((bash-ts-mode sh-mode) . flymake-mode))
    :custom
    (flymake-bashate-max-line-length 80))

Customizations

Ignoring Bashate errors

To make bashate ignore specific Bashate rules, such as E003 (ensure all indents are a multiple of 4 spaces) and E006 (check for lines longer than 79 columns), set the following variable:

(setq flymake-bashate-ignore "E003,E006")

(This corresponds to the -i or --ignore option in Bashate.)

Setting maximum line length

To define the maximum line length for Bashate to check:

(setq flymake-bashate-max-line-length 80)

(This corresponds to the --max-line-length option in Bashate.)

Specifying the Bashate executable

To change the path or filename of the Bashate executable:

(setq flymake-bashate-executable "/opt/different-directory/bin/bashate")

(Defaults to “bashate”.)

License

Copyright (C) 2024-2025 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

Emacs enhanced-evil-paredit.el package: Preventing Parenthesis Imbalance when Using Evil-mode with Paredit

Build Status MELPA MELPA Stable License

The enhanced-evil-paredit package prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure. This guarantees that your Lisp code remains syntactically correct while retaining the editing features of evil-mode.

If this enhances your workflow, please show your support by ⭐ starring enhanced-evil-paredit-mode on GitHub to help more Emacs users discover its benefits.

Installation

To install enhanced-evil-paredit from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.
  2. Add the following code to the Emacs init file to install enhanced-evil-paredit:
    (use-package enhanced-evil-paredit
    :ensure t
    :config
    (add-hook 'paredit-mode-hook #'enhanced-evil-paredit-mode))

Frequently asked questions

What are the differences between enhanced-evil-paredit and evil-paredit?

The enhanced-evil-paredit package is a modernized version of evil-paredit. It has been enhanced and fully functions in recent versions of Emacs (Emacs >= 28). The author decided to develop enhanced-evil-paredit because the evil-paredit package is no longer maintained and does not function in recent versions of Emacs and Evil.

Here are the enhancements in enhanced-evil-paredit:

  • Handles paste using p and P, ensuring that the pasted text has balanced parentheses.
  • Fix call to a non-existent function (evil-called-interactively-p), which has been replaced by (called-interactively-p 'any).
  • Add new functions: enhanced-evil-paredit-backward-delete and enhanced-evil-paredit-forward-delete.
  • enhanced-evil-paredit-mode only uses the paredit functions when paredit is enabled. Otherwise, enhanced-evil-paredit-mode uses Evil functions.
  • Add lexical binding with lexical-binding: t.
  • Suppress Emacs Lisp warnings and add Melpa tests.
  • Refactor and improve enhanced-evil-paredit.
  • Create a enhanced-evil-paredit customization group for user configuration.
  • Remove Evil state change from enhanced-evil-paredit-mode.
  • Improve error handling in enhanced-evil-paredit-check-region.
  • Enhance docstrings.
  • Remove keymap bindings that are reserved by Emacs.
  • Add &optional after the end argument to make it similar to Evil functions.
  • dd restores the column when there is a parentheses mismatch.

Author and License

The enhanced-evil-paredit Emacs package has been written by Roman Gonzalez and James Cherti. It is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2024-2025 James Cherti

Copyright (C) 2012-2015 Roman Gonzalez

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

Emacs flymake-ansible-lint.el – A Flymake backend for ansible-lint

Build Status MELPA MELPA Stable License

The flymake-ansible-lint package provides a Flymake backend for ansible-lint, enabling real-time syntax and style checking for Ansible playbooks and roles within Emacs.

(This package can also work with Flycheck: simply use the flymake-flycheck package, which allows any Emacs Flymake backend to function as a Flycheck checker.)

Requirements

Installation

To install flymake-ansible-lint from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code to your Emacs init file to install flymake-ansible-lint from MELPA:

    (use-package flymake-ansible-lint
    :ensure t
    :commands flymake-ansible-lint-setup
    :hook (((yaml-ts-mode yaml-mode) . flymake-ansible-lint-setup)
          ((yaml-ts-mode yaml-mode) . flymake-mode)))

Customizations

You can configure ansible-lint parameters using the flymake-ansible-lint-args variable:

(setq flymake-ansible-lint-args '("--offline"
                                  "-x" "run-once[play],no-free-form"))

Frequently asked questions

Why are some ansible-lint error messages truncated?

This issue is a known bug in ansible-lint, not in flymake-ansible-lint.

It is ansible-lint that truncates some error messages:

$ ansible-lint -p test.yaml
test.yaml:5: yaml[truthy]: Truthy value should be one of

License

The flymake-ansible-lint Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version. This package uses flymake-quickdef, by Karl Otness.

Copyright (C) 2024-2025 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

Emacs quick-fasd: Integrate Fasd for fast file and directory navigation

Build Status MELPA MELPA Stable License

The quick-fasd Emacs package integrates the Fasd tool into the Emacs environment. Fasd is a command-line utility that provides fast access to frequently used files and directories.

After installing quick-fasd and enabling quick-fasd-mode:

  • All visited files and directories are automatically added to the Fasd database.
  • The quick-fasd-find-path function prompts for input and presents candidates from the Fasd index. (For example, recently accessed files can be opened, and frequently used directories can be visited without leaving Emacs.)
  • When invoked from the minibuffer, quick-fasd-find-path appends the selected path, simplifying completion.

If this package improves the workflow, consider supporting the project by ⭐ starring quick-fasd.el on GitHub so that more Emacs users can benefit from it.

Requirements

  • The fasd command line tool.

Installation

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code to your Emacs init file to install easysession from MELPA:

(use-package quick-fasd
  :ensure t
  :bind (("C-x C-d" . quick-fasd-find-path)
         :map minibuffer-local-completion-map
         ("C-x C-d" . quick-fasd-find-path))
  :config
  (quick-fasd-mode))

Usage

Key binding

Add a shortcut key for quick-fasd-find-path:

(global-set-key (kbd "C-x C-d") 'quick-fasd-find-path)

;; When `quick-fasd-find-path' is invoked from the minibuffer, it appends
;; the selected path, simplifying completion.
;; Path insertion can be disabled by setting `quick-fasd-minibuffer-insert-path' to nil.
(define-key minibuffer-local-completion-map (kbd "C-x C-d") 'quick-fasd-find-path)

Customizations

You can configure quick-fasd using Emacs’ customization system:

M-x customize-group RET quick-fasd RET

Passing custom arguments to Fasd

The quick-fasd package allows customizing the types of results returned by Fasd using quick-fasd-standard-search:

;; Display directories only
(setq quick-fasd-standard-search '("-d"))

;; Display files only
(setq quick-fasd-standard-search '("-f"))

;; Display both files and directories
(setq quick-fasd-standard-search '("-a"))

Initial Prompt

By default, quick-fasd prompts for an initial query. To bypass the prompt and display all results immediately, set:

(setq quick-fasd-enable-initial-prompt nil)

Setting this to nil is useful when using completion frameworks such as Consult, Vertico, or Orderless, allowing them to handle filtering instead of fasd. However, fetching all paths from fasd can be slower for large file databases and may produce an overwhelming number of candidates.

Completion Function

The M-x quick-fasd-find-path command uses the standard completing-read-function, which may be backed by Consult, helm, ido, or any other completion framework you have configured.

Standard Search Behavior

By default, quick-fasd searches for both files and directories using the -a parameter. You can customize this behavior by setting the quick-fasd-standard-search option to refine the search criteria.

Automatically adding paths on buffer or window change

Quick-Fasd can optionally add the current file or directory to the Fasd database whenever the buffer or window changes. This behavior is controlled by the quick-fasd-auto-add-on-buffer-change option.

To enable automatic path addition, set the option to t:

(setq quick-fasd-auto-add-on-buffer-change t)

When enabled, Quick-Fasd will track every file or directory visited in Emacs, including those accessed through buffers and Dired windows, without requiring manual addition.

Benefits:

  • Seamless tracking: Ensures that all relevant files and directories are added to Fasd automatically.
  • Improved workflow: Facilitates faster navigation through frequently accessed paths using Quick-Fasd commands, without the need to manually update the database.

Drawbacks:

  • Increased background activity: Each buffer or window change spawns a background process to update the Fasd database. While this does not block Emacs, it can generate extra system activity if buffers are switched frequently.
  • Database growth: Continuous automatic additions may increase the size of the Fasd database over time, potentially including entries that are rarely used.

Use this option when the convenience of automatic tracking outweighs the potential performance and database size considerations.

Frequently asked questions

What is the difference between quick-fasd and the fasd Emacs package?

The quick-fasd Emacs package is a fork of the unmaintained fasd Emacs package. It supersedes fasd by providing additional features and bug fixes.

Key differences and improvements in quick-fasd include:

  • When quick-fasd-find-path is invoked from the minibuffer, it appends the selected path, simplifying completion. (This can be disabled by setting quick-fasd-minibuffer-insert-path to nil)
  • Adds support for indirect Dired buffers.
  • Enhances dired-mode detection to append paths using the fasd command, increasing their priority for subsequent fasd usage.
  • Fixes an issue in quick-fasd-add-path to ensure it respects quick-fasd-executable-path.
  • Caches the path to the fasd executable for efficiency.
  • Enhances modularity and readability of quick-fasd functions.
  • Fixes all Emacs warnings.
  • Renames global-quick-fasd-mode to quick-fasd-mode.
  • Refines overall code readability and structure.
  • Removes Ivy support, delegating it to a possible third-party package.
  • Allows customizing the Lighter
  • Removes the trailing slash from directories before adding them to Fasd ensures consistent path entries and prevents duplicates.
  • Normalizes the path before adding it to Fasd by expanding it (e.g., replacing ~/ with the home directory).
  • Provides a function to remove a specified path from the Fasd database (quick-fasd-delete-path).
  • Can optionally add the current file or directory to the Fasd database whenever the buffer or window changes. This behavior is controlled by the quick-fasd-auto-add-on-buffer-change option.

Author and License

The quick-fasd Emacs package James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version. It is based on the fasd package, originally written by Steckerhalter.

Copyright (C) 2024-2025 James Cherti

Copyright (C) 2013-2021 Steckerhalter

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

pre-commit-elisp – Pre-commit hooks for Emacs Lisp (Elisp) Git repositories

The pre-commit-elisp repository offers pre-commit hooks for Emacs Lisp (Elisp) projects. These hooks enforce code quality and consistency by performing automated checks on .el files prior to committing changes:

  • elisp-check-parens: Validates that all parentheses in .el files are correctly balanced.
  • elisp-check-byte-compile: Byte-compile Elisp files to detect compilation errors.
  • elisp-indent: Indent Elisp files according to Emacs Lisp style conventions.

These pre-commit hooks enforce syntactic correctness, successful byte-compilation, and consistent code formatting, ensuring a high standard of code quality and maintainability throughout the repository.

If this enhances your workflow, please show your support by ⭐ starring pre-commit-elisp on GitHub to help more Emacs users discover its benefits.

Installation

  1. Install pre-commit.

  2. Add this repository as a local hook in your .pre-commit-config.yaml:

---

repos:
  - repo: https://github.com/jamescherti/pre-commit-elisp
    rev: v1.0.5
    hooks:
      # Validate that all parentheses in .el files are correctly balanced
      - id: elisp-check-parens

      # Optional: Byte-compile .el files to identify compilation errors early
      # - id: elisp-check-byte-compile

      # Optional: Indent Elisp files according to Emacs Lisp style conventions
      # - id: elisp-indent
  1. Install the hooks in your project:
pre-commit install
  1. Run hooks manually on all files (optional):
pre-commit run --all-files

Customizations

Customizing load-path

Scripts such as elisp-check-byte-compile and elisp-byte-compile support customizing the load-path variable using a .dir-locals.el variable pre-commit-elisp-load-path. This variable allows specifying the directories that should be included in the load-path without modifying the scripts themselves, ensuring that dependencies and libraries located in the project or its subdirectories are correctly available for byte-compilation.

Customizing the load-path allows the byte-compilation scripts, such as elisp-check-byte-compile, to find and load project-specific Emacs Lisp files during compilation.

Here is an example of a .dir-locals.el file to place at the root of the Git repository:

((nil . ((pre-commit-elisp-load-path . ("." "lib/" "utils")))))

The pre-commit-elisp-load-path list is a list of directories relative to the Git repository root or project directory.

Each entry in the list determines how it is added to load-path:

  1. Directory ends with a slash (/): Recursively adds the directory and all its subdirectories to load-path. Example: "lib/" adds lib/ and all its subdirectories.

  2. Directory does not end with a slash: The directory is added non-recursively. Example: "utils" adds only the utils directory, not its subdirectories.

License

The pre-commit-elisp hooks have been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2025 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

Using Emacs vc-diff with tools such as git-crypt or Rails credentials: Handling Binary Diff Issues

Tools like git-crypt or Rails credentials provide an encryption layer for managing sensitive files within Git repositories. However, when using Emacs vc-diff on repositories protected by these tools, the diff output is incorrect because vc-diff compares the encrypted binary files directly rather than comparing the decrypted files. This occurs even when the repository is unlocked and the decrypted content is available, resulting in a failure to display meaningful diffs.

The root cause

Internally, vc-diff uses Git commands to compute diffs. However, it does not invoke them with the --textconv flag by default. Without --textconv, Git does not apply content filters, including decryption filters specified by tools such as git-crypt or Rails credentials. Consequently, Emacs vc-diff displays diffs of the raw binary files rather than the decrypted content.

The solution

A workaround for enabling human-readable diffs of encrypted files in Emacs is to modify the vc-git-diff-switches variable to include the --textconv argument:

;; Emacs vc-diff fails to produce meaningful output on git-crypt enabled
;; repositories because it does not use Git's --textconv flag by default. This
;; flag enables Git to apply text conversion filters (e.g., for encrypted files)
;; when generating diffs. Without it, vc-diff compares raw encrypted blobs, even
;; when the working tree shows decrypted content.
(unless (member "--textconv" vc-git-diff-switches)
  (setq vc-git-diff-switches (cons "--textconv" vc-git-diff-switches)))Code language: Lisp (lisp)

Adding the --textconv flag to the vc-git-diff-switches variable enables Emacs vc-diff to apply the text conversion filters specified in .gitattributes. This resolves the issue by displaying the diff of the decrypted files instead of the encrypted binary files.

Further Reading

Enhancing Git Diff for Emacs Lisp: Better Git Diff of Elisp function or macro definitions

By default, the git diff algorithm compares changes in Elisp files line by line without understanding the structural semantics of Emacs Lisp files. This means that when modifications are made within functions, the diff output does not convey how those changes relate to higher-level code constructs such as functions or macros.

As a result, reviewers are presented with fragmented and often verbose diffs where the context of a change, such as which function it belongs to, is not always readily apparent. This lack of structural awareness can make it difficult to assess the purpose and impact of changes efficiently.

Git can be configured to recognize function or macro definitions explicitly, ensuring that diffs are presented at the function or macro level rather than as arbitrary line changes. Here are the steps:

Step 1 – The Git configuration for Emacs Lisp diffs

Add the following elisp Git driver to your ~/.gitconfig file:

[diff "elisp"]
xfuncname = ^\\([^[:space:]]*def[^[:space:]]+[[:space:]]+([^()[:space:]]+)
Code language: plaintext (plaintext)

The regular expression above matches lines that begin with typical Emacs Lisp definition forms, such as defun, defmacro, and other def* constructs. It detects the symbol being defined, allowing Git to handle changes at the function or definition level intelligently. This configuration can also be found in the autogen.sh file, which is part of the Emacs source code.

Step 2 – Associating the Git Diff Driver with *.el files

Once the custom diff driver is defined, it needs to be associated with Elisp files. This is accomplished by adding the following line to the ~/.gitattributes file:

*.el diff=elisp
Code language: plaintext (plaintext)

With this setup, Git will apply the elisp diff driver to all files with the .el extension, using the custom pattern to identify function boundaries.

Conclusion

This configuration generates diffs that focus on changes within the scope of individual function and macro definitions, rather than arbitrary lines. As a result, reviews of Emacs Lisp code become more precise and contextually relevant. Reviewers can easily identify which functions were modified, without being distracted by unrelated or excessive diffs.

Related links

Emacs package: bufferfile – Delete or rename buffer file names with their associated buffers

Introduction

This bufferfile.el package provides helper functions to delete, rename, or copy buffer files:

  • bufferfile-rename: Renames the file visited by the current buffer, ensures that the destination directory exists, and updates the buffer name for all associated buffers, including clones/indirect buffers. It also ensures that buffer-local features referencing the file, such as Eglot or dired buffers, are correctly updated to reflect the new file name.
  • bufferfile-delete: Delete the file associated with a buffer and kill all buffers visiting the file, including clones/indirect buffers.
  • bufferfile-copy: Ensures that the destination directory exists and copies the file visited by the current buffer to a new file.

The functions above also ensures that any modified buffers are saved prior to executing operations like renaming, deleting, or copying.

If this enhances your workflow, please show your support by ⭐ starring bufferfile.el on GitHub to help more Emacs users discover its benefits.

(To make bufferfile use version control when renaming or deleting files, you can set the variable bufferfile-use-vc to t. This ensures that file operations within bufferfile interact with the version control system, preserving history and tracking changes properly.)

Installation from MELPA

To install bufferfile from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.
  2. Add the following code to your Emacs init file to install bufferfile from MELPA:
(use-package bufferfile
  :ensure t
  :custom
  ;; If non-nil, display messages during file renaming operations
  (bufferfile-verbose nil)

  ;; If non-nil, enable using version control (VC) when available
  (bufferfile-use-vc nil)

  ;; Specifies the action taken after deleting a file and killing its buffer.
  (bufferfile-delete-switch-to 'parent-directory))Code language: Lisp (lisp)

Usage

  • To rename the current buffer’s file and associated buffers, run: M-x bufferfile-rename
    (You will be prompted to enter a new name. The file will be renamed on disk, and the buffer—along with any associated buffers such as indirect buffers—will begin visiting the new file, with their buffer names updated accordingly.)
  • To delete the current buffer’s file and associated buffers, run: M-x bufferfile-delete
    (You will be asked to confirm the deletion. If confirmed, the file will be removed from disk, and all associated buffers, including indirect buffers, will be killed.)
  • To copy the current buffer’s file, run: M-x bufferfile-copy

Customizations

How to make Dired use bufferfile to rename files

By default, Dired’s rename operation (R) updates the file on disk but may not correctly update any buffers visiting the file, especially for renamed files with indirect (clone) buffers.

To address this, you can override Dired’s rename keybinding (R) to use bufferfile-dired-do-rename, which uses bufferfile rename functions. This ensures that all associated buffers, including indirect ones, are properly updated after the rename operation:

;; Override Dired's rename behavior to use bufferfile rename functions,
;; ensuring buffers visiting the renamed file are updated accordingly.
(with-eval-after-load 'dired
  (define-key dired-mode-map (kbd "R") #'bufferfile-dired-do-rename))Code language: PHP (php)

Making bufferfile use version control (VC), such as Git, when renaming or deleting files?

To make bufferfile use version control (VC) when renaming or deleting files, you can set the variable bufferfile-use-vc to t. This ensures that file operations within bufferfile interact with the version control system, preserving history and tracking changes properly.

(setq bufferfile-use-vc t)Code language: PHP (php)

Hook functions

The bufferfile package provides customizable hook variables that allow users to execute functions before and after renaming or deleting files. These hooks can be used to integrate additional logic, such as logging, or updating dependent buffers.

Hooks for Renaming Files

  • bufferfile-pre-rename-functions
    A list of functions executed before renaming a file.
    Each function receives three arguments:
  • previous-path: The original file path.
  • new-path: The new file path.
  • list-buffers: The list of buffers associated with the file.
  • bufferfile-post-rename-functions
    A list of functions executed after a file has been renamed.
    Each function receives the same three arguments as bufferfile-pre-rename-functions.

Hooks for Deleting Files

  • bufferfile-pre-delete-functions
    A list of functions executed before a file is deleted.
    Each function receives two arguments:
  • path: The file path to be deleted.
  • list-buffers: The list of buffers associated with the file.
  • bufferfile-post-delete-functions
    A list of functions executed after a file has been deleted.
    Each function receives the same two arguments as bufferfile-pre-delete-functions.

Frequently asked questions

What is the difference between bufferfile and the built-in Emacs rename and delete functions?

Here are the limitations of Emacs’ built-in functions:

  • Renaming: Indirect buffers point to the correct file path, but their buffer names become outdated.
  • Deleting: Indirect buffers are not removed when the base buffer or another indirect buffer is deleted.

The bufferfile package addresses these issues by ensuring that buffer names are updated when renaming a file and that all buffers, including indirect buffers, are deleted when a file is removed.

These limitations of the built-in functions motivated the development of bufferfile, which improves support for renaming and deleting buffers, including indirect buffers.

Author and License

The bufferfile Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2024-2025 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Testimonials

  • tinkerorb: I can’t even remember for how long I have wanted something that solves this (but I also have not lifted a single finger of my own to solve it for myself). Thank you for this package!

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

Emacs: persist-text-scale.el – Persist and Restore the Text Scale for All Buffers

The persist-text-scale Emacs package provides persist-text-scale-mode, which ensures that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions. As a result, the text size in each buffer remains consistent, even after restarting Emacs.

This package also facilitates grouping buffers into categories, allowing buffers within the same category to share a consistent text scale. This ensures uniform font sizes when adjusting text scaling. By default:

  • Each file-visiting buffer has its own independent text scale.
  • Special buffers, identified by their buffer names, each retain their own text scale setting.
  • All Dired buffers maintain the same font size, treating Dired as a unified “file explorer” where the text scale remains consistent across different buffers.

This category-based behavior can be further customized by assigning a function to the persist-text-scale-buffer-category-function variable. The function determines how buffers are categorized by returning a category identifier (string) based on the buffer’s context. Buffers within the same category will share the same text scale.

If this enhances your workflow, please show your support by ⭐ starring persist-text-scale on GitHub to help more Emacs users discover its benefits.

Features

  • Lightweight and efficient, requiring minimal configuration.
  • Automatically saves and restores the text scale for all buffer types, including file, indirect, dired, and special buffers.
  • Periodically saves text scale data at intervals defined by persist-text-scale-autosave-interval, which can be set to nil to disable or specified in seconds to enable.
  • Provides unified text scaling across buffer categories, with fully customizable logic for categorizing buffers based on text scale. Users can customize categorization by specifying a function for the persist-text-scale-buffer-category-function variable, ensuring that groups of buffers maintain consistent text scale persistence and restoration.
  • The user can define the maximum number of retained entries using persist-text-scale-history-length.

Installation

Emacs

To install persist-text-scale from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.
  2. Add the following code to your Emacs init file to install persist-text-scale from MELPA:
(use-package persist-text-scale
  :ensure t
  :custom
  ;; Time interval, in seconds, between automatic saves of text scale data.
  ;; If set to an integer value, enables periodic autosaving of persisted text
  ;; scale information at the specified interval.
  ;; If set to nil, disables timer-based autosaving entirely.
  (persist-text-scale-autosave-interval (* 7 60))
  :config
  (persist-text-scale-mode))Code language: CSS (css)

Alternative: Doom Emacs

Here is how to install persist-text-scale on Doom Emacs:

  1. Add to the ~/.doom.d/packages.el file:
(package! persist-text-scale)
  1. Add to ~/.doom.d/config.el:
;; TODO: Load the mode here
(after! persist-text-scale
  ;; Time interval, in seconds, between automatic saves of text scale data.
  ;; If set to an integer value, enables periodic autosaving of persisted text
  ;; scale information at the specified interval.
  ;; If set to nil, disables timer-based autosaving entirely.
  (setq persist-text-scale-autosave-interval (* 7 60))

  (persist-text-scale-mode))Code language: JavaScript (javascript)
  1. Run the doom sync command:
doom sync

Customizations

persist-text-scale-autosave-interval

  • Type: Integer or nil
  • Default: (* 11 60) seconds (11 minutes)

Defines the time interval, in seconds, between automatic saves of text scale data.

  • Setting an integer enables periodic autosaving at the specified interval.
  • Setting it to nil disables timer-based autosaving entirely.

This ensures that text scale adjustments are preserved automatically without requiring manual saving.

persist-text-scale-history-length

  • Type: Integer or nil
  • Default: 100

Specifies the maximum number of entries to retain. Each entry corresponds to a buffer category (e.g., file-visiting buffers, special buffers).

  • If set to an integer, older entries are deleted once the limit is reached.
  • If set to nil, cleanup is disabled and no entries are removed. (not recommended)

This helps manage memory usage and prevents the data file from growing indefinitely.

persist-text-scale-buffer-category-function

  • Type: Function or nil
  • Default: nil

Allows custom classification of buffers for text scale persistence. When provided, this function overrides the default classification.

Here is an example:

(defun my-persist-text-scale-function ()
    (let ((buffer-name (buffer-name)))
      (cond
       ((string-prefix-p "*Embark Export:" buffer-name)
        "category:embark-export")

       ((string-prefix-p "*sdcv:" buffer-name)
        "category:sdcv"))))

(setq persist-text-scale-buffer-category-function 'my-persist-text-scale-function)Code language: PHP (php)

The function must return one of:

  • A string or symbol representing the buffer category (for grouping purposes),
  • :ignore to exclude the buffer from persistence,
  • nil to defer to the default persist-text-scale classification.

This option provides flexibility in defining how text scale settings are grouped and applied across different types of buffers.

persist-text-scale-restore-once

  • Type: Boolean
  • Default: nil

Controls whether the text scale is restored only once per buffer.

  • When non-nil, the text scale is applied either when the buffer is first loaded or when it is displayed in a window for the first time.
  • Subsequent window changes or re-displays of the buffer do not trigger additional restorations.

If you are unsure, it is recommended to leave this option as nil to allow normal repeated restoration behavior.

persist-text-scale-handle-file-renames

  • Type: Boolean
  • Default: t

Determines whether text scale settings are preserved when a buffer’s underlying file is renamed.

  • When enabled, the buffer association is updated to the new file path, ensuring that the previously configured text scale remains applied.
  • When disabled, renaming a file resets its text scale to the default value.

These options give users control over messaging, restoration frequency, and resilience to file renames, improving both usability and reliability of text scale persistence.

persist-text-scale-fallback-to-previous-scale

  • Type: boolean
  • Default: t

The persist-text-scale-fallback-to-previous-scale option allows persist-text-scale-mode to use the last used text scale when a buffer category does not yet have a defined scale (i.e., the text scale for this category has never been changed).

This is useful if you frequently switch between buffers or modes that have not been explicitly assigned a text scale, maintaining readability without manual adjustment.

persist-text-scale-verbose

  • Type: Boolean
  • Default: nil

When enabled (t), persist-text-scale displays informative messages during text scale restoration. These messages indicate when and how the text scale was restored, which is useful for debugging or monitoring the package’s behavior.

Author and License

The persist-text-scale Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2025 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

Emacs: Toggling symbol highlighting with unique colors for each symbol using built-in functions

Symbol highlighting is a useful feature for quickly identifying occurrences of a symbol in a buffer. For example, when reading an algorithm with nested loops and multiple function calls, the distinct colors for each symbol, variable, or function make it easier to identify where each is used by simply scanning the highlighted symbols. This article presents a function that simplifies toggling the highlight for the symbol at point in Emacs using the built-in hi-lock package, which provides dynamic text highlighting.

(The function provided in this article can serve as a replacement for packages like symbol-overlay or highlight-symbol if your primary goal is simply highlighting symbols. However, if you require advanced features such as jumping between occurrences, I recommend using a more full-featured package.)

The function to toggle symbol highlighting

Here is the function that enables or disables highlighting for the symbol at point:

(require 'hi-lock)  ; Built-in Emacs package

(defun simple-toggle-highlight-symbol-at-point ()
  "Toggle highlighting for the symbol at point."
  (interactive)
  (when-let* ((regexp (find-tag-default-as-symbol-regexp)))
    (if (member regexp (hi-lock--regexps-at-point))
        ;; Unhighlight symbol at point
        (hi-lock-unface-buffer regexp)
      ;; Highlight symbol at point
      (hi-lock-face-symbol-at-point))))Code language: Lisp (lisp)

One advantage of the built-in hi-lock function is that it highlights each symbol with a unique color, making it easier to distinguish between different symbols.

Here is how it works:

  1. Checking if the symbol is already highlighted: The function first retrieves a list of regular expressions corresponding to currently highlighted text in the buffer using hi-lock--regexps-at-point. It then checks whether the symbol at point is among the highlighted expressions using member.
  2. Unhighlighting the symbol: If the symbol is already highlighted, the function calls hi-lock-unface-buffer with the appropriate regular expression, removing the highlighting.
  3. Highlighting the symbol: If the symbol is not currently highlighted, the function invokes hi-lock-face-symbol-at-point, which applies highlighting to the symbol.

Usage

You can configure a key binding, such as C-c h, with the following:

(global-set-key (kbd "C-c h") #'simple-toggle-highlight-symbol-at-point)Code language: Lisp (lisp)

Alternatively, you can use the function interactively by placing the cursor on a symbol and executing:

M-x simple-toggle-highlight-symbol-at-point

(If the symbol is not highlighted, it will be highlighted. If it is already highlighted, the function will remove the highlighting.)

You can also remove a symbol highlight from the entire buffer by selecting it from the list and removing it using:

M-x hi-lock-unface-buffer

Conclusion

The simple-toggle-highlight-symbol-at-point function provides an efficient way to toggle symbol highlighting in Emacs without relying on external packages. It offers a lightweight solution for users who primarily need highlighting functionality. While it does not include advanced navigation features found in third-party packages, it serves as a simple and effective alternative for quick visual identification of symbols in a buffer.

Emacs: Highlighting Codetags Like TODO, FIXME, BUG, NOTE…

Highlighting keywords such as TODO, FIXME, NOTE, BUG, and others (often referred to as tags, codetags, or tokens) enhances workflow by making key annotations more visible. This allows developers to quickly identify tasks, warnings, and notes within the code, reducing the time spent searching for unfinished work or potential issues.

This article outlines an Elisp code that highlights these codetags.

(There are packages like hl-todo and comment-tags that can highlight these codetags for those who need a more feature-rich solution. However, they contain hundreds of lines of code, which is excessive if your only goal is to just highlight codetags. While these packages likely offer additional features, such as navigating to the next codetag, the Elisp code in this article provides a much simpler solution for those who just want to highlight them.)

Elisp code to highlight codetags

To highlight these codetags, you can use the following Emacs Lisp code:

(defvar highlight-codetags-keywords
  '(("\\<\\(TODO\\|FIXME\\|BUG\\|XXX\\)\\>" 1 font-lock-warning-face prepend)
    ("\\<\\(NOTE\\|HACK\\)\\>" 1 font-lock-doc-face prepend)))

(define-minor-mode highlight-codetags-local-mode
  "Highlight codetags like TODO, FIXME..."
  :global nil
  (if highlight-codetags-local-mode
      (font-lock-add-keywords nil highlight-codetags-keywords)
    (font-lock-remove-keywords nil highlight-codetags-keywords))

  ;; Fontify the current buffer
  (when (bound-and-true-p font-lock-mode)
    (if (fboundp 'font-lock-flush)
        (font-lock-flush)
      (with-no-warnings (font-lock-fontify-buffer)))))Code language: Lisp (lisp)

To apply codetag highlighting across all programming modes, add highlight-codetags-local-mode to the prog-mode-hook:

(add-hook 'prog-mode-hook #'highlight-codetags-local-mode)Code language: Lisp (lisp)

If you call highlight-codetags-local-mode interactively, you can toggle the highlighting of codetags on and off.

Customizations

If desired (though not required), you can further customize the Elisp code:

  • You can customize the highlighting by substituting font-lock-warning-face or font-lock-doc-face with any other face of your choice. (You can view all available faces by executing the command: M-x list-faces-display)
  • Additionally, you can add more keywords to the regular expression.
    For instance, to add the MAYBE codetag to the \\<\\(NOTE\\|HACK\\)\\> pattern, simply append \\|MAYBE before the closing parenthesis \\):
    \\<\\(NOTE\\|HACK\\|MAYBE\\)>.

Conslusion

This simple configuration enhances keyword visibility in Emacs, making it easier to track important annotations while editing source code.

Emacs: buffer-terminator.el – Safely Terminate Emacs Buffers Automatically

Build Status MELPA MELPA Stable License

The buffer-terminator Emacs package automatically and safely kills buffers, ensuring a clean and efficient workspace while enhancing the performance of Emacs by reducing open buffers, which minimizes active modes, timers, processes…

Beyond performance, buffer-terminator provides other benefits. For instance, if you occasionally need to close annoying or unused buffers, buffer-terminator can handle this automatically, eliminating the need for manual intervention. (The default configuration is suitable for most users. However, the buffer-terminator package is highly customizable. You can define specific rules for retaining or terminating buffers by modifying the buffer-terminator-rules-alist with your preferred set of rules.)

Activating (buffer-terminator-mode) safely terminates all buffers that have been inactive for longer than the duration specified by buffer-terminator-inactivity-timeout (default: 30 minutes). It checks every buffer-terminator-interval (default: 10 minutes) to determine if a buffer should be terminated.

The following buffers are not terminated by default:

  • Special buffers (These buffers are non-file buffers that: start with a space, or start and end with *, or whose major mode is derived from special-mode, or they serve as the Minibuffer).
  • Modified file-visiting buffers that have not been saved; the user must save them first.
  • Buffers currently displayed in any visible window or tab-bar tab. (This also includes buffers indirectly made visible, such as org-src source edit buffers, which cause their originating buffers to be considered visible, or markdown-mode edit-indirect buffers that reference the original Markdown file.)
  • Buffers associated with running processes.

If this package enhances your productivity, please show your support by ⭐ starring buffer-terminator on GitHub to help more users discover its benefits.

Table of Contents

Installation from MELPA

To install buffer-terminator from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.
  2. Add the following code to the Emacs init file:
    
    (use-package buffer-terminator
    :ensure t
    :custom
    (buffer-terminator-verbose nil)

;; Set the inactivity timeout (in seconds) after which buffers are considered ;; inactive (default is 30 minutes): (buffer-terminator-inactivity-timeout (* 30 60)) ; 30 minutes

;; Define how frequently the cleanup process should run (default is every 10 ;; minutes): (buffer-terminator-interval (* 10 60)) ; 10 minutes

:config (buffer-terminator-mode 1))


## Configuration

### Verbose Mode

Enable verbose mode to log buffer cleanup events:

```elisp
(setq buffer-terminator-verbose t)

Timeout for Inactivity

Set the inactivity timeout (in seconds) after which buffers are considered inactive (default is 30 minutes):

(setq buffer-terminator-inactivity-timeout (* 30 60)) ; 30 minutes

Cleanup Interval

Define how frequently the cleanup process should run (default is every 10 minutes):

(customize-set-variable 'buffer-terminator-interval (* 10 60)) ; 10 minutes

(Using customize-set-variable allows buffer-terminator-interval to update the timer dynamically, without the need to restart buffer-terminator-mode.)

Rules

By default, buffer-terminator automatically determines which buffers are safe to terminate.

However, if you need to define specific rules for keeping or terminating certain buffers, you can configure them using buffer-terminator-rules-alist.

The buffer-terminator-rules-alist variable holds instructions for keeping or terminating buffers based on their names or regular expressions. Each rule is a cons cell where the key is a symbol indicating the rule type, and the value is either string or a list of strings.

Here is an example:

(setq buffer-terminator-rules-alist
      ;; kill-buffer-name: Always kill buffers whose names match important-buffer-name1 and important-buffer-name2
      '((kill-buffer-name . ("temporary-buffer-name1"
                             "temporary-buffer-name2"))

        ;; keep-buffer-name: Always keep buffers whose names match important-buffer-name1 and important-buffer-name2
        (keep-buffer-name . ("important-buffer-name1"
                             "important-buffer-name2"))

        ;; kill-buffer-name: Always kill buffers whose names match temporary-buffer-name3
        (kill-buffer-name . "temporary-buffer-name3")

        ;; keep-buffer-name-regexp: Always keep buffers matching a regular expression
        (keep-buffer-name-regexp . ("\\` \\*Minibuf-[0-9]+\\*\\'"))

        ;; kill-buffer-name-regexp: Always kill buffers matching a regular expression
        (kill-buffer-name-regexp . "compile-angel")

        ;; Retain special buffers (DO NOT REMOVE).
        ;;
        ;; (If you choose to kill special buffers by removing the following,
        ;; ensure that the special buffers you want to keep are added
        ;; keep-buffer-name or keep-buffer-name-regexp rules above.)
        ;;
        ;; DO NOT REMOVE special buffers unless you know of what you are doing.
        (keep-buffer-property . special)

        ;; Retain process buffers.
        ;;
        ;; (Process buffers are buffers where an active process is running.
        ;; Removing the following will result in the termination of such
        ;; buffers, potentially disrupting active processes like vterm.)
        (keep-buffer-property . process)

        ;; Retain visible buffers (DO NOT REMOVE).
        ;;
        ;; Visible buffer are those currently displayed in any window.
        ;; It is generally discouraged to set this to nil, as doing so may result
        ;; in the termination of visible buffers, except for the currently active
        ;; buffer in the selected window.
        ;;
        ;; DO NOT REMOVE visible buffers unless necessary.
        (keep-buffer-property . visible)

        ;; Kill inactive buffers.
        ;; (This can be customized with `buffer-terminator-inactivity-timeout'
        ;; and `buffer-terminator-interval'.)
        (kill-buffer-property . inactive)

        ;; Call a function that decides the fate of a buffer. It returns:
        ;;   :kill    Indicates that the buffer should be killed.
        ;;   :keep    Indicates that the buffer should be kept.
        ;;   nil      Leave decision to the next rule specified
        ;;            in `buffer-terminator-rules-alist`.
        ;; (call-function . function-name)

        ;; Keep the remaining buffers that were not retained by previous rules
        (return . :keep)))

Here is another example by gavv, one of the first buffer-terminator users.

Frequently asked questions

What problem is buffer-terminator aiming to solve?

  • Some users prefer terminating inactive buffers to improve Emacs’ performance by reducing the number of open buffers. This, in turn, decreases the load from active modes, timers, and other processes associated with those buffers. Buffer-local modes and their timers consume both CPU and memory. Why keep them alive when they can be safely removed?
  • Some users prefer to keep only the buffers they actively need open, helping to declutter the buffer list. Decluttering the buffer list can also improve the performance of other packages. For example, saving and loading an easysession or desktop.el is much faster when the buffer list is reduced.
  • Some users prefer that buffers not part of an active window be automatically closed, as they are not actively needed.
  • Buffer-terminator helps users by automatically closing unnecessary buffers, eliminating the need for manual cleanup.
  • Some Emacs packages continue interacting with open buffers, even when they are buried (Reddit post: A function to periodically wipe buffers not recently shown; thoughts?).

How about modifying the quit-window function to kill buffers as soon as they are closed, instead of using buffer-terminator?

Using quit-window works if the goal is to immediately kill buffers upon closing a window, but it can lead to unintended consequences.

For instance, if a buffer is displayed in another tab or window, it will still be closed simply because one window showing it was closed. Additionally, killing buffers immediately is not always desirable. Delaying the closure preserves the state of file buffers and Dired buffers, including opened or closed headings, folds, and other buffer-specific context.

Buffer Terminator addresses these issues by performing additional checks before killing a buffer. By default, it verifies whether the buffer is visible in any other window or tab-bar tab, ensuring that buffers are only closed when truly no longer needed. Moreover, buffer-terminator does not terminate buffers immediately; a configurable delay is applied to provide a grace period, allowing users to continue working with a buffer if it is still required.

If this actually improves performance, I’d love to see some benchmarks or real-world numbers

Because each Emacs user’s configuration is unique, the performance benefits of using the buffer-terminator Emacs package depend on the number of enabled modes and active timers in that specific setup.

Leaving buffers open keeps their associated timers active, and the number of timers grows with the number of Emacs packages in use. Timers are responsible for scheduling functions to run at specific intervals or after a delay, often managing background tasks like updating buffers, fetching data, or performing periodic checks. Since each active timer triggers a function, an excessive number of timers can increase CPU usage, potentially leading to performance degradation in Emacs’ single-threaded environment.

Additionally, using buffer-terminator to reduce the buffer list can improve the performance of packages that iterate over the buffer-list function to operate on buffers. Since these packages iterate over open buffers, a shorter buffer list allows for faster execution of their operations. (For example, the built-in desktop.el package or the easysession package, which save and restore open buffers/frames, can be affected by buffer list length. If buffer-list is too long, Emacs startup may slow down, as it needs to restore a larger set of buffers.)

I prefer keeping buffers open because it is easier for me to reopen them

There is little benefit in leaving unused buffers open on the off-chance they might be needed later. If needed again, these buffers can be quickly reopened using recentf, project.el, dired, or similar tools.

How is this different from the builtin midnight-mode?

Midnight-mode does not address the problem that buffer-terminator solves, which is the safe and frequent termination of inactive buffers.

Midnight mode and clean-buffer-list are for killing buffers once a day. The Midnight option clean-buffer-list-delay-general specifies the number of days before a buffer becomes eligible for auto-killing, rather than using seconds or minutes as a timeout.

In contrast, buffer-terminator allows specifying the timeout interval in seconds (Default: 30 minutes), enabling more frequent termination of inactive buffers.

The buffer-terminator package offers additional features that are not supported by midnight and clean-buffer-list, including:

  • The buffer-terminator package is more customizable than Midnight Mode. It allows users to specify a customized list of rules using buffer-terminator-rules-alist, enabling them to determine which buffers should be killed based on factors such as inactivity, visibility, buffer name, whether it’s a file or process buffer, and other conditions.
  • Buffer-terminator does not kill visible buffers in other tabs, even if they exceed the timeout. This prevents disruptions to editing workflows. Buffer-terminator provides the option to choose whether to keep or kill specific types of buffers, such as those associated with processes or file-visiting buffers.
  • Buffer-terminator avoids relying on buffer-display-time, which is not always updated reliably. For instance, buffer-display-time may not reflect activity when switching to a window or tab displaying a specific buffer.
  • Buffer-terminator does not kill special buffers by default, whereas Midnight kills all special buffers by default unless the user tells Midnight to ignore them. Midnight’s behavior can disrupt packages like Corfu, Cape, Consult, Eglot, Flymake, and others that rely on special buffers to store data.
  • Buffer-terminator can also kill specific special buffers. It is useful, for example, if the user want to keep special buffers, but with a few exceptions: The user still want to kill Help and helpful … buffers (and maybe some other buffers related to documentation) if they weren’t used for a while.

Testimonials from users

  • ouboub: “I just did, thanks for nice package, wish I have known about it earlier…”

Author and License

The buffer-terminator Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2024-2025 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

The compile-angel Emacs package: Byte-compile and Native-compile Emacs Lisp libraries Automatically

Build Status MELPA MELPA Stable License

The compile-angel package speeds up Emacs by ensuring that all Elisp libraries are both byte-compiled and native-compiled:

  • Byte compilation reduces the overhead of loading Emacs Lisp code at runtime.
  • Native compilation improves performance by generating machine code that runs directly on the hardware, leveraging the full capabilities of the host CPU. The actual speedup varies with the characteristics of the Lisp code, but it is typically 2.5 to 5 times faster than the equivalent byte-compiled version.

This package offers:

  • (compile-angel-on-load-mode): A global mode that compiles .el files both before they are loaded via load or require, and after they are loaded, using after-load-functions.
  • (compile-angel-on-save-local-mode): A local mode that compiles .el files whenever the user saves them.

If this package enhances your workflow, please show your support by ⭐ starring compile-angel on GitHub to help more users discover its benefits.

Table of Contents

Why use compile-angel?

Because you are likely running a significant amount of interpreted, slow Elisp code that Emacs did not compile automatically. Ensuring that Elisp is native-compiled significantly improves Emacs’ performance. Unfortunately, functions like package-install and package-recompile-all do not compile .el files that were not installed using package.el. Since these files are not byte-compiled, the Emacs JIT compiler does not native-compile them either, as a byte-compiled file signals the JIT compiler to perform native compilation. In contrast, compile-angel modes ensure that all loaded .el files are compiled transparently, regardless of whether they are part of a package.

Before installing

It is highly recommended to set the following variables at the very beginning of your early-init.el:

;; Ensure Emacs loads the most recent byte-compiled files.
(setq load-prefer-newer t)

;; Make Emacs Native-compile .elc files asynchronously by setting
;; `native-comp-jit-compilation' to t.
(setq native-comp-jit-compilation t)
(setq native-comp-deferred-compilation native-comp-jit-compilation)  ; Deprecated

Additionally, ensure that native compilation is enabled: This should return t:

(native-comp-available-p)

Installation of compile-angel

Emacs

To install compile-angel on Emacs from MELPA:

  1. If you haven’t already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code at the very beginning of your init.el file, before all other packages:

    
    (use-package compile-angel
    :ensure t
    :demand t
    :config
    ;; Set `compile-angel-verbose' to nil to disable compile-angel messages.
    ;; (When set to nil, compile-angel won't show which file is being compiled.)
    (setq compile-angel-verbose t)

;; Uncomment the line below to compile automatically when an Elisp file is saved ;; (add-hook ’emacs-lisp-mode-hook #’compile-angel-on-save-local-mode)

;; The following directive prevents compile-angel from compiling your init ;; files. If you choose to remove this push to compile-angel-excluded-files' ;; and compile your pre/post-init files, ensure you understand the ;; implications and thoroughly test your code. For example, if you're using ;; theuse-package’ macro, you’ll need to explicitly add: ;; (eval-when-compile (require ‘use-package)) ;; at the top of your init file. (push “/init.el” compile-angel-excluded-files) (push “/early-init.el” compile-angel-excluded-files)

;; A global mode that compiles .el files before they are loaded ;; using load' orrequire’. (compile-angel-on-load-mode 1))


### Doom Emacs

Here is how to install *compile-angel* on Doom Emacs:

1. Add to the `~/.doom.d/packages.el` file:
```elisp
(package! compile-angel)
  1. Add to the top of ~/.doom.d/config.el:
    
    ;; Set `compile-angel-verbose' to nil to disable compile-angel messages.
    ;; (When set to nil, compile-angel won't show which file is being compiled.)
    (setq compile-angel-verbose t)

;; Uncomment the line below to compile automatically when an Elisp file is saved ;; (add-hook ’emacs-lisp-mode-hook #’compile-angel-on-save-local-mode)

;; A global mode that compiles .el files before they are loaded ;; using load' orrequire’. (compile-angel-on-load-mode)


3. Run the `doom sync` command:

doom sync


## Frequently Asked Questions

### Should files be compiled every time Emacs starts? How can I determine why compile-angel compiled a file?

The `compile-angel-on-load-mode` does not recompile packages every time Emacs starts; it only compiles a file when its `.el` source has changed.

To determine why an Emacs Lisp file was compiled, add the following to your init file **before** enabling `compile-angel-on-load-mode`:

```elisp
(setq compile-angel-debug t)

Then restart Emacs and switch to the *compile-angel:debug* buffer. If compile-angel triggered the compilation, the buffer will indicate the reason. If you believe a file was compiled incorrectly, please consider submitting an issue including the relevant lines from the *compile-angel:debug* buffer.

What are some interesting Emacs customizations to consider alongside compile-angel?

Below are a few interesting options:

;; Ensure that quitting only occurs once Emacs finishes native compiling,
;; preventing incomplete or leftover compilation files in `/tmp`.
(setq native-comp-async-query-on-exit t)
(setq confirm-kill-processes t)

;; Non-nil means to native compile packages as part of their installation.
(setq package-native-compile t)

;; -------------------------------------------------
;; Show buffer when there is a warning.
;; (NOT RECOMMENDED, except during development).
;; -------------------------------------------------
;; (setq compile-angel-verbose t)
;; (setq compile-angel-byte-compile-report-issues t)
;;
;; (setq warning-minimum-level :warning)
;; (setq byte-compile-verbose t)
;; (setq byte-compile-warnings t)
;; (setq native-comp-async-report-warnings-errors t)
;; (setq native-comp-warning-on-missing-source t)

How to exclude certain .el files from compilation in compile-angel?

You can exclude .el files from compilation by adding path suffixes to the compile-angel-excluded-files list.

For instance, the following excludes any path that ends with suffix.el (or its variations, such as /path/ANYTHINGsuffix.el.gz or ANYTHINGsuffix.el.gz) and exactly matches paths that end with /filename.el (including their variations, like /filename.el.gz or ANYTHING/filename.el.gz).

;; Run the following before enabling `compile-angel-on-load-mode'
(push "suffix.el" compile-angel-excluded-files)
(push "/filename.el" compile-angel-excluded-files)

;; Run here: (compile-angel-on-load-mode)

If a path suffix in compile-angel-excluded-files ends with .el, compile-angel will automatically exclude the .el.gz variant of that file. For instance, specifying suffix.el will also exclude suffix.el.gz.

How to exclude custom-file, recentf, savehist files?

You can exclude the custom-file, recentf, and savehist files using the following code snippet:

;; Exclude the custom-file, recentf, and savehist files
;;
;; Ensure that compile-angel is loaded using `require`, `use-package`, or
;; another package manager, as compile-angel-excluded-files is declared after
;; the package is loaded.

;; Ensure that the value of `savehist-file` is updated before proceeding
(with-eval-after-load "savehist"
  (push (concat "/" (file-name-nondirectory savehist-file))
        compile-angel-excluded-files))

;; Ensure that the value of `recentf-save-file` is updated before proceeding
(with-eval-after-load "recentf"
  (push (concat "/" (file-name-nondirectory recentf-save-file))
        compile-angel-excluded-files))

;; Ensure that the value of `custom-file` is updated before proceeding
(with-eval-after-load "cus-edit"
  (when (stringp custom-file)
    (push (concat "/" (file-name-nondirectory custom-file))
          compile-angel-excluded-files)))

;; Enable the (compile-angel-on-load-mode) mode after the above

How to enable or disable byte compilation and native compilation?

You can control whether compile-angel performs byte compilation or native compilation of your .el files by setting the following variables in your configuration:

  • compile-angel-enable-byte-compile: Set this variable to t to enable byte compilation. When enabled, compile-angel will generate .elc files for your .el files, making them load faster by converting them into bytecode. Set it to nil to disable byte compilation.
  • compile-angel-enable-native-compile: Set this variable to t to enable native compilation, which generates machine code for supported systems, further improving performance. Set it to nil to disable native compilation.

Example configuration:

;; Enable both byte compilation and native compilation (default)
(setq compile-angel-enable-byte-compile t)
(setq compile-angel-enable-native-compile t)

What’s the point of using compile-angel? My Emacs compiles packages automatically anyway!

Emacs often skips the compilation of certain Elisp files. To verify this:

  • Install compile-angel,
  • Enable verbose mode: (setq compile-angel-verbose t)
  • Enable the mode: (compile-angel-on-load-mode)

Observe whether compile-angel compiles any Elisp files (you will see “Wrote” .elc files in the *Messages* buffer). If it does, this indicates that Emacs missed compiling those files and that compile-angel can help improve the performance of your Emacs.

Could compiling all Elisp files not be accomplished with a script? (e.g., a GNU Parallel along with Emacs’s -batch mode.)

Compiling a large number of Emacs Lisp files regardless of their actual usage is inefficient.

One of the advantages of compile-angel is that it compiles files just before they are loaded, restricting the compilation process to only what is necessary and as a result significantly reducing compilation time.

Moreover, compile-angel guarantees that all relevant files are transparently both byte-compiled and native-compiled without requiring the user to invoke any scripts manually, which simplifies maintenance and reduces the risk of outdated files.

(If you are interested in compiling all Emacs Lisp files regardless of their actual usage, the author recommends trying elispcomp, which performs precisely that task. However, compile-angel offers greater efficiency.)

Why not just use the package-recompile-all function?

The package-recompile-all function is effective for recompiling files within packages, but it misses other files that are not part of a package.

In the compile-angel author’s configuration, for example, package-recompile-all skipped most of the local packages loaded using use-package with :ensure nil or require. Additionally, package-recompile-all does not compile transparently; the user must manually run it and wait for it to complete.

The compile-angel package, on the other hand, transparently compiles all packages without any user intervention. The user simply needs to enable (compile-angel-on-load-mode).

What is the impact on Emacs startup?

Compile-angel is optimized. It is fast enough that it is nearly imperceptible to the user. The author of compile-angel reports an Emacs startup time of 0.25 seconds with compile-angel enabled and 0.23 seconds without it. Feel free to share your own benchmarks.

What’s the difference between native and byte compiled?

Byte compilation translates Elisp code into an intermediate bytecode .elc that is faster to load than .el files.

Native compilation goes a step further by converting this bytecode into machine code, which is directly executed by the CPU without the need for an interpreter. Native compilation significantly improves performance.

What are some use-cases of compile-angel?

Emacs often misses the compilation of certain Elisp files.

One of the author’s primary use cases involves maintaining numerous Emacs packages, which are synchronized into ~/.emacs.d using automation scripts and rsync for testing during development. The author appreciates how compile-angel automatically compiles the files synchronized to the ~/.emacs.d directory while working on these packages.

There are many other use cases as well. For example, some Emacs users prefer storing packages locally or in GitHub repositories, periodically updating them using git pull. This approach is often adopted for packages that are no longer actively maintained, enabling users to manage them independently. In such cases, compile-angel can seamlessly handle both byte-compiling and native-compiling these packages whenever local modifications are made.

What is the difference between auto-compile and compile-angel?

Compile-angel offers more features and is more optimized than auto-compile (see details below).

The compile-angel author was previously an auto-compile user but encountered an issue where several Elisp files were not being compiled by auto-compile (see the explanation below), resulting in Emacs performance degradation due to the lack of native compilation.

The author of auto-compile has made some decisions that prevent it from guaranteeing that all .el packages are byte-compiled and native-compiled. For example, if the user deletes all the .elc files or if the .el files have never been compiled before, auto-compile won’t recompile them. Here is a quote from Jonas Bernouli, aka u/tarsius_, the auto-compile author (from this discussion):

Both [autocompile] modes only ever re-compile a source file when the respective byte code file already exists but is outdated. Otherwise they do not compile the source file. By “otherwise” I mean if:

  • The .elc exists but is newer than the corresponding .el, OR
  • The *.elc does not exist. In both cases the source file is not compiled, by design.

Here are additional features provided by compile-angel that are not available in auto-compile:

  • Compile-angel ensures that even when when the .elc file doesn’t exist, the .el source file is compiled. Auto-compile, on the other hand, requires (by design, as explained above) an existing .elc file in order to compile.
  • Compile-angel ensures that files are compiled before and after they are loaded, In addition to compiling the .el files loaded using load and require, also handles files that auto-compile misses, using the after-load-functions hook. This ensures that all files are byte-compiled and native-compiled.
  • Compile-angel can exclude files from compilation using regular expressions in compile-angel-excluded-files-regexps.
  • compile-angel can exclude files from compilation based on path suffixes listed in compile-angel-excluded-files. This list contains path suffixes such as ("loaddefs.el" "/cus-load.el" "/charprop.el"), which excludes any path ending with loaddefs.el (or its variations, such as loaddefs.el.gz) and exactly matches paths ending with /cus-load.el and /charprop.el (including their variations, like /cus-load.el.gz and /charprop.el.gz). If a path in compile-angel-excluded-files ends with .el, it will automatically exclude the corresponding .el.gz variant when Emacs is configured to load .el.gz files.
  • Compile-angel provides options to allow enabling and disabling specific functions that should be advised (load, require, etc.).
  • Compile-angel allows enabling debug mode, which allows knowing exactly what compile-angel does. Additionally, compiled files and features are stored in variables that help identify what was compiled.
  • compile-angel-on-save-mode supports compiling indirect buffers (clones).
  • compile-angel-on-load-mode compiles features that have already been loaded to make sure that they are compiled.
  • Compile-Angel can use caching to enhance performance when locating the .el file corresponding to a given feature. Auto-compile does not compile features.
  • Supports both Vanilla Emacs and Doom Emacs. For Doom Emacs, compile-angel ensures that the Doom Emacs user directory, Emacs directory, and modules directory are excluded from compilation. This is essential because .el files in these directories must not be compiled, or Doom may fail to load them correctly.
  • compile-angel-on-load-mode performs native compilation only when Emacs fails to do so. Explanation: When JIT compilation is enabled, loading a .elc file automatically triggers native compilation, making Emacs load the native-compiled version asynchronously and replacing the auto-compiled functions. (However, auto-compile disables native compilation by default, causing Emacs to skip native-compiling some files, even in save mode. When enabled, auto-compile compiles files before loading, but Emacs will still recompile them after loading the .elc file.)
  • Compile-Angel checks for unbalanced parentheses before compiling a file in save mode, without altering the cursor position, making it less intrusive than the default check-parens used by auto-compile.
  • Compile-Angel double-checks after packages are loaded to ensure that Emacs properly performs native compilation when JIT is enabled, as Emacs sometimes skips native-compiling .elc files that should be JIT compiled.
  • Prevent byte-compile-file from displaying Wrote messages in the Messages buffer unless compile-angel-verbose customization is set to t.
  • It has the ability to skip compiling features provided by Emacs core without associated Elisp files (e.g., pgtk, w32, lcms2, kqueue, emacs, mps, etc.). This includes features provided directly by C code as well as features provided by core Elisp that don’t have their own .el files. These features are excluded from compilation attempts since they have no source files to compile.

Comments from users

Author and License

The compile-angel Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2024-2025 James Cherti

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program.

Links

Other Emacs packages by the same author:

  • minimal-emacs.d: This repository hosts a minimal Emacs configuration designed to serve as a foundation for your vanilla Emacs setup and provide a solid base for an enhanced Emacs experience.
  • compile-angel.el: Speed up Emacs! This package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.
  • outline-indent.el: An Emacs package that provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.
  • vim-tab-bar.el: Make the Emacs tab-bar Look Like Vim’s Tab Bar.
  • easysession.el: Easysession is lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • elispcomp: A command line tool that allows compiling Elisp code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files.
  • tomorrow-night-deepblue-theme.el: The Tomorrow Night Deepblue Emacs theme is a beautiful deep blue variant of the Tomorrow Night theme, which is renowned for its elegant color palette that is pleasing to the eyes. It features a deep blue background color that creates a calming atmosphere. The theme is also a great choice for those who miss the blue themes that were trendy a few years ago.
  • Ultyas: A command-line tool designed to simplify the process of converting code snippets from UltiSnips to YASnippet format.
  • dir-config.el: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • flymake-bashate.el: A package that provides a Flymake backend for the bashate Bash script style checker.
  • flymake-ansible-lint.el: An Emacs package that offers a Flymake backend for ansible-lint.
  • inhibit-mouse.el: A package that disables mouse input in Emacs, offering a simpler and faster alternative to the disable-mouse package.
  • quick-sdcv.el: This package enables Emacs to function as an offline dictionary by using the sdcv command-line tool directly within Emacs.
  • enhanced-evil-paredit.el: An Emacs package that prevents parenthesis imbalance when using evil-mode with paredit. It intercepts evil-mode commands such as delete, change, and paste, blocking their execution if they would break the parenthetical structure.
  • stripspace.el: Ensure Emacs Automatically removes trailing whitespace before saving a buffer, with an option to preserve the cursor column.
  • persist-text-scale.el: Ensure that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions.
  • pathaction.el: Execute the pathaction command-line tool from Emacs. The pathaction command-line tool enables the execution of specific commands on targeted files or directories. Its key advantage lies in its flexibility, allowing users to handle various types of files simply by passing the file or directory as an argument to the pathaction tool. The tool uses a .pathaction.yaml rule-set file to determine which command to execute. Additionally, Jinja2 templating can be employed in the rule-set file to further customize the commands.

Essential Emacs Packages for Efficient Software Development and Text Editing

In the pursuit of an optimized Emacs setup, I focused on enhancing defaults and minimizing the number of installed packages to maintain simplicity and efficiency:

  • The initial step involved creating minimal-emacs.d, a project that has resonated with the Emacs community, providing a foundational template for many users’ init.el and early-init.el vanilla Emacs configuration.
  • Next, I experimented with hundreds of Emacs packages, carefully selecting the most valuable ones that, ideally, leverage built-in Emacs functions. (This is why I chose corfu over company, eglot over lsp-mode, and flymake over flycheck, etc.)

In this article, I will share the Emacs packages I use daily for software development and general text editing. Please share in the comments the Emacs packages you are using!

Where can I find the third-party packages listed below?

The following Emacs packages installed whether from MELPA or ELPA.

Category: Code completion

  • corfu: A completion framework that integrates with the built-in completion system in Emacs. For example, it can complete Python code when using the eglot package and a Python language server such as Pylsp.
  • prescient: Provides smart completion suggestions based on history and context. For example, it can enable fuzzy completion with Corfu/Cape or anticipate your next input based on previous selections.
  • cape: A completion-at-point extension for various completion frameworks in Emacs, enhancing Corfu.
  • nerd-icons-corfu: Integrates Nerd Icons with the Corfu completion framework, enhancing the appearance of completion candidates.

Category: Better minibuffer

  • vertico: minimalistic vertical completion UI. (EDIT: There is also built-in alternative to vertico: fido-vertical-mode, but the author prefers vertico because it provides more features.)
  • marginalia: Enhances the display of completion candidates in the minibuffer.
  • embark: Enhances minibuffer completion and interaction with various Emacs commands and actions.
  • consult: Provides intelligent search and navigation commands, powered by the Emacs completion function, completing-read.

Category: Software development (General)

  • apheleia: A package that runs code formatters asynchronously without moving the cursor. Apheleia supports formatting many languages. It formats code after saving, applying changes only if the buffer is unmodified, preventing latency and cursor jumps.
  • yasnippet and yasnippet-snippets: A template system for Emacs that allows for easy insertion of code snippets, improving coding efficiency. (The author is also using ultyas to share the same code snippets in Emacs and Vim)
  • outline-indent: Enables code folding based on indentation levels. This package is useful for editing indentation-based text files, such as YAML, Python, and other indented text files.
  • indent-bars: Provides indentation guide-bars.
  • dtrt-indent: Automatically adjusts indentation based on the surrounding context in code files, improving code readability.
  • stripspace: Ensures that Emacs removes trailing whitespace before saving a buffer. Ensure that the column is restored.
  • eglot (built-in): An LSP client that provides features like code completion, diagnostics, formatting, and more, powered by language servers. For example, it can be used to add Python code completion using the language server Pylsp. There are many language servers available for many other programming languages.
  • flymake (built-in): An on-the-fly syntax checking system that works well with eglot.
  • paren (built-in): Matching parenthesis highlighting. (Modes: show-paren-mode or show-paren-local-mode).
  • treesit (built-in): This package provides a way to work with tree-sitter, a syntax code parser that performs syntax highlighting, code navigation, and structural editing across various programming languages.
  • highlight-symbol: Highlight occurrences of symbols in your code. (The author is now using built-in functions to toggle symbol highlighting in Emacs )

Category: Session management / persist and restore

  • easysession: A lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • saveplace (built-in): Persist and restore your current cursor position.
  • savehist (built-in): Persist and restore your Emacs command history.
  • persist-text-scale: Provides persist-text-scale-mode, which ensures that all adjustments made with text-scale-increase and text-scale-decrease are persisted and restored across sessions. As a result, the text size in each buffer remains consistent, even after restarting Emacs.

Category: Themes

  • ef-themes: A collection of light and dark themes for GNU Emacs whose goal is to provide colorful themes.
  • modus-themes: Highly accessible themes for GNU Emacs, conforming with the highest standard for color contrast between background and foreground values.
  • doom-themes: An megapack of popular themes, including aesthetic extensions for popular packages (e.g., Tomorrow Night/Day, Solarized, Gruvbox…).
  • tomorrow-night-deepblue-theme: A blue color theme for Emacs inspired by the Tomorrow Night color scheme.

Category: Vim emulation

  • evil: An extensible vi layer for Emacs, providing a modal editing experience similar to Vim.
  • evil-collection: A collection of Emacs packages that integrate with Evil mode to provide consistent keybindings across multiple modes.
  • evil-surround: Enhances text object handling in Evil mode, allowing for easier manipulation of surrounding characters.
  • evil-matchit: An evil-mode package that allows jumping between matching text objects, such as HTML tags, if/then/else blocks, or parentheses. It improves code navigation and editing efficiency by enabling quick movement across related elements in various programming and markup modes.
  • vim-tab-bar: Provides a tab-bar interface reminiscent of Vim.
  • evil-snipe: Provides enhanced search and jump functionality for Evil mode. (EDIT: The author replaced this package with the avy package)
  • vdiff: Provides a visual interface for comparing two versions of a file that is similar to the Vim editor. (EDIT: The author is now uses the built-in ediff package)

Category: Terminal Emulators

  • vterm: A terminal emulator for Emacs, written in C.
  • eat: A terminal emulator, written in Elisp.

Category: Undo/Redo

  • undo-fu: An advanced undo/redo system that enhances the default undo behavior in Emacs.
  • undo-fu-session: Integrates with undo-fu to provide session management for undo history.

Category: Elisp

  • aggressive-indent: Automatically keeps your code indented as you type. The author mainly uses this package with Elisp.
  • compile-angel: Speed up Emacs by ensuring all libraries are byte-compiled and native-compiled. Byte-compilation reduces the overhead of loading Emacs Lisp code at runtime, while native compilation optimizes performance by generating machine code specific to your system.
  • Paredit: A minor mode that enforces balanced parentheses while editing Lisp code. (In addition to Paredit, the author uses enhanced-evil-paredit.)

Category: File Manager

  • dired (built-in): File manager. (EDIT: The author is also using the built-in modes dired-hide-details-mode and dired-omit-mode.)
  • nerd-icons-dired: Enhances Dired mode with icons from Nerd Fonts, improving file browsing.

Category: Other packages

  • buffer-terminator: A package that automatically and safely kills buffers to help maintain a clean and efficient workspace, while also improving Emacs’ performance by reducing the number of open buffers, thereby decreasing the number of active modes, timers, and other processes associated with those buffers.
  • expand-region: Expands the selected region in code, making it easier to select logical blocks of code or text.
  • inhibit-mouse: Disables mouse support within Emacs, encouraging keyboard-centric navigation and editing. This can be beneficial for some users who prefer a more traditional text editor experience.
  • bufferfile: Delete or rename buffer file names with their associated buffers.
  • quick-fasd: Offers fast access to files and directories based on your history and usage patterns, optimizing file navigation.
  • diff-hl: Displays git diff information in the fringe of your Emacs window. (Alternative to diff-hl: git-gutter.)
  • wgrep: Allows for in-buffer editing of grep results, improving the usability of search results. (It can be used to modify the occurrences returned by the Embark package embark-export function.)
  • dir-config: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • which-key (built-in): Displays available keybindings in a popup, helping users learn and remember key combinations in Emacs.
  • quick-sdcv: Bring the Stardict’s dictionary functionality directly into your Emacs workflow. This will turn Emacs into a dictionary.
  • golden-ratio: Automatic resizing of Emacs windows to the golden ratio.
  • diminish: This package implements hiding or abbreviation of the mode line displays (lighters) of minor-modes.
  • org (built-in): A powerful mode for organizing notes, tasks, and project planning within Emacs.
  • org-appear: Improves the visibility of Org mode elements in the buffer by automatically toggling visibility based on context.
  • toc-org: Automatically generates a table of contents for Org mode documents.
  • project.el (built-in): A package for managing and navigating projects, providing utilities for project-based operations like searching, switching, and file management within defined project directories.
  • flyspell-mode (built-in): An interface for spell-checking text using external programs like ispell, aspell, or hunspell for checking and correcting spelling in buffers. (EDIT: The author replaced Jinx with Flyspell because Jinx was slowing down Emacs.)
  • org-bullets: Replace org-mode leading stars with UTF-8 bullets (EDIT: The author is now using the org-ibullets fork)
  • hl-todo: highlight TODO, FIXME… (Alternatively, you can use this Elisp function that can highlight codetags such as TODO or FIXME)

Category: Miscellaneous file types

  • markdown-mode: Provides major mode support for editing Markdown files.
  • ace-window: A package for selecting a window to switch to.
  • treemacs: A file and project explorer for Emacs that provides a visually structured tree layout similar to file browsers in modern IDEs. It integrates well with various Emacs packages such as projectile, lsp-mode, evil, allowing users to navigate their project structure efficiently.
  • markdown-toc: Automatically generates and manages a table of contents for Markdown files, making navigation easier.
  • flymake-ansible-lint: Provides on-the-fly syntax checking for Ansible playbooks and roles, ensuring code quality.
  • flymake-bashate: Integrates bashate for syntax checking of Bash scripts in real-time within Emacs. (Emacs also offers a built-in Flymake backend for ShellCheck.)
  • combobulate: A package that provides structured editing and navigation capabilities across many programming languages. Rather than relying on conventional major modes that use fragile imperative logic and regular expressions to interpret code structure, Combobulate leverages the Emacs tree-sitter library. Tree-sitter maintains a concrete syntax tree of the source code, giving Combobulate precise and reliable insight into code structure, which allows for more accurate editing and movement operations.
  • lua-mode: Provides major mode support for editing Lua files. (EDIT: The author is now using the built-in lua-ts-mode.)
  • php-mode: Provides major mode support for editing PHP files. (EDIT: The author is now using the built-in php-ts-mode.)
  • dockerfile-mode: Provides syntax highlighting and editing support for Dockerfile files. (EDIT: The author is now using the built-in dockerfile-ts-mode.)
  • yaml-mode: Provides major mode support for editing YAML files, complete with syntax highlighting and formatting commands. (EDIT: The author is now using the built-in yaml-ts-mode.)

By focusing on these packages, the Emacs configuration was simplified while still maintaining a highly functional setup.