2018-08-18 Embedding files in Org-mode revisited

Some time ago I published a snippet of Elisp code to embed arbitrary files in Org-mode files using Base64 encoding. I was recently asked if it was possible to view this image.

Well, this being Emacs, of course it’s possible. The question is, how exactly. One way would be to call xdg-open (or equivalent) right after decoding the file to somewhere in the filesystem. (The file must be Base64-decoded, at least to some temporary directory, for any external program to do anything with it.) While I didn’t check it, I heard that the openwith mode might help with this.

Another possibility is to embed links to the files in the Org-mode file itself. This has the advantage of not having to run an external program and the disadvantage that it won’t “show” audio or video in the same way as images.

Anyway, here’s an updated version that inserts a link to the file you have just inserted. In the previous version, you had to change the filename manually; here, I decided to do this automatically (I just strip the path so that the file becomes local to the current directory).

(defun org-insert-file (filename)
      "Insert Elisp code block recreating FILE in the current
directory."
      (interactive "f")
      (let ((basename (file-name-nondirectory filename))
	    (base64-string
	     (with-temp-buffer
	       (insert-file-contents-literally filename)
	       (base64-encode-region (point-min) (point-max))
	       (buffer-string))))
	(save-excursion
	  (insert (format "[[./%s]]\n#+BEGIN_SRC emacs-lisp :results output silent\n  (with-temp-file %S\n    (insert (base64-decode-string\n      %S)))\n#+END_SRC" basename basename base64-string)))
	(forward-line)
	(copy-file filename basename 1)
	(org-display-inline-images)))

Notice a few things about this code. First of all, we use the file-name-nondirectory function, which strips the directory part from the filename. The forward-line is a nicety so that the point won’t end up invisible on the image. In order to copy the file to the current directory, we use the copy-file function with a third argument being any integer (this means that we allow overwriting a file, but request an explicit user confirmation for that). Finally, we turn on displaying inline images (which won’t do much good if the file is not an image – but in that case, we will just have a link, hopefully one that can be opened with C-c C-o).

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode