diff --git a/config.el b/config.el index 259dbac..f70d6bc 100644 --- a/config.el +++ b/config.el @@ -84,6 +84,64 @@ (after! evil (setq evil-want-clipboard t)) +;;; ============================================================ +;;; CLIPBOARD IMAGE PASTE (macOS — cmd+v) +;;; ============================================================ +;; Requires: brew install pngpaste +;; +;; cmd+v behaviour: +;; clipboard has image → saves to attachments/ → inserts link +;; clipboard has text → normal paste (yank) +;; +;; Org: [[./attachments/image-TIMESTAMP.png]] +;; Markdown: ![image-TIMESTAMP.png](./attachments/image-TIMESTAMP.png) +;; +;; attachments/ is always relative to the current file's directory. + +(defun my/clipboard-has-image-p () + "Return non-nil if macOS clipboard contains an image (requires pngpaste)." + (and (executable-find "pngpaste") + (let ((tmp (make-temp-file "emacs-imgcheck" nil ".png"))) + (prog1 (= 0 (call-process "pngpaste" nil nil nil tmp)) + (ignore-errors (delete-file tmp)))))) + +(defun my/paste-image-from-clipboard () + "Save clipboard image to attachments/ subdir and insert link at point. +File: image-YYYYMMDD-HHMMSS.png. Supports org-mode and markdown-mode." + (interactive) + (let* ((base-dir (if buffer-file-name + (file-name-directory (buffer-file-name)) + default-directory)) + (attach-dir (expand-file-name "attachments" base-dir)) + (filename (format-time-string "image-%Y%m%d-%H%M%S.png")) + (filepath (expand-file-name filename attach-dir)) + (relpath (concat "attachments/" filename))) + (make-directory attach-dir t) + (if (= 0 (call-process "pngpaste" nil nil nil filepath)) + (progn + (insert (pcase major-mode + ('org-mode (format "[[./%s]]" relpath)) + ('markdown-mode (format "![%s](./%s)" filename relpath)) + (_ relpath))) + (message "✓ Image saved: %s" relpath)) + (error "pngpaste failed — no image in clipboard?")))) + +(defun my/smart-paste () + "Paste image if clipboard has one, else normal yank (text paste). +Bound to cmd+v in org-mode and markdown-mode." + (interactive) + (if (my/clipboard-has-image-p) + (my/paste-image-from-clipboard) + (yank))) + +;; Bind cmd+v to smart paste in org and markdown +(map! :after org + :map org-mode-map + "s-v" #'my/smart-paste) +(map! :after markdown-mode + :map markdown-mode-map + "s-v" #'my/smart-paste) + ;; macOS Zoom accessibility — cancel persp-mode's 2.5s cache timer after startup ;; (reduces unnecessary redraws that cause Zoom to jump) (run-with-timer 3 nil