Run, evaluate and compile functionality for a variety of different languages
and modes. The specific "compilation" method is different across each add-on
library, which are called flexible compilers. For example, for ESS and
Clojure you can evaluate a specific file and/or evaluate a specfic expression
via a REPL. For running a script or starting a make
an async process is
started.
- Introduction
- Configuration
- Usage
- Compiler Configuration
- Compilers
- Invoking a Compiler Programmatically
- Writing Your Own Compiler
- Changelog
- License
The general idea is the keybindings to compile you get use to are "switched" to whatever specific problem you're working on. For example, if you're compiling with a makefile, use the make compiler to initiate an make process. If you're working with a REPL based langauage (i.e. flex-compile-python, flex-compile-clojure etc) instead a buffer or expression is evaluated.
Many of the "compilers" (i.e. the flex-compile-command and flex-compile-script) don't do much more than invoke a function or execute a script. However, when jumping between several development tasks the strength of the library comes from easily switching between compilers using the same keybindings and finger muscle memory to invoke them.
To install the package from MELPA, add the following to your ~/.emacs
file:
(unless (assoc-default "melpa-stable" package-archives)
(add-to-list 'package-archives
'("melpa-stable" . "https://stable.melpa.org/packages/") t))
(use-package flex-compile
:ensure t
;; recommended global key bindings
:bind (("C-x C-p" . flex-compiler-do-activate)
("C-x C-u" . flex-compiler-do-compile)
("C-x C-y" . flex-compiler-do-clean)
("C-x C-i" . flex-compiler-do-run-or-set-config)
;; clobbers `delete-blank-lines'
("C-x C-o" . flex-compiler-do-eval)))
This loads the library and creates global key bindings.
Most flexible compilers (any subclass of config-flex-compiler
) define a
specific source file called the config file.
There are the operations (also included are the given key bindings):
- Choose a Compiler (
C-x C-p
orM-x flex-compiler-do-activate
): select/activate a flex compiler. - Set Configuration (
C-u C-x C-u
orC-u M-x flex-compiler-do-compile
): This allows the configuration of the compiler. In most compilers the first step is to select the property, then the configuration for that property is prompted. In some cases a specific property is set, like the Make compiler jumps to the target. All properties are always available for configuration withC-u 0 C-x C-u
. - Select or Get Information (
M-x flex-compiler-do-list
): This displays a list of available compilers that are selectable with RET or provide documentation and configuration with?
. In addition,e
configures the compiler. - Prompt for Config File (
C-u 1 C-x C-u
orC-u 1 M-x flex-compiler-do-compile
): This the file the compiler will use. For example, the Script compiler will run selected script file and display the output on compile. For REPL compilers, like the Python copiler, the starting directory can also be set (see Set Configuration).. - Set Config File (
C-u 1 C-x C-i
orC-u 1 flex-compiler-do-run-or-set-config
): This sets the config file to compile, run or interpret. The term config is a nomenclature and examples includeMakefile
,.clj
,.r
,.sh
files. - Go to Config File (
C-u C-x C-i
orC-u M-x flex-compiler-do-run-or-set-config
): This displays the config file/buffer to the current buffer. For some compilers, this also displays the interactive (i.e. REPL) buffer. See the reveal buffer section for more information, and specifically how to force show the buffer. - Compile (
C-x C-u
orM-x flex-compiler-do-compile
): This is the default make something command. For make it invokes the first target, for REPL languages like Clojure and ESS it evaluates a.clj
or.r
file. - Run (
C-x C-i
orM-x flex-compiler-do-run-or-set-config
): This starts invokes arun
target for make, starts the REPL for REPL type languages. - Evaluate (
C-x C-o
orM-x flex-compiler-do-eval
): This invokes the compiler's evaluation functionality. For REPL based languages, this evaluates the current form and stores the result in the kill buffer. - Clean (
C-x C-y
orM-x flex-compiler-do-clean
): This invokes theclean
target for make and kills the REPL for REPL based compilers. - Generate Compiler Docs (
M-x flex-compiler-doc-show
): this generates the documentation given in the compilers section (verbatim).
Each compiler also has configuration setting ability, which is invoked with the
C-u
universal argument to the compile C-x C-u
invocation per the
aforementioned flex-compiler-do-run-or-set-config
.
Some compilers are configured differently for the default configuration key
binding. For example the make compiler sets the make target defined
in the make file, and in this case uses C-u 0 C-u
to set configuration
properties.
This package uses a configuration system that moves the responsibility out of
the specific compilers for configuration. This package extends from the
config-manage
framework in the buffer manage library by extending and
building configuration meta data. For example, the M-x flex-compiler-list
lists available compiler with ?
providing information and e
configuring the
compiler.
One of the features of the flex compiler library is it provides specific
behavior on example where and how to display buffers, which is a compiler
configuration. These buffers are usually interactive buffers, i.e. REPL
buffers. Any compiler that extends single-buffer-flex-compiler
has this
capability, which include the following:
- flex-compile-make
- flex-compile-command
- flex-compile-cli
- flex-compile-script
- flex-compile-clojure
- flex-compile-python
- flex-compile-ess
- flex-compile-xml-validate
- flex-compile-choice-program
The two properties for these compilers include:
- Buffer New Mode: used when the interactive buffer is created.
- Buffer Exists Mode: used when the interactive buffer is already exists.
These can be set to the Global settings, which means to take it from the
customzied variables flex-compile-single-buffer-display-buffer-new-mode
and
flex-compile-single-buffer-display-buffer-exists-mode
. These variables and
the compiler level properties can be set to one of:
- Switch to Buffer means to first pop then switch to the buffer.
- Display Buffer means to show the buffer in a different window.
- Next Frame Otherwise Switch means to use the next frame if there are multiple frames, otherwise pop and switch to the buffer.
- Next Frame Otherwise Display means to use the next frame if there are multiple frames, otherwise show buffer.
- Next Frame Skip Switch means to do nothing there are multiple frames, otherwise pop and switch to the buffer.
- Next Frame Skip Display means to do nothing there are multiple frames, otherwise display the buffer.
- Never means to never show the buffer.
- Only If Error means to display the buffer if at least one error was detected such a compilation error with the make compiler. Note: and not all compilers support this option.
The decision of where to show a buffer (or not) happens either when the
interative buffer is created or during a compilation. In many cases you might
not want to ever show the buffer, so you could set both buffer new
and
exist
properties to never. In this case, you still force the interactive
buffer with C-u 2 C-x C-i
or C-u 2 M-x flex-compiler-run-or-set-config
.
Concrete instances of flexible compilers that provide a common interface. Each is an implementation of glue code to the respective compilation method.
Note that all compilers that extend from conf-file-flex-compiler
, which
include make
, script
, xml-validate
, org-mode
, python
, clojure
, and
ess
have their start-directory
property unset each time the config-file
is set.
This documentation was generated with M-x flex-compiler-doc-show
.
Prompt and more easily invoke choice/action based programs using the Choice Program Emacs library.
Properties:
- Program: An instance of
choice-program
. - Action: The action to invoke on the program.
- Buffer Exists Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-exists-mode
. - Buffer New Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-new-mode
. - Kill Buffer Clean: If non-nil kill the buffer on clean.
Provides support for user input for action mnemonics and options using Python programs that use the Zensols action CLI.
This compiler gets the command line metadata as a list of actions and their respective positional and option arguments. It this prompts the user with documentation associated, first the action, then the action's arguments. Finally, it constructs the command line and executes the Python program with the arguments.
Properties:
- Action: The action to invoke on the program.
- Config File: The file to use for configuring the compiler.
- Arguments: The arguments to give to the script.
- Cache Metadata: Whether or not to cache the Python program's CLI metadata.
- Buffer Exists Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-exists-mode
. - Buffer New Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-new-mode
. - Kill Buffer Clean: If non-nil kill the buffer on clean.
- Start Directory: The directory for starting the compilation.
This is a REPL based compiler that allows for evaluation Clojure buffers, expressions and starting the REPL using Cider.
The Clojure compiler connects using two Cider modes: the default jack-in
mode or connecting to a host and port remotely with cider-connect
. You can
switch betwee these two methods with the given keybindings:
M-x 1 C-u C-x C-u
See documetation with M-h f flex-compiler-query-eval
method for more
inforamtion (and current binding).
Todo: support multiple Cider buffers as this implementation currently does not.
Properties:
- Config File: The file to use for configuring the compiler.
- Buffer Exists Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-exists-mode
. - Buffer New Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-new-mode
. - Kill Buffer Clean: If non-nil kill the buffer on clean.
- Connect Mode: Defines how to connect to a Clojure REPL.
- Repl Port: The port running the REPL; default: 32345
- Output Clear: Whether or not to clear comint buffer after a compilation.
- Prompt Kill Repl Buffer: If non-
nil
then prompt to kill a REPL buffer on clean. - Repl Buffer Start Timeout: Number of seconds as an integer to wait to start before giving up (and not displaying).
- Repl Buffer Start Wait: Number of seconds (as a float) to wait before issuing any first command to the REPL.
- Start Directory: The directory for starting the compilation.
Send text to any running comint
buffer.
This is useful for entering a command in a shell, SQL etc buffer that otherwise
requires switching back and forth between buffers, which is a hassle.
Properties:
- Config File: The file to use for configuring the compiler.
- Content: The string to insert in the buffer referred by the
buffer
slot. - Buffer: The buffer to insert the
content
slot. - Start Directory: The directory for starting the compilation.
This "compiler" is more of a convenience to invoke an Emacs Lisp function or
form. This is handy for functions that you end up invoking over and over with
M-x
(i.e. cider-test-run-ns-tests
). See motivation.
Properties:
- Sexp: The symbol expression to evaluate.
A no-op compiler for the disabled state.
This is a REPL based compiler to evaluate R code with Emacs Speaks Statistics .
Properties:
- Config File: The file to use for configuring the compiler.
- Buffer Exists Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-exists-mode
. - Buffer New Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-new-mode
. - Kill Buffer Clean: If non-nil kill the buffer on clean.
- Output Clear: Whether or not to clear comint buffer after a compilation.
- Prompt Kill Repl Buffer: If non-
nil
then prompt to kill a REPL buffer on clean. - Repl Buffer Start Timeout: Number of seconds as an integer to wait to start before giving up (and not displaying).
- Repl Buffer Start Wait: Number of seconds (as a float) to wait before issuing any first command to the REPL.
- Start Directory: The directory for starting the compilation.
This is a REPL based compiler that allows for evaluation Lisp buffers and expressions using slime.
Properties:
- Config File: The file to use for configuring the compiler.
- Buffer Exists Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-exists-mode
. - Buffer New Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-new-mode
. - Kill Buffer Clean: If non-nil kill the buffer on clean.
- Compile On Load: Whether to also compile when loading the source file.
- Output Clear: Whether or not to clear comint buffer after a compilation.
- Prompt Kill Repl Buffer: If non-
nil
then prompt to kill a REPL buffer on clean. - Repl Buffer Start Timeout: Number of seconds as an integer to wait to start before giving up (and not displaying).
- Repl Buffer Start Wait: Number of seconds (as a float) to wait before issuing any first command to the REPL.
- Start Directory: The directory for starting the compilation.
This compiler invokes make as an asynchronous process in a
buffer. The first target, run
target, and clean
target are
invoked respectfully with compile, run and clean Emacs
commands (see usage).
This is a special compiler in it's configuration. Instead of
setting properties, the default configuration mechanism is to set
the make target instead. If you want to set a flex compiler
property, use \C-u 0 \C-u
.
When setting the configuration file the target property is unset.
Properties:
- Config File: The file to use for configuring the compiler.
- Target: The make file target to satisfy.
- Run Target: The target used to run or test as the secondary compilation functionality.
- Buffer Exists Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-exists-mode
. - Buffer New Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-new-mode
. - Kill Buffer Clean: If non-nil kill the buffer on clean.
- Start Directory: The directory for starting the compilation.
This compiler exports Org mode to external formats and then shows the output in the browser. Only HTML is currently supported.
Properties:
- Config File: The file to use for configuring the compiler.
- Export Fn: The Org mode export function.
- Open File: Whether to open the file after exported.
- Output Directory: The output directory.
- Frame Focus Command: The command to refocus the Emacs frame after rendering the output (browser).
- Frame Focus Delay: Seconds before refocusing the Emacs frame after redering the output.
- Start Directory: The directory for starting the compilation.
This is a REPL based compiler that allows for evaluation Python buffers and expressions using python mode.
Properties:
- Config File: The file to use for configuring the compiler.
- Buffer Exists Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-exists-mode
. - Buffer New Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-new-mode
. - Kill Buffer Clean: If non-nil kill the buffer on clean.
- Output Clear: Whether or not to clear comint buffer after a compilation.
- Prompt Kill Repl Buffer: If non-
nil
then prompt to kill a REPL buffer on clean. - Repl Buffer Start Timeout: Number of seconds as an integer to wait to start before giving up (and not displaying).
- Repl Buffer Start Wait: Number of seconds (as a float) to wait before issuing any first command to the REPL.
- Start Directory: The directory for starting the compilation.
This compiler runs a script with optional arguments in an async buffer. See motivation.
Properties:
- Config File: The file to use for configuring the compiler.
- Buffer Exists Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-exists-mode
. - Buffer New Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-new-mode
. - Kill Buffer Clean: If non-nil kill the buffer on clean.
- Arguments: The arguments to give to the script.
- Start Directory: The directory for starting the compilation.
Implementation compiler for XML validation using command line xmllint command line tool.
Properties:
- Config File: The file to use for configuring the compiler.
- Schema File: Location of the schema file to validate against.
- Buffer Exists Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-exists-mode
. - Buffer New Mode: Compiler instance of
flex-compile-single-buffer-display-buffer-new-mode
. - Kill Buffer Clean: If non-nil kill the buffer on clean.
- Start Directory: The directory for starting the compilation.
There might be instances where it's necessary to execute other actions along with a compilation. If you know Emacs Lisp, you can create your own function to invoke other compilers, and then use the Command compiler to invoke it as a command (an interactive function), such as:
(defun clean-and-call-python-compiler ()
"Invoke `make clean', then call the Python compiler."
(interactive)
(shell-command "make clean")
(let ((this (flex-compiler-by-name "python")))
(flex-compiler-compile this)))
Other Emacs Lisp snippets that do things with compilers:
;; names of compilers
(let* ((this flex-compile-manage-inst)
(names (config-manager-entry-names this)))
names)
;; the currently set compiler's name and descriptor
(let* ((this flex-compile-manage-inst)
(active (flex-compile-manager-active this)))
(format "Current compiler: %s (desc: %s)"
(slot-value active 'object-name)
(slot-value active 'description)))
;; get a compiler by name and set its configuration file
(let ((this (flex-compiler-by-name "python")))
(with-slots (config-file start-directory) this
(setq config-file "~/work/src/example.py"
start-directory "~/work")))
;; run the compiler
(let ((this (flex-compiler-by-name "python")))
(flex-compiler-compile this))
;; set the active compilerby name
(let ((this flex-compile-manage-inst))
(config-manager-activate this "python"))
Writing your own flexible compiler is pretty easy if you know how to write Emacs object oriented programs. Even if you don't, you should be able to find a compiler already written that follows your use case among those concerete (see compilers) that are already given in this package. You can also submit an issue (see the contributing instructions).
An extensive changelog is available here.
Copyright © 2017-2023 Paul Landes
GNU Lesser General Public License, Version 2.0