Inserting images and files in ORG mode


Another useful feature to have while writing documentation or posts is the ability to drag files or images into an ORG file. I made some modifications to the code provided by John Kitchin where the files are actually copied to a local subdirectory of the current buffer. This is convenient when then distributing the org document and the linked files as HTML.

(defun make-buffer-subdir (name)
  (let ((path  (concat (file-name-directory buffer-file-name) name)))
    (make-directory path t)
    (file-name-as-directory path))

(defun copy-and-get-relative-path (path dir-name)
  (let ((file (concat (make-buffer-subdir dir-name) (file-name-nondirectory path)))

    (copy-file path file)
    (concat "./" dir-name "/"  (file-name-nondirectory path))

(defun my-dnd-func (event)
  (interactive "e")
  (goto-char (nth 1 (event-start event)))
  (x-focus-frame nil)
  (let* ((payload (car (last event)))
         (type (car payload))
         (fname (cadr payload))
         (img-regexp "\\(png\\|jp[e]?g\\)\\>"))
     ;; insert image link
     ((and  (eq 'drag-n-drop (car event))
            (eq 'file type)
            (string-match img-regexp fname))
      (insert (format "[[file:%s]]" (copy-and-get-relative-path fname "images")))
      (org-display-inline-images t t))
     ;; insert image link with caption
     ((and  (eq 'C-drag-n-drop (car event))
            (eq 'file type)
            (string-match img-regexp fname))
      (insert "#+ATTR_ORG: :width 300\n")
      (insert (concat  "#+CAPTION: " (read-input "Caption: ") "\n"))
      (insert (format "[[file:%s]]"  (copy-and-get-relative-path fname "images")))
      (org-display-inline-images t t))
     ;; C-drag-n-drop to open a file
     ((and  (eq 'C-drag-n-drop (car event))
            (eq 'file type))
      (find-file fname))
     ((and (eq 'M-drag-n-drop (car event))
           (eq 'file type))
      (insert (format "[[attachfile:%s]]"  (copy-and-get-relative-path fname "files"))))
     ;; regular drag and drop on file
     ((eq 'file type)
      (insert (format "[[%s]]\n" (copy-and-get-relative-path fname "files")))
      (error "I am not equipped for dnd on %s" payload)))))

(define-key org-mode-map (kbd "<drag-n-drop>") 'my-dnd-func)
(define-key org-mode-map (kbd "<C-drag-n-drop>") 'my-dnd-func)
(define-key org-mode-map (kbd "<M-drag-n-drop>") 'my-dnd-func)