Using the function subemacs-eval
, a form can be synchronously
evaluated in a freshly started Emacs process, which inherits only
the load-path
from the current process.
Other values must be passed explicitly by making them part of the form, e.g. by writing
(let ((my-int 10))
(subemacs-eval `(+ 5 ',my-int)))
=> 15
subemacs-eval
also supports errors raised by Emacs' signal
and
related functions, and displays messages emitted in the subprocess.
The original motivation for writing this package was Emacs Lisp
byte-compilation. When byte-compiling a file from within a running
Emacs process, missing require
calls for dependencies and typos
may be hidden from the byte compiler due to the environment already
containing them.
Such issues may not become apparent until the code is executed by a
user, who does not load the same files during startup. While they
can be diagnosed by testing code with emacs -Q
, this solution is
inconvenient.
Instead, compiling Emacs Lisp files in a clean process by default turns the byte-compiler into a powerful ad-hoc tool to identify issues from byte-compiler warnings.
Functions subemacs-byte-compile-file
and
subemacs-byte-recompile-directory
are therefore provided and also
serve as a demonstration of the use of subemacs-eval
.
Originally I had planned to implement subemacs-funcall
, as
passing functions to the subprocess would allow compile-time
checking of the passed expressions for issues.
Passing a lambda
form to a hypothetical subemacs-funcall
in an
environment where lexical-binding
is enabled, will capture the
lexical environment into the resulting closure
form and make it
available to the subprocess. This behaviour however is not
documented and may break in the future. As a consequence an
implementation of subemacs-funcall
would either require enforcing
unexpected limitations (e.g. not allowing closures) or risk the
creation of code that depends on an undocumented feature of current
Emacs versions.
Passing a quoted lambda
form would avoid these problems, but
would also sacrifice compile-time checks, and thus the only
advantage.
async.el implements a
superset of the functionality of subemacs.el
, with
async-sandbox
having essentially the functionality of
subemacs-eval
. However, a few complementary properties allow
subemacs.el
to remain useful.
-
subemacs-eval
forwards the STDOUT and STDERR of the subprocess and allows access to the contents as a string.async-sandbox
does not. -
With
subemacs-byte-compile-file
, the module contains a useful development tool, that is optimized for quickly checking against compiler warnings. -
On Windows at least,
async-sandbox
has more overhead.(async-sandbox '(lambda ())) ; ≈ 0.75 seconds (subemacs-eval '(progn)) ; ≈ 0.35 seconds
-
On Windows, I sometimes experience
async-sandbox
hanging, while I never had such a problem withsubemacs-eval
.
- Rewrote
subemacs-byte-compile-file
. - Adjusted README text to describe usecases compared to
async.el
.
Original release. Supports exclusively synchronous execution.