Skip to content

Modules

Prelude provides extra functionality through modules. Some modules may require extra steps to enable all functionality. These steps and the functionality provided by these modules are documented on the following links.

What's a module?

Prelude modules are plain old Elisp libraries - there's absolutely nothing magical about them. Most of them simply install a few Emacs packages and provide some sensible baseline configuration for them. Here's a real example.

;;; prelude-ruby.el --- Emacs Prelude: A nice setup for Ruby devs.
;;; Code:

(require 'prelude-programming)

;; Use ruby-ts-mode when the tree-sitter grammar is available
(prelude-treesit-remap 'ruby 'ruby-mode 'ruby-ts-mode)

;; We never want to edit Rubinius bytecode
(add-to-list 'completion-ignored-extensions ".rbc")

(defun prelude-ruby-mode-defaults ()
  ;; Don't auto-insert encoding comments
  ;; Those are almost never needed in Ruby 2+
  (setq ruby-insert-encoding-magic-comment nil)
  (inf-ruby-minor-mode +1)
  ;; CamelCase aware editing operations
  (subword-mode +1)
  (prelude-lsp-enable))

;; Run a Ruby REPL (IRB/Pry) inside Emacs and send code to it
(use-package inf-ruby
  :ensure t
  :defer t)

;; Browse Ruby documentation via ri (C-h R)
(use-package yari
  :ensure t
  :defer t
  :bind (:map help-map ("R" . yari)))

(add-hook 'prelude-ruby-mode-hook #'prelude-ruby-mode-defaults)

(add-hook 'ruby-mode-hook (lambda ()
                            (run-hooks 'prelude-ruby-mode-hook)))
(add-hook 'ruby-ts-mode-hook (lambda ()
                               (run-hooks 'prelude-ruby-mode-hook)))

(provide 'prelude-ruby)
;;; prelude-ruby.el ends here

To use a module you simply have to require it. No new concepts. No magic.

Writing a Module

When writing or modifying a module, follow these conventions for consistency:

Structure

A typical programming language module follows this pattern:

;;; prelude-example.el --- Emacs Prelude: Example config.
;;; Code:

(require 'prelude-programming)

;; Use the tree-sitter mode when its grammar is available
(prelude-treesit-remap 'example 'example-mode 'example-ts-mode)

(use-package example-mode
  :ensure t
  :defer t)

(defun prelude-example-mode-defaults ()
  (subword-mode +1)
  (prelude-lsp-enable))

(add-hook 'prelude-example-mode-hook #'prelude-example-mode-defaults)

(add-hook 'example-mode-hook
          (lambda ()
            (run-hooks 'prelude-example-mode-hook)))
(add-hook 'example-ts-mode-hook
          (lambda ()
            (run-hooks 'prelude-example-mode-hook)))

(provide 'prelude-example)
;;; prelude-example.el ends here

Conventions

  • Require prelude-programming as the foundation for all programming language modules. Lisp-family modules should require prelude-lisp instead.
  • Define a prelude-*-mode-defaults function with the mode-specific setup. This makes it easy for users to override.
  • Use the prelude-*-mode-hook pattern: add the defaults function to the hook with add-hook, and run the hook from the major mode hooks. Users can then add to it, or remove the defaults function, from their personal config.
  • Enable subword-mode for CamelCase-aware editing.
  • Call prelude-lsp-enable for LSP support. This respects the user's prelude-lsp-client setting (Eglot or lsp-mode).
  • Add tree-sitter support with prelude-treesit-remap, which switches to the tree-sitter mode when its grammar is available (and offers to install it otherwise). When there's no classic mode to remap, map file names directly with prelude-treesit-auto-mode. Always add hooks for both the legacy mode and the tree-sitter mode.
  • Use with-eval-after-load to defer configuration until the relevant package is loaded.
  • Install packages with use-package and :ensure t, not manual package-install calls. Prelude keeps track of the packages installed this way (see prelude-packages).

Foundation Modules

These modules provide shared functionality used by other modules:

  • Programming - common foundation for all programming modes
  • Lisp Base - common foundation for Lisp-family language modules
  • LSP - common foundation for modules using the Language Server Protocol
  • Eglot Booster - speeds up Eglot via the emacs-lsp-booster wrapper
  • Company - completion framework (legacy)
  • Corfu - lightweight modern alternative to Company
  • Apheleia - async, unified format-on-save

Programming Language Modules

The following programming languages have enhanced support in Prelude:

Completion Frameworks

Prelude supports several completion frameworks. You should only enable one of these:

  • Helm - incremental completion and narrowing
  • Ido - built-in completion with fuzzy matching
  • Ivy - lightweight completion with Swiper/Counsel
  • Vertico - vertical completion with Consult

Other Modules