AI generated
Compilation mode runs a shell command, captures the output, and parses error messages so you can jump directly to the source location. It works for compilers, linters, test runners, and anything else that outputs file/line references.
The compile package is configured in lisp/init-prog.el:
(use-package compile :ensure nil :custom (compilation-scroll-output 'first-error) (compilation-ask-about-save nil) (compilation-always-kill t))
compilation-scroll-output is set to 'first-error — the compilation buffer scrolls to follow output and stops scrolling when the first error appears.
compilation-ask-about-save is disabled — Emacs saves modified buffers before compiling without prompting.
compilation-always-kill is enabled — starting a new compilation kills any running one without asking.
M-x compile prompts for a shell command and runs it. M-x recompile (or g in the compilation buffer) re-runs the last command.
For per-language compile commands, compile-multi is configured in lisp/init-project.el with presets for Go, Python, Haskell, Nix, and Rust:
(compile-multi-config
'((go-ts-mode . (("go test" . "go test ./...")
("go test current" . "go test .")
("go test -race" . "go test -race ./...")
("go build" . "go build ./...")
("go run" . "go run .")
("go vet" . "go vet ./...")
("golangci-lint" . "golangci-lint run")))
(go-mod-ts-mode . (("go mod tidy" . "go mod tidy")
("go mod download" . "go mod download")))
(python-mode . (("pytest" . "pytest")
("pytest file" . "pytest %file-name%")))
(haskell-mode . (("stack test" . "stack test")
("cabal test" . "cabal test")))
(nix-ts-mode . (("nix flake check" . "nix flake check")
("nix fmt" . "nix fmt")))
(rust-ts-mode . (("cargo test" . "cargo test")
("cargo clippy" . "cargo clippy --all-targets")
("cargo build" . "cargo build")))))
Run M-x compile-multi to pick from these. The consult-compile-multi integration provides a narrowing UI.
The wgrep package (configured in lisp/init-prog.el) enables editing grep result buffers in place. The workflow is:
consult-ripgrep — search across the project
C-c C-o (embark-export) — export results to a grep buffer
C-x C-q — enter wgrep edit mode
C-c C-c — apply changes to all matched files
Starting with Emacs 31, a built-in grep-edit-mode will also be available.
Compilation mode uses compilation-error-regexp-alist and compilation-error-regexp-alist-alist to parse error output. Emacs ships with dozens of entries for GCC, Java, Ruby, Python, Perl, and many more — no configuration needed for common tools.
Each entry has the shape:
(SYMBOL REGEXP FILE LINE COLUMN TYPE HYPERLINK HIGHLIGHT...)
Where TYPE controls severity: 2 = error, 1 = warning, 0 = info. The TYPE field can also be a cons cell for conditional severity based on match groups.
If you use a tool whose output format is not recognized, you can teach compilation mode about it:
(with-eval-after-load 'compile
(push '(my-linter
"^\\[\\(?:ERROR\\|\\(WARN\\)\\)\\] \\([^:]+\\):\\([0-9]+\\):\\([0-9]+\\)"
2 3 4 (1))
compilation-error-regexp-alist-alist)
(push 'my-linter compilation-error-regexp-alist))
Beyond what this config sets, a few more compilation variables are worth knowing:
;; Skip warnings and info when navigating with next-error.
;; 2 = only errors, 1 = errors + warnings, 0 = everything (default).
(setopt compilation-skip-threshold 2)
;; Some languages (e.g. OCaml) use 0-indexed columns.
(setq compilation-first-column 0)
;; Auto-close the compilation window on success.
(add-hook 'compilation-finish-functions
(lambda (buf status)
(when (string-match-p "finished" status)
(run-at-time 1 nil #'delete-windows-on buf))))
Compilation mode is not just for compilers — it is the infrastructure for any structured output with source locations:
M-x grep, M-x rgrep, M-x lgrep all produce compilation-derived buffers with the same navigation.
M-x occur participates in the same next-error infrastructure.
Any tool that outputs file/line references can plug into this system. Whether you are navigating compiler errors, grep results, test failures, or linter output, the workflow is the same: M-g n to jump to the next problem.