]> git.eshelyaron.com Git - emacs.git/commitdiff
Make yank-media auto select the best mime type
authorVisuwesh <visuweshm@gmail.com>
Thu, 13 Feb 2025 11:13:06 +0000 (16:43 +0530)
committerEshel Yaron <me@eshelyaron.com>
Sun, 23 Feb 2025 08:10:11 +0000 (09:10 +0100)
* lisp/yank-media.el (yank-media-preferred-types): Add new
variable that holds the list of mime types in order of their
preference.
(yank-media-autoselect-function): Add new variable and function
to choose the most preferred media type.
(yank-media): Make 'yank-media' choose the most preferred mime
type by default.
* doc/emacs/killing.texi (Clipboard):
* doc/lispref/frames.texi (Yanking Media): Document the new
behaviour, and the new variables.
* etc/NEWS: Announce the change.  (Bug#75116)

(cherry picked from commit 0ee50a3420fb8df8f3477dac610dcd53c633fff5)

doc/emacs/killing.texi
doc/lispref/frames.texi
lisp/yank-media.el

index 070e15dee7633828955ae62f486c42cca973ccb9..aee68608bbfc2c4ccda9bf3b7d4ec6692946bbc5 100644 (file)
@@ -587,8 +587,10 @@ change the variable @code{select-enable-clipboard} to @code{nil}.
 instance, a web browser will usually let you choose ``Copy Image'' on
 images, and this image will be put on the clipboard.  On capable
 platforms, Emacs can yank these objects with the @code{yank-media}
-command---but only in modes that have support for it (@pxref{Yanking
-Media,,, elisp, The Emacs Lisp Reference Manual}).
+command---but only in modes that have support for it.  By default, it
+auto-selects the preferred media type available in the clipboard but
+this can be overriden by giving the prefix argument to the command
+(@pxref{Yanking Media,,, elisp, The Emacs Lisp Reference Manual}).
 
 @cindex clipboard manager
 @vindex x-select-enable-clipboard-manager
index bc2d6b07ae8342679c690436f052b8b6afa9c344..984f9bb597def6e3d9bae03b64238ecbf4dab4c6 100644 (file)
@@ -4812,6 +4812,30 @@ designating the matching selection data type, and the data returned by
 @code{gui-get-selection}.
 @end defun
 
+The @code{yank-media} command auto selects the preferred @sc{mime} type
+by default.  The rules used for the selection can be controlled through
+the variables @code{yank-media-autoselect-function} and
+@code{yank-media-preferred-types}.
+
+@defvar yank-media-autoselect-function
+This variable should specify a function that will be called with the
+list of @sc{mime} types available for the current major mode, and should
+return a list of preferred @sc{mime} types to use.  The first @sc{mime}
+type in the list will always be used by the @code{yank-media} command
+when auto selection is requested.
+@end defvar
+
+@defvar yank-media-preferred-types
+This variable changes the default selection process of
+@code{yank-media-autoselect-function}.  It is a list that should contain
+the sole @sc{mime} type to choose in the order of their preference.  It
+can also contain a function in which case it is called with the list of
+available @sc{mime} types and must return a list of preferred @sc{mime}
+types in order of their preference.  This list is passed onto the
+@code{yank-media} command so the first element of the returned list is
+chosen when auto selection is requested.
+@end defvar
+
 The @code{yank-media-types} command presents a list of selection data
 types that are currently available, which is useful when implementing
 yank-media handlers; for programs generally offer an eclectic and
index 2b9a0e70e45109fcb0033ffcaafb467a0b2b736d..71f617d30b25a4ed22ff3ac618508b877cf5a464 100644 (file)
 
 (defvar yank-media--registered-handlers nil)
 
+(defvar yank-media-autoselect-function #'yank-media-autoselect-function
+  "Function to auto select the best MIME types when many are available.
+The function is called with a list of MIME types that have handler in
+the current buffer, and should return the list of MIME types to use in
+order of their priority.  When `yank-media' auto-selects the MIME type,
+it will always choose the first one of the returned list.
+Major-mode authors can change this variable to influence the selection
+process.")
+
+(defvar yank-media-preferred-types
+  `(;; Check first since LibreOffice also puts a PNG image in the
+    ;; clipboard when a table cell is copied.
+    application/x-libreoffice-tsvc
+    ;; Give PNG more priority.
+    image/png
+    image/jpeg
+    ;; These are files copied/cut to the clipboard from a file manager
+    ;; in a GNU/Linux and/or BSD environment.
+    ,@(when (memq window-system '(x pgtk))
+        (list (lambda (mimetypes)
+                (ensure-list
+                 (seq-find (lambda (type)
+                             (string-match-p "x-special/\\(gnome\\|KDE\\|mate\\)-copied-files"
+                                             (symbol-name type)))
+                           mimetypes)))))
+    ;; FIXME: We should have a way to handle text/rtf.
+    text/html)
+  "List of MIME types in the order of preference.
+Each element in the list should be a symbol to choose that MIME type
+exclusively, or a function of one argument and should return the list of
+MIME types to use in order of their priority or nil if no preferred type
+is found.
+Major-mode authors can change this variable to influence the selection
+process, or by directly changing the variable
+`yank-media-autoselect-function'.")
+
+(defun yank-media-autoselect-function (mimetypes)
+  (catch 'preferred
+    (dolist (typ yank-media-preferred-types)
+      (let ((ret (if (functionp typ)
+                     (funcall typ mimetypes)
+                   (and (memq typ mimetypes) (list typ)))))
+        (when ret (throw 'preferred ret))))))
+
 ;;;###autoload
-(defun yank-media ()
+(defun yank-media (&optional noselect)
   "Yank media (images, HTML and the like) from the clipboard.
 This command depends on the current major mode having support for
 accepting the media type.  The mode has to register itself using
 the `yank-media-handler' mechanism.
+Optional argument NOSELECT non-nil (interactively, with a prefix
+argument) means to skip auto-selecting the best MIME type and ask for
+the MIME type to use.
 
 Also see `yank-media-types' for a command that lets you explore
 all the different selection types."
-  (interactive)
+  (interactive "P")
   (unless yank-media--registered-handlers
     (user-error "The `%s' mode hasn't registered any handlers" major-mode))
-  (let ((all-types nil))
+  (let ((all-types nil)
+        pref-type)
     (pcase-dolist (`(,handled-type . ,handler)
                    yank-media--registered-handlers)
       (dolist (type (yank-media--find-matching-media handled-type))
@@ -49,18 +97,35 @@ all the different selection types."
     (unless all-types
       (user-error
        "No handler in the current buffer for anything on the clipboard"))
-    ;; We have a handler in the current buffer; if there's just
-    ;; matching type, just call the handler.
-    (if (length= all-types 1)
+    (setq pref-type (and (null noselect)
+                         (funcall yank-media-autoselect-function
+                                  (mapcar #'car all-types))))
+    (cond
+     ;; We are asked to autoselect and have a preferred MIME type.
+     ((and (null noselect) pref-type)
+      (funcall (cdr (assq (car pref-type) all-types))
+               (car pref-type)
+               (yank-media--get-selection (car pref-type))))
+     ;; We are asked to autoselect and no preferred MIME type.
+     ((and (null noselect) (null pref-type))
+      (message
+       (substitute-command-keys
+        "No preferred MIME type to yank, try \\[universal-argument] \\[yank-media]")))
+     ;; No autoselection and there's only one media type available.
+     ((and noselect (length= all-types 1))
+      (when (y-or-n-p (format "Yank the `%s' clipboard item?"
+                              (caar all-types)))
         (funcall (cdar all-types) (caar all-types)
-                 (yank-media--get-selection (caar all-types)))
-      ;; More than one type the user for what type to insert.
+                 (yank-media--get-selection (caar all-types)))))
+     ;; No autoselection and multiple media types available.
+     ((and noselect (length> all-types 1))
       (let ((type
              (intern
               (completing-read "Several types available, choose one: "
-                               (mapcar #'car all-types) nil t))))
+                               (or pref-type (mapcar #'car all-types))
+                               nil t))))
         (funcall (alist-get type all-types)
-                 type (yank-media--get-selection type))))))
+                 type (yank-media--get-selection type)))))))
 
 (defun yank-media--find-matching-media (handled-type)
   (seq-filter