Accumulating Clipboard

March 5, 2021
Katamari Damacy image of a big rolling ball

I regularly read and digest large amounts of text with the intent of summarizing or quoting parts of it.1 My typical workflow for this is to have both the source documents and a blank target document open; As I find interesting text, I’ll select and copy the text, switch to the blank target document, and then paste it.

But it can be annoying to have to switch focus back and forth from app to app, especially when the source text is large.

I built a clipboard hack recently that’s helped a lot - the “accumulating” clipboard.2 It consists of a single new hotkey - hyper-C - which accumulates whatever is selected in the focused app instead of doing the normal Cmd-C copy behavior where the previous contents of your clipboard get completely replaced by the new copied content.

This lets you “build” up the text you want just by changing your selection and then activating the hotkey - no app switching of any kind is needed until you are done grabbing all the text snippets you want. At that point, a standard Cmd - V paste deposits your text into the destination doc.

The Tech Details

I use Hammerspoon to build this functionality. In your HammerSpoon init.lua:

hyper:bind({}, 'c', nil, function() 
  -- get and "save" the current contents of the pasteboard
  local board = hs.pasteboard.getContents()

  -- copy the selection from the current app by sending sending cmd-c. The pasteboard now contains just that content.
  hs.eventtap.keyStroke({"cmd"}, "c")

  -- concatenate the two pieces of content and stick it back in the pasteboard
  board = board .. " | " .. hs.pasteboard.getContents()

I liked how surgical this felt. It uses the existing clipboard so Cmd-C and Cmd-V all continue to work normally, and it adds a single new function that really expands how I use copy and paste.

  1. For example, producing a summary of the week’s work, or doing reviews. ↩︎

  2. There are several smart clipboard apps, but most seem to focus on clipboard histories and / or are more complex than what I wanted. ↩︎