/compile-multi

Multi target interface to compile.

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

compile-multi

MELPA

A multi-target M-x compile interface inspired by multi-compile.

https://user-images.githubusercontent.com/23294780/246896395-eb920b00-1c0e-4d55-972f-1c4ac2b195cf.png

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.

Table of Contents

Installation

Manually

  1. Clone the repo.
  2. Add the repo path to your emacs load-path.
  3. Load it when needed.

From MELPA

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)

Deviations from emacs-multi-compile

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.

Configuration

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

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)

Actions

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)

Extensions

consult-multi-compile

MELPA

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))

compile-multi-all-the-icons

MELPA

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)

compile-multi-nerd-icons

MELPA

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)

compile-multi-embark

MELPA

This extension adds support between compile-multi embark. This has 2 affects:

  1. 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.
  2. 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))