Modern Emacs

New tools that make Emacs better and faster

noshadow

Marie-Hélène Burle

March 5, 2024


Faster Emacs

Lexical binding

Introduced in version 24
Lexical binding can be used instead of dynamic binding for Emacs Lisp code
Set as a file local variable

Dynamic binding

Name resolution depends on program state (runtime context), determined at run time
Global environment for all variables

Makes modifying behaviour easy

Lexical binding

Name resolution depends on lexical context (static context), determined at compile time
Local environments of functions and let, defconst, defvar, etc. expressions

Makes compiler optimization much easier → faster Elisp code = faster Emacs

JIT native compilation

Introduced in version 28
Requires libgccjit
Build Emacs --with-native-compilation
Packages can also be compiled natively (automatic with straight)

Lazy loading

Built-in since version 29
Fine-tuned loading of packages with use-package
Integrates nicely with straight

  • Faster startup time
  • More organized init file
  • Easier to reload configurations for single package

Perfect parsing

Accurate syntax tree

Built-in since version 29
Tree-sitter for Emacs
Code is parsed accurately instead of using regexp

  • Perfect syntax highlighting, indentation, and navigation
  • Faster

Simplest setup with treesit-auto:

(use-package treesit-auto
  :config
  (treesit-auto-add-to-auto-mode-alist 'all))

More efficient completions

History of code completion in Emacs: IDO

History of code completion in Emacs: IDO vertical

From oremacs

History of code completion in Emacs: HELM

From oracleyue

History of code completion in Emacs: Ivy

With optional Counsel & Swiper

New framework

External packages
Use default Emacs functions (less code)
Faster, flexible, customizable with discrete units

Packages

Minibuffer

In buffer

  • corfu    frontend completion UI
  • orderless  backend completion style
  • cape    backend completion functions
  • eglot     backend LSP client

Compared to previous frameworks

  • Integrates beautifully with internal Emacs functions
  • Easy jump back & forth between buffer and completion buffer
  • Much faster than HELM
  • Lightning fast previews with auto-closing buffers
  • Easy customization

Example configuration

Vertico (frontend for completion in minibuffer)

(use-package vertico
  :init
  (vertico-mode 1)
  (vertico-multiform-mode 1)
  :config
  (setq vertico-multiform-commands
    '((consult-line buffer)
      (consult-line-thing-at-point buffer)
      (consult-recent-file buffer)
      (consult-mode-command buffer)
      (consult-complex-command buffer)
      (embark-bindings buffer)
      (consult-locate buffer)
      (consult-project-buffer buffer)
      (consult-ripgrep buffer)
      (consult-fd buffer)))
  :bind (:map vertico-map
          ("C-k" . kill-whole-line)
          ("C-u" . kill-whole-line)
          ("C-o" . vertico-next-group)
          ("<tab>" . minibuffer-complete)
          ("M-<return>" . minibuffer-force-complete-and-exit)))

;; save search history
(use-package savehist
  :init
  (savehist-mode 1))

Language Server Protocol client

Built-in since version 29

Eglot (Emacs Polyglot) allows to connect to a programming language server

Example: Julia

Need to install an LSP for Julia:

(straight-use-package 'eglot-jl)

Then run eglot-jl-init

Now eglot in a Julia buffer connects to the server

Similarly, you can install an LSP for R or Python or any language and use Eglot with R, Python, or whatever language

❤ to all Emacs developers and maintainers

In particular,

developers, maintainers, and contributors to Emacs core,
developers and maintainers to some of the mentioned packages:
Daniel Mendler
Omar Antolín Camarena
João Távora
Robb Enzmann
John Wiegley
Adam B
and all their contributors