Make yank-media auto select the best mime type

* 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)
This commit is contained in:
Visuwesh 2025-02-13 16:43:06 +05:30 committed by Eli Zaretskii
parent 3e26937150
commit 0ee50a3420
4 changed files with 111 additions and 12 deletions

View 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

View 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

View file

@ -1252,6 +1252,14 @@ connected, to facilitate enabling 'strokes-mode' in sessions where the
availability of a mouse device varies during execution (as is frequently
observed on Android).
** Yank media
+++
*** 'yank-media' now auto-selects the most preferred MIME type.
Major-mode authors can customise the variables
'yank-media-autoselect-function' and/or 'yank-media-preferred-types' to
change the selection rules.
* New Modes and Packages in Emacs 31.1

View file

@ -29,19 +29,67 @@
(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