I have been an org-mode user for a decent amount of time (years? decades? What even is time these days?) Not quite the grandpa “back in my day” length of time that makes people roll their eyes and immediately go back to browsing Reddit on their phones, but I have done a decent amount of customization and adaptations in my workflow over time.
One issue I frequently ran into when integrating org-protocol into my workflow is that several configuration examples lying around the web simply did not work for me. Org-protocol seems to be finicky based on tool versions and system configurations.
This post is an attempt to outline how I use it on my system and to hopefully help anyone with similar problems to solve. It focuses on integrating org-protocol into a workflow along with Firefox and Mutt. Org-protocol obviously integrates with other tools as well, but I do not have experience with anything else at the moment … so here we are. This post is written with the assumption that the system has Emacs installed and that the reader has at least minimal familiarity with org-mode. It is also written from the perspective of a GNU/Linux system, so there may be some adjustments required for other types of environments.
Setup of org-protocol
The first step needed in Emacs itself is to enable org-protocol as a component
of org-mode. Modern versions of org-mode ship with org-protocol. It can be
enabled either by adding it to the org-modules
variable in your .emacs
file,
or via the customization dialog accessible by invoking M-x customize-group
and selecting org
.
Org-protocol works by intercepting messages from emacsclient
. In order for
this work (at least in my experience), the Emacs daemon must be running on the
system. There are fancier ways to set this up as a system service on startup or
on user login, but I just start it with following in my .xinitrc
. Since I am
usually in a GUI environment anyway it has not caused any issues. As long as it
is running in some capacity you should be good to go.
emacs --daemon
There are a few default handlers that org-protocol can use to process incoming data. These are outlined here.
My setup uses org-protocol-capture
since it allows for capture templates, but
org-protocol-store-link
also works well for grabbing links and other
information from a web browser.
To keep things simple I have two capture templates specifically for use with org-protocol - one for website links and one for e-mails. They both file the item as a new TODO item in my Inbox for later processing.
(setq org-capture-templates
(quote (
...other capture templates...
("w" "web site" entry (file+headline org-default-notes-file "Inbox")
"* TODO [[%:link][%:description]] :@web:\n\n %i" :immediate-finish t)
("e" "email" entry (file+headline org-default-notes-file "Inbox")
"* TODO Read/Reply: %:description :@email:" :immediate-finish t))))
To break these down a little:
w: Adds a new TODO item with a link to the web site, using the title of the web site for the name of the link. If any text is currently selected on the page, it will be added to the body of the TODO item.
e: Adds a new TODO item prefixed with “Read/Reply:”. The headline also includes the e-mail subject and the sender.
Usage with Firefox (web browsing)
For Firefox we need to both set up the “bookmarklet” (a bookmark that executes
JavaScript) to store the link, and configure Firefox to use emacsclient
as
the external application with which to open that type of link. I have found
that the following works for links - create a new bookmark with something like
this as the url:
javascript:location.href='org-protocol:/capture?template=w&url='+encodeURIComponent(location.href)+
'&title='+encodeURIComponent(document.title)+'&body='+encodeURIComponent(window.getSelection()
Note the “template=w” section. Replace “w” with whatever you named the corresponding capture template for web sites in your org-mode configuration. When used with the “w” template above, this bookmarklet will create a link with the page title as the description. If any text is selected when the bookmark is invoked, that will be added to the body of the TODO item. If no text is selected, the body will be empty.
Note that there are some other formats for bookmarklets that can be used (links at the end of this post).
Once a bookmark has been created (I recommend adding it to your bookmarks
toolbar for easy access), clicking it while on a website will cause Firefox to
ask you to associate an external application with “org-protocol” links.
Depending on your system that may be in /usr/bin/emacsclient
(or you know …
somewhere else).
After that is selected, it can be changed at any time from the Firefox settings:
Assuming the Emacs daemon is running, invoking that bookmark should add a new capture entry to your org-mode files per the specifications of your capture template. It can then be refiled/edited/etc. like any other entry in org-mode. For example, here is an entry in mine for this post that was made with some text selected on the page:
Note: Depending on your version/build of Firefox, there may be an additional
step required. If the capture does not appear to be working, add the following
option to firefox using the about:config
URL to expose handling for
org-protocol:
network.protocol-handler.expose.org-protocol true
Usage with Mutt (e-mail)
The setup for Mutt is more generalized and can be adapted to other input
sources you may want to use with org-protocol. There are three components to it
(although the first two could easily be combined) - a shell script to actually
call the emacsclient
executable with the appropriate arguments, an Awk script
to pull the subject/sender information out of the e-mail, and of course the
modifications to muttrc
.
The shell script (POSIX) that calls emacsclient
is straightforward. It takes
one argument and uses emacsclient
to send that to org-protocol. The script
below uses the e template, but it can be anything as long as there is a
corresponding named capture template in your org-mode configuration.
#!/bin/sh
if [ -z "${1}" ]; then
echo "The name of the subscript to execute is required."
fi
subscript_result=$(${1})
if [ -z "${subscript_result}" ]; then
echo "The script called did not send anything to stdout."
return 1
fi
emacsclient "org-protocol:/capture?template=e&title=${subscript_result}"
The second script (Awk) extracts header information from the e-mail to send to the script above.
#!/usr/bin/awk -f
BEGIN {
FS=":"
}
/^Subject:/ {
gsub(/^[ \t]+/, "", $2)
subject = $2
}
/^From:/ {
gsub(/^[ \t]+/, "", $2)
from = $2
}
END {
headers = subject " - " from
print headers
}
The remaining piece is the assignment of shortcuts in the muttrc
configuration. In my case the first script is called ec-helper.sh
and the
second is called extract-email-headers.awk
.
macro index <F9> "<pipe-message>/scripts/ec-helper.sh
/scripts/extract-email-headers.awk<Enter>" "Send Message Information to Emacs"
macro pager <F9> "<pipe-message>//scripts/ec-helper.sh
/scripts/extract-email-headers.awk<Enter>" "Send Message Information to Emacs"
With this setup, hitting F9 while using the index or pager in Mutt will add the e-mail subject and sender to the org-mode Inbox similar to the capture from Firefox. For example:
Closing
Hopefully this gives you some ideas for incorporating org-protocol into your workflow. I have found this setup useful for quickly noting websites and videos to be viewed later with minimal disruption. Since the captured item is an org-mode task, it can be searched/edited/expanded as needed.
The Mutt integration is similarly great for tracking e-mails that need some type of follow-up, especially if there is research or information gathering involved since keeping related items in one place follows pretty naturally.
Other Resources
Below are some other resources that I have found useful while setting up and troubleshooting org-protocol.
Org-mode Documentation
Firefox Integration
- http://weblog.zamazal.org/org-mode-firefox/
- http://kb.mozillazine.org/Register_protocol
- https://stackoverflow.com/questions/47647948/getting-org-protocol-to-work-on-firefox-quantum-no-server-buffers-remain-to