This blog is currently written in an awkward mix of
org-mode and jekyll.
Previously my work-flow has been to manually start
jekyll serve -w and
org-mode files from within
emacs. This is a bit tedious
and it diverges from the work-flow I’ve come to expect from my other
projects where saving a file automatically triggers a rebuild.
In this blog post I’ll explain how I was able to export my
files from a
Makefile. You can find the entire solution on Github at
Publishing from the shell
The first step was to figure out how to publish a single
from the shell. Turns out that this could be achieved fairly easily by
using some of the command-line arguments that emacs provide.
emacs \ --quick \ --directory <path-to-org-mode> \ --script init.el \ --eval "(org-publish-file \"<path-to-org-file>\" nil nil)"
Lets look at each of the options:
--quickis used to reduce the boot time of emacs. It’s equivalent to using all of
--no-splash, that is, it will start a bare-bones version of emacs that doesn’t use any of your personal configuration or packages.
--directoryadds a directory to the emacs load path. In this case I use it to add
org-modeto the load path.
emacsto run a file as an Emacs Lisp script. In this case I use it to run a script,
init.el, that configures
org-modeso it knows how to publish my project. Using
--scriptalso has the convenient effect that
emacsdoesn’t start an interactive display; it simply executes the script and exits. Together with
--evalthis means you can use
emacsjust as an interpreter for Emacs Lisp which is exactly what we need in this case.
--evaltells emacs to evaluate an Emacs Lisp expression. The expression that I’m using publishes an
This is all there is to it. Writing a
Makefile that runs this command
.org file and watches for changes to perform a rebuild is
fairly simple (if you know Make, if not I strongly recommend the first
couple of chapters Managing Projects with GNU
Random thought It’s quite fun to play around with using
for its ability to interpret Emacs Lisp. You can play around with it
emacs --batch --eval "(message \"hi there\")"
You could stop here and you would have a nice way to export
from Make. However, I got curious and explored another way to do it. In
the next section I’ll show a way to speed up the build-time a bit – it’s
really not necessary but it is quite fun and it requires a couple of
tricks that might be useful in other scenarios.
Speeding up the build using
emacs has the capability of starting an
emacs server that you can
connect to using
emacsclient. There are various use-cases for this but
in this case we’ll use it to avoid having to start a fresh
instance whenever we want to export an
Keeping the original goal in mind, that
make watch should rebuild the
necessary things whenever a file is saved, here’s what we want to have
Jekyllrunning in server mode so I can see my blog locally and have it rebuild whenever a
- A loop that calls
make buildevery second. This is the simplest solution to re-export my
.orgfiles when they are changed.
Instead of having
make build starting a fresh
emacs every time a
file needs to be build (as we did in the previous section) let us
instead start an
emacs server and connect to it using
This means our
make watch target should have an extra process running:
emacsserver that can export
In order to achieved this we need to use a couple of tricks. I’ll go through each of them now.
A target that runs other targets in parallel
In order to run these three
make targets we’ll introduce the first
xargs -P to start processes. Here’s a
(or well, it’s a multi-line
that supposed to be used with
but I like to think of it as a function) that will run all the
targets you give it in separate processes
# $(call make-parallel, targets) # Runs (sub) make targets, with each target running in a separate process define make-parallel $(call print-rule,$0,$1 - [$(words $1) targets]) $(QUIET)echo $1 | xargs -n 1 -P $(words $1) \ $(MAKE) --no-print-directory -f $(firstword $(MAKEFILE_LIST)) endef
I then use it like this to run three targets in parallel
watch_targets := \ _watch-continous-make \ _watch-jekyll-server \ _watch-emacs-server watch: $(call make-parallel, $(watch_targets))
make watch will result in three invocations of
running in parallel, namely
make _watch-emacs-server. When I hit
(control-c) all of the processes are killed (as long as the targets
are running in the foreground).
Starting and stopping an
Now to the next piece of the puzzle, namely how to start, communicate
with, and stop and
Starting & stopping the server
By using the emacs command-line option
--daemon=<daemon-name> you can
start an emacs server and give it a specific name. We explicitly give
the daemon a name so we can refer to it later. Here’s how the emacs
daemon is started.
emacs \ --quick \ --directory <path-to-org-mode> \ --script init.el \ --daemon=<daemon-name>
org-mode I’ve added an extra important thing to
init.el file that is required in order to start many daemons and
emacsclient communicate with a specific one:
;; If non-nil, use TCP sockets instead of local sockets. (setq server-use-tcp t)
Alright, so that’s how to get the
emacs server up and running but
there’s one problem. When using the
emacs will run
in the background. That’s a problem as my
requires that all the targets run in the foreground in order to be
able to shut them down once I hit
^C. In order to fix this I came up
with this little hack.
#! /bin/sh trap "emacsclient --server-file=$1 --eval '(kill-emacs)'; exit" SIGINT SIGHUP SIGKILL tail -f /dev/null
It’s a shell script that will run forever (this is achieved by
tail -f /dev/null. However it also registers a
SIGKILL events. The
trap kills the server by using
emacsclient to send
(kill-emacs) to the server.
So the final
_watch-emacs-server target looks like this
# Starts emacs in server-mode, blocks until SIGINT/SIGHUP/SIGKILL is # sent and then shuts down the emacs server instance. _watch-emacs-server: $(QUIET)emacs \ --quick \ --directory $(abspath $(setup.dir)/org-$(org_version)/lisp) \ --script init.el \ --daemon=$(strip $(emacs_daemon_name)) $(if $(QUIET),&> /dev/null,) $(QUIET)sh wait-and-shutdown.sh $(emacs_daemon_name)
Communicating with the server
Once the daemon is running you can start an
emacsclient and use it to
.org file like this.
emacsclient \ --server-file=$(strip $(emacs_daemon_name)) \ --eval "(org-publish-file \"<path-to-org-file>\" nil nil)"
The last trick is to create a make target that simply calls
# Calls `make build` every second. _watch-continous-make: $(QUIET)while true; do \ sleep 1; \ $(MAKE) \ -f $(firstword $(MAKEFILE_LIST)) \ -no-print-directory \ uild WATCH_MODE=1 \ | grep -v "Nothing to be done for" ; \ done
That’s it. I hope you learned a few