Editing org-attach attachments at point

Today I added the following config and in particular iko/edit-attachment-at-point to my config to easily edit inline images with ksnip.

You can use it by calling iko/edit-attachment-at-point while having the point on an attachment: link. Then ksnip is opened and you can edit your image. To end the ksnip process on closing the ksnip window you probably want to disable the tray in the settings, unless you already have ksnip running in the tray.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
(cl-defun iko/run-process-async (name program &key stdin args on-exit)
  "Run PROGRAM asynchronously with ARGS, outputting to BUFFER-NAME."
  (with-current-buffer (get-buffer-create (concat "*" name "*"))
    (let ((b (current-buffer))
          (p (apply #'start-process name (current-buffer) program args)))
      (set-process-sentinel
       p
       (lambda (proc event)
         (when (eq (process-status proc) 'exit)
           (when on-exit
             (funcall on-exit
                      (process-exit-status proc)
                      (with-current-buffer b (buffer-string))
                      proc
                      event))
           (kill-buffer b))))
      (when stdin
        (process-send-string p (if (string-suffix-p "\n" stdin)
                                   stdin
                                 (concat stdin "\n")))
        (process-send-eof p))
      p)))

(defun iko/org-attach-get-absolute-path-at-point ()
  (let* ((ctx (org-element-context)))
    (if (and (eq (org-element-type ctx) 'link)
             (string= (org-element-property :type ctx) "attachment"))
        (let* ((raw (org-element-property :raw-link ctx))
               (file (string-remove-prefix "attachment:" raw))
               (abs (org-attach-expand file)))
          (message "%s" abs)
          abs)
      (user-error "Not on an attachment link."))))

(defun iko/edit-attachment-at-point ()
  (interactive)
  (let ((file (iko/org-attach-get-absolute-path-at-point)))
    (iko/run-process-async "ksnip" "ksnip"
                           :args `(,file)
                           :on-exit
                           (lambda (status-code _output _proc _event)
                             (if (= status-code 0)
                                 (progn
                                   (org-redisplay-inline-images)
                                   (message "Successfully edited %s" file))
                               (user-error "ksnip failed with code %s" status-code))))))
Licensed under CC BY-NC-SA 4.0
Last updated on Nov 28, 2025 13:45 CET
Built with Hugo
Theme Stack designed by Jimmy