Babblings of an aging geek in love with the Absurd, his family, and his own hubris.... oh, and Lisp.

Capturing Content for Emacs

Let’s suppose you are current investigating a new code base, system or other problem, and you are following my advice and copying code, storing output, and taking notes along the way. All of this gets stored into your engineering notebook, aka primary org mode file (for me, this is often my current Sprint page).

Let’s talk about copying that information into your org-mode file…

Sure, selecting code, switching buffers or windows, pasting the code (maybe even jotting down some notes), and then popping back to your original file, may not be many keystrokes, but I dare say, it exacts just a bit of mental tax.

The typical solution to this problem is to use the org-capture feature (see Step 3 of Sacha Chua’s essay, Learn how to take notes more efficiently in Org Mode). While org-capture makes copying content into your org file easy, I am trying to improve on it. What follows is some of my experiments.

The “Current” Task

One mentally taxing aspect of org-capture is determining where something should go. Do you have a dozen (file) reference destinations? I have found the (clock) reference ideal for altering a default destination. Specifically, I begin work on a task, and designate it the focus of my attention (i.e. the destination of my work), by clocking in, using org-clock-in (C-c C-x C-i or , I in Spacemacs).

Now, we can add the following to the org-capture list:

(add-to-list 'org-capture-templates
             `("c" "Item to Current Clocked Task" item
               "%i%?" :empty-lines 1))

This capture destination allows me to easily specify any header as a special destination with a simple clock in. However, we do have the mental interruption associated with creating a new buffer. Let’s minimize that by allowing us to put something on the kill ring, and send it to that clocked-in task:

(add-to-list 'org-capture-templates
             `("K" "Kill-ring to Current Clocked Task" plain
               "%c" :immediate-finish t :empty-lines 1))

The trick here is the use of :immediate-finish, where it doesn’t even bother with a buffer, but just injects the kill-ring contents to the clocked in task without even a sneeze. Don’t want the hassle of sending something to the kill-ring? With this one, you only have to select the text, then kick off the capture:

(add-to-list 'org-capture-templates
             `("C" "Contents to Current Clocked Task" plain
               "%i" :immediate-finish t :empty-lines 1))

In fact, create the following function and keybinding, and you can select text, and immediately copy it to your clocked in task without bothering with the org-capture menu:

(defun region-to-clocked-task (start end)
  "Copies the selected text to the currently clocked in org-mode task."
  (interactive "r")
  (org-capture-string (buffer-substring-no-properties start end) "C"))

(global-set-key (kbd "C-<F17>") 'region-to-clocked-task)

This is great for general textual content, but much of what I want to copy is code, which could bring along a bit of meta data.

Code References

Much of my ideas got started after reading this blog entry where the idea is to have a function gather meta data associated with the currently selected text, and help to leave a back trace to the original code file.

I wanted to copy both code and regular text, so I made ha/org-capture-clip-snippet for wrapping the region in an EXAMPLE:

(defun ha/org-capture-clip-snippet (f)
  "Given a file, F, this captures the currently selected text
within an Org EXAMPLE block and a backlink to the file."
  (with-current-buffer (find-buffer-visiting f)
    (ha/org-capture-fileref-snippet f "EXAMPLE" "" nil)))

And ha/org-capture-code-snippet for getting function name and the code type:

(defun ha/org-capture-code-snippet (f)
  "Given a file, F, this captures the currently selected text
within an Org SRC block with a language based on the current mode
and a backlink to the function and the file."
  (with-current-buffer (find-buffer-visiting f)
    (let ((org-src-mode (replace-regexp-in-string "-mode" "" (format "%s" major-mode)))
          (func-name (which-function)))
      (ha/org-capture-fileref-snippet f "SRC" org-src-mode func-name))))

Both of these function do not do much, but given some values to Nick’s original function (which I’ve modified the format to fit my personal style):

(defun ha/org-capture-fileref-snippet (f type headers func-name)
  (let* ((code-snippet
          (buffer-substring-no-properties (mark) (- (point) 1)))
         (file-name   (buffer-file-name))
         (file-base   (file-name-nondirectory file-name))
         (line-number (line-number-at-pos (region-beginning)))
         (initial-txt (if (null func-name)
                          (format "From [[file:%s::%s][%s]]:"
                                  file-name line-number file-base)
                        (format "From ~%s~ (in [[file:%s::%s][%s]]):"
                                func-name file-name line-number
    (format "

   #+BEGIN_%s %s
   #+END_%s" initial-txt type headers code-snippet type)))

However, content I want to store in an org-mode comes from more than just Emacs buffers.

Output from Terminal Commands

What if the end result of a command sequence on the Terminal was a pipe to a program that could use cat to gather textual data from standard input, and then use emacsclient call org-capture to store it?

Yeah, and interesting idea when sent to the current clocked in task:


$(cat | sed 's/^/     /g')

if [[ -n $TITLE ]]

/usr/local/bin/emacsclient -c -n \
  -e "(progn (org-capture-string \"$CONTENT\" \"C\") (delete-frame))"

Here I’m using our latest C capture template to that just takes textual context and stores is. Let’s try it in action by typing the following in a shell:

date | ec

Works like a charm:

Thu Jun  7 22:45:23 PDT 2018

Content from Browsers

Like many software people, I have a love-hate relationship with browsers. I often find myself copying/pasting information from a web site into my engineering notebook. Pasting text data into an org-mode file looses all text formatting as well as hyperlink references. But operating system clipboards can store some of this formatting data, so we just need to tap into it.

I’m currently using a Mac, so the following is very Mac-centric, but perhaps the ideas can lend you to build a Linux or Windows version (if so, let me know).

I’m going to use Alfred to start this Workflow, as it will allow me to trigger these scripts in succession as shown in this diagram:


The trigger (in this case, every meta-key on a laptop), will start the first script that basically issues the Command-C to copy the selected text to the clipboard:

tell application "System Events" to keystroke "c" using command down

Yes, this works with any application, including browsers.

The next script basically takes the contents of the clipboard (as HTML), render that to an org-compatible format with pandoc (which you’ll need to install), and then use emacsclient to call my org-capture routine with the “C” selection, so that the contents go directly to my clocked in task:

query=$(osascript -e 'the clipboard as "HTML"' | \
            perl -ne 'print chr foreach unpack("C*",pack("H*",substr($_,11,-3)))' | \
            /usr/local/bin/pandoc -f html -t org | \
            sed 's/"//g' | sed 's/^/   /' )

/usr/local/bin/emacsclient -c -n \
                           -e "(progn (org-capture-string \"${query}\" \"C\") (delete-frame))"

The script is a modified version from Roland Crosby. How well does it work? I just selected some of the homepage at orgmode.org, and clocked this header as my current task, and ended up with this getting pasted:

The stable version of Org is *9.1.13*, as of May 2018. See the
[[https://orgmode.org/Changes.html][release notes]].

Get it with =M-x package-install RET org RET= (see
[[https://orgmode.org/elpa.html][Org ELPA]]).

Or download it as a [[https://orgmode.org/org-9.1.13.tar.gz][tar.gz]] or
[[https://orgmode.org/org-9.1.13.zip][zip]] archives.

In other words, it renders quite well…which is especially good, since this pasting business happens completely in the background while I am still surfin’ the web.


My workflow proposal amounts to gathering data from a web browser, shell commands, and source code, and be able to fling it into my engineering notebook without switching out of that application.

Later, I will return to my notebook in Emacs and clean up and summarize my capturing. Once clean, the issues or knowledge I wish to share can then be easily exported from org.

The side-benefit, is that I automatically remind myself to clock in to my task.