The Final Result

Let me start this article by showing you my usage of the functionality described. I work as a Data Scientist and use org-mode in Emacs for a large number of every day tasks. One of them is the documentation of new findings within datasets or other software's documentation or websites etc. In order to easily collect all these informations into a single reference, I like to use screenshots:

The story of this painting is really fascinating, please do check out the book 'A History of the World in 10 1/2 Chapters' by Julian Barnes (Ch. 5)

An example usage of the code presented here.

The only thing "hidden" from this clip is the fact that I hit the combination C-c s right after finishing my sentence. Everything else ran automatically.

The Step-by-Step Guide (there is only one step)

Assuming you run Emacs on Windows 10, the result is extremely simple to achieve. For Windows 7 and 8, I assume that this approach works perfectly fine, I couldn't put this assumption to the test, though. Here is the singe step needed: edit your .emacs or init.el to include the following block:

;;
;; My Function for Screenshots
;;

(defun my-org-screenshot ()
  "Take a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (interactive)
  (setq filename
        (concat
         (make-temp-name
          (concat (buffer-file-name)
                  "_"
                  (format-time-string "%Y%m%d_%H%M%S_")) ) ".png"))
  (shell-command "snippingtool /clip")
  (shell-command (concat "powershell -command \"Add-Type -AssemblyName System.Windows.Forms;if ($([System.Windows.Forms.Clipboard]::ContainsImage())) {$image = [System.Windows.Forms.Clipboard]::GetImage();[System.Drawing.Bitmap]$image.Save('" filename "',[System.Drawing.Imaging.ImageFormat]::Png); Write-Output 'clipboard content saved as file'} else {Write-Output 'clipboard does not contain image data'}\""))
  (insert (concat "[[file:" filename "]]"))
  (org-display-inline-images))

(global-set-key "\C-cs" 'my-org-screenshot)

Copy it in, evaluate it, and you're ready to go: just hit C-c s whenever you are inside an org-mode-buffer and take screenshots at any whim. They will be saved inside your org-mode folder and displayed inline.

The (a little more) detailed description

So, what does the magic function do and how does it do it? There are three major parts:

Creating a Unique Name for the Image

This is the first 4 lines, in which the filename of the buffer, the current time stamp and a random combination of letters (via make-temp_name) is created.

Getting the Screenshot into the Clipboard

This is the function of the line

(shell-command "snippingtool /clip")

which calls the wonderful "SnippingTool" inside Windows and skips all preliminary steps with the command line argument /clip.

Saving the Contents of the Clipboard to Disk

This part took me the longest to figure out. The core idea is that powershell.exe, when called from CMD, has the functionality to save Clipboard contents to file. Hence, the command given here

  • Adds appropriate types for Powershell to understand
  • Checks if the Clipboard contains an image, and if so
  • Saves it to filename, given in step 3.