Hello all! Welcome to EmacsConf 2021.
I'm Tom Gillespie.
Thank you to the organizers for
all your hard work,
and for inviting me to
give this short talk on
"Org as an executable format".
The links to the talk page,
the GitHub page for the project,
and the package on MELPA
are listed on the right.
Let's start with one of the motivating
use cases for executable Org files.
Many users keep global configuration
for Org in an init.el file,
which works for many workflows.
However, for reproducible research,
this is a challenge
because if an Org file is
dissociated from the init.el file,
then often it will no longer
function as expected.
One potential solution to this problem
is to be able to include all of the
global configuration for Emacs
and the environment in the Org file itself,
in which case when you
go to reuse the Org file,
it will work as expected.
What does an executable Org file
look like in action?
Here's a demo of an executable Org file
running in Bash, Dash, Zsh, and PowerShell.
So, we are currently in Bash,
and we can run our demo,
and it will print some stuff,
and wait for input.
We can also run it in Dash,
which is the default for Debian
and derivatives.
Same program works as expected.
Zsh also. And lastly PowerShell,
if we try to run demo.org itself,
we see (that) we get an error
because PowerShell cares
about file extensions,
so, if we symlink to ps1,
then it works as expected,
and there are ways to alias this,
so that you can run it as a program
without the ps1 extension.
So, how does this work?
There are three components
to an executable Org file
that all need to be present
in order for this to work.
Starting from the top of the file,
we have a shebang block.
Next we have an Org Babel block
written in Emacs Lisp,
which is what we actually saw executing,
and then there are some
eval local variables or Elvs
that are involved in making this
actually executable.
Let's start with the shebang block.
Org syntax does not have support
for shebang lines.
However, it supports the shebang block.
This is because Org comments, blocks,
keywords, etc. that start with the
sharp sign have the same syntax as
comments in POSIX and PowerShell.
This block is in fact valid
Bash, Dash, Zsh, PowerShell,
and maybe some other shells as well.
In essence what it does is,
perform some setup
to avoid polluting standard output,
and then it runs Emacs
to load the file itself.
The Elisp that is passed on the command line
is explicated over here on the right,
and in essence what it does is,
to keep the startup time minimal
and as low as possible,
it loads the absolute bare minimum
needed for Babel,
and then it calls hack-local-variables
triggering the eval-local-variables.
What do the eval-local-variables do,
and how those work?
The essence of the approach is to
use org-confirm-babel-evaluate
to allow Babel execution.
We can't set it to nil because that is
an arbitrary code execution vector,
which we don't want if we're sharing files.
Instead what we do is,
we use the fact that it can be a function,
and we normalize the block of code,
we checksum it, and then we check
that it matches this checksum up here
at the top of the file,
and then sort of inside there,
inside of org-sbe,
which is Org source block evaluate,
we call the block.
The actual implementation of this
is somewhat more complicated.
However, it's small enough to fit in
the local variables at the end of the file.
One thing to note is that
if you are using PowerShell,
PowerShell parses the whole file
which means that
for any normal Org content,
you need to put it in
a multi-line PowerShell comment,
and close it.
So, once we hit
hack-local-variables at the end,
we run the eval-local-variables block,
then we enter this Elisp block,
and you can write whatever you want.
All the power of Org Babel is
now at your fingertips
in order to do what you need
for this file.
Finally, let's do a quick demo
of how to use this to make
your own Org files executable.
Orgstrap is available on MELPA as mentioned,
and it can be installed using package.el
by calling package-install orgstrap.
It will download, and it will install.
Then you can open an existing file
or a new file. In this case,
let me open a file called example.org.
And then orgstrap provides
command called orgstrap-init.
What orgstrap-init does is,
it populates a file with the machinery
needed to run an orgstrap block.
We're just going to do a message
"hello orgstrap!".
If you look up at the top,
you will see that the
orgstrap-block-checksum will change
when I save the file.
This makes it much easier to author files
with orgstrap blocks.
And then we need one last piece
of machinery,
which is the shebang block.
I am just going to steal
the shebang block from
this other file over here
since it is available.
You can also get it from shebang.org,
and I have plans to add a command
to insert this into the file directly,
which may actually be done by the time
this video is actually posted and visible.
There's one last step,
which is that we need to run dired
in order to… There we go.
So, we use Shift m, capital m,
in order to make our
example file executable,
and then if we come back to here,
we see that example.org is now executable,
and we can run it.
"hello orgstrap!", and we're done.
So, that's the basic workflow
for getting orgstrap files
to be executable.
I will be around to answer questions live,
and I will be also available in
the #emacsconf IRC channel all day.
I hope you have found this useful,
and thank you very much for watching.
[captions by bhavin192 (Bhavin Gandhi)]