Modern Emacs

New tools that make Emacs better and faster

Author

Marie-Hélène Burle

Content from the webinar slides for easier browsing.

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

Provides:

Lazy loading

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

Provides:

  • 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.

Provides:

  • 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

IDO

IDO vertical

From oremacs

HELM

From oracleyue

Ivy

With optional Counsel & Swiper.

A new framework

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

Packages

Minibuffer
 

Frontend completion UI Backend completion style Backend completion functions Annotations Actions on completion buffer

In buffer
 

Frontend completion UI Backend completion style Backend completion functions Backend LSP client

Advantages

  • 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

In particular: