diff --git a/CHANGELOG.md b/CHANGELOG.md
index 75c4a0bcd0..0d29ce3662 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@
### New features
+- Add `prelude-swift` module: Swift support via the tree-sitter powered `swift-ts-mode` and `sourcekit-lsp` (registered with Eglot, since Eglot has no built-in entry for Swift). Starts an LSP session through the usual `prelude-lsp-enable` abstraction.
+- Add `prelude-mistty` module: a terminal based on [MisTTY](https://github.com/szermatt/mistty), a pure-elisp shell/comint hybrid on top of `term.el` (no native module to compile). Rebinds Prelude's terminal key `C-c t` to `mistty`.
+- Add a `prelude-spell-checker` option to choose between `flyspell` (the default) and [jinx](https://github.com/minad/jinx), a faster libenchant-based spell checker that only checks the visible part of the buffer. Jinx is installed on demand and enabled as a single global mode; set `(setq prelude-spell-checker 'jinx)` in your personal config to opt in (requires libenchant and a C compiler).
+- Add a `prelude-whitespace-cleanup-style` option to choose how whitespace is cleaned on save: `whitespace-cleanup` (the default, tidies the whole file) or [ws-butler](https://github.com/lewang/ws-butler), which trims only the lines you actually edited so saving a file in someone else's project no longer produces noisy whitespace-only diffs. ws-butler is installed on demand.
- Add `prelude-ai` module: a thin wrapper around [gptel](https://github.com/karthink/gptel) for LLM-backed chat (Claude, GPT, Gemini, Ollama, etc.). Binds `gptel-menu` to `C-c q`. Backends and API keys are configured in personal config -- see the module documentation for examples.
- Add `prelude-forge` module: enables [Forge](https://github.com/magit/forge) on top of Magit so you can read and reply to GitHub/GitLab/Gitea pull requests and issues without leaving Emacs.
- Add `prelude-eglot-booster` module: speeds up Eglot via the [emacs-lsp-booster](https://github.com/blahgeek/emacs-lsp-booster) wrapper. The Emacs side ([eglot-booster](https://github.com/jdtsmith/eglot-booster)) is auto-installed via `package-vc-install` when the booster binary is on `PATH`; otherwise the module no-ops.
@@ -14,6 +18,14 @@
### Changes
+- Add an `early-init.el` that tunes startup: it raises the GC threshold while Emacs loads (restoring a modest value once startup is over), disables the tool bar via frame parameters so the initial frame is never drawn with one, sets `frame-inhibit-implied-resize`, native-compiles packages at install time (`package-native-compile`), and sets a sane `LANG` for GUI Emacs on macOS (which otherwise starts in the `C` locale and breaks spell-checker dictionaries and subprocess sorting).
+- Populate `treesit-language-source-alist` with recipes for the languages Prelude's modules use, so a missing grammar can be installed with `M-x treesit-install-language-grammar` without hunting down repository URLs.
+- Modernize the Eglot event-log setting to prefer `eglot-events-buffer-config` on newer Eglot, falling back to the obsolete `eglot-events-buffer-size` on older versions.
+- Bridge Eglot diagnostics into Flycheck via [flycheck-eglot](https://github.com/flycheck/flycheck-eglot) when `prelude-lsp-client` is `eglot`, so LSP diagnostics show up in Prelude's Flycheck UI instead of only through Flymake. Installed on demand; lsp-mode users are unaffected (lsp-mode has its own Flycheck integration).
+- Add [Embark](https://github.com/oantolin/embark) (and `embark-consult`) to `prelude-vertico`: a keyboard-driven context menu bound to `C-.` (`embark-act`), `C-;` (`embark-dwim`) and `C-h B` (`embark-bindings`), with `embark-export` into editable grep/occur buffers. In Flyspell buffers those keys keep their Flyspell auto-correct meaning; Embark still works in the minibuffer and elsewhere.
+- Enable the `vertico-directory` extension in `prelude-vertico`: `RET` descends into the selected directory, `DEL` deletes a whole path component, and `M-DEL` deletes a word of it.
+- Enable `corfu-history-mode` in `prelude-corfu` so recently chosen completion candidates sort first (persisted across sessions via savehist).
+- Set `consult-narrow-key` to `<` in `prelude-vertico`, so you can narrow consult candidates to a single group (e.g. `< b` for buffers in `consult-buffer`).
- Tidy up `prelude-common-lisp`: drop stale `slime-autodoc-use-multiline-p` setting (the variable was removed from upstream SLIME; modern autodoc honors `eldoc-echo-area-use-multiline-p`), set `inferior-lisp-program` to `sbcl` so `M-x run-lisp` works without SLIME, and add `slime-quicklisp` to `slime-contribs` for Quicklisp integration.
### Bugs fixed
diff --git a/core/prelude-core.el b/core/prelude-core.el
index 1731cb6cab..c02b32a7ca 100644
--- a/core/prelude-core.el
+++ b/core/prelude-core.el
@@ -151,6 +151,30 @@ Does nothing if Emacs was compiled without tree-sitter support."
(treesit-ready-p grammar t))
(add-to-list 'major-mode-remap-alist (cons old-mode new-mode))))
+;; Grammar recipes for the languages Prelude's modules know about, so a
+;; missing grammar can be installed with `M-x treesit-install-language-grammar'
+;; (or `treesit-install-language-grammar' for the whole set) instead of
+;; hunting down repository URLs. Add your own recipes from personal config.
+(when (require 'treesit nil t)
+ (dolist (recipe
+ '((bash "https://github.com/tree-sitter/tree-sitter-bash")
+ (c "https://github.com/tree-sitter/tree-sitter-c")
+ (cpp "https://github.com/tree-sitter/tree-sitter-cpp")
+ (css "https://github.com/tree-sitter/tree-sitter-css")
+ (elixir "https://github.com/elixir-lang/tree-sitter-elixir")
+ (go "https://github.com/tree-sitter/tree-sitter-go")
+ (gomod "https://github.com/camdencheek/tree-sitter-go-mod")
+ (heex "https://github.com/phoenixframework/tree-sitter-heex")
+ (javascript "https://github.com/tree-sitter/tree-sitter-javascript")
+ (json "https://github.com/tree-sitter/tree-sitter-json")
+ (python "https://github.com/tree-sitter/tree-sitter-python")
+ (ruby "https://github.com/tree-sitter/tree-sitter-ruby")
+ (rust "https://github.com/tree-sitter/tree-sitter-rust")
+ (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")
+ (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")
+ (yaml "https://github.com/ikatyang/tree-sitter-yaml")))
+ (add-to-list 'treesit-language-source-alist recipe)))
+
(defun prelude-lsp-enable ()
"Enable the LSP client configured via `prelude-lsp-client'."
(pcase prelude-lsp-client
@@ -162,7 +186,11 @@ Does nothing if Emacs was compiled without tree-sitter support."
;; Eglot configuration
(with-eval-after-load 'eglot
(setq eglot-autoshutdown t)
- (setq eglot-events-buffer-size 0)
+ ;; don't log every LSP event - the logging adds overhead with chatty
+ ;; servers (set these back when you need to debug an LSP session)
+ (if (boundp 'eglot-events-buffer-config)
+ (setq eglot-events-buffer-config '(:size 0 :format full)) ; newer Eglot
+ (setq eglot-events-buffer-size 0)) ; older Eglot
(setq eglot-extend-to-xref t)
(define-key eglot-mode-map (kbd "C-c C-l r") #'eglot-rename)
diff --git a/core/prelude-custom.el b/core/prelude-custom.el
index b863eda3e7..6fcbb28099 100644
--- a/core/prelude-custom.el
+++ b/core/prelude-custom.el
@@ -77,11 +77,31 @@ Will only occur if `prelude-whitespace' is also enabled."
:type 'boolean
:group 'prelude)
+(defcustom prelude-whitespace-cleanup-style 'whitespace-cleanup
+ "How whitespace is cleaned up on save when enabled.
+`whitespace-cleanup' (the default) tidies the whole file, which can
+produce noisy whitespace-only diffs in projects that aren't already
+clean. `ws-butler' instead trims only the lines you actually edited,
+leaving the rest of the file untouched (installed on demand)."
+ :type '(choice (const :tag "whitespace-cleanup (whole file)" whitespace-cleanup)
+ (const :tag "ws-butler (edited lines only)" ws-butler))
+ :group 'prelude)
+
(defcustom prelude-flyspell t
- "Non-nil values enable Prelude's flyspell support."
+ "Non-nil values enable Prelude's spell checking support."
:type 'boolean
:group 'prelude)
+(defcustom prelude-spell-checker 'flyspell
+ "The spell checker to use when `prelude-flyspell' is enabled.
+`flyspell' is the classic built-in checker (it needs an external
+aspell/hunspell binary). `jinx' is a faster, libenchant-based
+checker that only checks the visible portion of the buffer, but it
+requires libenchant and a C compiler to build its native module."
+ :type '(choice (const :tag "Flyspell (built-in)" flyspell)
+ (const :tag "Jinx (libenchant)" jinx))
+ :group 'prelude)
+
(defcustom prelude-user-init-file (expand-file-name "personal/"
user-emacs-directory)
"Path to your personal customization file.
diff --git a/core/prelude-editor.el b/core/prelude-editor.el
index 9370f79695..4137564bf6 100644
--- a/core/prelude-editor.el
+++ b/core/prelude-editor.el
@@ -206,20 +206,46 @@
ispell-extra-args '("--sug-mode=ultra")))
(defun prelude-enable-flyspell ()
- "Enable command `flyspell-mode' if `prelude-flyspell' is not nil."
- (when (and prelude-flyspell (executable-find ispell-program-name))
+ "Enable command `flyspell-mode' when Prelude's spell checker is Flyspell.
+Does nothing when `prelude-spell-checker' is set to something else
+\(e.g. `jinx', which is a single global mode enabled below)."
+ (when (and prelude-flyspell
+ (eq prelude-spell-checker 'flyspell)
+ (executable-find ispell-program-name))
(flyspell-mode +1)))
+;; jinx is an enchant-based spell checker; unlike flyspell it's a
+;; single global mode that checks only the visible part of the buffer,
+;; so it's enabled once here rather than per-buffer. The enable is
+;; guarded so a missing libenchant only warns instead of aborting startup.
+(when (and prelude-flyspell (eq prelude-spell-checker 'jinx))
+ (prelude-require-package 'jinx)
+ (with-demoted-errors "Prelude: could not enable jinx: %S"
+ (global-jinx-mode +1)))
+
(defun prelude-cleanup-maybe ()
"Invoke `whitespace-cleanup' if `prelude-clean-whitespace-on-save' is not nil."
(when prelude-clean-whitespace-on-save
(whitespace-cleanup)))
+;; ws-butler trims trailing whitespace on save, but only on the lines
+;; you actually edited, so saving a file in someone else's project
+;; doesn't produce noisy whitespace-only diffs. Only pull it in when
+;; it's the chosen cleanup style.
+(when (and prelude-whitespace
+ prelude-clean-whitespace-on-save
+ (eq prelude-whitespace-cleanup-style 'ws-butler))
+ (prelude-require-package 'ws-butler)
+ (require 'ws-butler nil t))
+
(defun prelude-enable-whitespace ()
"Enable `whitespace-mode' if `prelude-whitespace' is not nil."
(when prelude-whitespace
;; keep the whitespace decent all the time (in this buffer)
- (add-hook 'before-save-hook 'prelude-cleanup-maybe nil t)
+ (when prelude-clean-whitespace-on-save
+ (if (eq prelude-whitespace-cleanup-style 'ws-butler)
+ (ws-butler-mode +1)
+ (add-hook 'before-save-hook 'prelude-cleanup-maybe nil t)))
(whitespace-mode +1)))
(add-hook 'text-mode-hook 'prelude-enable-flyspell)
diff --git a/core/prelude-ui.el b/core/prelude-ui.el
index 00a7f5da52..2063ca5059 100644
--- a/core/prelude-ui.el
+++ b/core/prelude-ui.el
@@ -31,10 +31,8 @@
;;; Code:
-;; the toolbar is just a waste of valuable screen estate
-;; in a tty tool-bar-mode does not properly auto-load, and is
-;; already disabled anyway
-(tool-bar-mode -1)
+;; the toolbar is disabled via `default-frame-alist' in early-init.el,
+;; so the initial frame is never drawn with one
(when prelude-minimalistic-ui
(menu-bar-mode -1))
diff --git a/docs/installation.md b/docs/installation.md
index baa541ea41..32c529f209 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -173,6 +173,7 @@ modules visit the [docs](modules/index.md).
;; (require 'prelude-scheme)
(require 'prelude-shell)
;; (require 'prelude-scss)
+;; (require 'prelude-swift)
;; (require 'prelude-ts)
(require 'prelude-web) ;; Emacs mode for web templates
(require 'prelude-xml)
@@ -180,6 +181,7 @@ modules visit the [docs](modules/index.md).
;;; Misc
(require 'prelude-erc) ;; A popular Emacs IRC client
+;; (require 'prelude-mistty) ;; MisTTY terminal (pure elisp, no native module)
```
You'll need to adjust your `prelude-modules.el` file once the
diff --git a/docs/modules/mistty.md b/docs/modules/mistty.md
new file mode 100644
index 0000000000..950f266f8e
--- /dev/null
+++ b/docs/modules/mistty.md
@@ -0,0 +1,17 @@
+# Prelude MisTTY
+
+[MisTTY](https://github.com/szermatt/mistty) is a shell/comint hybrid
+built on top of `term.el`. It gives you full terminal emulation for TUI
+programs while keeping ordinary Emacs editing and motion on the command
+line. Unlike `vterm` it's pure Emacs Lisp, so there's no native module
+to compile.
+
+## Key bindings
+
+Enabling this module rebinds Prelude's terminal key, C-c t,
+from `crux-visit-term-buffer` to `mistty`, on the assumption that if
+you've turned it on you'd rather that key opened MisTTY. You can pick a
+different binding in your personal config if you prefer.
+
+Inside a MisTTY buffer, C-c C-j and C-c C-q toggle
+between the terminal and the Emacs editing modes.
diff --git a/docs/modules/swift.md b/docs/modules/swift.md
new file mode 100644
index 0000000000..e38900c122
--- /dev/null
+++ b/docs/modules/swift.md
@@ -0,0 +1,31 @@
+# Prelude Swift
+
+!!! Note
+
+ This module builds on top of the shared [Programming](programming.md) module.
+
+## Package Prerequisites
+
+For the proper functioning of this module, you'll need the following on
+your system:
+
+- a Swift toolchain (`swift`, `swiftc`)
+- `sourcekit-lsp` (bundled with the Xcode command line tools or a Swift toolchain)
+
+## Swift Mode
+
+The module uses the tree-sitter powered `swift-ts-mode` for editing
+Swift code, so you'll need the `swift` tree-sitter grammar installed.
+Prelude ships a recipe for it, so `M-x treesit-install-language-grammar
+RET swift` will fetch and build it for you.
+
+Whenever you are editing Swift code run C-h m to look at the
+Swift mode key bindings.
+
+## LSP support
+
+The module starts an LSP session automatically via Prelude's
+`prelude-lsp-enable`, using whichever client `prelude-lsp-client`
+selects (Eglot by default). Eglot has no built-in entry for Swift, so
+the module registers `sourcekit-lsp` for it. lsp-mode users get Swift
+support through the `lsp-sourcekit` package.
diff --git a/docs/modules/vertico.md b/docs/modules/vertico.md
index 61a510c352..65b8bc2b39 100644
--- a/docs/modules/vertico.md
+++ b/docs/modules/vertico.md
@@ -17,8 +17,14 @@ packages for a modern and lightweight completion experience.
- [vertico](https://github.com/minad/vertico) - the vertical completion UI
- [orderless](https://github.com/oantolin/orderless) - flexible
completion style (space-separated patterns)
+- [marginalia](https://github.com/minad/marginalia) - rich annotations
+ in the minibuffer (docstrings, file sizes, etc.)
- [consult](https://github.com/minad/consult) - enhanced versions
of built-in commands
+- [embark](https://github.com/oantolin/embark) - a keyboard-driven
+ context menu for candidates and things at point
+- [embark-consult](https://github.com/oantolin/embark) - integration
+ between Embark and Consult
## Consult Key Bindings
@@ -74,3 +80,29 @@ Prelude:
The module configures the `orderless` completion style, which allows you to
type space-separated patterns that can match in any order. For example, typing
`buf swi` would match `switch-to-buffer`.
+
+## Acting on Candidates with Embark
+
+[Embark](https://github.com/oantolin/embark) is a keyboard-driven context
+menu. Point it at a minibuffer candidate or a thing at point (a file, a URL, a
+symbol, ...) and it offers the actions that make sense for it.
+
+| Key | Command | Description |
+| --- | ------- | ----------- |
+| C-. | `embark-act` | Act on the thing at point or candidate |
+| C-; | `embark-dwim` | Run the default action directly |
+| C-h B | `embark-bindings` | Browse the bindings at point |
+
+A particularly handy trick is `embark-export`: from a `consult-ripgrep` (or
+`consult-line`, etc.) session you can export the whole candidate set into a
+proper `grep`/`occur` buffer, which you can then edit in place with
+[wgrep](https://github.com/mhayashi1120/Emacs-wgrep).
+
+!!! Note
+
+ C-. and C-; are also bound by `flyspell-mode`
+ (auto-correct), so in buffers where Prelude enables Flyspell those keys
+ keep their Flyspell meaning. Embark still works everywhere else, including
+ the minibuffer, which is where you'll use it most with Vertico and Consult.
+ Switch to the `jinx` spell checker (see `prelude-spell-checker`), or rebind
+ the keys, if you'd rather have Embark at point in prose buffers too.
diff --git a/early-init.el b/early-init.el
new file mode 100644
index 0000000000..75282af8bb
--- /dev/null
+++ b/early-init.el
@@ -0,0 +1,68 @@
+;;; early-init.el --- Prelude's early configuration.
+;;
+;; Copyright (c) 2011-2026 Bozhidar Batsov
+;;
+;; Author: Bozhidar Batsov
+;; URL: https://github.com/bbatsov/prelude
+;; Version: 1.1.0
+;; Keywords: convenience
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; This file is loaded before the package system and the UI are
+;; initialized, which makes it the right place for a few settings that
+;; have to be applied very early during startup.
+
+;;; License:
+
+;; 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 GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+;; Raise the garbage collection threshold as high as possible for the
+;; duration of startup, so we don't pay for repeated collections while
+;; a lot of code is being loaded. A modest threshold is restored once
+;; startup is over (a permanently huge threshold trades frequent short
+;; pauses for rare, long freezes).
+(setq gc-cons-threshold most-positive-fixnum)
+
+(add-hook 'emacs-startup-hook
+ (lambda ()
+ (setq gc-cons-threshold (* 50 1000 1000) ; 50MB
+ gc-cons-percentage 0.2)))
+
+;; Disable the tool bar via frame parameters, so the initial frame is
+;; never created with one in the first place. Toggling `tool-bar-mode'
+;; later forces an expensive frame resize.
+(push '(tool-bar-lines . 0) default-frame-alist)
+
+;; Don't resize the frame in response to font or UI changes during
+;; startup - it's needless work before the frame is even visible.
+(setq frame-inhibit-implied-resize t)
+
+;; Native-compile packages when they are installed rather than lazily
+;; on first load, so you don't hit compilation pauses while working.
+(setq package-native-compile t)
+
+;; GUI Emacs on macOS doesn't inherit the environment from the shell,
+;; so without LANG it ends up in the "C" locale, which breaks things
+;; like spell-checker dictionaries and subprocess sorting.
+(when (and (eq system-type 'darwin) (not (getenv "LANG")))
+ (setenv "LANG" "en_US.UTF-8"))
+
+;;; early-init.el ends here
diff --git a/init.el b/init.el
index 8f81ec1b05..145c2e8754 100644
--- a/init.el
+++ b/init.el
@@ -94,9 +94,8 @@ by Prelude.")
(add-to-list 'load-path prelude-vendor-dir)
(prelude-add-subfolders-to-load-path prelude-vendor-dir)
-;; reduce the frequency of garbage collection by making it happen on
-;; each 50MB of allocated data (the default is on every 0.76MB)
-(setq gc-cons-threshold 50000000)
+;; the garbage collection threshold is tuned in early-init.el (raised
+;; during startup, restored to a modest value once startup is over)
;; warn when opening files bigger than 100MB
(setq large-file-warning-threshold 100000000)
diff --git a/mkdocs.yml b/mkdocs.yml
index ba19f788b4..380577dfc2 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -42,6 +42,7 @@ nav:
- Scheme: modules/scheme.md
- SCSS: modules/scss.md
- Shell: modules/shell.md
+ - Swift: modules/swift.md
- TypeScript: modules/ts.md
- Web/HTML: modules/web.md
- XML: modules/xml.md
@@ -58,6 +59,7 @@ nav:
- Forge (PRs/Issues): modules/forge.md
- Key Chord: modules/key_chord.md
- Literate Programming: modules/literate-programming.md
+ - MisTTY (Terminal): modules/mistty.md
- Org Mode: modules/orgmode.md
- FAQ: faq.md
- Troubleshooting: troubleshooting.md
diff --git a/modules/prelude-corfu.el b/modules/prelude-corfu.el
index caaced447a..d7851ae446 100644
--- a/modules/prelude-corfu.el
+++ b/modules/prelude-corfu.el
@@ -49,7 +49,11 @@
:init
(global-corfu-mode)
:config
- (corfu-popupinfo-mode))
+ (corfu-popupinfo-mode)
+ ;; sort candidates by recency of selection, so the ones you pick
+ ;; often bubble to the top; the history persists across sessions
+ ;; when savehist-mode is on (which Prelude enables in core)
+ (corfu-history-mode))
(use-package cape
:ensure t
diff --git a/modules/prelude-mistty.el b/modules/prelude-mistty.el
new file mode 100644
index 0000000000..73d0161d2f
--- /dev/null
+++ b/modules/prelude-mistty.el
@@ -0,0 +1,51 @@
+;;; prelude-mistty.el --- Emacs Prelude: mistty terminal.
+;;
+;; Copyright © 2011-2026 Bozhidar Batsov
+;;
+;; Author: Bozhidar Batsov
+;; URL: https://github.com/bbatsov/prelude
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; MisTTY is a shell/comint hybrid built on top of term.el: it gives
+;; you full terminal emulation for TUI programs while keeping ordinary
+;; Emacs editing and motion on the command line. Unlike vterm it's
+;; pure Emacs Lisp, so there's no native module to compile.
+
+;; This module rebinds Prelude's terminal key (`C-c t') from
+;; `crux-visit-term-buffer' to `mistty', on the assumption that if
+;; you've enabled it you'd rather that key opened MisTTY.
+
+;;; License:
+
+;; 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 GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+(require 'prelude-mode)
+
+(use-package mistty
+ :ensure t
+ :commands (mistty)
+ :init
+ ;; take over Prelude's terminal key inside prelude-mode-map (a global
+ ;; binding would be shadowed by that minor-mode map)
+ (define-key prelude-mode-map (kbd "C-c t") #'mistty))
+
+(provide 'prelude-mistty)
+;;; prelude-mistty.el ends here
diff --git a/modules/prelude-programming.el b/modules/prelude-programming.el
index 9047337020..9d89761caa 100644
--- a/modules/prelude-programming.el
+++ b/modules/prelude-programming.el
@@ -59,8 +59,9 @@
(defun prelude-prog-mode-defaults ()
"Default coding hook, useful with any programming language."
- (when (and (executable-find ispell-program-name)
- prelude-flyspell)
+ (when (and prelude-flyspell
+ (eq prelude-spell-checker 'flyspell)
+ (executable-find ispell-program-name))
(flyspell-prog-mode))
(when prelude-guru
(guru-mode +1)
@@ -79,6 +80,15 @@
(global-flycheck-mode +1)
(add-hook 'prog-mode-hook 'flycheck-mode))
+;; When Eglot is the LSP client, route its diagnostics through Flycheck
+;; as well. On its own Eglot reports only via Flymake, so without this
+;; bridge LSP diagnostics wouldn't show up in Prelude's Flycheck UI.
+;; (lsp-mode has its own Flycheck integration, so this is Eglot-only.)
+(when (eq prelude-lsp-client 'eglot)
+ (prelude-require-package 'flycheck-eglot)
+ (require 'flycheck-eglot)
+ (global-flycheck-eglot-mode +1))
+
;; Makefiles require tabs for indentation
(defun prelude-makefile-mode-defaults ()
(whitespace-toggle-options '(tabs))
diff --git a/modules/prelude-swift.el b/modules/prelude-swift.el
new file mode 100644
index 0000000000..fdeea29510
--- /dev/null
+++ b/modules/prelude-swift.el
@@ -0,0 +1,61 @@
+;;; prelude-swift.el --- Emacs Prelude: Swift programming support.
+;;
+;; Copyright © 2011-2026 Bozhidar Batsov
+;;
+;; Author: Bozhidar Batsov
+;; URL: https://github.com/bbatsov/prelude
+
+;; This file is not part of GNU Emacs.
+
+;;; Commentary:
+
+;; Prelude configuration for Swift, based on the tree-sitter powered
+;; `swift-ts-mode' and the sourcekit-lsp language server (which ships
+;; with the Xcode command line tools or a Swift toolchain).
+
+;;; License:
+
+;; 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 GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+(require 'prelude-programming)
+
+;; You may need to install the following on your system:
+;; * a Swift toolchain (swift, swiftc)
+;; * sourcekit-lsp (bundled with the Xcode command line tools)
+
+;; Eglot has no built-in entry for Swift, so point it at sourcekit-lsp.
+;; (lsp-mode users get Swift support via the lsp-sourcekit package.)
+(with-eval-after-load 'eglot
+ (add-to-list 'eglot-server-programs '(swift-ts-mode . ("sourcekit-lsp"))))
+
+(defun prelude-swift-mode-defaults ()
+ "Default coding hook, useful with Swift."
+ ;; CamelCase aware editing operations
+ (subword-mode +1)
+ (prelude-lsp-enable))
+
+(setq prelude-swift-mode-hook 'prelude-swift-mode-defaults)
+
+;; Tree-sitter based major mode for Swift (requires the swift grammar)
+(use-package swift-ts-mode
+ :ensure t
+ :mode "\\.swift\\'"
+ :hook (swift-ts-mode . (lambda () (run-hooks 'prelude-swift-mode-hook))))
+
+(provide 'prelude-swift)
+;;; prelude-swift.el ends here
diff --git a/modules/prelude-vertico.el b/modules/prelude-vertico.el
index 0c6464d585..48ca504880 100644
--- a/modules/prelude-vertico.el
+++ b/modules/prelude-vertico.el
@@ -50,6 +50,21 @@
;; (setq vertico-cycle t)
)
+;; Smarter path editing in file prompts (ships as part of Vertico):
+;; RET descends into the selected directory instead of opening it in
+;; Dired, DEL deletes a whole directory component at once, and M-DEL
+;; deletes just a word of it.
+(use-package vertico-directory
+ :ensure nil ; comes with vertico
+ :after vertico
+ :bind (:map vertico-map
+ ("RET" . vertico-directory-enter)
+ ("DEL" . vertico-directory-delete-char)
+ ("M-DEL" . vertico-directory-delete-word))
+ ;; tidy the shadowed part of the path when you re-root it (e.g. type
+ ;; ~/ or / in the middle of a path)
+ :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
+
;; A few more useful configurations for Vertico
(use-package emacs
:init
@@ -131,7 +146,33 @@
("M-s L" . consult-line-multi)
("M-s m" . multi-occur)
("M-s k" . consult-keep-lines)
- ("M-s u" . consult-focus-lines)))
+ ("M-s u" . consult-focus-lines))
+ :config
+ ;; press < followed by a group key to narrow the candidates to a
+ ;; single group (e.g. in consult-buffer, < b shows only buffers);
+ ;; press < again to remove the narrowing
+ (setq consult-narrow-key "<"))
+
+;; Embark - a keyboard-driven context menu. Point it at a minibuffer
+;; candidate or a thing at point (a file, a URL, a symbol, ...) and it
+;; offers the actions that make sense for it.
+;;
+;; Note: C-. and C-; are also bound by `flyspell-mode' (auto-correct),
+;; so in buffers where Prelude enables Flyspell those keys keep their
+;; Flyspell meaning; Embark still works everywhere else, including the
+;; minibuffer. We deliberately leave `prefix-help-command' alone so
+;; which-key keeps handling the C-h-after-a-prefix help.
+(use-package embark
+ :ensure t
+ :bind (("C-." . embark-act) ;; act on the thing at point / candidate
+ ("C-;" . embark-dwim) ;; run the default action
+ ("C-h B" . embark-bindings))) ;; browse bindings via completing-read
+
+;; Integration between Embark and Consult, e.g. `embark-export' from a
+;; consult-ripgrep session into an editable grep buffer.
+(use-package embark-consult
+ :ensure t
+ :hook (embark-collect-mode . consult-preview-at-point-mode))
(provide 'prelude-vertico)
;;; prelude-vertico.el ends here
diff --git a/sample/prelude-modules.el b/sample/prelude-modules.el
index 166790209e..7f272fd71d 100644
--- a/sample/prelude-modules.el
+++ b/sample/prelude-modules.el
@@ -94,6 +94,7 @@
;; (require 'prelude-scheme)
(require 'prelude-shell)
;; (require 'prelude-scss)
+;; (require 'prelude-swift)
;; (require 'prelude-ts)
(require 'prelude-web) ;; Emacs mode for web templates
(require 'prelude-xml)
@@ -103,6 +104,7 @@
;; (require 'prelude-ai) ;; LLM-backed chat via gptel
;; (require 'prelude-erc) ;; A popular Emacs IRC client
;; (require 'prelude-forge) ;; GitHub/GitLab/Gitea PRs and issues via Magit
+;; (require 'prelude-mistty) ;; MisTTY terminal (pure elisp, no native module; rebinds C-c t)
(provide 'prelude-modules)
;;; prelude-modules.el ends here