From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp10.migadu.com ([2001:41d0:306:2d92::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms8.migadu.com with LMTPS id AHw+DlFHNmXQJQEAG6o9tA:P1 (envelope-from ) for ; Mon, 23 Oct 2023 12:13:37 +0200 Received: from aspmx1.migadu.com ([2001:41d0:306:2d92::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp10.migadu.com with LMTPS id AHw+DlFHNmXQJQEAG6o9tA (envelope-from ) for ; Mon, 23 Oct 2023 12:13:37 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 8204E38782 for ; Mon, 23 Oct 2023 12:13:36 +0200 (CEST) Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=Y0gfdI34; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1698056016; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=tdfRgCGGKJNqZfX/J4hd8P9sNzVq7skRi9HN7GzcHoM=; b=spRn448uqDkPGfqdKmUJzdluNqiXDsqutU6dT05Ea6mO3tss7X+D651YqaztlMrnmqNEmb hV8TRTYwHYveG16CTwSutBtarfe+M+ElpNSllRX4UyMJHA5UIqfR8Zp7CvPLP8M7Ic/9sz iZ1Vj+jhm/pJHXMOjNNC6/Nq6CJeT8OfdCy8RBJPHM1q78Zf1PGz3ry0js61ltoImnaRoF sMnJcdHByLbOi0BBMMSvkm3K0jm50zdrxARqXGHYdwvY6U/8NpXOrz0sUfJaRyGFcdmMnZ 0caVvzkiL5MrJ7+BcKEoWzcUWRbwmLs/vbOG7Ra3+YGMXVwXwoPauaWOkNVNzg== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=Y0gfdI34; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=gmail.com ARC-Seal: i=1; s=key1; d=yhetil.org; t=1698056016; a=rsa-sha256; cv=none; b=CHOrHMwUpJu2DEHdSaciiV+wGA5fuiiKAbL2gyPQVLBtRacAWy9uQgVCR5Az5sol7LfdvH MQD5zZyy4aIeWFwks07vX4RcM6Dl+49WIrR9Ldr+8M9Pj8kwKiF3SrKWd78YykRgZEu2C4 i3S78NqL8UBxeXf7QbYXwwdM5N6C3PhpY9sGvx2o2UGbePPUX0QU8WGRRDHuwrTGwOe4nC kfTfJ6e0HnvsTU9YeFar9RjtLi4Hxy0a0YuWttCf8XWATec7Bvvn1jDc6HyIukrGI+9isq crGc1S2Y1SaJh7BrSh5OUl5ThgAvGsNqfNLoLoMA9wuBpAUK2z0hhc4WupSHQg== Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qurvP-0006JS-2b; Mon, 23 Oct 2023 06:12:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qurvM-0006Ir-Sh for emacs-orgmode@gnu.org; Mon, 23 Oct 2023 06:12:40 -0400 Received: from mail-pf1-x441.google.com ([2607:f8b0:4864:20::441]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qurvJ-0004qn-TI for emacs-orgmode@gnu.org; Mon, 23 Oct 2023 06:12:40 -0400 Received: by mail-pf1-x441.google.com with SMTP id d2e1a72fcca58-6b5e6301a19so2955751b3a.0 for ; Mon, 23 Oct 2023 03:12:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698055956; x=1698660756; darn=gnu.org; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=tdfRgCGGKJNqZfX/J4hd8P9sNzVq7skRi9HN7GzcHoM=; b=Y0gfdI34GE68GOlhSjqQQBCdsrqsGSf/Y6XCj+UFqXq3PVPnLZRa4Juqrg7sD3MPTV SykfaYKejcy7xeFy+K0AWxIlGOb9qZz0LrWEjhqb7xoSXME3ktB++gvngI6Rp9269NRs jS8zg+QS6hHOGFZdFe3l0DnQekFv9caSamFXNUMS8de60N1bLSn7nT5NsTscZxzIKPGy VQOf7QqWz9sHGCWHEbieF9s7jFm9oaTz0dn9TGKo96x3txHmFbZpMJPC5h/TDCiW74UX OEEOPNA+yif8GwW7LhipWR5GiKJXpV6sgL76++rm3jyJWaxTif8QWmcC12sFGXg97wrA kk7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698055956; x=1698660756; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=tdfRgCGGKJNqZfX/J4hd8P9sNzVq7skRi9HN7GzcHoM=; b=GY+cfB/l5nv3nKIknryhgz8BVj727t7JLHG5abvgCBccuqjprUetxIbU5n9H/d2QUJ wXgtI7tsE3ucESu0ls5O8ii3nqnb2qQ5EfLQvz051xRsouTeQF82jICDxcKHnoTHyCpv szePBgeNDOGkBtEK9LZv76P9qFAfwnzLSGHF/WLifFDCBPbm5Wwb1hy+WbJFdWozaDyn vE+FGEGbhOfibRJC054yNPDmfH3FBP5hipApyB3BrZP7LbvGWn+wqCmPjzpX17evY8g0 VgKtFjXr+SQNKO33lpN9Agg2cXo7uIL8q8KgWJfHU+4h8tY0h332HMWlgBf/6I0ILLIB boGQ== X-Gm-Message-State: AOJu0YziLD9ssYjww4YQYyDF2R8Nb5n30ZS329697hre6opU8KCnCsXJ K6UQPUq0oGnWBq1ti3jZDTk= X-Google-Smtp-Source: AGHT+IHHcmSY/LMkdZqpkls/om/L+6CcV1iPPILgoMs07RzzHwh6O1OxrumF9+PCIMrQyY+GsieMjw== X-Received: by 2002:a05:6a20:1611:b0:16b:e2e5:fe55 with SMTP id l17-20020a056a20161100b0016be2e5fe55mr11082120pzj.51.1698055955678; Mon, 23 Oct 2023 03:12:35 -0700 (PDT) Received: from localhost ([118.185.152.162]) by smtp.gmail.com with ESMTPSA id b13-20020aa7950d000000b0068ffd4eb66dsm5762432pfp.35.2023.10.23.03.12.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 03:12:34 -0700 (PDT) From: Visuwesh To: Ihor Radchenko Cc: emacs-orgmode@gnu.org, Po Lu Subject: Re: [BUG] [PATCH] Add yank-media and DND handler [9.6.7 (9.6.7-g6eb773 @ /home/viz/lib/emacs/straight/build/org/)] In-Reply-To: <875y2xaf6d.fsf@localhost> (Ihor Radchenko's message of "Mon, 23 Oct 2023 08:58:18 +0000") References: <87jzsintv0.fsf@gmail.com> <87lecx2nff.fsf@localhost> <87bkdsomm2.fsf@gmail.com> <87a5tamm3j.fsf@gmail.com> <877cnyzlda.fsf@localhost> <87a5sur51r.fsf@gmail.com> <875y3ir0lu.fsf@gmail.com> <87ttr1pild.fsf@localhost> <87v8bhpdg8.fsf@gmail.com> <87edi4m4my.fsf@localhost> <87wmvf89ha.fsf@gmail.com> <875y2xaf6d.fsf@localhost> Date: Mon, 23 Oct 2023 15:42:32 +0530 Message-ID: <87a5s98x67.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2607:f8b0:4864:20::441; envelope-from=visuweshm@gmail.com; helo=mail-pf1-x441.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: emacs-orgmode-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: -6.40 X-Spam-Score: -6.40 X-Migadu-Queue-Id: 8204E38782 X-Migadu-Scanner: mx2.migadu.com X-TUID: Cd0GtFrOfv17 --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable [=E0=AE=A4=E0=AE=BF=E0=AE=99=E0=AF=8D=E0=AE=95=E0=AE=B3=E0=AF=8D =E0=AE=85= =E0=AE=95=E0=AF=8D=E0=AE=9F=E0=AF=8B=E0=AE=AA=E0=AE=B0=E0=AF=8D 23, 2023] I= hor Radchenko wrote: >>> Also, we might want to add a subsection describing the new customizatio= n to >>> 17 Miscellaneous section of the manual. Otherwise, users might have >>> difficulties discovering relevant settings to customize dnd and yank >>> behavior. >> >> I have now added these to the manual with a few relevant concept >> indices. Please check if they are understandable as I am terrible at >> writing documentation. Thanks. > > Thanks! > Upon reading the manual sections I have further comments on the code: > > 1. org-yank-image-save-type feels a bit inconsistent. What about > org-yank-image-save-method? "Type" sounds more like extension (png, > jpeg, etc) You're right, I have now changed the name to say method instead. > 2. org-dnd-method allows either attaching files/images or putting them > into a dedicated directory. Same for yanked images. But it is not the > case for yanked files - they are always attached, which is not > consistent. May we also allow dedicated directory for yanked files? > Or maybe simply merge the org-dnd-method customization for yank and > dnd together. Hmm... yes, I now made yank-media also respect the value of org-dnd-method. I changed the name of org-dnd-method to org-yank-dnd-method and similarly for the rest of the common user options. Here's the new patch: --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Add-support-for-yank-media-and-DND.patch >From c7492fc2adb72a45691124929527798bf9482c2b Mon Sep 17 00:00:00 2001 From: Visuwesh Date: Fri, 22 Sep 2023 20:11:41 +0530 Subject: [PATCH] Add support for yank-media and DND * lisp/org.el (org-mode): Call the setup function for yank-media and DND. (org-setup-yank-dnd-handlers): Register yank-media-handler and DND handler. (org-yank-image-save-method, org-yank-image-file-name-function) (org-yank-dnd-method, org-yank-dnd-default-attach-method): New defcustoms. (org--image-yank-media-handler, org--copied-files-yank-media-handler) (org--dnd-rmc, org--dnd-attach-file, org--dnd-local-file-handler) (org--dnd-xds-method, org--dnd-xds-function): Add yank-media and DND handlers. * doc/org-manual.org: (Drag and Drop & ~yank-media~): Describe the new feature in the manual. * etc/ORG-NEWS: Advertise the new features. --- doc/org-manual.org | 45 +++++++++ etc/ORG-NEWS | 24 +++++ lisp/org.el | 231 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 299 insertions(+), 1 deletion(-) diff --git a/doc/org-manual.org b/doc/org-manual.org index 3e9d42f55..7b14eb937 100644 --- a/doc/org-manual.org +++ b/doc/org-manual.org @@ -21095,6 +21095,51 @@ most recent since the mobile application searches files that were last pulled. To get an updated agenda view with changes since the last pull, pull again. +** Drag and Drop & ~yank-media~ +:PROPERTIES: +:DESCRIPTION: Dropping and pasting files and images +:END: + +#+cindex: dropping files +#+cindex: dragging files +#+cindex: drag and drop +#+cindex: dnd +#+vindex: org-yank-dnd-method +Org mode supports drag and drop (DnD) of files. By default, Org asks +the user what must be done with the dropped file: attach it, insert +=file:= link, or open the file. Customize ~org-yank-dnd-method~ to +set the default DnD action. + +When DnD method is "attach", Org mode first consults DnD metadata to +decide the attach method. For example, when file/files are dragged +from a file manager, Org may attach by copying or by moving. + +#+vindex: org-yank-dnd-default-attach-method +If Org cannot figure out which attachment method to use from the +metadata, it defaults to ~org-yank-dnd-default-attach-method~ [fn::By +default, ~org-yank-dnd-default-attach-method~ is set to nil -- use the same +value as ~org-attach-method~ (~cp~ by default).] + +#+cindex: pasting files, images from clipboard +Starting from Emacs 29, Org mode supports ~yank-media~ command to yank +images from the clipboard and files from a file manager. + +#+vindex: org-yank-image-save-method +When yanking images from clipboard, Org saves the image on disk and +inserts the image link to Org buffer. Images are either saved as +attachments to heading (default) or to a globally defined directory. +The save location is controlled by ~org-yank-image-save-method~. + +#+vindex: org-yank-image-file-name-function +The yanked images are saved under automatically generated name. You +can customize ~org-yank-image-file-name-function~ to make Org query +the image names or change the naming scheme. + +When yanking files copied from a file manager, Org respects the value +of ~org-yank-dnd-method~. Image files pasted this way also respect +the value of ~org-yank-image-save-method~ when the action to perform +is =attach=. + * Hacking :PROPERTIES: :DESCRIPTION: How to hack your way around. diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 252c5a9f9..7c40ec0fe 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -596,6 +596,30 @@ return a matplotlib Figure object to plot. For output results, the current figure (as returned by =pyplot.gcf()=) is cleared before evaluation, and then plotted afterwards. +*** Images and files in clipboard can be pasted + +Org asks the user what must be done when pasting images and files +copied to the clipboard from a file manager using the ~yank-media~ +command. The default action can be set by customizing +~org-yank-dnd-method~. The ~yank-media~ command was added in Emacs +29. + +Images can be saved to a separate directory instead of being attached, +customize ~org-yank-image-save-method~. + +Image filename chosen can be customized by setting +~org-yank-image-file-name-function~ which by default autogenerates a +filename based on the current time. + +*** Files and images can be attached by dropping onto Emacs + +By default, Org asks the user what to do with the dropped file like +for pasted files. The same user option ~org-yank-dnd-method~ is +respected. + +Images dropped also respect the value of ~org-yank-image-save-method~ +when ~org-yank-dnd-method~ is =attach=. + ** New functions and changes in function arguments *** =TYPES= argument in ~org-element-lineage~ can now be a symbol diff --git a/lisp/org.el b/lisp/org.el index d0b2355ea..317cd267f 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -4999,7 +4999,10 @@ The following commands are available: (org--set-faces-extend '(org-block-begin-line org-block-end-line) org-fontify-whole-block-delimiter-line) (org--set-faces-extend org-level-faces org-fontify-whole-heading-line) - (setq-local org-mode-loading nil)) + (setq-local org-mode-loading nil) + + ;; `yank-media' handler and DND support. + (org-setup-yank-dnd-handlers)) ;; Update `customize-package-emacs-version-alist' (add-to-list 'customize-package-emacs-version-alist @@ -20254,6 +20257,232 @@ it has a `diary' type." (org-format-timestamp timestamp fmt t)) (org-format-timestamp timestamp fmt (eq boundary 'end))))))) +;;; Yank media handler and DND +(defun org-setup-yank-dnd-handlers () + "Setup the `yank-media' and DND handlers for buffer." + (setq-local dnd-protocol-alist + (cons '("^file:///" . org--dnd-local-file-handler) + dnd-protocol-alist)) + (when (fboundp 'yank-media-handler) + (yank-media-handler "image/.*" #'org--image-yank-media-handler) + ;; Looks like different DEs go for different handler names, + ;; https://larsee.com/blog/2019/05/clipboard-files/. + (yank-media-handler "x/special-\\(?:gnome\|KDE\|mate\\)-files" + #'org--copied-files-yank-media-handler)) + (when (boundp 'x-dnd-direct-save-function) + (setq-local x-dnd-direct-save-function #'org--dnd-xds-function))) + +(defcustom org-yank-image-save-method 'attach + "Method to save images yanked from clipboard and dropped to Emacs. +It can be the symbol `attach' to add it as an attachment, or a +directory name to copy/cut the image to that directory." + :group 'org + :package-version '(Org . "9.7") + :type '(choice (const :tag "Add it as attachment" attach) + (directory :tag "Save it in directory")) + :safe (lambda (x) (eq x 'attach))) + +(defcustom org-yank-image-file-name-function #'org-yank-image-autogen-filename + "Function to generate filename for image yanked from clipboard. +By default, this autogenerates a filename based on the current +time. +It is called with no arguments and should return a string without +any extension which is used as the filename." + :group 'org + :package-version '(Org . "9.7") + :type '(radio (function-item :doc "Autogenerate filename" + org-yank-image-autogen-filename) + (function-item :doc "Ask for filename" + org-yank-image-read-filename) + function)) + +(defun org-yank-image-autogen-filename () + "Autogenerate filename for image in clipboard." + (format-time-string "clipboard-%Y%m%dT%H%M%S.%6N")) + +(defun org-yank-image-read-filename () + "Read filename for image in clipboard." + (read-string "Basename for image file without extension: ")) + +(declare-function org-attach-attach "org-attach" (file &optional visit-dir method)) + +(defun org--image-yank-media-handler (mimetype data) + "Save image DATA of mime-type MIMETYPE and insert link at point. +It is saved as per `org-yank-image-save-method'. The name for the +image is prompted and the extension is automatically added to the +end." + (let* ((ext (symbol-name (mailcap-mime-type-to-extension mimetype))) + (iname (funcall org-yank-image-file-name-function)) + (filename (file-name-with-extension iname ext)) + (absname (expand-file-name + filename + (if (eq org-yank-image-save-method 'attach) + temporary-file-directory + org-yank-image-save-method))) + link) + (when (and (not (eq org-yank-image-save-method 'attach)) + (not (file-directory-p org-yank-image-save-method))) + (make-directory org-yank-image-save-method t)) + (with-temp-file absname + (insert data)) + (if (null (eq org-yank-image-save-method 'attach)) + (setq link (org-link-make-string (concat "file:" (file-relative-name absname)))) + (require 'org-attach) + (org-attach-attach absname nil 'mv) + (setq link (org-link-make-string (concat "attachment:" filename)))) + (insert link))) + +;; I cannot find a spec for this but +;; https://indigo.re/posts/2021-12-21-clipboard-data.html and pcmanfm +;; suggests that this is the format. +(defun org--copied-files-yank-media-handler (_mimetype data) + "Handle copied or cut files from file manager. +They are handled as per `org-yank-dnd-method'. +DATA is a string where the first line is the operation to +perform: copy or cut. Rest of the lines are file: links to the +concerned files." + ;; pcmanfm adds a null byte at the end for some reason. + (let* ((data (split-string data "[\0\n\r]" t)) + (files (cdr data)) + (action (if (equal (car data) "cut") + 'copy + 'move))) + (dolist (f files) + (if (file-readable-p f) + (org--dnd-local-file-handler f action) + (message "File `%s' is not readable, skipping" f))))) + +(defcustom org-yank-dnd-method 'ask + "Action to perform on the dropped and the pasted files. +When the value is the symbol, + . `attach' -- attach dropped/pasted file + . `open' -- visit/open dropped/pasted file in Emacs + . `file-link' -- insert file: link to dropped/pasted file + . `ask' -- ask what to do out of the above." + :group 'org + :package-version '(Org . "9.7") + :type '(choice (const :tag "Attach" attach) + (const :tag "Open/Visit file" open) + (const :tag "Insert file: link" file-link) + (const :tag "Ask what to do" ask))) + +(defcustom org-yank-dnd-default-attach-method nil + "Default attach method to use when DND action is unspecified. +This attach method is used when the DND action is `private'. +This is also used when `org-yank-image-save-method' is nil. +When nil, use `org-attach-method'." + :group 'org + :package-version '(Org . "9.7") + :type '(choice (const :tag "Default attach method" nil) + (const :tag "Copy" cp) + (const :tag "Move" mv) + (const :tag "Hard link" ln) + (const :tag "Symbolic link" lns))) + +(declare-function mailcap-file-name-to-mime-type "mailcap" (file-name)) +(defvar org-attach-method) + +(defun org--dnd-rmc (prompt choices) + (if (null (use-dialog-box-p)) + (caddr (read-multiple-choice prompt choices)) + (setq choices + (mapcar + (pcase-lambda (`(_key ,message ,val)) + (cons (capitalize message) val)) + choices)) + (x-popup-menu t (list prompt (cons "" choices))))) + +(defun org--dnd-local-file-handler (url action) + "Handle file URL as per ACTION." + (let ((method (if (eq org-yank-dnd-method 'ask) + (org--dnd-rmc + "What to do with file?" + '((?a "attach" attach) + (?o "open" open) + (?f "insert file: link" file-link))) + org-yank-dnd-method))) + (pcase method + (`attach (org--dnd-attach-file url action)) + (`open (dnd-open-local-file url action)) + (`file-link + (let ((filename (dnd-get-local-file-name url))) + (insert (org-link-make-string (concat "file:" filename)))))))) + +(defun org--dnd-attach-file (url action) + "Attach filename given by URL using method pertaining to ACTION. +If ACTION is `move', use `mv' attach method. +If `copy', use `cp' attach method. +If `ask', ask the user. +If `private', use the method denoted in `org-yank-dnd-default-attach-method'. +The action `private' is always returned." + (require 'mailcap) + (let* ((filename (dnd-get-local-file-name url)) + (mimetype (mailcap-file-name-to-mime-type filename)) + (separatep (and (string-prefix-p "image/" mimetype) + (not (eq 'attach org-yank-image-save-method)))) + (method (pcase action + ('copy 'cp) + ('move 'mv) + ('ask (org--dnd-rmc + "Attach using method" + '((?c "copy" cp) + (?m "move" mv) + (?l "hard link" ln) + (?s "symbolic link" lns)))) + ('private (or org-yank-dnd-default-attach-method + org-attach-method))))) + (if separatep + (funcall + (pcase method + ('cp #'copy-file) + ('mv #'rename-file) + ('ln #'add-name-to-file) + ('lns #'make-symbolic-link)) + filename + (expand-file-name (file-name-nondirectory filename) + org-yank-image-save-method)) + (org-attach-attach filename nil method)) + (insert + (org-link-make-string + (concat (if separatep + "file:" + "attachment:") + (if separatep + (expand-file-name (file-name-nondirectory filename) + org-yank-image-save-method) + (file-name-nondirectory filename)))) + "\n") + 'private)) + +(defvar-local org--dnd-xds-method nil + "The method to use for dropped file.") +(defun org--dnd-xds-function (need-name filename) + "Handle file with FILENAME dropped via XDS protocol. +When NEED-NAME is t, FILNAME is the base name of the file to be +saved. +When NEED-NAME is nil, the drop is complete." + (if need-name + (let ((method (if (eq org-yank-dnd-method 'ask) + (org--dnd-rmc + "What to do with dropped file?" + '((?a "attach" attach) + (?o "open" open) + (?f "insert file: link" file-link))) + org-yank-dnd-method))) + (setq-local org--dnd-xds-method method) + (pcase method + (`attach (expand-file-name filename (org-attach-dir 'create))) + (`open (expand-file-name (make-temp-name "emacs.") temporary-file-directory)) + (`file-link (read-file-name "Write file to: " nil nil nil filename)))) + (pcase org--dnd-xds-method + (`attach (insert (org-link-make-string + (concat "attachment:" (file-name-nondirectory filename))) + "\n")) + (`file-link (insert (org-link-make-string (concat "file:" filename)) + "\n")) + (`open (find-file filename))) + (setq-local org--dnd-xds-method nil))) + ;;; Other stuff (defvar reftex-docstruct-symbol) -- 2.42.0 --=-=-= Content-Type: text/plain > I am attaching my further amendments on top of your patch. > For simpler review, I am also adding the manual section verbatim. > > To other readers of this thread: Please help reviewing the manual > section - it should be as clear as possible for everyone. Thanks for your review. The manual now says: ** Drag and Drop & ~yank-media~ :PROPERTIES: :DESCRIPTION: Dropping and pasting files and images :END: #+cindex: dropping files #+cindex: dragging files #+cindex: drag and drop #+cindex: dnd #+vindex: org-yank-dnd-method Org mode supports drag and drop (DnD) of files. By default, Org asks the user what must be done with the dropped file: attach it, insert =file:= link, or open the file. Customize ~org-yank-dnd-method~ to set the default DnD action. When DnD method is "attach", Org mode first consults DnD metadata to decide the attach method. For example, when file/files are dragged from a file manager, Org may attach by copying or by moving. #+vindex: org-yank-dnd-default-attach-method If Org cannot figure out which attachment method to use from the metadata, it defaults to ~org-yank-dnd-default-attach-method~ [fn::By default, ~org-yank-dnd-default-attach-method~ is set to nil -- use the same value as ~org-attach-method~ (~cp~ by default).] #+cindex: pasting files, images from clipboard Starting from Emacs 29, Org mode supports ~yank-media~ command to yank images from the clipboard and files from a file manager. #+vindex: org-yank-image-save-method When yanking images from clipboard, Org saves the image on disk and inserts the image link to Org buffer. Images are either saved as attachments to heading (default) or to a globally defined directory. The save location is controlled by ~org-yank-image-save-method~. #+vindex: org-yank-image-file-name-function The yanked images are saved under automatically generated name. You can customize ~org-yank-image-file-name-function~ to make Org query the image names or change the naming scheme. When yanking files copied from a file manager, Org respects the value of ~org-yank-dnd-method~. Image files pasted this way also respect the value of ~org-yank-image-save-method~ when the action to perform is =attach=. --=-=-=--