Recent Posts

Org-Mode - Saving Blog Comments in Org-Mode

Update: I added clocking as a feature later.

I like to save my blog comments and other things I post to the web, for a couple reasons. First, once in a while a comment form fails, especially at sites like Blogspot. You spend 20 minutes writing and proofreading a comment, press the submit button, and poof -- an error page and your comment is lost. So saving them provides a backup. But I also like to keep them in case I want to refer back to something I wrote later. Back in the days of Usenet and mailing lists, it was just standard to save outgoing copies of everything. But on the web, it's rare for a site to have that kind of functionality, and it can be difficult to track a comment down with a web search if you can't remember the exact wording -- and there's always the chance a site will go away.

So for a few years now, I've been using an extension for Chromium called Comment Save. It's supposed to save everything you submit in a textarea (the standard multi-line text field). There are some problems with it, though. It's flaky -- sometimes when I go looking for a comment, it doesn't have it. It also doesn't seem to work with some of the sites where I post frequently. It's also only for Chromium/Chrome, and I'd like to shift to Qupzilla for most of my browsing.

I didn't see any promising alternatives, so I started thinking about other ways to do it. I use another extension called Edit with Emacs, which allows you to use Emacs to edit textarea fields. It puts a button next to each textarea, and when you press it, the textarea's contents pop up in an emacs buffer (via a small daemon called edit-server). You edit it there, save it with C-c C-c, and the edited text appears back in the textarea in Chromium. It works pretty nicely, and editing in Emacs is much nicer than editing in a standard text box, but I haven't used it much up to now.

So I started thinking: when I hit C-c C-c to tell edit-server to send the new text back to Chromium, surely I could hack into that code to have it save the buffer to a file. Sure enough, edit-server even provides a hook, edit-server-done-hook, which runs at that point. So I started thinking about how I would arrange the saved comments into a file tree, perhaps arranged by URL/year/month/day, or something like that. Then it hit me -- why not save them into org-mode? It already has journal-style capture functionality, with the ability to save entries by date. Then instead of having them scattered through a bunch of files, I'll have them all arranged in org-mode where I can use familiar tools to search them, back them up, and do whatever else might come to mind.

This sounded very promising, so I got to work. First, I needed a capture template for capturing these entries into a date-arranged tree. I added this to the list in org-capture-templates:

("e" "Edit with Emacs" entry (file+datetree "~/work/org/")
  "* %U\n%i\n\n" :immediate-finish t)

Here's what the elements in that template do:

The key that org-capture will use to specify this template.
"Edit with Emacs"
A description for this template.
The type, in this case a normal org-mode entry with a headline.
The entry will go in a file, specified by the next argument, arranged in a date-tree.
The file into which the entries will be captured.
"* %U\n%i\n\n"
The actual template. This one says the entry has a headline (the *), the %U is replaced with a date-time stamp, and %i is replaced with the edited text buffer contents. Each \n is a newline.
:immediate-finish t
Don't clock in a task or prompt me for anything, just capture it and save it.

In the file, org-capture will automatically create the necessary date-tree outline sections. So if I save a comment today, it will be filed under an outline showing the year, month, and day, with its own date/time-stamp (%U), like this:

* 2015
** 2015-06 June
*** 2015-06-08 Monday
**** [2015-06-08 Mon 21:12]
     A test comment.

Now I just need the code to hook into edit-server and pass the edited buffer contents to this capture template. Here's the code I added to my .emacs:

(defun ajb/save-edit-server-buffer ()
  "Save the edit-server buffer as an org-mode entry via org-capture
   when it is saved with C-c C-c.
   Should be called from edit-server-done-hook."
  (when (not (string-match "edit-server" (buffer-name)))
    (goto-char (point-min))
    (insert (buffer-name) "\n")
    (org-capture nil "e")
    (goto-char (point-min))
    (kill-line 1)))
(add-hook 'edit-server-done-hook 'ajb/save-edit-server-buffer)

It's fairly straightforward, but it took a while to work out the bugs. First, for some reason, the hook gets called twice -- once on a buffer named for the web site where the text came from (like ""), then again for a buffer called " *edit-server*-343434", where the number at the end keeps changing. I'm not sure why it does that, but the (when line handles that by ignoring the buffer with "edit-server" in the name.

The rest is pretty simple. It goes to the beginning of the buffer (goto-char (point-min)), and inserts the name of the buffer and a newline there. I did that so I have the name of the site where the comment came from saved at the beginning of it. It only gives the domain. It might be nice to have the full URL to the page, so I may come back later and see if edit-server has access to that information. But at least this way I know what the comment was about, and I can do a site: search if I need to track down the specific page.

Next it marks the whole buffer for processing by org-capture, which it calls specifying the "e" template that I setup earlier. This is where the actual capture happens, and the buffer is saved in, in the right spot in the date-tree outline.

Next it goes to the beginning of the buffer again, and removes the first line (kill-line 1), which contains the buffer-name that I wrote there earlier. That way the buffer name is saved to, but doesn't show up over in Chromium. In other words, it restores the buffer to the contents it had when the hook was called.

Then the function ends, so edit-server moves on and sends the contents of the buffer back over to Chromium, where I can post it or whatever.

I've tested it a bit, and it works nicely. As I mentioned, I'll probably try to get the full URL instead of just the buffer-name, if possible. Other than that, I can't think of any improvements right now, but something may come to me as I use it for a while. The main thing I'll have to get used to is using Edit with Emacs for all my posting, and not typing quick comments in directly if I want to save them.

I'm still hoping to switch to Qupzilla for more of my browsing, and I don't think there's an Edit with Emacs extension for it, so as a future project I may need to port that over to it.

Update: I added clocking as a feature here.

Posted on: 2015-06-13