- Synopsys
- Releases
- Installation
- Basic usage
- Main function
- Local variables
- Custom faces
- Custom variables
- Authors
- License
transient-compile
implements configurable, automatically built transient menu for interactive selection of the compilation target.
Basically, you need just one command, M-x transient-compile
. It searches for known build files in current directory and parents, retrieves available targets, groups targets by common prefixes, and displays a menu. After you select the target, it formats command and passed it to compile
function.
Tools supported out of the box:
Example of M-x transient-compile
in project using doit
:
Example of M-x transient-compile
in project using just
:
Changelog file can be found here: changelog.
Elisp dependencies that are not part of emacs:
Package was tested on Emacs 29.2 on Linux.
Instructions for straight.el:
(straight-use-package 'f) (straight-use-package 's) (straight-use-package '(transient-compile :type git :host github :repo "gavv/transient-compile" :branch "main"))
For a typical use case, no configuration is needed. Just run M-x transient-compile
from a buffer inside your project.
If you’re using project.el or projectile, you may want to set transient-compile-function
to 'project-compile
instead of 'compile
.
(custom-set-variables '(transient-compile-function 'project-compile) )
You can configure tools via transient-compile-tool-alist
, for example to change make
command to gmake
, you can use:
(let ((make (assoc 'make transient-compile-tool-alist))) (setcdr make (plist-put (cdr make) :exe "gmake")))
You can also use transient-compile-tool-alist
to register you own tools:
(add-to-list 'transient-compile-tool-alist '(foo :match ("Foofile" "foofile") :exe "foo" :chdir t :targets #'foofile-targets :command #'foofile-command))
Example above instructs transient-compile
to use foo
tool when it founds “Foofile” or “foofile” in current directory or one of its parents.
You’ll need to implement two functions:
:targets
- to retrieve list of targets:command
- to format build command after user selects a target
See documentation for transient-compile-tool-alist
for futher details.
By default, transient-compile
automatically detects build tool and directory by searching current directory (as defined by default-directory
) and its parents.
You can force it to use specific tool or directory by setting variables transient-compile-tool
and transient-compile-directory
. It may be handy to set them via .dir-locals.el
or file local variables.
You can override almost every aspect of the default behavior (grouping, sorting, assigning key characters, etc) by toggling various flags or registering custom functions.
See section below for the full list of custom variables.
You can enable verbose logging (to messages) using:
(setq transient-compile-verbose t)
transient-compile
is the main entry point of the package.
Open transient menu for compilation.
The following steps are performed:
- Build tool and directory is detected. See
transient-compile-tool-alist
andtransient-compile-detect-function
. - Available targets are collected according to the
:targets
function of the selected tool fromtransient-compile-tool-alist
. - Targets are organized into groups. See
transient-compile-group-function
,transient-compile-split-function
,transient-compile-sort-function
and other related options. - For each target, a unique key sequence is assigned. See
transient-compile-keychar-function
and other related options. - Transient menu is built. See
transient-compile-menu-heading-function
andtransient-compile-menu-columns-function
for altering its appearance. - Transient menu is opened. Now we wait until selects target using its key sequence, or cancels operation.
- After user have selected target, compilation command is formatted using
:command
function of the selected tool fromtransient-compile-tool-alist
. - Formatted command is padded to
compile
, orproject-compile
, or other function. Seetransient-compile-function
.
After that, transient-compile
closes menu and returns, while the command
keeps running in the compilation buffer.
The following local variables are designed to be bound during the call to transient-compile
.
Currently active compilation tool.
This variable is holding a symbol key from transient-compile-tool-alist
(like ‘make).
Normally, transient-compile
automatically detects tool and directory and binds
transient-compile-tool
and transient-compile-directory
during the call.
If desired, you can manually bind one or both of the variables before calling
transient-compile
to force using of specific tool and/or directory.
Default value:
nil
Currently active compilation directory.
This variable is holding a directory path with the tool-specific build file (e.g. for ‘make it’s the directory with Makefile).
Normally, transient-compile
automatically detects tool and directory and binds
transient-compile-tool
and transient-compile-directory
during the call.
If desired, you can manually bind one or both of the variables before calling
transient-compile
to force using of specific tool and/or directory.
Default value:
nil
Currently active compilation target.
After the user selects target in transient menu, transient-compile
binds this
variable to the selected target during the call to transient-compile-function
(In addition to transient-compile-tool
and transient-compile-directory
).
It may be useful if you provide your own compilation function. Setting this variable manually has no effect.
Default value:
nil
In addition to standard transient faces, transient-compile
adds a couple of its own.
Face used for transient menu heading.
Applied by transient-compile-default-menu-heading-function
.
Default value:
'((t :inherit font-lock-builtin-face))
Introduced in version:
- 0.1
Face to highlight key character inside group or target name.
Applied if transient-compile-keychar-highlight
is t.
Default value:
'((t :inherit font-lock-string-face :underline t))
Introduced in version:
- 0.1
This section provides the full list of supported custom variables. They allow significant changes in transient-compile
behavior, such as algorithms for detecting build tool, grouping and sorting of targets, choosing key characters for transient menu, arranging items on screen, etc.
Function to run compilation command.
You can set it to project-compile
if you’re using project
or projectile
.
Variable type:
(choice (const :tag "compile" compile) (const :tag "project-compile" project-compile) function)
Default value:
#'compile
Introduced in version:
- 0.1
Print what’s happening to messages.
Variable type:
(boolean)
Default value:
nil
Introduced in version:
- 0.1
Assoc list of supported tools.
Alist key is a symbol, e.g. ‘make. Alist value is a plist with the following fields:
:match - list of file names or functions for auto-detection (see below) :exe - executable name or path :chdir - whether to change directory when running :targets - function to get list of targets :command - function to format build command
When you invoke transient-compile
, it performs a search from the current
directory through the parents, until it finds a match with any of the
commands registered in transient-compile-tool-alist
.
A command is matched if any of the elements in its :match
list is matched:
- If an element is a string, it matches if the directory contains a file with that name.
- If an element is a function, then the function is invoked with the directory path, and the element matches if it returned non-nil.
:match
can be also just a string or a function, which is equivalent to
a single-element list.
If multiple tools can be matched, the order of transient-compile-tool-alist
keys defines their precedence.
After a command is matched, it is used to collect targets, build the transient menu, and run the compilation command.
The :targets
property defines a function that takes the matched directory
path as an argument (e.g. where Makefile is located in case of make
), and
returns the list of string names of the available targets.
The :command
property defines a function that takes two arguments: the
matched directory and the target name. It returns a string with the command
to run. The command is then passed to compile
(or other function, as
defined by transient-compile-function
).
:exe
and :chdir
properties are used by the default implementations of
the functions set in :targets
and :command
properties, e.g.
transient-compile-makefile-targets
and transient-compile-makefile-command
.
:exe
is useful when the tool is not available in PATH or is named
differently on your system.
:chdir
defines how to pass matched directory path to the tool:
- when t, we’ll run the tool from that directory
- when nil, we’ll instead pass the directory as an argument
(
:command
function should do it)
Variable type:
(sexp)
Default value:
`( ;; /~https://github.com/go-task/task (task :match ,(lambda (directory) (seq-some (lambda (f) (string-match "^[Tt]askfile\\(\\.dist\\)?\\.ya?ml$" f)) (directory-files directory))) :exe "task" :chdir t :targets transient-compile-taskfile-targets :command transient-compile-taskfile-command) ;; /~https://github.com/casey/just (just :match ,(lambda (directory) (or (member-ignore-case "justfile" (directory-files directory)) (member-ignore-case ".justfile" (directory-files directory)))) :exe "just" :chdir t :targets transient-compile-justfile-targets :command transient-compile-justfile-command) ;; /~https://github.com/pydoit/doit (doit :match ("dodo.py") :exe "doit" :chdir t :targets transient-compile-dodofile-targets :command transient-compile-dodofile-command) ;; /~https://github.com/ruby/rake (rake :match ("Rakefile" "rakefile" "Rakefile.rb" "rakefile.rb") :exe "rake" :chdir t :targets transient-compile-rakefile-targets :command transient-compile-rakefile-command) ;; any POSIX-compliant make (make :match ("GNUmakefile" "BSDmakefile" "makefile" "Makefile") :exe "make" :chdir t :targets transient-compile-makefile-targets :command transient-compile-makefile-command) )
Introduced in version:
- 0.1
Function that detects compilation tool and directory.
Should take no arguments and return a cons, where car is the tool (symbol key
from transient-compile-tool-alist
), and cdr is directory path.
Default implementation is based on :match
lists defined in
transient-compile-tool-alist
for each tool.
For most cases, it should be enough to modify transient-compile-tool-alist
and
there is no need to redefine this function.
You can also temporary bind local variables transient-compile-tool
and/or
transient-compile-directory
instead of redefining this function.
Variable type:
(function)
Default value:
#'transient-compile-default-detect-function
Introduced in version:
- 0.1
The name of the fallback group for targets without group.
Variable type:
(string)
Default value:
"default"
Introduced in version:
- 0.1
Regexp to match group name from target name.
Group name should be captured by the first parenthesized sub-expression.
Used by transient-compile-default-group-function
.
Variable type:
(regexp)
Default value:
"^\\(.+\\)[^[:alnum:]][[:alnum:]]+$"
Introduced in version:
- 0.1
Function that takes target name and returns group name.
If it returns nil, fallback group is used (transient-compile-group-fallback
).
Default implementation uses transient-compile-group-regexp
.
Variable type:
(function)
Default value:
#'transient-compile-default-group-function
Introduced in version:
- 0.1
Function that takes list of targets names and returns assoc list, where key is group name, and value is list of target names in this group.
Default implementation uses transient-compile-group-function
with some
reasonable heuristics.
For most customizations, it should be enough to override either
transient-compile-group-regexp
or transient-compile-group-function
.
Providing custom transient-compile-split-function
is useful when you need
custom groupping logic that takes into account all available targets.
Variable type:
(function)
Default value:
#'transient-compile-default-split-function
Introduced in version:
- 0.1
Function that takes assoc list returned by transient-compile-split-function
,
and returns its sorted version.
The function is allowed to sort both groups and targets inside groups.
Default implementation sorts groups alphabetically, does not sort targets, and places fallback group first.
Variable type:
(function)
Default value:
#'transient-compile-default-sort-function
Introduced in version:
- 0.1
If non-nil, if a target doesn’t have a group, and target name is a prefix of a group name, move target into that group.
Has effect only if you’re using transient-compile-default-split-function
.
Variable type:
(boolean)
Default value:
t
Introduced in version:
- 0.1
If non-nil, if a group has no more than specified number of targets, and there is another group which name is the prefix of the first one, move targets into that prefix group.
Has effect only if you’re using transient-compile-default-split-function
.
Variable type:
(choice (const :tag "Disable" nil) (integer :tag "Threshold"))
Default value:
1
Introduced in version:
- 0.1
If non-nil, if a group has no more than given number of targets, move targets into fallback group.
Has effect only if you’re using transient-compile-default-split-function
.
Variable type:
(choice (const :tag "Disable" nil) (integer :tag "Threshold"))
Default value:
1
Introduced in version:
- 0.1
If non-nil, highlight key characters inside group and target names with
transient-compile-keychar
face.
Variable type:
(boolean)
Default value:
t
Introduced in version:
- 0.1
If non-nil, allow using upcase and downcase variants of the original character as the key character.
Variable type:
(boolean)
Default value:
t
Introduced in version:
- 0.1
Regexp for allowed key characters. Only those characters in group and target names, which match this regex, can become key characters.
Variable type:
(regexp)
Default value:
"[[:alnum:]]"
Introduced in version:
- 0.1
Custom function that chooses unique key character for a word.
The function should take 3 arguments:
- name - group or target name for which we choose a key
- all-names - list of all names, among which the key must be unique
- key-map - hashtable of taken keys
- group-p - whether it’s group or target
The function should return character to be used as a key. Character must not be taken by other words (other groups or other targets in group), i.e. it must not be present in the key-map.
The function can return nil if it doesn’t have a good key. In this case default algorithm is used for this word.
Variable type:
(choice (const :tag "Default" nil) function)
Default value:
nil
Introduced in version:
- 0.1
Function that returns menu heading.
Takes 2 arguments:
- tool - symbol key from
transient-compile-tool-alist
, e.g. ‘make - directory - path to dir where command will be executed
Returns propertized string heading or nil to hide heading.
Variable type:
(function)
Default value:
#'transient-compile-default-menu-heading-function
Introduced in version:
- 0.1
If non-nil, limits maximum allowed number of menu columns.
Used by transient-compile-default-menu-columns-function
.
Variable type:
(choice (const :tag "Unlimited" nil) (integer :tag "Limit"))
Default value:
nil
Introduced in version:
- 0.1
Function that returns menu column count.
Takes assoc list returned by transient-compile-split-function
.
Returns desired number of columns.
transient-compile
will arange groups into N columns by inserting
a break after each Nth group.
Variable type:
(function)
Default value:
#'transient-compile-default-menu-columns-function
Introduced in version:
- 0.1
Authors ordered by first contribution:
- Victor Gaydov (victor@enise.org)
- Sergio Pastor Pérez (sergio.pastorperez@outlook.es)