Patch Emacs org-open-file using advice.
Contents
Background.
On Windows, I run Emacs on WSL 1 whilst displaying to Windows via the X410 X-Server.
This is currently the best compromise if one wants to interoperate with the NTFS side, at least until the WSL 2 developers manage to fix up its current cross-OS IO performance issues.
As part of this setup, I have written a small xdg-open replacement in Python which does path translation. This enables me to open any links from Emacs, running on WSL 1, using the relevant Windows file handler, no matter whether the file finds itself on the Windows or the WSL side of the world.
For example, if I’ve linked to a PPTX from my orgmode notes, pressing C-c C-o
opens up that file using the true-blue Microsoft PowerPoint application on
Windows. The same goes for any attachments that I open using mu4e, my favourite
Emacs mail client.
This gives me the best of both worlds between Emacs on the WSL-Linux side, and all of the Windows applications on the other.
100% CPU blocking bug.
Recently however, I ran into a bug where only orgmode links would result in the
Windows cmd.exe
or explorer.exe
process (which I use as the catch-all URL
filetype opener) blocking while eating up 100% CPU, but with the handler never
actually appearing.
Opening up non-orgmode links, for example with Emacs browse-url
, would work
perfectly.
Analysis.
Once I found time to dig into the difference above (discovering the difference
took weeks, as I only ever spent a few minutes at a time before working around
the problem. Fortunately I took good notes in Orgmode! ;) I discovered that
browse-url
used call-process
and org-open-file
used
start-process-shell-command
.
When I temporarily changed the code of the fairly long org-open-file
function
to use call-process-shell-command
, it worked perfectly!
The fix.
Because this is Emacs Lisp, we have a number of great ways to fix the function.
In this case, I chose to
advise the 150 line long
org-open-file
function to use call-process-shell-command
instead of
start-process-shell-command
.
I added the following code to my init.el
:
|
|
- With
advice-add
and:around
, we ask that Emacs call our special wsl function instead oforg-open-file
, whenever the latter is invoked. - Our replacement function receives the original “unfixed”
org-open-file
and its arguments. - With
cl-letf
, we temporarily replacestart-process-shell-command
withcall-process-shell-command
, only while we invoke the originalorg-open-file
.
Conclusion.
The elegance and precision with which it is possible to modify the run-time behaviour of Emacs, is one of the many reasons that this 40-year-old editor is still the king.
Tangential Post Scriptum.
Emacs is always running on my computers.
However, I will also use VSCode and any of the JetBrains IDEs when the relevant tool suits the job better.
That being said, I am still waiting for any other editor to come close to the same level of integration between extension code and runtime behaviour that Emacs offers.
In Emacs, I can write and interact with code to modify just about any aspect of the editor at runtime. VSCode, for example, offers only limited possibilities via its extension API.
Leave a comment if you would like to discuss!