A multi-target M-x compile
interface inspired by multi-compile.
This package provides a framework for associating actions with triggers. A trigger is any predicate that applies to the current file, project or directory. An action is a shell command or interactive function or anything that can be invoked when the associated trigger is set. You can use this to construct rich command interfaces emulating those offered by more integrated development environments. You can also plug in compilation targets directly from build frameworks or test tools, etc. See projection-multi-compile for a package that plugs compile-multi into various build tools.
- Clone the repo.
- Add the repo path to your emacs
load-path
. - Load it when needed.
This package is on MELPA. You can add this to your package-archives
variable and
then install through M-x package-install
.
(push '("melpa" . "https://melpa.org/packages/") package-archives)
(package-refresh-contents)
(package-install 'compile-multi)
This package isn’t a copy of emacs-multi-compile, it’s a lighter and more feature-full re-write. The main changes from upstream are:
- No special formatting-directives/percent-sequences. Commands are lisp lists that are evaluated, shell-quoted and concatenated together smartly.
- Support for dynamic command generation (such as from Makefiles) which can let you use this package as a replacement for helm-make and as a convenient base for other such build frameworks.
- Support for lisp functions as direct compilation functions. For example rustic-mode provides its own wrappers around compile, test and run and this package can let you interface with those as well.
The main configuration for compile-multi
is compile-multi-config
. This should be an
alist with the car
being the something matching current file, buffer or simply a
list form that can evaluates to true. The cdr
should be a list of tasks/actions
that users can select when the trigger fires. An action is an cons of the action
name and something to be done when that action is selected.
Here’s an example of the general layout of the configuration variable.
(setq
compile-multi-config '((trigger-1
("action1" . command-1)
("action2" . command-2))
(trigger-2
("action1" . command-1)
("action2" . command-2))))
Triggers can be mode-symbols, strings, interpreted as regexps for the buffer-file-name or if the buffer has no file name then its buffer-name, or any lisp form that is triggered when it evaluates to true.
This can be used alongside (setq compile-multi-default-directory #'projectile-project-root)
to setup trigger based on project files.
(push '((file-exists-p "Makefile")
("make:build" . "make build")
("make:test" . "make test")
("make:all" . "make all"))
compile-multi-config)
As a special case an action can be inserted as a function instead of an cons cell. When this is the case the function will be called and expected to return a collection of actions to be put in place of the functions position in the configuration.
For example you can write a compile-multi-make
that’ll parse out all the targets
from a Makefile and generate actions for them.
(require 'compile-multi-make)
(defun compile-multi-make-targets+ ()
;; Read targets from Makefile.
'(("make:foo" . "foo")))
(push `((file-exists-p "Makefile")
("action-1" . command-1)
,#'compile-multi-make-targets+
("action-2" . command-2))
compile-multi-config)
When written as an alist the car
of an action must always be the action name. The
cdr
can vary depending on what the user wants.
When it’s a string then the string is taken as a shell command to run for
compilation.
When a list each argument of the list is evaluated, shell-quoted and then
concatenated together.
When a plist you can set the :command
property and supply any alternative
properties to customise the execution of the target. For example the :annotation
property sets the affixated annotation for the action in the minibuffer.
Note: We don’t shell quote strings, only evaluated lisp forms.
Note: Symbols can be replaced instead of evaluated using compile-multi-forms
.
For example
(push `(python-mode
("python:pylint" "python3" "-m" "pylint" (buffer-file-name)))
compile-multi-config)
Lastly the action can be a function. In this case the function is called when the action is selected. For example:
(defun byte-compile-this-file+ ()
(byte-compile-file (buffer-file-name)))
(push `(emacs-lisp-mode
("emacs:bytecompile" . ,#'byte-compile-this-file+))
compile-multi-config)
Is an extension for multi-compile that runs the interactive selection of targets through consult instead of completing-read. This is very similar to the existing completing-read interface but enhances it with some useful consult features such as narrowing.
(use-package consult-compile-multi
:ensure t
:after compile-multi
:demand t
:config (consult-compile-multi-mode))
This extension adds a handler to all-the-icons-completion for affixating
compile-multi with icons related to the compile-multi type. You have to setup
all-the-icons-completion
correctly before this package will work.
(use-package compile-multi-all-the-icons
:ensure t
:after all-the-icons-completion
:after compile-multi
:demand t)
This extension adds a handler to nerd-icons-completion for affixating
compile-multi with nerd icons related to the compile-multi type. You have to setup
nerd-icons-completion
correctly before this package will work.
(use-package compile-multi-nerd-icons
:ensure t
:after nerd-icons-completion
:after compile-multi
:demand t)
This extension adds support between compile-multi embark. This has 2 affects:
- Defines a new compile-multi command map for Embark. This map has a command to let you edit a compile-multi target before executing it.
- Adds a transformer to embark so any actions you run on compile-multi through
embark in the minibuffer actually route to the underlying command you wanted to
run them on. For example this can be used with the
kill-new
feature to copy the compilation command compile-multi would have run.
To use this extension you must install it and use enable compile-multi-embark-mode
.
(use-package compile-multi-embark
:ensure t
:after embark
:after compile-multi
:demand t
:config (compile-multi-embark-mode +1))