unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#66394: 29.1; Make register-read-with-preview more useful
@ 2023-10-07 19:03 Thierry Volpiatto
  2023-10-08  6:45 ` bug#66394: [RE] " Thierry Volpiatto
                   ` (6 more replies)
  0 siblings, 7 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-07 19:03 UTC (permalink / raw)
  To: 66394


When using `copy-to-register`, it is hard to see which register is
already taken in the preview buffer.
This patch highlight the register entered at prompt if it is already
taken otherwise a minibuffer message is sent to notify user the register
is available.
If any interest here is the patch, feel free to modify if needed.
Thanks.

diff --git a/lisp/register.el b/lisp/register.el
index ca6de450993..4c83264d4eb 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -154,27 +154,37 @@ listing existing registers after `register-preview-delay' seconds.
 If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
-	 (timer (when (numberp register-preview-delay)
-		  (run-with-timer register-preview-delay nil
-				  (lambda ()
-				    (unless (get-buffer-window buffer)
-				      (register-preview buffer))))))
-	 (help-chars (cl-loop for c in (cons help-char help-event-list)
-			      when (not (get-register c))
-			      collect c)))
+         (pat "")
+         result timer)
+    (register-preview buffer)
     (unwind-protect
-	(progn
-	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
-		       help-chars)
-	    (unless (get-buffer-window buffer)
-	      (register-preview buffer 'show-empty)))
-          (when (or (eq ?\C-g last-input-event)
-                    (eq 'escape last-input-event)
-                    (eq ?\C-\[ last-input-event))
-            (keyboard-quit))
-	  (if (characterp last-input-event) last-input-event
-	    (error "Non-character input-event")))
-      (and (timerp timer) (cancel-timer timer))
+         (progn
+           (minibuffer-with-setup-hook
+               (lambda ()
+                 (setq timer
+                       (run-with-idle-timer
+                        0.3 'repeat
+                        (lambda ()
+                          (with-selected-window (minibuffer-window)
+                            (let ((input (minibuffer-contents)))
+                              (when (not (string= input pat))
+                                (setq pat input))))
+                          (with-current-buffer buffer
+                            (let ((ov (make-overlay (point-min) (point-min))))
+                              (goto-char (point-min))
+                              (if (string= pat "")
+                                  (remove-overlays)
+                                (if (re-search-forward (concat "^" pat) nil t)
+                                    (progn (move-overlay
+                                            ov
+                                            (match-beginning 0) (match-end 0))
+                                           (overlay-put ov 'face 'helm-match))
+                                  (with-selected-window (minibuffer-window)
+                                    (minibuffer-message
+                                     "Register `%s' is available" pat))))))))))
+             (setq result (read-from-minibuffer prompt)))
+           (string-to-char result))
+      (when timer (cancel-timer timer))
       (let ((w (get-buffer-window buffer)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buffer) (kill-buffer buffer)))))



In GNU Emacs 29.1 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo
version 1.16.0, Xaw3d scroll bars) of 2023-10-01 built on IPad-S340
Windowing system distributor 'The X.Org Foundation', version 11.0.12101004
System Description: Linux Mint 21.2

Configured using:
 'configure CFLAGS=-O8 --bindir=/usr/local/sbin/emacs-29.1 --with-cairo
--with-x-toolkit=lucid --with-modules --without-tree-sitter
--without-native-compilation'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY
INOTIFY PDUMPER PNG RSVG SECCOMP SOUND THREADS TIFF TOOLKIT_SCROLL_BARS
X11 XAW3D XDBE XIM XINPUT2 XPM LUCID ZLIB

Important settings:
  value of $LANG: fr_FR.UTF-8
  locale-coding-system: utf-8-unix

Major mode: 

Minor modes in effect:
  emms-mode-line-mode: t
  emms-playing-time-display-mode: t
  emms-playing-time-mode: t
  bug-reference-prog-mode: t
  server-mode: t
  psession-mode: t
  psession-savehist-mode: t
  global-undo-tree-mode: t
  undo-tree-mode: t
  global-git-gutter-mode: t
  git-gutter-mode: t
  display-time-mode: t
  winner-mode: t
  tv-save-place-mode: t
  helm-epa-mode: t
  helm-descbinds-mode: t
  helm-top-poll-mode: t
  helm-adaptive-mode: t
  helm-mode: t
  helm-minibuffer-history-mode: t
  helm-ff-icon-mode: t
  shell-dirtrack-mode: t
  helm-popup-tip-mode: t
  async-bytecomp-package-mode: t
  dired-async-mode: t
  minibuffer-depth-indicate-mode: t
  gcmh-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  mouse-wheel-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  column-number-mode: t
  line-number-mode: t
  auto-fill-function: do-auto-fill
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
None found.

Features:
(epa-mail face-remap addressbook-bookmark tv-mu4e-config config-w3m
mu4e-contrib eshell esh-cmd generator esh-ext esh-opt esh-proc esh-io
esh-arg esh-module esh-groups esh-util mu4e-patch mu4e mu4e-org
org-config ob-gnuplot org-crypt org-protocol org ob ob-tangle ob-ref
ob-lob ob-table ob-exp org-macro org-src ob-comint org-pcomplete
org-list org-footnote org-faces org-entities noutline outline
ob-emacs-lisp ob-core ob-eval org-cycle org-table ol org-fold
org-fold-core org-keys oc org-loaddefs org-version org-compat org-macs
mu4e-notification notifications mu4e-main mu4e-view mu4e-mime-parts
gnus-art mm-uu mml2015 mm-view mml-smime smime gnutls dig gnus-sum
gnus-group gnus-undo gnus-start gnus-dbus gnus-cloud nnimap nnmail
mail-source utf7 nnoo gnus-spec gnus-int gnus-range gnus-win gnus
nnheader range appt diary-lib diary-loaddefs cal-menu calendar
cal-loaddefs mu4e-headers mu4e-thread mu4e-compose mu4e-draft
mu4e-actions smtpmail mu4e-search mu4e-lists mu4e-bookmarks mu4e-mark
mu4e-message shr pixel-fill kinsoku url-file svg dom flow-fill hl-line
mu4e-contacts mu4e-update mu4e-folders mu4e-context mu4e-query-items
mu4e-server mu4e-modeline mu4e-vars mu4e-helpers mu4e-config mu4e-window
ido mu4e-obsolete mailalias mailclient textsec uni-scripts idna-mapping
ucs-normalize uni-confusable textsec-check qp helm-dabbrev shadow
mail-extr emacsbug message yank-media puny rfc822 mml mml-sec gnus-util
mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils
mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr
mail-utils smerge-mode whitespace cl-extra helm-command helm-x-files
helm-for-files helm-bookmark bookmark emms-config emms-mpris
emms-librefm-stream emms-librefm-scrobbler emms-playlist-limit emms-i18n
emms-history emms-score emms-stream-info emms-metaplaylist-mode
emms-bookmarks emms-cue emms-mode-line-icon emms-browser sort
emms-volume emms-volume-sndioctl emms-volume-mixerctl emms-volume-pulse
emms-volume-amixer emms-playlist-sort emms-last-played emms-player-xine
emms-player-mpd tq emms-lyrics emms-url emms-streams emms-show-all
emms-tag-editor emms-tag-tracktag emms-mark emms-mode-line emms-cache
emms-info-native emms-info-spc bindat emms-info-exiftool
emms-info-tinytag emms-info-metaflac emms-info-opusinfo
emms-info-ogginfo emms-info-mp3info emms-playlist-mode emms-player-vlc
emms-player-mpv emms-playing-time emms-info emms-later-do
emms-player-mplayer emms-player-simple emms-source-playlist
emms-source-file locate emms-setup emms emms-compat emms-auto
helm-external helm-net tramp-archive tramp-gvfs tramp-cache time-stamp
zeroconf dbus xml helm-ring helm-elisp helm-eval edebug debug backtrace
find-func helm-info cl-indent helm-ls-git vc-git diff-mode vc
vc-dispatcher jka-compr make-mode flymake-shellcheck cus-start
flymake-proc flymake project warnings thingatpt sh-script smie treesit
executable bug-reference naquadah-theme server imenu psession frameset
undo-tree diff queue pcase git-gutter mule-util dired-extension time
winner describe-variable help-fns radix-tree help-mode tv-utils
tv-save-place.el advice init-helm epa derived epg rfc6068 epg-config
helm-epa isl helm-descbinds cus-edit pp icons wid-edit helm-sys popup
helm-adaptive helm-mode helm-misc helm-files image-dired
image-dired-tags image-dired-external image-dired-util xdg image-mode
exif filenotify tramp tramp-loaddefs trampver tramp-integration files-x
tramp-compat rx shell pcomplete parse-time iso8601 time-date
helm-buffers all-the-icons all-the-icons-faces data-material
data-weathericons data-octicons data-fileicons data-faicons
data-alltheicons helm-occur helm-tags helm-locate helm-grep wgrep-helm
wgrep grep compile text-property-search comint ansi-osc ring helm-regexp
format-spec ansi-color helm-utils helm-help helm-types
helm-extensions-autoloads helm-autoloads helm helm-global-bindings
helm-easymenu edmacro kmacro helm-core easy-mmode async-bytecomp
helm-source helm-multi-match helm-lib dired-async async dired-aux dired
dired-loaddefs mb-depth avoid cus-load gcmh all-the-icons-autoloads
gcmh-autoloads info ledger-mode-autoloads markdown-mode-autoloads
nerd-icons-autoloads w3m-load w3m-autoloads yaml-mode-autoloads package
browse-url url url-proxy url-privacy url-expand url-methods url-history
url-cookie generate-lisp-file url-domsuf url-util mailcap url-handlers
url-parse auth-source cl-seq eieio eieio-core cl-macs password-cache
json subr-x map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs
cl-lib rmc iso-transl tooltip cconv eldoc paren electric uniquify
ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win
term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode lisp-mode prog-mode register
page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads dbusbind inotify lcms2 dynamic-setting system-font-setting
font-render-setting cairo x-toolkit xinput2 x multi-tty
make-network-process emacs)

Memory information:
((conses 16 854462 334476)
 (symbols 48 35404 26)
 (strings 32 219034 39971)
 (string-bytes 1 6357489)
 (vectors 16 99232)
 (vector-slots 8 2128904 396764)
 (floats 8 1791 2270)
 (intervals 56 37515 32129)
 (buffers 976 138))
<#secure method=pgpmime mode=sign>

-- 
Thierry





^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-07 19:03 bug#66394: 29.1; Make register-read-with-preview more useful Thierry Volpiatto
@ 2023-10-08  6:45 ` Thierry Volpiatto
  2023-10-12  6:43 ` Thierry Volpiatto
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-08  6:45 UTC (permalink / raw)
  To: 66394

[-- Attachment #1: Type: text/plain, Size: 3730 bytes --]


Here a modified version of the patch that fix the face, send an error
when exiting with empty prompt and prevent adding more than one char in
prompt.
From this code, it is now easy to modify the behavior as needed (ideas welcome).

diff --git a/lisp/register.el b/lisp/register.el
index ca6de450993..47645098e6d 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -154,27 +154,45 @@ listing existing registers after `register-preview-delay' seconds.
 If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
-	 (timer (when (numberp register-preview-delay)
-		  (run-with-timer register-preview-delay nil
-				  (lambda ()
-				    (unless (get-buffer-window buffer)
-				      (register-preview buffer))))))
-	 (help-chars (cl-loop for c in (cons help-char help-event-list)
-			      when (not (get-register c))
-			      collect c)))
+         (pat "")
+         result timer)
+    (register-preview buffer)
     (unwind-protect
-	(progn
-	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
-		       help-chars)
-	    (unless (get-buffer-window buffer)
-	      (register-preview buffer 'show-empty)))
-          (when (or (eq ?\C-g last-input-event)
-                    (eq 'escape last-input-event)
-                    (eq ?\C-\[ last-input-event))
-            (keyboard-quit))
-	  (if (characterp last-input-event) last-input-event
-	    (error "Non-character input-event")))
-      (and (timerp timer) (cancel-timer timer))
+         (progn
+           (minibuffer-with-setup-hook
+               (lambda ()
+                 (setq timer
+                       (run-with-idle-timer
+                        0.3 'repeat
+                        (lambda ()
+                          (with-selected-window (minibuffer-window)
+                            (setq minibuffer-scroll-window
+                                  (get-buffer-window buffer))
+                            (let ((input (minibuffer-contents)))
+                              (when (> (length input) 1)
+                                (setq input (substring input 0 1))
+                                (delete-minibuffer-contents)
+                                (insert input))
+                              (when (not (string= input pat))
+                                (setq pat input))))
+                          (with-current-buffer buffer
+                            (let ((ov (make-overlay (point-min) (point-min))))
+                              (goto-char (point-min))
+                              (if (string= pat "")
+                                  (remove-overlays)
+                                (if (re-search-forward (concat "^" pat) nil t)
+                                    (progn (move-overlay
+                                            ov
+                                            (match-beginning 0) (match-end 0))
+                                           (overlay-put ov 'face 'match))
+                                  (with-selected-window (minibuffer-window)
+                                    (minibuffer-message
+                                     "Register `%s' is available" pat))))))))))
+             (setq result (read-from-minibuffer prompt)))
+           (cl-assert (and result (not (string= result "")))
+                      nil "No register specified")
+           (string-to-char result))
+      (when timer (cancel-timer timer))
       (let ((w (get-buffer-window buffer)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buffer) (kill-buffer buffer)))))

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-07 19:03 bug#66394: 29.1; Make register-read-with-preview more useful Thierry Volpiatto
  2023-10-08  6:45 ` bug#66394: [RE] " Thierry Volpiatto
@ 2023-10-12  6:43 ` Thierry Volpiatto
  2023-10-14  2:04   ` Richard Stallman
  2023-10-19  2:42 ` bug#66394: 29.1; " Michael Heerdegen
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-12  6:43 UTC (permalink / raw)
  To: 66394

[-- Attachment #1: Type: text/plain, Size: 646 bytes --]


I moved the code here if any interest.
https://gist.github.com/thierryvolpiatto/2219f99ac96ed1b468fac204bca23b4a

I added filters to register-preview (jump-to-register should show
only positions and insert-register should show only text).
Also added navigation (up and down) in preview buffer (see gif).

Still need to modify (or add) docstrings and also decide what to do with
`register-preview-delay` (just a flag in this patch).
AFAIU the only reason to delay preview is when executing kbd macro, in
this case we could use executing-kbd-macro, but maybe I miss something
and there is other reasons to delay this.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-12  6:43 ` Thierry Volpiatto
@ 2023-10-14  2:04   ` Richard Stallman
  2023-10-14  5:59     ` Thierry Volpiatto
  2023-10-15  7:56     ` Thierry Volpiatto
  0 siblings, 2 replies; 121+ messages in thread
From: Richard Stallman @ 2023-10-14  2:04 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

Thanks for inviting people to work with you on improving this code.
But please don't use github as the place to host your free software --
especially not if it relates to GNU.

Github requires a person to run nonfree software simply to make an
account; so if you invite people to collaborate with you on that
platform, indirectly that asks people to run nonfree software.

See https://www.gnu.org/software/repo-criteria-evaluation.html.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-14  2:04   ` Richard Stallman
@ 2023-10-14  5:59     ` Thierry Volpiatto
  2023-10-16  2:04       ` Richard Stallman
  2023-10-15  7:56     ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-14  5:59 UTC (permalink / raw)
  To: rms; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 715 bytes --]


Richard Stallman <rms@gnu.org> writes:

> Thanks for inviting people to work with you on improving this code.
> But please don't use github as the place to host your free software --
> especially not if it relates to GNU.
>
> Github requires a person to run nonfree software simply to make an
> account; so if you invite people to collaborate with you on that
> platform, indirectly that asks people to run nonfree software.

I don't invite anybody to collaborate on github.
The code is stored there and AFAIK anybody can look at it without creating an
account, if any interest in this code I will provide a patch on this
list, what I did in previous mails without any answer BTW...

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-14  2:04   ` Richard Stallman
  2023-10-14  5:59     ` Thierry Volpiatto
@ 2023-10-15  7:56     ` Thierry Volpiatto
  2023-10-15  8:18       ` Stefan Kangas
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-15  7:56 UTC (permalink / raw)
  To: 66394-done

[-- Attachment #1: Type: text/plain, Size: 59 bytes --]


Closed for no interest in this feature.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-15  7:56     ` Thierry Volpiatto
@ 2023-10-15  8:18       ` Stefan Kangas
  2023-10-15 10:05         ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Stefan Kangas @ 2023-10-15  8:18 UTC (permalink / raw)
  To: Thierry Volpiatto, 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> Closed for no interest in this feature.

The lack of a reply doesn't mean that there is a lack of interest.  As
for myself, I've been too busy to find the time to review it in the last
week.  I also have many other things on my plate.

In the future, please allow for, at minimum, 2-4 weeks to let people
comment, and then feel free to ping us if you still didn't get a reply.

If it's fine by you, I'd like to reopen this bug report.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-15  8:18       ` Stefan Kangas
@ 2023-10-15 10:05         ` Thierry Volpiatto
  2023-10-15 12:55           ` Stefan Kangas
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-15 10:05 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 613 bytes --]


Stefan Kangas <stefankangas@gmail.com> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> Closed for no interest in this feature.
>
> The lack of a reply doesn't mean that there is a lack of interest.  As
> for myself, I've been too busy to find the time to review it in the last
> week.  I also have many other things on my plate.
>
> In the future, please allow for, at minimum, 2-4 weeks to let people
> comment, and then feel free to ping us if you still didn't get a reply.
>
> If it's fine by you, I'd like to reopen this bug report.

Ok, please do.

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-15 10:05         ` Thierry Volpiatto
@ 2023-10-15 12:55           ` Stefan Kangas
  2023-11-18 18:39             ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Stefan Kangas @ 2023-10-15 12:55 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

reopen 66394
thanks

Thierry Volpiatto <thievol@posteo.net> writes:

>> If it's fine by you, I'd like to reopen this bug report.
>
> Ok, please do.

Done, thanks.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-14  5:59     ` Thierry Volpiatto
@ 2023-10-16  2:04       ` Richard Stallman
  0 siblings, 0 replies; 121+ messages in thread
From: Richard Stallman @ 2023-10-16  2:04 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I don't invite anybody to collaborate on github.
  > The code is stored there and AFAIK anybody can look at it without creating an
  > account, if any interest in this code I will provide a patch on this
  > list, what I did in previous mails without any answer BTW...

That is not as bad.  But if the code is only to look at, would it work
just as well to refer people to the code in the ELPA repo?
be an equally good place to refer people to?

Ifthat method has some drawback compared with referring to github, can
you describe the drawback?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-07 19:03 bug#66394: 29.1; Make register-read-with-preview more useful Thierry Volpiatto
  2023-10-08  6:45 ` bug#66394: [RE] " Thierry Volpiatto
  2023-10-12  6:43 ` Thierry Volpiatto
@ 2023-10-19  2:42 ` Michael Heerdegen
  2023-10-19  6:16   ` Thierry Volpiatto
  2023-12-05  7:34 ` Tino Calancha
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-19  2:42 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> When using `copy-to-register`, it is hard to see which register is
> already taken in the preview buffer.  This patch highlight the
> register entered at prompt if it is already taken otherwise a
> minibuffer message is sent to notify user the register is available.
> If any interest here is the patch, feel free to modify if needed.

I am not sure what's the best way to address this kind of problem.  If
your version is accepted, I would vote for an option to get the old
behavior back.  Your intended behavior is safer but requires more keys
(at least confirmation with RET).  Some people might prefer the old way.

I'm also not sure about the visual feedback.  If you use lots of
registers you might miss your register highlighting in the preview
buffer.  Maybe using the minibuffer always for the visual feedback might
be better, I don't know.  Or give only feedback when the register is
already taken?  Or maybe require the user to hit RET two times to
confirm overwriting?

Personally I hacked the code so that I can lock registers I don't want
to overwrite.  I can also restore registers.  That takes away a bit of
the pressure.

There also had been a request to be able to delete register bindings,
but it had been rejected.

In any way there should be some way to allow a cleaner working with
registers.

Just my two cents.


Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-19  2:42 ` bug#66394: 29.1; " Michael Heerdegen
@ 2023-10-19  6:16   ` Thierry Volpiatto
  2023-10-20  5:00     ` Michael Heerdegen
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-19  6:16 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 2607 bytes --]


Hello Michael,

Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> When using `copy-to-register`, it is hard to see which register is
>> already taken in the preview buffer.  This patch highlight the
>> register entered at prompt if it is already taken otherwise a
>> minibuffer message is sent to notify user the register is available.
>> If any interest here is the patch, feel free to modify if needed.
>
> I am not sure what's the best way to address this kind of problem.  If
> your version is accepted, I would vote for an option to get the old
> behavior back.  Your intended behavior is safer but requires more keys
> (at least confirmation with RET).  Some people might prefer the old way.

There is only RET as additional key and it is a good thing IMO as it let
the time to user to see what he is doing.  Anyway using a real
minibuffer with its keymap is much better and allows further
modifications in the future to fit the needs of everybody. Using
read-key doesn't allow more alternatives.

> I'm also not sure about the visual feedback.  If you use lots of
> registers you might miss your register highlighting in the preview
> buffer.

It's easy to make the selection always visible, now fixed, thanks.

> Maybe using the minibuffer always for the visual feedback might be
> better, I don't know.  Or give only feedback when the register is
> already taken?  Or maybe require the user to hit RET two times to
> confirm overwriting?

Don't think it is necessary with the register highlighting, and with the
real minibuffer, we must hit RET at least one time to exit wich act as a
confirmation (previously read-key was exiting immediately).
>
> Personally I hacked the code so that I can lock registers I don't want
> to overwrite.  I can also restore registers.  That takes away a bit of
> the pressure.

Ok, that's another approach but doesn't help to see what is available or
not.
Note that now you can use M-n to select in minibuffer the available keys (this
only for setting or modifying a register).

> There also had been a request to be able to delete register bindings,
> but it had been rejected.

You can delete your registers with helm, but this is unrelated to this
thread.

> In any way there should be some way to allow a cleaner working with
> registers.

Probably what I propose is not perfect but it is a first step to have
something better than what we have actually.

Thanks for your feedback.

> Just my two cents.
>
>
> Michael.


-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-19  6:16   ` Thierry Volpiatto
@ 2023-10-20  5:00     ` Michael Heerdegen
  2023-10-20  5:49       ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-20  5:00 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> There is only RET as additional key and it is a good thing IMO as it let
> the time to user to see what he is doing.  Anyway using a real
> minibuffer with its keymap is much better and allows further
> modifications in the future to fit the needs of everybody. Using
> read-key doesn't allow more alternatives.

For keys like C-a you also need to hit C-q.  It's not 100% compatible.

But wait: What I find confusing is that I also need need to confirm for
`jump-to-register'.  Is this intended?


> Note that now you can use M-n to select in minibuffer the available
> keys (this only for setting or modifying a register).

In Helm or in vanilla Emacs?  I don't see that for M-n in vanilla Emacs.

Oh, and there is a little bug when the register binding list is empty
(e.g. after restarting Emacs): your code errors because Emacs does not
pop up a preview window in that case.


Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-20  5:00     ` Michael Heerdegen
@ 2023-10-20  5:49       ` Thierry Volpiatto
  2023-10-21  1:09         ` Michael Heerdegen
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-20  5:49 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 1411 bytes --]


Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> There is only RET as additional key and it is a good thing IMO as it let
>> the time to user to see what he is doing.  Anyway using a real
>> minibuffer with its keymap is much better and allows further
>> modifications in the future to fit the needs of everybody. Using
>> read-key doesn't allow more alternatives.
>
> For keys like C-a you also need to hit C-q.  It's not 100% compatible.

I don't understand, what C-a and C-q have to do here? Also, what C-q is
intended to do in minibuffer?

> But wait: What I find confusing is that I also need need to confirm for
> `jump-to-register'.  Is this intended?

Do you mean RET? If so yes.

>
>> Note that now you can use M-n to select in minibuffer the available
>> keys (this only for setting or modifying a register).
>
> In Helm or in vanilla Emacs?  I don't see that for M-n in vanilla Emacs.

Once the patch is applied, C-x r x M-n (repeat if necessary), same for
C-x r w/n etc...

> Oh, and there is a little bug when the register binding list is empty
> (e.g. after restarting Emacs): your code errors because Emacs does not
> pop up a preview window in that case.

I think you mean when hitting C-n/p or up/down?
It is fixed in last version of the patch (not publied yet).

>
> Michael.


-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-20  5:49       ` Thierry Volpiatto
@ 2023-10-21  1:09         ` Michael Heerdegen
  2023-10-21  3:34           ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-21  1:09 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> > For keys like C-a you also need to hit C-q.  It's not 100%
> > compatible.
>
> I don't understand, what C-a and C-q have to do here? Also, what C-q
> is intended to do in minibuffer?

Registers are characters.  Control characters are valid registers.  So
you can for example do C-x r s C-a to save the region string into register
`C-a'.  Your patch complicates inputting such registers.  Dunno if
people use such registers, but I wanted to mention this.  It's a bit
harder now to use non-printable characters as registers now.


> > But wait: What I find confusing is that I also need need to confirm for
> > `jump-to-register'.  Is this intended?
>
> Do you mean RET? If so yes.

For jumping?  Why is this useful?


> >> Note that now you can use M-n to select in minibuffer the available
> >> keys (this only for setting or modifying a register).
> >
> > In Helm or in vanilla Emacs?  I don't see that for M-n in vanilla Emacs.
>
> Once the patch is applied, C-x r x M-n (repeat if necessary), same for
> C-x r w/n etc...

Is this part in the patch you had been posting in the first messages?
Because I only get "End of history; no default available" with that
patch installed.


> > Oh, and there is a little bug when the register binding list is empty
> > (e.g. after restarting Emacs): your code errors because Emacs does not
> > pop up a preview window in that case.
>
> I think you mean when hitting C-n/p or up/down?
> It is fixed in last version of the patch (not publied yet).

Let me try to be more precise what I saw: If I start Emacs modified with
your patch and do C-x r s with an active region, I see this message in
the minibuffer:

  Error running timer: (error "No buffer named *Register Preview*")

Maybe that's already what you have fixed.

One more detail: I see "Invalid face reference: helm-match" in the
*Messages* of emacs -Q.  Still using your first patch (Could you please
post the newest version again?).


Thanks so far,

Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-21  1:09         ` Michael Heerdegen
@ 2023-10-21  3:34           ` Thierry Volpiatto
  2023-10-23  4:09             ` Michael Heerdegen
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-21  3:34 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 2118 bytes --]


Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> > For keys like C-a you also need to hit C-q.  It's not 100%
>> > compatible.
>>
>> I don't understand, what C-a and C-q have to do here? Also, what C-q
>> is intended to do in minibuffer?
>
> Registers are characters.  Control characters are valid registers.  So
> you can for example do C-x r s C-a to save the region string into register
> `C-a'.  Your patch complicates inputting such registers.  Dunno if
> people use such registers, but I wanted to mention this.  It's a bit
> harder now to use non-printable characters as registers now.

Yes, probably this is one downside of this patch, but as you mentionned
one can use C-q C-a if really needed, I for one never used such
registers.

>
>> > But wait: What I find confusing is that I also need need to confirm for
>> > `jump-to-register'.  Is this intended?
>>
>> Do you mean RET? If so yes.
>
> For jumping?  Why is this useful?

Well, actually with original behavior you can jump to a register
recorded as a string, which returns an error of course because the
register is meant to use with insert.  Now the situation is better
because the candidates are filtered but you can still jump to an
unwanted place, read-from-minibuffer lets you the time to see where you
are going.

>
>> >> Note that now you can use M-n to select in minibuffer the available
>> >> keys (this only for setting or modifying a register).
>> >
>> > In Helm or in vanilla Emacs?  I don't see that for M-n in vanilla Emacs.
>>
>> Once the patch is applied, C-x r x M-n (repeat if necessary), same for
>> C-x r w/n etc...
>
> Is this part in the patch you had been posting in the first messages?
> Because I only get "End of history; no default available" with that
> patch installed.

No, I will prepare a patch later, when there is interest in this
feature, for now use the gist I maintain here as mentionned previously:

https://gist.github.com/thierryvolpiatto/2219f99ac96ed1b468fac204bca23b4a

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-21  3:34           ` Thierry Volpiatto
@ 2023-10-23  4:09             ` Michael Heerdegen
  2023-10-23  5:14               ` Thierry Volpiatto
  2023-10-24  7:19               ` Thierry Volpiatto
  0 siblings, 2 replies; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-23  4:09 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> > For jumping?  Why is this useful?
>
> Well, actually with original behavior you can jump to a register
> recorded as a string, which returns an error of course because the
> register is meant to use with insert.  Now the situation is better
> because the candidates are filtered but you can still jump to an
> unwanted place, read-from-minibuffer lets you the time to see where you
> are going.

Ah - ok.  Then that's definitely useful.  Haven't yet tried the complete
code, but I had a look at the link you posted.

It would not be good to carve the current register type system
into stone.  Instead of your `register-type' function I would prefer
something extensible, for the case of new register types being added
(even a normal user might want to do this).  So, when one wants to add a
new register type, it is necessary that one is able to declare, in some
way, whether registers of this type should be included or not for
`insert-register' (and maybe also `jump-to-register').

Instead of a detour via type names a better way seems to be adding new
predicate methods that accept one argument, a register, and should
return non-nil when the argument register can be inserted, or jumped to.

I can try to modify your patch accordingly if you are interested.


Thx,

Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-23  4:09             ` Michael Heerdegen
@ 2023-10-23  5:14               ` Thierry Volpiatto
  2023-10-24  3:42                 ` Michael Heerdegen
  2023-10-24  7:19               ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-23  5:14 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 2160 bytes --]


Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> > For jumping?  Why is this useful?
>>
>> Well, actually with original behavior you can jump to a register
>> recorded as a string, which returns an error of course because the
>> register is meant to use with insert.  Now the situation is better
>> because the candidates are filtered but you can still jump to an
>> unwanted place, read-from-minibuffer lets you the time to see where you
>> are going.
>
> Ah - ok.  Then that's definitely useful.  Haven't yet tried the complete
> code, but I had a look at the link you posted.
>
> It would not be good to carve the current register type system
> into stone.  Instead of your `register-type' function I would prefer
> something extensible, for the case of new register types being added
> (even a normal user might want to do this).  So, when one wants to add a
> new register type, it is necessary that one is able to declare, in some
> way, whether registers of this type should be included or not for
> `insert-register' (and maybe also `jump-to-register').
>
> Instead of a detour via type names a better way seems to be adding new
> predicate methods that accept one argument, a register, and should
> return non-nil when the argument register can be inserted, or jumped to.

Not sure to understand what you envisage here, but if you do something
like this you have to make the types used for the two register commands
configurable as well.
Actually we have insert-register that accept '(string number) types and
jump-to-register that accept '(window frame marker) types and this is
hardcoded. I guess you want to make register-type a generic function and
add several method that fit the types we actually have and if one wants
to add a new type he just have to write a new defmethod and add the new
type to the methods suitable for insert or jump.

> I can try to modify your patch accordingly if you are interested.

Yes but I think this should go into another commit on top of my patch to
avoid having a "too big patch".

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-23  5:14               ` Thierry Volpiatto
@ 2023-10-24  3:42                 ` Michael Heerdegen
  2023-10-24  3:54                   ` Michael Heerdegen
  2023-10-24  5:30                   ` Thierry Volpiatto
  0 siblings, 2 replies; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-24  3:42 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> Yes but I think this should go into another commit on top of my patch
> to avoid having a "too big patch".

Yes, maybe.

Ok, some more remarks (I have looked at that url now...):

* Would it make sense to also allow M-n (known as "future history" for
  `completing-read') to gather the next free register (seems also
  natural - just a thought)

* Multiple times I saw "contains no text" where a better hint would have
  been to say "empty".  Not all registers contain text.  Happens
  e.g. for C-x r SPC R where R is any unused register.

* register-preview-default-keys may be initialized using
  (mapcar #'string (number-sequence ?a ?z)) if you like.


Hope we get more opinions about this interface suggestion.


Thx,

Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-24  3:42                 ` Michael Heerdegen
@ 2023-10-24  3:54                   ` Michael Heerdegen
  2023-10-24  5:30                   ` Thierry Volpiatto
  1 sibling, 0 replies; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-24  3:54 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: Evgenii Klimov, 66394

Michael Heerdegen <michael_heerdegen@web.de> writes:

> Hope we get more opinions about this interface suggestion.

Adding Evgenii to the thread.  AFAIR he had suggested a subset of this
suggestion (the filtering part, in July in emacs-devel).  Maybe he feels
like trying Thierry's approach.  Code is here, just eval if interested:

  https://gist.github.com/thierryvolpiatto/2219f99ac96ed1b468fac204bca23b4a

Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-24  3:42                 ` Michael Heerdegen
  2023-10-24  3:54                   ` Michael Heerdegen
@ 2023-10-24  5:30                   ` Thierry Volpiatto
  2023-10-25  3:54                     ` Michael Heerdegen
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-24  5:30 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 1128 bytes --]


Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> Yes but I think this should go into another commit on top of my patch
>> to avoid having a "too big patch".
>
> Yes, maybe.
>
> Ok, some more remarks (I have looked at that url now...):
>
> * Would it make sense to also allow M-n (known as "future history" for
>   `completing-read') to gather the next free register (seems also
>   natural - just a thought)

It is already done ;-)

> * Multiple times I saw "contains no text" where a better hint would have
>   been to say "empty".  Not all registers contain text.  Happens
>   e.g. for C-x r SPC R where R is any unused register.

Yes I used the message vanilla Emacs already use somewhere, but yes
empty seems better.

> * register-preview-default-keys may be initialized using
>   (mapcar #'string (number-sequence ?a ?z)) if you like.

Yes could be done. 

PS: I found a bug in my code with frame configs not appearing in preview,
now fixed, will update the gist right now with your suggestions as well.

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-23  4:09             ` Michael Heerdegen
  2023-10-23  5:14               ` Thierry Volpiatto
@ 2023-10-24  7:19               ` Thierry Volpiatto
  2023-10-25  4:10                 ` Michael Heerdegen
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-24  7:19 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 1703 bytes --]


Michael Heerdegen <michael_heerdegen@web.de> writes:

> It would not be good to carve the current register type system
> into stone.  Instead of your `register-type' function I would prefer
> something extensible, for the case of new register types being added
> (even a normal user might want to do this).  So, when one wants to add a
> new register type, it is necessary that one is able to declare, in some
> way, whether registers of this type should be included or not for
> `insert-register' (and maybe also `jump-to-register').

A possible solution for this is adding two vars, insert-register-types
and jump-to-register-types and define register-type like this (named
register--type here):

(defun register--type (register)
  ;; Call register/type against the register value.
  (register/type (if (consp (cdr register))
                     (cadr register)
                   (cdr register))))

(cl-defgeneric register/type (regval))

(cl-defmethod register/type ((regval string)) 'string)
(cl-defmethod register/type ((regval number)) 'number)
(cl-defmethod register/type ((regval marker)) 'marker)
(cl-defmethod register/type ((regval window-configuration)) 'window)
(cl-deftype frame-register () '(satisfies frameset-register-p))
(cl-defmethod register/type :extra "frame-register" (regval) 'frame)

;; set a new register and check its type like this:
(register--type (car register-alist))

So if one wants a new register type he has just to add the type to one
of insert-register-types or jump-to-register-types and add a new
defmethod for this type. If the new type in not one of cl-typep he may
have to define a new type like above.


-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-24  5:30                   ` Thierry Volpiatto
@ 2023-10-25  3:54                     ` Michael Heerdegen
  0 siblings, 0 replies; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-25  3:54 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> > * Multiple times I saw "contains no text" where a better hint would have
> >   been to say "empty".  Not all registers contain text.  Happens
> >   e.g. for C-x r SPC R where R is any unused register.
>
> Yes I used the message vanilla Emacs already use somewhere, but yes
> empty seems better.

Thanks.  In register.el I see a message like that only for text related
register commands.


Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-24  7:19               ` Thierry Volpiatto
@ 2023-10-25  4:10                 ` Michael Heerdegen
  2023-10-25  6:38                   ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-25  4:10 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> A possible solution for this is adding two vars, insert-register-types
> and jump-to-register-types and define register-type like this (named
> register--type here):
>
> (defun register--type (register)
>   ;; Call register/type against the register value.
>   (register/type (if (consp (cdr register))
>                      (cadr register)
>                    (cdr register))))
>
> (cl-defgeneric register/type (regval))
>
> (cl-defmethod register/type ((regval string)) 'string)
> (cl-defmethod register/type ((regval number)) 'number)
> (cl-defmethod register/type ((regval marker)) 'marker)
> (cl-defmethod register/type ((regval window-configuration)) 'window)
> (cl-deftype frame-register () '(satisfies frameset-register-p))
> (cl-defmethod register/type :extra "frame-register" (regval) 'frame)
>
> ;; set a new register and check its type like this:
> (register--type (car register-alist))

This looks promising.

But I'm not sure whether the detour via type names (instead of an
approach using only generics) is the best solution.  Why not define just
a new generic (register-eligible-for-command-p REG COMMAND) and use that
as predicate in the interactive specs of the commands (providing
`this-command' as second arg)?  Seems simpler to me and still more
extensible and controllable.

Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-25  4:10                 ` Michael Heerdegen
@ 2023-10-25  6:38                   ` Thierry Volpiatto
  2023-10-26  4:18                     ` Michael Heerdegen
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-25  6:38 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 3191 bytes --]


Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> A possible solution for this is adding two vars, insert-register-types
>> and jump-to-register-types and define register-type like this (named
>> register--type here):
>>
>> (defun register--type (register)
>>   ;; Call register/type against the register value.
>>   (register/type (if (consp (cdr register))
>>                      (cadr register)
>>                    (cdr register))))
>>
>> (cl-defgeneric register/type (regval))
>>
>> (cl-defmethod register/type ((regval string)) 'string)
>> (cl-defmethod register/type ((regval number)) 'number)
>> (cl-defmethod register/type ((regval marker)) 'marker)
>> (cl-defmethod register/type ((regval window-configuration)) 'window)
>> (cl-deftype frame-register () '(satisfies frameset-register-p))
>> (cl-defmethod register/type :extra "frame-register" (regval) 'frame)
>>
>> ;; set a new register and check its type like this:
>> (register--type (car register-alist))
>
> This looks promising.
>
> But I'm not sure whether the detour via type names (instead of an
> approach using only generics) is the best solution.  Why not define just
> a new generic (register-eligible-for-command-p REG COMMAND) and use that
> as predicate in the interactive specs of the commands (providing
> `this-command' as second arg)?  Seems simpler to me and still more
> extensible and controllable.

Not sure to understand what you want to do here.

We don't want to modify each command, and anyway I don't see what
(register-eligible-for-command-p REG COMMAND) would do in the
interactive spec of each command.

There is two things we want to make more flexible:

1) The ability to allow adding a new type of register and
use this type of register to filter out the register-alist according to
the command in use.

2) Allow one to add a new register command
and assign its type, message to use and action it
provide.

Example, if I want to define a new command register-delete:

    (defun register-delete (register)
      (interactive (list (register-read-with-preview "Delete register: ")))
      (setq register-alist (delete register register-alist)))

If I run this command I will have a minibuffer message "Overwrite
register <n>", this is not what I expect, I expect "Delete register
<n>".

So we need something to customize this.
I added a new var and a structure to achieve this, so now one can do in
e.g. its .emacs:

    (with-eval-after-load 'register
      (require 'register-preview)
      (add-to-list 'register-commands-data
                   `(register-delete
                     .
                     ,(make-register-preview-commands
                       :types '(all)
                       :msg "Delete register `%s'"
                       :act 'delete)))
      (defun register-delete (register)
        (interactive (list (register-read-with-preview "Delete register: ")))
        (setq register-alist (delete register register-alist))))


But maybe what you propose is simpler to achieve the two tasks above,
don't know.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-25  6:38                   ` Thierry Volpiatto
@ 2023-10-26  4:18                     ` Michael Heerdegen
  2023-10-26  6:17                       ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-26  4:18 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> Not sure to understand what you want to do here.

Maybe it's easier if I post a patch.  Will try to do this tomorrow.

What I want to do is that `register-read-with-preview' accepts another
argument, a predicate, that is used to filter the registers to be
included in the preview.

And the hierarchy defining which registers support which operations I
want to define implicitly using method specializers, not explicitly
using types.

Because I think using generics is more flexible.  When the type system
you propose defines, for example, that string registers can be inserted,
and appendend and prepended to (we have commands for that), and
then, say, somebody wants to define a wrapper register type "read-only
register" that can hold anything a register can hold but with the
difference that the read-only register can't be modified, you want to
fall back to the filtering of the base type (which can be anything, so
this has to be done dynamically) - but disallow append and prepend for
string registers, for example.

Just an example, but such wrappers can be useful for registers.  You can
define registers with annotations for example: the annotations are
displayed in the preview but don't affect the behavior of the base
register.

Such things are hard to code using a type system.  Of course there are
more changes to be made to allow everything I outlined, but I want that
we don't do anything that limits what could be added to register.el in
the future.

Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-26  4:18                     ` Michael Heerdegen
@ 2023-10-26  6:17                       ` Thierry Volpiatto
  2023-10-27  1:27                         ` Michael Heerdegen
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-26  6:17 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 622 bytes --]


Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> Not sure to understand what you want to do here.
>
> Maybe it's easier if I post a patch.  Will try to do this tomorrow.

Yes, not sure to understand what you want to do.

> What I want to do is that `register-read-with-preview' accepts another
> argument, a predicate, that is used to filter the registers to be
> included in the preview.

Why do you need another argument as long as you use `this-command`?
You can use e.g. (pcase this-command ('foo #'foo-p) etc...)
Isn't it?

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-26  6:17                       ` Thierry Volpiatto
@ 2023-10-27  1:27                         ` Michael Heerdegen
  2023-10-27  4:24                           ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Michael Heerdegen @ 2023-10-27  1:27 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> Why do you need another argument as long as you use `this-command`?
> You can use e.g. (pcase this-command ('foo #'foo-p) etc...)

I doubt all potential uses will use `this-command'.

It's cleaner if the command that knows what it wants passes the
information via argument than to make the other function derive it
indirectly from the context (functional style).

Maybe in the future we might need to pass other predicates as well.
What when a user wants to add another register command?  Or if a future
command needs to prompt more than once?

A predicate passed to the function can also be wrapped for further
filtering etc... that's all more controllable and extensible than hiding
the decision in a defun.

Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-27  1:27                         ` Michael Heerdegen
@ 2023-10-27  4:24                           ` Thierry Volpiatto
  2023-11-03  4:58                             ` Michael Heerdegen
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-10-27  4:24 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 864 bytes --]


Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> Why do you need another argument as long as you use `this-command`?
>> You can use e.g. (pcase this-command ('foo #'foo-p) etc...)
>
> I doubt all potential uses will use `this-command'.
>
> It's cleaner if the command that knows what it wants passes the
> information via argument than to make the other function derive it
> indirectly from the context (functional style).

It is what I did initially after realizing it is simpler to use
this-command from register-read-with-preview.

> Maybe in the future we might need to pass other predicates as well.
> What when a user wants to add another register command?

You can with the current register-preview.el add a new command and
control filtering of this command.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-27  4:24                           ` Thierry Volpiatto
@ 2023-11-03  4:58                             ` Michael Heerdegen
  2023-11-19 19:37                               ` Thierry Volpiatto
  2023-11-20  6:00                               ` Thierry Volpiatto
  0 siblings, 2 replies; 121+ messages in thread
From: Michael Heerdegen @ 2023-11-03  4:58 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> > Maybe in the future we might need to pass other predicates as well.
> > What when a user wants to add another register command?
>
> You can with the current register-preview.el add a new command and
> control filtering of this command.

Cool, thanks.  Looks reasonable.

In my perfect world, the `register-commands-data' would not be specified
as a list but also using methods.  Maybe also
`register-preview-get-defaults'.

I will have a closer look tomorrow, had been a little busy so that I
just now returned to this thread.


Regards,

Michael.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: [RE] Make register-read-with-preview more useful
  2023-10-15 12:55           ` Stefan Kangas
@ 2023-11-18 18:39             ` Thierry Volpiatto
  0 siblings, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-11-18 18:39 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 453 bytes --]


Hello Stefan,

Stefan Kangas <stefankangas@gmail.com> writes:

> reopen 66394
> thanks
>
> Thierry Volpiatto <thievol@posteo.net> writes:
>
>>> If it's fine by you, I'd like to reopen this bug report.
>>
>> Ok, please do.
>
> Done, thanks.

More than one month now, what do you want to do with this?
I had constructive exchanges with Michael and the code has been updated
according to those discussions...

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-03  4:58                             ` Michael Heerdegen
@ 2023-11-19 19:37                               ` Thierry Volpiatto
  2023-11-20  6:00                               ` Thierry Volpiatto
  1 sibling, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-11-19 19:37 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: 66394

[-- Attachment #1: Type: text/plain, Size: 15952 bytes --]

Michael Heerdegen <michael_heerdegen@web.de> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> > Maybe in the future we might need to pass other predicates as well.
>> > What when a user wants to add another register command?
>>
>> You can with the current register-preview.el add a new command and
>> control filtering of this command.
>
> Cool, thanks.  Looks reasonable.
>
> In my perfect world, the `register-commands-data' would not be specified
> as a list but also using methods.  Maybe also
> `register-preview-get-defaults'.
>
> I will have a closer look tomorrow, had been a little busy so that I
> just now returned to this thread.

Here all the work done so far.

diff --git a/lisp/register.el b/lisp/register.el
index ca6de450993..78643d10c17 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -35,6 +35,8 @@
 
 ;; FIXME: Clean up namespace usage!
 
+(declare-function frameset-register-p "frameset")
+
 (cl-defstruct
   (registerv (:constructor nil)
 	     (:constructor registerv--make (&optional data print-func
@@ -91,6 +93,7 @@ of the marked text."
   :type '(choice (const :tag "None" nil)
 		 (character :tag "Use register" :value ?+)))
 
+;; FIXME: This is no more needed, remove it.
 (defcustom register-preview-delay 1
   "If non-nil, time to wait in seconds before popping up register preview window.
 If nil, do not show register previews, unless `help-char' (or a member of
@@ -99,6 +102,14 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
 
+(defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
+  "Default keys for setting a new register."
+  :type '(repeat string))
+
+(defcustom register-use-preview t
+  "Always show register preview when non nil."
+  :type 'boolean)
+
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
   (alist-get register register-alist))
@@ -128,53 +139,263 @@ See the documentation of the variable `register-alist' for possible VALUEs."
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
 The function should return a string, the description of the argument.")
 
-(defun register-preview (buffer &optional show-empty)
+(cl-defstruct register-preview-info
+  "Store data for a specific register command.
+TYPES are the types of register supported.
+MSG is the minibuffer message to send when a register is selected.
+ACT is the type of action the command is doing on register.
+SMATCH accept a boolean value to say if command accept non matching register."
+  types msg act smatch)
+
+(cl-defgeneric register-command-info (command)
+  "Returns a `register-preview-info' object storing data for COMMAND."
+  (ignore command))
+(cl-defmethod register-command-info ((_command (eql insert-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Insert register `%s'"
+   :act 'insert
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql jump-to-register)))
+  (make-register-preview-info
+   :types  '(window frame marker kmacro
+             file buffer file-query)
+   :msg "Jump to register `%s'"
+   :act 'jump
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql view-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "View register `%s'"
+   :act 'view
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql append-to-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Append to register `%s'"
+   :act 'modify
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql prepend-to-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Prepend to register `%s'"
+   :act 'modify
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql increment-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Increment register `%s'"
+   :act 'modify
+   :smatch t))
+
+(defun register-preview-forward-line (arg)
+  "Move to next or previous line in register preview buffer.
+If ARG is positive goto next line, if negative to previous.
+Do nothing when defining or executing kmacros."
+  ;; Ensure user enter manually key in minibuffer when recording a macro.
+  (unless (or defining-kbd-macro executing-kbd-macro
+              (not (get-buffer-window "*Register Preview*" 'visible)))
+    (let ((fn (if (> arg 0) #'eobp #'bobp))
+          (posfn (if (> arg 0)
+                     #'point-min
+                     (lambda () (1- (point-max)))))
+          str)
+      (with-current-buffer "*Register Preview*"
+        (let ((ovs (overlays-in (point-min) (point-max)))
+              pos)
+          (goto-char (if ovs
+                         (overlay-start (car ovs))
+                         (point-min)))
+          (setq pos (point))
+          (and ovs (forward-line arg))
+          (when (and (funcall fn)
+                     (or (> arg 0) (eql pos (point))))
+            (goto-char (funcall posfn)))
+          (setq str (buffer-substring-no-properties
+                     (pos-bol) (1+ (pos-bol))))
+          (remove-overlays)
+          (with-selected-window (minibuffer-window)
+            (delete-minibuffer-contents)
+            (insert str)))))))
+
+(defun register-preview-next ()
+  "Goto next line in register preview buffer."
+  (interactive)
+  (register-preview-forward-line 1))
+
+(defun register-preview-previous ()
+  "Goto previous line in register preview buffer."
+  (interactive)
+  (register-preview-forward-line -1))
+
+(defun register-type (register)
+  "Return REGISTER type.
+Current register types actually returned are one of:
+- string
+- number
+- marker
+- buffer
+- file
+- file-query
+- window
+- frame
+- kmacro
+
+One can add new types to a specific command by defining a new `cl-defmethod'
+matching this command. Predicate for type in new `cl-defmethod' should
+satisfy `cl-typep' otherwise the new type should be defined with
+`cl-deftype'."
+  ;; Call register--type against the register value.
+  (register--type (if (consp (cdr register))
+                     (cadr register)
+                   (cdr register))))
+
+(cl-defgeneric register--type (regval)
+  "Returns type of register value REGVAL."
+  (ignore regval))
+
+(cl-defmethod register--type ((_regval string)) 'string)
+(cl-defmethod register--type ((_regval number)) 'number)
+(cl-defmethod register--type ((_regval marker)) 'marker)
+(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer)
+(cl-defmethod register--type ((_regval (eql 'file))) 'file)
+(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query)
+(cl-defmethod register--type ((_regval window-configuration)) 'window)
+(cl-deftype frame-register () '(satisfies frameset-register-p))
+(cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
+(cl-deftype kmacro-register () '(satisfies kmacro-register-p))
+(cl-defmethod register--type :extra "kmacro-register" (_regval) 'kmacro)
+
+(defun register-of-type-alist (types)
+  "Filter `register-alist' according to TYPES."
+  (if (memq 'all types)
+      register-alist
+    (cl-loop for register in register-alist
+             when (memq (register-type register) types)
+             collect register)))
+
+(defun register-preview-1 (buffer &optional show-empty types)
   "Pop up a window showing the registers preview in BUFFER.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
+Argument TYPES (a list) specify the types of register to show, when nil show all
+registers, see `register-type' for suitable types. 
 Format of each entry is controlled by the variable `register-preview-function'."
-  (when (or show-empty (consp register-alist))
-    (with-current-buffer-window
-     buffer
-     (cons 'display-buffer-below-selected
-	   '((window-height . fit-window-to-buffer)
-	     (preserve-size . (nil . t))))
-     nil
-     (with-current-buffer standard-output
-       (setq cursor-in-non-selected-windows nil)
-       (mapc (lambda (elem)
-               (when (get-register (car elem))
-                 (insert (funcall register-preview-function elem))))
-             register-alist)))))
+  (let ((registers (register-of-type-alist (or types '(all)))))
+    (when (or show-empty (consp registers))
+      (with-current-buffer-window
+        buffer
+        (cons 'display-buffer-below-selected
+	      '((window-height . fit-window-to-buffer)
+	        (preserve-size . (nil . t))))
+        nil
+        (with-current-buffer standard-output
+          (setq cursor-in-non-selected-windows nil)
+          (mapc (lambda (elem)
+                  (when (get-register (car elem))
+                    (insert (funcall register-preview-function elem))))
+                registers))))))
+
+(cl-defgeneric register-preview-get-defaults (action)
+  "Returns default registers according to ACTION."
+  (ignore action))
+(cl-defmethod register-preview-get-defaults ((_action (eql set)))
+  (cl-loop for s in register-preview-default-keys
+           unless (assoc (string-to-char s) register-alist)
+           collect s))
 
 (defun register-read-with-preview (prompt)
   "Read and return a register name, possibly showing existing registers.
-Prompt with the string PROMPT.  If `register-alist' and
-`register-preview-delay' are both non-nil, display a window
-listing existing registers after `register-preview-delay' seconds.
+Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
-	 (timer (when (numberp register-preview-delay)
-		  (run-with-timer register-preview-delay nil
-				  (lambda ()
-				    (unless (get-buffer-window buffer)
-				      (register-preview buffer))))))
-	 (help-chars (cl-loop for c in (cons help-char help-event-list)
-			      when (not (get-register c))
-			      collect c)))
+         (pat "")
+         (map (let ((m (make-sparse-keymap)))
+                (set-keymap-parent m minibuffer-local-map)
+                m))
+         (data (register-command-info this-command))
+         types msg result timer act win strs smatch)
+    (if data
+        (setq types  (register-preview-info-types data)
+              msg    (register-preview-info-msg   data)
+              act    (register-preview-info-act   data)
+              smatch (register-preview-info-smatch data))
+      (setq types '(all)
+            msg   "Overwrite register `%s'"
+            act   'set))
+    (setq strs (mapcar (lambda (x)
+                         (string (car x)))
+                       (register-of-type-alist types)))
+    (when (and (memq act '(insert jump view)) (null strs))
+      (error "No register suitable for `%s'" act))
+    (dolist (k (cons help-char help-event-list))
+      (define-key map
+          (vector k) (lambda ()
+                       (interactive)
+                       (unless (get-buffer-window buffer)
+                         (with-selected-window (minibuffer-selected-window)
+                           (register-preview-1 buffer 'show-empty types))))))
+    (define-key map (kbd "<down>") 'register-preview-next)
+    (define-key map (kbd "<up>")   'register-preview-previous)
+    (define-key map (kbd "C-n")    'register-preview-next)
+    (define-key map (kbd "C-p")    'register-preview-previous)
+    (unless (or executing-kbd-macro (null register-use-preview))
+      (register-preview-1 buffer nil types))
     (unwind-protect
-	(progn
-	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
-		       help-chars)
-	    (unless (get-buffer-window buffer)
-	      (register-preview buffer 'show-empty)))
-          (when (or (eq ?\C-g last-input-event)
-                    (eq 'escape last-input-event)
-                    (eq ?\C-\[ last-input-event))
-            (keyboard-quit))
-	  (if (characterp last-input-event) last-input-event
-	    (error "Non-character input-event")))
-      (and (timerp timer) (cancel-timer timer))
+         (progn
+           (minibuffer-with-setup-hook
+               (lambda ()
+                 (setq timer
+                       (run-with-idle-timer
+                        0.01 'repeat
+                        (lambda ()
+                          (with-selected-window (minibuffer-window)
+                            (let ((input (minibuffer-contents)))
+                              (when (> (length input) 1)
+                                (let ((new (substring input 1))
+                                      (old (substring input 0 1)))
+                                  (setq input (if (or (null smatch)
+                                                      (member new strs))
+                                                  new old))
+                                  (delete-minibuffer-contents)
+                                  (insert input)))
+                              (when (and smatch (not (string= input ""))
+                                         (not (member input strs)))
+                                (setq input "")
+                                (delete-minibuffer-contents)
+                                (minibuffer-message "Not matching"))
+                              (when (not (string= input pat))
+                                (setq pat input))))
+                          (if (setq win (get-buffer-window buffer))
+                              (with-selected-window win
+                                (let ((ov (make-overlay (point-min) (point-min))))
+                                  (goto-char (point-min))
+                                  (remove-overlays)
+                                  (unless (string= pat "")
+                                    (if (re-search-forward (concat "^" pat) nil t)
+                                        (progn (move-overlay
+                                                ov
+                                                (match-beginning 0) (pos-eol))
+                                               (overlay-put ov 'face 'match)
+                                               (when msg
+                                                 (with-selected-window (minibuffer-window)
+                                                   (minibuffer-message msg pat))))
+                                      (with-selected-window (minibuffer-window)
+                                        (minibuffer-message
+                                         "Register `%s' is empty" pat))))))
+                            (unless (string= pat "")
+                              (if (member pat strs)
+                                  (with-selected-window (minibuffer-window)
+                                    (minibuffer-message msg pat))
+                                (with-selected-window (minibuffer-window)
+                                  (minibuffer-message
+                                   "Register `%s' is empty" pat)))))))))
+             (setq result (read-from-minibuffer
+                           prompt nil map nil nil (register-preview-get-defaults act))))
+           (cl-assert (and result (not (string= result "")))
+                      nil "No register specified")
+           (string-to-char result))
+      (when timer (cancel-timer timer))
       (let ((w (get-buffer-window buffer)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buffer) (kill-buffer buffer)))))

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-03  4:58                             ` Michael Heerdegen
  2023-11-19 19:37                               ` Thierry Volpiatto
@ 2023-11-20  6:00                               ` Thierry Volpiatto
  2023-11-20 17:33                                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-02  9:24                                 ` Bastien
  1 sibling, 2 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-11-20  6:00 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: stefankangas, monnier, 66394


[-- Attachment #1.1: Type: text/plain, Size: 406 bytes --]


Here the full patch attached, the previous was not applying properly.

Ccing also Stefan monnier because for some reasons the patch when
applied doesn't compile (when compiling Emacs) unless we add on
top:

    (cl--generic-prefill-dispatchers 0 (eql 'x) integer)

following the advice of the compiler, but I am not sure it is the way to
do.

Compiling register.el manually without this works correctly.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: register-preview --]
[-- Type: text/x-diff, Size: 16878 bytes --]

From c794d62a45b4c83131e506699f465e54b7dae7b5 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Sun, 19 Nov 2023 20:42:56 +0100
Subject: [PATCH] Improve register-preview (Fix bug#66394)

A minibuffer is used now instead of read-key.
Registers in preview buffer are now filtered according to type of
registers the current command requires.
Navigation with C-n/p or up/down is now provided and update
minibuffer.
Current register is highlighted in preview buffer.

* register.el:

* (register-preview-default-keys): new user var.
* (register-use-preview): Same.
* (register-preview-info): New structure to store various info for
  preview.
* (register-command-info): New generic.
* (register-preview-forward-line): New, provide navigation in preview
  buffer.
* (register-preview-next, register-preview-previous): New, navigation.
* (register-type): New, returns register type.
* (register--type): Generic fn, new, returns register type according
  to value.
* (register-of-type-alist): New, filter register-alist according to
  type.
* (register-preview): Signature changed, use TYPES now.
* (register-preview-get-defaults): New generic, compute defauts
  according to action.
* (register-read-with-preview): Now use read-from-minibuffer and
  minibuffer-setup-hook.
---
 lisp/register.el | 296 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 259 insertions(+), 37 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index ca6de450993..47f0dfa389c 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -30,11 +30,14 @@
 ;; documented in the Emacs user's manual: (info "(emacs) Registers").
 
 (eval-when-compile (require 'cl-lib))
+(cl--generic-prefill-dispatchers 0 (eql 'x) integer)
 
 ;;; Code:
 
 ;; FIXME: Clean up namespace usage!
 
+(declare-function frameset-register-p "frameset")
+
 (cl-defstruct
   (registerv (:constructor nil)
 	     (:constructor registerv--make (&optional data print-func
@@ -91,6 +94,7 @@ of the marked text."
   :type '(choice (const :tag "None" nil)
 		 (character :tag "Use register" :value ?+)))
 
+;; FIXME: This is no more needed, remove it.
 (defcustom register-preview-delay 1
   "If non-nil, time to wait in seconds before popping up register preview window.
 If nil, do not show register previews, unless `help-char' (or a member of
@@ -99,6 +103,14 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
 
+(defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
+  "Default keys for setting a new register."
+  :type '(repeat string))
+
+(defcustom register-use-preview t
+  "Always show register preview when non nil."
+  :type 'boolean)
+
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
   (alist-get register register-alist))
@@ -128,53 +140,263 @@ See the documentation of the variable `register-alist' for possible VALUEs."
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
 The function should return a string, the description of the argument.")
 
-(defun register-preview (buffer &optional show-empty)
+(cl-defstruct register-preview-info
+  "Store data for a specific register command.
+TYPES are the types of register supported.
+MSG is the minibuffer message to send when a register is selected.
+ACT is the type of action the command is doing on register.
+SMATCH accept a boolean value to say if command accept non matching register."
+  types msg act smatch)
+
+(cl-defgeneric register-command-info (command)
+  "Returns a `register-preview-info' object storing data for COMMAND."
+  (ignore command))
+(cl-defmethod register-command-info ((_command (eql insert-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Insert register `%s'"
+   :act 'insert
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql jump-to-register)))
+  (make-register-preview-info
+   :types  '(window frame marker kmacro
+             file buffer file-query)
+   :msg "Jump to register `%s'"
+   :act 'jump
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql view-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "View register `%s'"
+   :act 'view
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql append-to-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Append to register `%s'"
+   :act 'modify
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql prepend-to-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Prepend to register `%s'"
+   :act 'modify
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql increment-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Increment register `%s'"
+   :act 'modify
+   :smatch t))
+
+(defun register-preview-forward-line (arg)
+  "Move to next or previous line in register preview buffer.
+If ARG is positive goto next line, if negative to previous.
+Do nothing when defining or executing kmacros."
+  ;; Ensure user enter manually key in minibuffer when recording a macro.
+  (unless (or defining-kbd-macro executing-kbd-macro
+              (not (get-buffer-window "*Register Preview*" 'visible)))
+    (let ((fn (if (> arg 0) #'eobp #'bobp))
+          (posfn (if (> arg 0)
+                     #'point-min
+                     (lambda () (1- (point-max)))))
+          str)
+      (with-current-buffer "*Register Preview*"
+        (let ((ovs (overlays-in (point-min) (point-max)))
+              pos)
+          (goto-char (if ovs
+                         (overlay-start (car ovs))
+                         (point-min)))
+          (setq pos (point))
+          (and ovs (forward-line arg))
+          (when (and (funcall fn)
+                     (or (> arg 0) (eql pos (point))))
+            (goto-char (funcall posfn)))
+          (setq str (buffer-substring-no-properties
+                     (pos-bol) (1+ (pos-bol))))
+          (remove-overlays)
+          (with-selected-window (minibuffer-window)
+            (delete-minibuffer-contents)
+            (insert str)))))))
+
+(defun register-preview-next ()
+  "Goto next line in register preview buffer."
+  (interactive)
+  (register-preview-forward-line 1))
+
+(defun register-preview-previous ()
+  "Goto previous line in register preview buffer."
+  (interactive)
+  (register-preview-forward-line -1))
+
+(defun register-type (register)
+  "Return REGISTER type.
+Current register types actually returned are one of:
+- string
+- number
+- marker
+- buffer
+- file
+- file-query
+- window
+- frame
+- kmacro
+
+One can add new types to a specific command by defining a new `cl-defmethod'
+matching this command. Predicate for type in new `cl-defmethod' should
+satisfy `cl-typep' otherwise the new type should be defined with
+`cl-deftype'."
+  ;; Call register--type against the register value.
+  (register--type (if (consp (cdr register))
+                     (cadr register)
+                   (cdr register))))
+
+(cl-defgeneric register--type (regval)
+  "Returns type of register value REGVAL."
+  (ignore regval))
+
+(cl-defmethod register--type ((_regval string)) 'string)
+(cl-defmethod register--type ((_regval number)) 'number)
+(cl-defmethod register--type ((_regval marker)) 'marker)
+(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer)
+(cl-defmethod register--type ((_regval (eql 'file))) 'file)
+(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query)
+(cl-defmethod register--type ((_regval window-configuration)) 'window)
+(cl-deftype frame-register () '(satisfies frameset-register-p))
+(cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
+(cl-deftype kmacro-register () '(satisfies kmacro-register-p))
+(cl-defmethod register--type :extra "kmacro-register" (_regval) 'kmacro)
+
+(defun register-of-type-alist (types)
+  "Filter `register-alist' according to TYPES."
+  (if (memq 'all types)
+      register-alist
+    (cl-loop for register in register-alist
+             when (memq (register-type register) types)
+             collect register)))
+
+(defun register-preview (buffer &optional show-empty types)
   "Pop up a window showing the registers preview in BUFFER.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
+Argument TYPES (a list) specify the types of register to show, when nil show all
+registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
-  (when (or show-empty (consp register-alist))
-    (with-current-buffer-window
-     buffer
-     (cons 'display-buffer-below-selected
-	   '((window-height . fit-window-to-buffer)
-	     (preserve-size . (nil . t))))
-     nil
-     (with-current-buffer standard-output
-       (setq cursor-in-non-selected-windows nil)
-       (mapc (lambda (elem)
-               (when (get-register (car elem))
-                 (insert (funcall register-preview-function elem))))
-             register-alist)))))
+  (let ((registers (register-of-type-alist (or types '(all)))))
+    (when (or show-empty (consp registers))
+      (with-current-buffer-window
+        buffer
+        (cons 'display-buffer-below-selected
+	      '((window-height . fit-window-to-buffer)
+	        (preserve-size . (nil . t))))
+        nil
+        (with-current-buffer standard-output
+          (setq cursor-in-non-selected-windows nil)
+          (mapc (lambda (elem)
+                  (when (get-register (car elem))
+                    (insert (funcall register-preview-function elem))))
+                registers))))))
+
+(cl-defgeneric register-preview-get-defaults (action)
+  "Returns default registers according to ACTION."
+  (ignore action))
+(cl-defmethod register-preview-get-defaults ((_action (eql set)))
+  (cl-loop for s in register-preview-default-keys
+           unless (assoc (string-to-char s) register-alist)
+           collect s))
 
 (defun register-read-with-preview (prompt)
   "Read and return a register name, possibly showing existing registers.
-Prompt with the string PROMPT.  If `register-alist' and
-`register-preview-delay' are both non-nil, display a window
-listing existing registers after `register-preview-delay' seconds.
+Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
-	 (timer (when (numberp register-preview-delay)
-		  (run-with-timer register-preview-delay nil
-				  (lambda ()
-				    (unless (get-buffer-window buffer)
-				      (register-preview buffer))))))
-	 (help-chars (cl-loop for c in (cons help-char help-event-list)
-			      when (not (get-register c))
-			      collect c)))
+         (pat "")
+         (map (let ((m (make-sparse-keymap)))
+                (set-keymap-parent m minibuffer-local-map)
+                m))
+         (data (register-command-info this-command))
+         types msg result timer act win strs smatch)
+    (if data
+        (setq types  (register-preview-info-types data)
+              msg    (register-preview-info-msg   data)
+              act    (register-preview-info-act   data)
+              smatch (register-preview-info-smatch data))
+      (setq types '(all)
+            msg   "Overwrite register `%s'"
+            act   'set))
+    (setq strs (mapcar (lambda (x)
+                         (string (car x)))
+                       (register-of-type-alist types)))
+    (when (and (memq act '(insert jump view)) (null strs))
+      (error "No register suitable for `%s'" act))
+    (dolist (k (cons help-char help-event-list))
+      (define-key map
+          (vector k) (lambda ()
+                       (interactive)
+                       (unless (get-buffer-window buffer)
+                         (with-selected-window (minibuffer-selected-window)
+                           (register-preview buffer 'show-empty types))))))
+    (define-key map (kbd "<down>") 'register-preview-next)
+    (define-key map (kbd "<up>")   'register-preview-previous)
+    (define-key map (kbd "C-n")    'register-preview-next)
+    (define-key map (kbd "C-p")    'register-preview-previous)
+    (unless (or executing-kbd-macro (null register-use-preview))
+      (register-preview buffer nil types))
     (unwind-protect
-	(progn
-	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
-		       help-chars)
-	    (unless (get-buffer-window buffer)
-	      (register-preview buffer 'show-empty)))
-          (when (or (eq ?\C-g last-input-event)
-                    (eq 'escape last-input-event)
-                    (eq ?\C-\[ last-input-event))
-            (keyboard-quit))
-	  (if (characterp last-input-event) last-input-event
-	    (error "Non-character input-event")))
-      (and (timerp timer) (cancel-timer timer))
+         (progn
+           (minibuffer-with-setup-hook
+               (lambda ()
+                 (setq timer
+                       (run-with-idle-timer
+                        0.01 'repeat
+                        (lambda ()
+                          (with-selected-window (minibuffer-window)
+                            (let ((input (minibuffer-contents)))
+                              (when (> (length input) 1)
+                                (let ((new (substring input 1))
+                                      (old (substring input 0 1)))
+                                  (setq input (if (or (null smatch)
+                                                      (member new strs))
+                                                  new old))
+                                  (delete-minibuffer-contents)
+                                  (insert input)))
+                              (when (and smatch (not (string= input ""))
+                                         (not (member input strs)))
+                                (setq input "")
+                                (delete-minibuffer-contents)
+                                (minibuffer-message "Not matching"))
+                              (when (not (string= input pat))
+                                (setq pat input))))
+                          (if (setq win (get-buffer-window buffer))
+                              (with-selected-window win
+                                (let ((ov (make-overlay (point-min) (point-min))))
+                                  (goto-char (point-min))
+                                  (remove-overlays)
+                                  (unless (string= pat "")
+                                    (if (re-search-forward (concat "^" pat) nil t)
+                                        (progn (move-overlay
+                                                ov
+                                                (match-beginning 0) (pos-eol))
+                                               (overlay-put ov 'face 'match)
+                                               (when msg
+                                                 (with-selected-window (minibuffer-window)
+                                                   (minibuffer-message msg pat))))
+                                      (with-selected-window (minibuffer-window)
+                                        (minibuffer-message
+                                         "Register `%s' is empty" pat))))))
+                            (unless (string= pat "")
+                              (if (member pat strs)
+                                  (with-selected-window (minibuffer-window)
+                                    (minibuffer-message msg pat))
+                                (with-selected-window (minibuffer-window)
+                                  (minibuffer-message
+                                   "Register `%s' is empty" pat)))))))))
+             (setq result (read-from-minibuffer
+                           prompt nil map nil nil (register-preview-get-defaults act))))
+           (cl-assert (and result (not (string= result "")))
+                      nil "No register specified")
+           (string-to-char result))
+      (when timer (cancel-timer timer))
       (let ((w (get-buffer-window buffer)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buffer) (kill-buffer buffer)))))
-- 
2.34.1


[-- Attachment #1.3: Type: text/plain, Size: 16 bytes --]


-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-20  6:00                               ` Thierry Volpiatto
@ 2023-11-20 17:33                                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-11-20 18:51                                   ` Thierry Volpiatto
  2023-12-02  9:24                                 ` Bastien
  1 sibling, 1 reply; 121+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-20 17:33 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: Michael Heerdegen, stefankangas, 66394

> Ccing also Stefan monnier because for some reasons the patch when
> applied doesn't compile (when compiling Emacs) unless we add on
> top:
>
>     (cl--generic-prefill-dispatchers 0 (eql 'x) integer)
>
> following the advice of the compiler,

Indeed, this is needed because `register.el` is preloaded and method
dispatcher are generated&compiled "on the fly" but we don't want to
preload the compiler, so we want to pre-compile the dispatchers used
by the preloaded code.

> but I am not sure it is the way to do.

`cl--generic-prefill-dispatchers` is not guaranteed to be defined when
we load `register.el` (it's only defined if we loaded the non-compiled
version of `cl-generic.el`) so the above call should be in
`cl-generic.el` rather than in `register.el`.

I'd put it next to the following block:

    (cl--generic-prefill-dispatchers 0 (eql nil))
    (cl--generic-prefill-dispatchers window-system (eql nil))
    (cl--generic-prefill-dispatchers (terminal-parameter nil 'xterm--get-selection)
                                     (eql nil))
    (cl--generic-prefill-dispatchers (terminal-parameter nil 'xterm--set-selection)
                                     (eql nil))

which is already about dispatchers needed to support other files.


        Stefan






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-20 17:33                                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-11-20 18:51                                   ` Thierry Volpiatto
  2023-11-25 10:23                                     ` Eli Zaretskii
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-11-20 18:51 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Michael Heerdegen, stefankangas, 66394

[-- Attachment #1: Type: text/plain, Size: 1607 bytes --]


Hello Stefan,

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> Ccing also Stefan monnier because for some reasons the patch when
>> applied doesn't compile (when compiling Emacs) unless we add on
>> top:
>>
>>     (cl--generic-prefill-dispatchers 0 (eql 'x) integer)
>>
>> following the advice of the compiler,
>
> Indeed, this is needed because `register.el` is preloaded and method
> dispatcher are generated&compiled "on the fly" but we don't want to
> preload the compiler, so we want to pre-compile the dispatchers used
> by the preloaded code.
>
>> but I am not sure it is the way to do.
>
> `cl--generic-prefill-dispatchers` is not guaranteed to be defined when
> we load `register.el` (it's only defined if we loaded the non-compiled
> version of `cl-generic.el`) so the above call should be in
> `cl-generic.el` rather than in `register.el`.
>
> I'd put it next to the following block:
>
>     (cl--generic-prefill-dispatchers 0 (eql nil))
>     (cl--generic-prefill-dispatchers window-system (eql nil))
>     (cl--generic-prefill-dispatchers (terminal-parameter nil 'xterm--get-selection)
>                                      (eql nil))
>     (cl--generic-prefill-dispatchers (terminal-parameter nil 'xterm--set-selection)
>                                      (eql nil))
>
> which is already about dispatchers needed to support other files.

I will for now leave the call to `cl--generic-prefill-dispatchers` in
the patch as a reminder that it should be added instead in cl-defgeneric
once merging.

Thanks for your explanation.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-20 18:51                                   ` Thierry Volpiatto
@ 2023-11-25 10:23                                     ` Eli Zaretskii
  2023-11-25 19:59                                       ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Eli Zaretskii @ 2023-11-25 10:23 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, 66394, monnier, stefankangas

> Cc: Michael Heerdegen <michael_heerdegen@web.de>, stefankangas@gmail.com,
>  66394@debbugs.gnu.org
> From: Thierry Volpiatto <thievol@posteo.net>
> Date: Mon, 20 Nov 2023 18:51:10 +0000
> 
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
> 
> >> Ccing also Stefan monnier because for some reasons the patch when
> >> applied doesn't compile (when compiling Emacs) unless we add on
> >> top:
> >>
> >>     (cl--generic-prefill-dispatchers 0 (eql 'x) integer)
> >>
> >> following the advice of the compiler,
> >
> > Indeed, this is needed because `register.el` is preloaded and method
> > dispatcher are generated&compiled "on the fly" but we don't want to
> > preload the compiler, so we want to pre-compile the dispatchers used
> > by the preloaded code.
> >
> >> but I am not sure it is the way to do.
> >
> > `cl--generic-prefill-dispatchers` is not guaranteed to be defined when
> > we load `register.el` (it's only defined if we loaded the non-compiled
> > version of `cl-generic.el`) so the above call should be in
> > `cl-generic.el` rather than in `register.el`.
> >
> > I'd put it next to the following block:
> >
> >     (cl--generic-prefill-dispatchers 0 (eql nil))
> >     (cl--generic-prefill-dispatchers window-system (eql nil))
> >     (cl--generic-prefill-dispatchers (terminal-parameter nil 'xterm--get-selection)
> >                                      (eql nil))
> >     (cl--generic-prefill-dispatchers (terminal-parameter nil 'xterm--set-selection)
> >                                      (eql nil))
> >
> > which is already about dispatchers needed to support other files.
> 
> I will for now leave the call to `cl--generic-prefill-dispatchers` in
> the patch as a reminder that it should be added instead in cl-defgeneric
> once merging.

I tried to install the patch, but it fails to compile:

    ELC      ../lisp/register.elc

  In toplevel form:
  register.el:33:37: Warning: `eql' called with 1 argument, but requires 2
  register.el:33:45: Warning: reference to free variable `integer'

This then fails the build, since 'register' is preloaded.

Thierry, can you please fix the code, so that I could install it?  Or
what am I missing?

P.S. Also, the log message is not according to our conventions.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-25 10:23                                     ` Eli Zaretskii
@ 2023-11-25 19:59                                       ` Thierry Volpiatto
  2023-11-25 20:10                                         ` Eli Zaretskii
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-11-25 19:59 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas

[-- Attachment #1: Type: text/plain, Size: 2821 bytes --]


Hello Eli,

Eli Zaretskii <eliz@gnu.org> writes:

>> Cc: Michael Heerdegen <michael_heerdegen@web.de>, stefankangas@gmail.com,
>>  66394@debbugs.gnu.org
>> From: Thierry Volpiatto <thievol@posteo.net>
>> Date: Mon, 20 Nov 2023 18:51:10 +0000
>> 
>> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>> 
>> >> Ccing also Stefan monnier because for some reasons the patch when
>> >> applied doesn't compile (when compiling Emacs) unless we add on
>> >> top:
>> >>
>> >>     (cl--generic-prefill-dispatchers 0 (eql 'x) integer)
>> >>
>> >> following the advice of the compiler,
>> >
>> > Indeed, this is needed because `register.el` is preloaded and method
>> > dispatcher are generated&compiled "on the fly" but we don't want to
>> > preload the compiler, so we want to pre-compile the dispatchers used
>> > by the preloaded code.
>> >
>> >> but I am not sure it is the way to do.
>> >
>> > `cl--generic-prefill-dispatchers` is not guaranteed to be defined when
>> > we load `register.el` (it's only defined if we loaded the non-compiled
>> > version of `cl-generic.el`) so the above call should be in
>> > `cl-generic.el` rather than in `register.el`.
>> >
>> > I'd put it next to the following block:
>> >
>> >     (cl--generic-prefill-dispatchers 0 (eql nil))
>> >     (cl--generic-prefill-dispatchers window-system (eql nil))
>> >     (cl--generic-prefill-dispatchers (terminal-parameter nil 'xterm--get-selection)
>> >                                      (eql nil))
>> >     (cl--generic-prefill-dispatchers (terminal-parameter nil 'xterm--set-selection)
>> >                                      (eql nil))
>> >
>> > which is already about dispatchers needed to support other files.
>> 
>> I will for now leave the call to `cl--generic-prefill-dispatchers` in
>> the patch as a reminder that it should be added instead in cl-defgeneric
>> once merging.
>
> I tried to install the patch, but it fails to compile:
>
>     ELC      ../lisp/register.elc
>
>   In toplevel form:
>   register.el:33:37: Warning: `eql' called with 1 argument, but requires 2
>   register.el:33:45: Warning: reference to free variable `integer'

I have not these warnings.

> This then fails the build, since 'register' is preloaded.

Here it is building fine, this from the last Emacs master from tonight.

> Thierry, can you please fix the code, so that I could install it?  Or
> what am I missing?

Don't know, did you "make clean" first?

NOTE: I leaved the patch like this but it needs the change suggested by
Stefan before merging (or with an extra commit) see above.

> P.S. Also, the log message is not according to our conventions.

I don't remember now what are your conventions for commits, perhaps you
can correct it if needed?

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-25 19:59                                       ` Thierry Volpiatto
@ 2023-11-25 20:10                                         ` Eli Zaretskii
  2023-11-25 21:14                                           ` Thierry Volpiatto
  2023-11-25 21:38                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 2 replies; 121+ messages in thread
From: Eli Zaretskii @ 2023-11-25 20:10 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, 66394, monnier, stefankangas

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>   stefankangas@gmail.com,  66394@debbugs.gnu.org
> Date: Sat, 25 Nov 2023 19:59:26 +0000
> 
> >     ELC      ../lisp/register.elc
> >
> >   In toplevel form:
> >   register.el:33:37: Warning: `eql' called with 1 argument, but requires 2
> >   register.el:33:45: Warning: reference to free variable `integer'
> 
> I have not these warnings.

Strange.  Maybe Stefan can explain how could that happen.

> > This then fails the build, since 'register' is preloaded.
> 
> Here it is building fine, this from the last Emacs master from tonight.

I'm also applying to master, obviously.

> > Thierry, can you please fix the code, so that I could install it?  Or
> > what am I missing?
> 
> Don't know, did you "make clean" first?

How would "make clean" help?  I did remove register.elc, it didn't
help.

> NOTE: I leaved the patch like this but it needs the change suggested by
> Stefan before merging (or with an extra commit) see above.

OK, so I guess I shouldn't have tried to install it.

> > P.S. Also, the log message is not according to our conventions.
> 
> I don't remember now what are your conventions for commits, perhaps you
> can correct it if needed?

Of course, I can correct it.  I just thought that if you are going to
submit a fixed patch, perhaps you could fix the log message as well,
to spare me some manual work.  Never mind now, since I'm not going to
install it yet.

Thanks.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-25 20:10                                         ` Eli Zaretskii
@ 2023-11-25 21:14                                           ` Thierry Volpiatto
  2023-11-26 10:38                                             ` Eli Zaretskii
  2023-11-29 14:04                                             ` Eli Zaretskii
  2023-11-25 21:38                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 2 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-11-25 21:14 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas


[-- Attachment #1.1: Type: text/plain, Size: 496 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

> How would "make clean" help?  I did remove register.elc, it didn't
> help.

Not only register is involved here but indirectly cl-generic.

> OK, so I guess I shouldn't have tried to install it.

Here a patch with the change suggested by Stefan applied, slighly
modified though because it fails if I put the call to
cl--generic-prefill-dispatchers at the recommended place.

I recompiled Emacs with this patch with no errors.
 
-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Improve-register-preview-Fix-bug-66394.patch --]
[-- Type: text/x-diff, Size: 17350 bytes --]

From ccecd34b8307c7168e89289f933e63590ce6fc9c Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Sun, 19 Nov 2023 20:42:56 +0100
Subject: [PATCH] Improve register-preview (Fix bug#66394)

A minibuffer is used now instead of read-key.
Registers in preview buffer are now filtered according to type of
registers the current command requires.
Navigation with C-n/p or up/down is now provided and update
minibuffer.
Current register is highlighted in preview buffer.

* cl-generic.el: Add a call to `cl--generic-prefill-dispatchers` to
  fix build error.

* register.el:

* (register-preview-default-keys): new user var.
* (register-use-preview): Same.
* (register-preview-info): New structure to store various info for
  preview.
* (register-command-info): New generic.
* (register-preview-forward-line): New, provide navigation in preview
  buffer.
* (register-preview-next, register-preview-previous): New, navigation.
* (register-type): New, returns register type.
* (register--type): Generic fn, new, returns register type according
  to value.
* (register-of-type-alist): New, filter register-alist according to
  type.
* (register-preview): Signature changed, use TYPES now.
* (register-preview-get-defaults): New generic, compute defauts
  according to action.
* (register-read-with-preview): Now use read-from-minibuffer and
  minibuffer-setup-hook.
---
 lisp/emacs-lisp/cl-generic.el |   1 +
 lisp/register.el              | 295 +++++++++++++++++++++++++++++-----
 2 files changed, 259 insertions(+), 37 deletions(-)

diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 56eb83e6f75..0ef0d1e192a 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -1379,6 +1379,7 @@ See the full list and their hierarchy in `cl--typeof-types'."
 (cl--generic-prefill-dispatchers 0 integer)
 (cl--generic-prefill-dispatchers 1 integer)
 (cl--generic-prefill-dispatchers 0 cl--generic-generalizer integer)
+(cl--generic-prefill-dispatchers 0 (eql 'x) integer)
 
 ;;; Dispatch on major mode.
 
diff --git a/lisp/register.el b/lisp/register.el
index ca6de450993..61bef503f91 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -35,6 +35,8 @@
 
 ;; FIXME: Clean up namespace usage!
 
+(declare-function frameset-register-p "frameset")
+
 (cl-defstruct
   (registerv (:constructor nil)
 	     (:constructor registerv--make (&optional data print-func
@@ -91,6 +93,7 @@ of the marked text."
   :type '(choice (const :tag "None" nil)
 		 (character :tag "Use register" :value ?+)))
 
+;; FIXME: This is no more needed, remove it.
 (defcustom register-preview-delay 1
   "If non-nil, time to wait in seconds before popping up register preview window.
 If nil, do not show register previews, unless `help-char' (or a member of
@@ -99,6 +102,14 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
 
+(defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
+  "Default keys for setting a new register."
+  :type '(repeat string))
+
+(defcustom register-use-preview t
+  "Always show register preview when non nil."
+  :type 'boolean)
+
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
   (alist-get register register-alist))
@@ -128,53 +139,263 @@ See the documentation of the variable `register-alist' for possible VALUEs."
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
 The function should return a string, the description of the argument.")
 
-(defun register-preview (buffer &optional show-empty)
+(cl-defstruct register-preview-info
+  "Store data for a specific register command.
+TYPES are the types of register supported.
+MSG is the minibuffer message to send when a register is selected.
+ACT is the type of action the command is doing on register.
+SMATCH accept a boolean value to say if command accept non matching register."
+  types msg act smatch)
+
+(cl-defgeneric register-command-info (command)
+  "Returns a `register-preview-info' object storing data for COMMAND."
+  (ignore command))
+(cl-defmethod register-command-info ((_command (eql insert-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Insert register `%s'"
+   :act 'insert
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql jump-to-register)))
+  (make-register-preview-info
+   :types  '(window frame marker kmacro
+             file buffer file-query)
+   :msg "Jump to register `%s'"
+   :act 'jump
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql view-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "View register `%s'"
+   :act 'view
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql append-to-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Append to register `%s'"
+   :act 'modify
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql prepend-to-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Prepend to register `%s'"
+   :act 'modify
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql increment-register)))
+  (make-register-preview-info
+   :types '(string number)
+   :msg "Increment register `%s'"
+   :act 'modify
+   :smatch t))
+
+(defun register-preview-forward-line (arg)
+  "Move to next or previous line in register preview buffer.
+If ARG is positive goto next line, if negative to previous.
+Do nothing when defining or executing kmacros."
+  ;; Ensure user enter manually key in minibuffer when recording a macro.
+  (unless (or defining-kbd-macro executing-kbd-macro
+              (not (get-buffer-window "*Register Preview*" 'visible)))
+    (let ((fn (if (> arg 0) #'eobp #'bobp))
+          (posfn (if (> arg 0)
+                     #'point-min
+                     (lambda () (1- (point-max)))))
+          str)
+      (with-current-buffer "*Register Preview*"
+        (let ((ovs (overlays-in (point-min) (point-max)))
+              pos)
+          (goto-char (if ovs
+                         (overlay-start (car ovs))
+                         (point-min)))
+          (setq pos (point))
+          (and ovs (forward-line arg))
+          (when (and (funcall fn)
+                     (or (> arg 0) (eql pos (point))))
+            (goto-char (funcall posfn)))
+          (setq str (buffer-substring-no-properties
+                     (pos-bol) (1+ (pos-bol))))
+          (remove-overlays)
+          (with-selected-window (minibuffer-window)
+            (delete-minibuffer-contents)
+            (insert str)))))))
+
+(defun register-preview-next ()
+  "Goto next line in register preview buffer."
+  (interactive)
+  (register-preview-forward-line 1))
+
+(defun register-preview-previous ()
+  "Goto previous line in register preview buffer."
+  (interactive)
+  (register-preview-forward-line -1))
+
+(defun register-type (register)
+  "Return REGISTER type.
+Current register types actually returned are one of:
+- string
+- number
+- marker
+- buffer
+- file
+- file-query
+- window
+- frame
+- kmacro
+
+One can add new types to a specific command by defining a new `cl-defmethod'
+matching this command. Predicate for type in new `cl-defmethod' should
+satisfy `cl-typep' otherwise the new type should be defined with
+`cl-deftype'."
+  ;; Call register--type against the register value.
+  (register--type (if (consp (cdr register))
+                     (cadr register)
+                   (cdr register))))
+
+(cl-defgeneric register--type (regval)
+  "Returns type of register value REGVAL."
+  (ignore regval))
+
+(cl-defmethod register--type ((_regval string)) 'string)
+(cl-defmethod register--type ((_regval number)) 'number)
+(cl-defmethod register--type ((_regval marker)) 'marker)
+(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer)
+(cl-defmethod register--type ((_regval (eql 'file))) 'file)
+(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query)
+(cl-defmethod register--type ((_regval window-configuration)) 'window)
+(cl-deftype frame-register () '(satisfies frameset-register-p))
+(cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
+(cl-deftype kmacro-register () '(satisfies kmacro-register-p))
+(cl-defmethod register--type :extra "kmacro-register" (_regval) 'kmacro)
+
+(defun register-of-type-alist (types)
+  "Filter `register-alist' according to TYPES."
+  (if (memq 'all types)
+      register-alist
+    (cl-loop for register in register-alist
+             when (memq (register-type register) types)
+             collect register)))
+
+(defun register-preview (buffer &optional show-empty types)
   "Pop up a window showing the registers preview in BUFFER.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
+Argument TYPES (a list) specify the types of register to show, when nil show all
+registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
-  (when (or show-empty (consp register-alist))
-    (with-current-buffer-window
-     buffer
-     (cons 'display-buffer-below-selected
-	   '((window-height . fit-window-to-buffer)
-	     (preserve-size . (nil . t))))
-     nil
-     (with-current-buffer standard-output
-       (setq cursor-in-non-selected-windows nil)
-       (mapc (lambda (elem)
-               (when (get-register (car elem))
-                 (insert (funcall register-preview-function elem))))
-             register-alist)))))
+  (let ((registers (register-of-type-alist (or types '(all)))))
+    (when (or show-empty (consp registers))
+      (with-current-buffer-window
+        buffer
+        (cons 'display-buffer-below-selected
+	      '((window-height . fit-window-to-buffer)
+	        (preserve-size . (nil . t))))
+        nil
+        (with-current-buffer standard-output
+          (setq cursor-in-non-selected-windows nil)
+          (mapc (lambda (elem)
+                  (when (get-register (car elem))
+                    (insert (funcall register-preview-function elem))))
+                registers))))))
+
+(cl-defgeneric register-preview-get-defaults (action)
+  "Returns default registers according to ACTION."
+  (ignore action))
+(cl-defmethod register-preview-get-defaults ((_action (eql set)))
+  (cl-loop for s in register-preview-default-keys
+           unless (assoc (string-to-char s) register-alist)
+           collect s))
 
 (defun register-read-with-preview (prompt)
   "Read and return a register name, possibly showing existing registers.
-Prompt with the string PROMPT.  If `register-alist' and
-`register-preview-delay' are both non-nil, display a window
-listing existing registers after `register-preview-delay' seconds.
+Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
-	 (timer (when (numberp register-preview-delay)
-		  (run-with-timer register-preview-delay nil
-				  (lambda ()
-				    (unless (get-buffer-window buffer)
-				      (register-preview buffer))))))
-	 (help-chars (cl-loop for c in (cons help-char help-event-list)
-			      when (not (get-register c))
-			      collect c)))
+         (pat "")
+         (map (let ((m (make-sparse-keymap)))
+                (set-keymap-parent m minibuffer-local-map)
+                m))
+         (data (register-command-info this-command))
+         types msg result timer act win strs smatch)
+    (if data
+        (setq types  (register-preview-info-types data)
+              msg    (register-preview-info-msg   data)
+              act    (register-preview-info-act   data)
+              smatch (register-preview-info-smatch data))
+      (setq types '(all)
+            msg   "Overwrite register `%s'"
+            act   'set))
+    (setq strs (mapcar (lambda (x)
+                         (string (car x)))
+                       (register-of-type-alist types)))
+    (when (and (memq act '(insert jump view)) (null strs))
+      (error "No register suitable for `%s'" act))
+    (dolist (k (cons help-char help-event-list))
+      (define-key map
+          (vector k) (lambda ()
+                       (interactive)
+                       (unless (get-buffer-window buffer)
+                         (with-selected-window (minibuffer-selected-window)
+                           (register-preview buffer 'show-empty types))))))
+    (define-key map (kbd "<down>") 'register-preview-next)
+    (define-key map (kbd "<up>")   'register-preview-previous)
+    (define-key map (kbd "C-n")    'register-preview-next)
+    (define-key map (kbd "C-p")    'register-preview-previous)
+    (unless (or executing-kbd-macro (null register-use-preview))
+      (register-preview buffer nil types))
     (unwind-protect
-	(progn
-	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
-		       help-chars)
-	    (unless (get-buffer-window buffer)
-	      (register-preview buffer 'show-empty)))
-          (when (or (eq ?\C-g last-input-event)
-                    (eq 'escape last-input-event)
-                    (eq ?\C-\[ last-input-event))
-            (keyboard-quit))
-	  (if (characterp last-input-event) last-input-event
-	    (error "Non-character input-event")))
-      (and (timerp timer) (cancel-timer timer))
+         (progn
+           (minibuffer-with-setup-hook
+               (lambda ()
+                 (setq timer
+                       (run-with-idle-timer
+                        0.01 'repeat
+                        (lambda ()
+                          (with-selected-window (minibuffer-window)
+                            (let ((input (minibuffer-contents)))
+                              (when (> (length input) 1)
+                                (let ((new (substring input 1))
+                                      (old (substring input 0 1)))
+                                  (setq input (if (or (null smatch)
+                                                      (member new strs))
+                                                  new old))
+                                  (delete-minibuffer-contents)
+                                  (insert input)))
+                              (when (and smatch (not (string= input ""))
+                                         (not (member input strs)))
+                                (setq input "")
+                                (delete-minibuffer-contents)
+                                (minibuffer-message "Not matching"))
+                              (when (not (string= input pat))
+                                (setq pat input))))
+                          (if (setq win (get-buffer-window buffer))
+                              (with-selected-window win
+                                (let ((ov (make-overlay (point-min) (point-min))))
+                                  (goto-char (point-min))
+                                  (remove-overlays)
+                                  (unless (string= pat "")
+                                    (if (re-search-forward (concat "^" pat) nil t)
+                                        (progn (move-overlay
+                                                ov
+                                                (match-beginning 0) (pos-eol))
+                                               (overlay-put ov 'face 'match)
+                                               (when msg
+                                                 (with-selected-window (minibuffer-window)
+                                                   (minibuffer-message msg pat))))
+                                      (with-selected-window (minibuffer-window)
+                                        (minibuffer-message
+                                         "Register `%s' is empty" pat))))))
+                            (unless (string= pat "")
+                              (if (member pat strs)
+                                  (with-selected-window (minibuffer-window)
+                                    (minibuffer-message msg pat))
+                                (with-selected-window (minibuffer-window)
+                                  (minibuffer-message
+                                   "Register `%s' is empty" pat)))))))))
+             (setq result (read-from-minibuffer
+                           prompt nil map nil nil (register-preview-get-defaults act))))
+           (cl-assert (and result (not (string= result "")))
+                      nil "No register specified")
+           (string-to-char result))
+      (when timer (cancel-timer timer))
       (let ((w (get-buffer-window buffer)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buffer) (kill-buffer buffer)))))
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-25 20:10                                         ` Eli Zaretskii
  2023-11-25 21:14                                           ` Thierry Volpiatto
@ 2023-11-25 21:38                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 0 replies; 121+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-11-25 21:38 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Thierry Volpiatto, michael_heerdegen, stefankangas, 66394

>> >   In toplevel form:
>> >   register.el:33:37: Warning: `eql' called with 1 argument, but requires 2
>> >   register.el:33:45: Warning: reference to free variable `integer'
>> I have not these warnings.
> Strange.  Maybe Stefan can explain how could that happen.

It's because of:

    (cl--generic-prefill-dispatchers 0 (eql 'x) integer)

This needs to be in `cl-generic.el` because that's where the
`cl--generic-prefill-dispatchers` macro is defined.  Thierry had it in
`register.el` which worked OK when `register.el` gets compiled with the
bootstrap Emacs where `cl-generic` has not yet been compiled but it
fails when compiled with an Emacs where `cl-generic` has been compiled
because in that case the macro is not defined so the compiler compiles
the above line as a function call, resulting in the above two warnings.


        Stefan






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-25 21:14                                           ` Thierry Volpiatto
@ 2023-11-26 10:38                                             ` Eli Zaretskii
  2023-11-26 16:46                                               ` Thierry Volpiatto
  2023-11-29 14:04                                             ` Eli Zaretskii
  1 sibling, 1 reply; 121+ messages in thread
From: Eli Zaretskii @ 2023-11-26 10:38 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, 66394, monnier, stefankangas

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>   stefankangas@gmail.com,  66394@debbugs.gnu.org
> Date: Sat, 25 Nov 2023 21:14:31 +0000
> 
> Here a patch with the change suggested by Stefan applied, slighly
> modified though because it fails if I put the call to
> cl--generic-prefill-dispatchers at the recommended place.
> 
> I recompiled Emacs with this patch with no errors.

Thanks.

Stefan, any further comments, or should I install this as submitted?





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-26 10:38                                             ` Eli Zaretskii
@ 2023-11-26 16:46                                               ` Thierry Volpiatto
  0 siblings, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-11-26 16:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas

[-- Attachment #1: Type: text/plain, Size: 2047 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Thierry Volpiatto <thievol@posteo.net>
>> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>>   stefankangas@gmail.com,  66394@debbugs.gnu.org
>> Date: Sat, 25 Nov 2023 21:14:31 +0000
>> 
>> Here a patch with the change suggested by Stefan applied, slighly
>> modified though because it fails if I put the call to
>> cl--generic-prefill-dispatchers at the recommended place.
>> 
>> I recompiled Emacs with this patch with no errors.
>
> Thanks.
>
> Stefan, any further comments, or should I install this as submitted?

Do you want the ability to jump to more than one line at the time before
merging, (e.g. C-u 3 C-n and C-u 3 C-p) or is it ok like this for you?

diff --git a/lisp/register.el b/lisp/register.el
index 61bef503f91..bca967a4efe 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -207,7 +207,7 @@ Do nothing when defining or executing kmacros."
                          (overlay-start (car ovs))
                          (point-min)))
           (setq pos (point))
-          (and ovs (forward-line arg))
+          (forward-line (if ovs arg (1- arg)))
           (when (and (funcall fn)
                      (or (> arg 0) (eql pos (point))))
             (goto-char (funcall posfn)))
@@ -218,15 +218,15 @@ Do nothing when defining or executing kmacros."
             (delete-minibuffer-contents)
             (insert str)))))))
 
-(defun register-preview-next ()
+(defun register-preview-next (&optional arg)
   "Goto next line in register preview buffer."
-  (interactive)
-  (register-preview-forward-line 1))
+  (interactive "p")
+  (register-preview-forward-line arg))
 
-(defun register-preview-previous ()
+(defun register-preview-previous (&optional arg)
   "Goto previous line in register preview buffer."
-  (interactive)
-  (register-preview-forward-line -1))
+  (interactive "p")
+  (register-preview-forward-line (- arg)))
 
 (defun register-type (register)
   "Return REGISTER type.
 
-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-25 21:14                                           ` Thierry Volpiatto
  2023-11-26 10:38                                             ` Eli Zaretskii
@ 2023-11-29 14:04                                             ` Eli Zaretskii
  2023-11-29 18:18                                               ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Eli Zaretskii @ 2023-11-29 14:04 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, 66394, monnier, stefankangas

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>   stefankangas@gmail.com,  66394@debbugs.gnu.org
> Date: Sat, 25 Nov 2023 21:14:31 +0000
> 
> Here a patch with the change suggested by Stefan applied, slighly
> modified though because it fails if I put the call to
> cl--generic-prefill-dispatchers at the recommended place.
> 
> I recompiled Emacs with this patch with no errors.

Thanks, installed on master.

After this, a test in register-tests.el fails:

  Running 1 tests (2023-11-29 09:01:59-0500, selector ‘(not (or (tag :unstable) (tag :nativecomp)))’)
  Point to register: a
  Test register-test-bug27634 backtrace:
    signal(ert-test-failed (((should (equal 'quit (condition-case err (c
    ert-fail(((should (equal 'quit (condition-case err (call-interactive
    (if (unwind-protect (setq value-2 (apply fn-0 args-1)) (setq form-de
    (let (form-description-4) (if (unwind-protect (setq value-2 (apply f
    (let ((value-2 'ert-form-evaluation-aborted-3)) (let (form-descripti
    (let* ((fn-0 #'equal) (args-1 (condition-case err (let ((signal-hook
    (progn (fset 'read-key #'ignore) (let* ((fn-0 #'equal) (args-1 (cond
    (unwind-protect (progn (fset 'read-key #'ignore) (let* ((fn-0 #'equa
    (let* ((vnew event) (old (symbol-function 'read-key)) (register-alis
    (let ((event (car tail))) (let* ((vnew event) (old (symbol-function
    (while tail (let ((event (car tail))) (let* ((vnew event) (old (symb
    (let ((tail (list 7 'escape 27))) (while tail (let ((event (car tail
    (closure (t) nil (let ((tail (list 7 'escape 27))) (while tail (let
    ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
    ert-run-test(#s(ert-test :name register-test-bug27634 :documentation
    ert-run-or-rerun-test(#s(ert--stats :selector ... :tests ... :test-m
    ert-run-tests((not (or (tag :unstable) (tag :nativecomp))) #f(compil
    ert-run-tests-batch((not (or (tag :unstable) (tag :nativecomp))))
    ert-run-tests-batch-and-exit((not (or (tag :unstable) (tag :nativeco
    eval((ert-run-tests-batch-and-exit '(not (or (tag :unstable) (tag :n
    command-line-1(("-L" ":." "-l" "ert" "-l" "lisp/register-tests.el" "
    command-line()
    normal-top-level()
  Test register-test-bug27634 condition:
      (ert-test-failed
       ((should (equal 'quit (condition-case err ... ...))) :form
	(equal quit #<marker in no buffer>) :value nil :explanation
	(different-types quit #<marker in no buffer>)))
     FAILED  1/1  register-test-bug27634 (1.758961 sec) at lisp/register-tests.el:30

The response "a" to the "Point to register:" question is something I
needed to type; previously the test never asked any questions (and it
shouldn't, AFAIU).

Could you please see if the test suite needs some adaptations to these
changes?





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-29 14:04                                             ` Eli Zaretskii
@ 2023-11-29 18:18                                               ` Thierry Volpiatto
  2023-11-30  6:00                                                 ` Eli Zaretskii
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-11-29 18:18 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas

[-- Attachment #1: Type: text/plain, Size: 1386 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Thierry Volpiatto <thievol@posteo.net>
>> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>>   stefankangas@gmail.com,  66394@debbugs.gnu.org
>> Date: Sat, 25 Nov 2023 21:14:31 +0000
>> 
>> Here a patch with the change suggested by Stefan applied, slighly
>> modified though because it fails if I put the call to
>> cl--generic-prefill-dispatchers at the recommended place.
>> 
>> I recompiled Emacs with this patch with no errors.
>
> Thanks, installed on master.

Thanks.

> The response "a" to the "Point to register:" question is something I
> needed to type;

Of course we are using now read-from-minibuffer and the test is related
to read-key not quitting with C-g

> previously the test never asked any questions (and it shouldn't,
> AFAIU).

Yes, it shouldn't, but now we are using a real minibuffer, is this test
really needed?
It is like if you had to make tests in all functions using
read-from-minibuffer to check if it quit properly with C-g (it does of course).

> Could you please see if the test suite needs some adaptations to these
> changes?

If you really need this test, it needs a complete rewrite.

ALSO: I intentionally leave register-preview-delay defcustom with a FIXME
comment, do you want to remove it? It is not used anymore now AFAIK.

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-29 18:18                                               ` Thierry Volpiatto
@ 2023-11-30  6:00                                                 ` Eli Zaretskii
  2023-11-30 10:21                                                   ` Thierry Volpiatto
  2023-12-02  5:51                                                   ` Thierry Volpiatto
  0 siblings, 2 replies; 121+ messages in thread
From: Eli Zaretskii @ 2023-11-30  6:00 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, 66394, monnier, stefankangas

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>   stefankangas@gmail.com,  66394@debbugs.gnu.org
> Date: Wed, 29 Nov 2023 18:18:40 +0000
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > The response "a" to the "Point to register:" question is something I
> > needed to type;
> 
> Of course we are using now read-from-minibuffer and the test is related
> to read-key not quitting with C-g
> 
> > previously the test never asked any questions (and it shouldn't,
> > AFAIU).
> 
> Yes, it shouldn't, but now we are using a real minibuffer, is this test
> really needed?
> It is like if you had to make tests in all functions using
> read-from-minibuffer to check if it quit properly with C-g (it does of course).

Can we have a similar issue with read-from-minibuffer?  Not with C-g,
but with some other invalid input, like some function key or non-ASCII
character or invalid character codepoint?  If this cannot happen, then
perhaps the whole test file should be removed?

Anyway, I trust you to do what is needed here, I just want the test
suite to keep running successfully, and I don't have time to work on
this myself.  TIA.

> ALSO: I intentionally leave register-preview-delay defcustom with a FIXME
> comment, do you want to remove it? It is not used anymore now AFAIK.

This should be declared obsolete, with an explanation that it is no
longer used, and a note about that should be added to NEWS, in the
incompatible changes section.  Then we can remove the FIXME.

Thanks.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-30  6:00                                                 ` Eli Zaretskii
@ 2023-11-30 10:21                                                   ` Thierry Volpiatto
  2023-12-02  5:51                                                   ` Thierry Volpiatto
  1 sibling, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-11-30 10:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas


[-- Attachment #1.1: Type: text/plain, Size: 2322 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Thierry Volpiatto <thievol@posteo.net>
>> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>>   stefankangas@gmail.com,  66394@debbugs.gnu.org
>> Date: Wed, 29 Nov 2023 18:18:40 +0000
>> 
>> Eli Zaretskii <eliz@gnu.org> writes:
>> 
>> > The response "a" to the "Point to register:" question is something I
>> > needed to type;
>> 
>> Of course we are using now read-from-minibuffer and the test is related
>> to read-key not quitting with C-g
>> 
>> > previously the test never asked any questions (and it shouldn't,
>> > AFAIU).
>> 
>> Yes, it shouldn't, but now we are using a real minibuffer, is this test
>> really needed?
>> It is like if you had to make tests in all functions using
>> read-from-minibuffer to check if it quit properly with C-g (it does of course).
>
> Can we have a similar issue with read-from-minibuffer?  Not with C-g,
> but with some other invalid input, like some function key or non-ASCII
> character or invalid character codepoint?

No, because unlike read-key, read-from-minibuffer doesn't read these
keys and exit immediately.  For example we can now set a register to C-g
by using "C-q C-g" but hitting directly C-g will quit minibuffer (as
expected), BTW I have updated the manual, see the attached patchs.  I
have also fixed register-preview-default accordingly so that it print
the register as a string but not a key representation e.g. "^X" instead
of "C-x" (if one find this ugly we could use "C-x" as a display property
of "^X").

> If this cannot happen, then perhaps the whole test file should be
> removed?

I think it can be removed, yes (done in patch below).

> Anyway, I trust you to do what is needed here, I just want the test
> suite to keep running successfully, and I don't have time to work on
> this myself.  TIA.

Ok, can you review (and merge if ok) following patchs.

>> ALSO: I intentionally leave register-preview-delay defcustom with a FIXME
>> comment, do you want to remove it? It is not used anymore now AFAIK.
>
> This should be declared obsolete, with an explanation that it is no
> longer used, and a note about that should be added to NEWS, in the
> incompatible changes section.  Then we can remove the FIXME.

done.

Thanks.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Make-register-preview-delay-obsolete.patch --]
[-- Type: text/x-diff, Size: 1914 bytes --]

From 3df81fb5dc5809cab7843e5358c17d0039b55eb1 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 30 Nov 2023 08:03:45 +0100
Subject: [PATCH 1/4] Make register-preview-delay obsolete

* etc/NEWS: Update.
* lisp/register.el (register-preview-delay): Make it obsolete.
---
 etc/NEWS         | 5 +++++
 lisp/register.el | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/etc/NEWS b/etc/NEWS
index 6661ac70e1b..bab3529339f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1138,6 +1138,11 @@ showcases all their customization options.
 \f
 * Incompatible Lisp Changes in Emacs 30.1
 
+---
+** 'register-preview-delay' is no longer used.
+Register preview is no more delayed.  If you want to disable it use
+'register-use-preview' instead with a boolean value.
+
 +++
 ** 'M-TAB' now invokes 'completion-at-point' also in Text mode.
 Text mode no longer binds 'M-TAB' to 'ispell-complete-word', and
diff --git a/lisp/register.el b/lisp/register.el
index 61bef503f91..88d0e8e1d10 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -93,7 +93,6 @@ of the marked text."
   :type '(choice (const :tag "None" nil)
 		 (character :tag "Use register" :value ?+)))
 
-;; FIXME: This is no more needed, remove it.
 (defcustom register-preview-delay 1
   "If non-nil, time to wait in seconds before popping up register preview window.
 If nil, do not show register previews, unless `help-char' (or a member of
@@ -101,6 +100,7 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
+(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Fix-register-preview-default.patch --]
[-- Type: text/x-diff, Size: 1054 bytes --]

From bcf7bd8feb05914e6000b572c3e75664a9090c1a Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 30 Nov 2023 10:38:52 +0100
Subject: [PATCH 2/4] Fix register-preview-default

We need to print the string representation (one char) of an eventual
key description e.g. "^X" instead of "C-x".

* lisp/register.el (register-preview-default): Use `string' to print register.
---
 lisp/register.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lisp/register.el b/lisp/register.el
index 88d0e8e1d10..9b457e716f2 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -131,7 +131,7 @@ See the documentation of the variable `register-alist' for possible VALUEs."
 (defun register-preview-default (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
-	  (single-key-description (car r))
+	  (string (car r))
 	  (register-describe-oneline (car r))))
 
 (defvar register-preview-function #'register-preview-default
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.4: 0003-Update-register-manual.patch --]
[-- Type: text/x-diff, Size: 1169 bytes --]

From 93c07593bac8d7f0428a92502ee5de8def128c5c Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 30 Nov 2023 10:53:46 +0100
Subject: [PATCH 3/4] Update register manual

doc/emacs/regs.texi: Do it.
---
 doc/emacs/regs.texi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/doc/emacs/regs.texi b/doc/emacs/regs.texi
index e52f68dd18e..5e5b7ae2b16 100644
--- a/doc/emacs/regs.texi
+++ b/doc/emacs/regs.texi
@@ -16,9 +16,8 @@ jump back to that position once or many times.
 we will denote by @var{r}; @var{r} can be a letter (such as @samp{a})
 or a number (such as @samp{1}); case matters, so register @samp{a} is
 not the same as register @samp{A}.  You can also set a register in
-non-alphanumeric characters, for instance @samp{*} or @samp{C-d}.
-Note, it's not possible to set a register in @samp{C-g} or @samp{ESC},
-because these keys are reserved for quitting (@pxref{Quitting}).
+non-alphanumeric characters, for instance @samp{C-d} by using for
+example @key{C-q} @samp{C-d}.
 
 @findex view-register
   A register can store a position, a piece of text, a rectangle, a
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.5: 0004-Delete-register-tests.el-now-no-more-needed.patch --]
[-- Type: text/x-diff, Size: 2187 bytes --]

From d60e3b4969a420fe9ba66b5732f57243385e5e88 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 30 Nov 2023 11:04:47 +0100
Subject: [PATCH 4/4] Delete register-tests.el now no more needed

* register-tests.el: Deleted file.
---
 test/lisp/register-tests.el | 43 -------------------------------------
 1 file changed, 43 deletions(-)
 delete mode 100644 test/lisp/register-tests.el

diff --git a/test/lisp/register-tests.el b/test/lisp/register-tests.el
deleted file mode 100644
index 6283d1c31e0..00000000000
--- a/test/lisp/register-tests.el
+++ /dev/null
@@ -1,43 +0,0 @@
-;;; register-tests.el --- tests for register.el  -*- lexical-binding: t-*-
-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
-
-;; Author: Tino Calancha <tino.calancha@gmail.com>
-;; Keywords:
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-\f
-;;; Code:
-(require 'ert)
-(require 'cl-lib)
-
-(ert-deftest register-test-bug27634 ()
-  "Test for https://debbugs.gnu.org/27634 ."
-  (dolist (event (list ?\C-g 'escape ?\C-\[))
-    (cl-letf (((symbol-function 'read-key) #'ignore)
-              (last-input-event event)
-              (register-alist nil))
-      (should (equal 'quit
-                     (condition-case err
-                         (call-interactively 'point-to-register)
-                       (quit (car err)))))
-      (should-not register-alist))))
-
-(provide 'register-tests)
-;;; register-tests.el ends here
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-30  6:00                                                 ` Eli Zaretskii
  2023-11-30 10:21                                                   ` Thierry Volpiatto
@ 2023-12-02  5:51                                                   ` Thierry Volpiatto
  2023-12-02  7:50                                                     ` Eli Zaretskii
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-02  5:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas


[-- Attachment #1.1: Type: text/plain, Size: 327 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

> Anyway, I trust you to do what is needed here, I just want the test
> suite to keep running successfully, and I don't have time to work on
> this myself.  TIA.

Here again the patchs (0002 with a little modification).
Let me know if I can commit them.

Thanks.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Make-register-preview-delay-obsolete.patch --]
[-- Type: text/x-diff, Size: 1914 bytes --]

From 3df81fb5dc5809cab7843e5358c17d0039b55eb1 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 30 Nov 2023 08:03:45 +0100
Subject: [PATCH 1/4] Make register-preview-delay obsolete

* etc/NEWS: Update.
* lisp/register.el (register-preview-delay): Make it obsolete.
---
 etc/NEWS         | 5 +++++
 lisp/register.el | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/etc/NEWS b/etc/NEWS
index 6661ac70e1b..bab3529339f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1138,6 +1138,11 @@ showcases all their customization options.
 \f
 * Incompatible Lisp Changes in Emacs 30.1
 
+---
+** 'register-preview-delay' is no longer used.
+Register preview is no more delayed.  If you want to disable it use
+'register-use-preview' instead with a boolean value.
+
 +++
 ** 'M-TAB' now invokes 'completion-at-point' also in Text mode.
 Text mode no longer binds 'M-TAB' to 'ispell-complete-word', and
diff --git a/lisp/register.el b/lisp/register.el
index 61bef503f91..88d0e8e1d10 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -93,7 +93,6 @@ of the marked text."
   :type '(choice (const :tag "None" nil)
 		 (character :tag "Use register" :value ?+)))
 
-;; FIXME: This is no more needed, remove it.
 (defcustom register-preview-delay 1
   "If non-nil, time to wait in seconds before popping up register preview window.
 If nil, do not show register previews, unless `help-char' (or a member of
@@ -101,6 +100,7 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
+(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Fix-register-preview-default.patch --]
[-- Type: text/x-diff, Size: 1206 bytes --]

From 0fa70dad21d3475d3a5dae54a09d8a9e60b668ae Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 30 Nov 2023 10:38:52 +0100
Subject: [PATCH 2/4] Fix register-preview-default

We need to print the string representation (one char) of an eventual
key description e.g. "^X" instead of "C-x".
However the key description is still displayed in a display property.

* lisp/register.el (register-preview-default): Use `string' to print register.
---
 lisp/register.el | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lisp/register.el b/lisp/register.el
index 88d0e8e1d10..46ec38821e5 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -131,7 +131,8 @@ See the documentation of the variable `register-alist' for possible VALUEs."
 (defun register-preview-default (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
-	  (single-key-description (car r))
+	  (propertize (string (car r))
+                      'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
 (defvar register-preview-function #'register-preview-default
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.4: 0003-Update-register-manual.patch --]
[-- Type: text/x-diff, Size: 1169 bytes --]

From 408126b6d56a0cc36f621348212e16d0715fd671 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 30 Nov 2023 10:53:46 +0100
Subject: [PATCH 3/4] Update register manual

doc/emacs/regs.texi: Do it.
---
 doc/emacs/regs.texi | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/doc/emacs/regs.texi b/doc/emacs/regs.texi
index e52f68dd18e..5e5b7ae2b16 100644
--- a/doc/emacs/regs.texi
+++ b/doc/emacs/regs.texi
@@ -16,9 +16,8 @@ jump back to that position once or many times.
 we will denote by @var{r}; @var{r} can be a letter (such as @samp{a})
 or a number (such as @samp{1}); case matters, so register @samp{a} is
 not the same as register @samp{A}.  You can also set a register in
-non-alphanumeric characters, for instance @samp{*} or @samp{C-d}.
-Note, it's not possible to set a register in @samp{C-g} or @samp{ESC},
-because these keys are reserved for quitting (@pxref{Quitting}).
+non-alphanumeric characters, for instance @samp{C-d} by using for
+example @key{C-q} @samp{C-d}.
 
 @findex view-register
   A register can store a position, a piece of text, a rectangle, a
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.5: 0004-Delete-register-tests.el-now-no-more-needed.patch --]
[-- Type: text/x-diff, Size: 2187 bytes --]

From cd6e66f955d20d31686a617ed8a5cd043585c71f Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 30 Nov 2023 11:04:47 +0100
Subject: [PATCH 4/4] Delete register-tests.el now no more needed

* register-tests.el: Deleted file.
---
 test/lisp/register-tests.el | 43 -------------------------------------
 1 file changed, 43 deletions(-)
 delete mode 100644 test/lisp/register-tests.el

diff --git a/test/lisp/register-tests.el b/test/lisp/register-tests.el
deleted file mode 100644
index 6283d1c31e0..00000000000
--- a/test/lisp/register-tests.el
+++ /dev/null
@@ -1,43 +0,0 @@
-;;; register-tests.el --- tests for register.el  -*- lexical-binding: t-*-
-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
-
-;; Author: Tino Calancha <tino.calancha@gmail.com>
-;; Keywords:
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-\f
-;;; Code:
-(require 'ert)
-(require 'cl-lib)
-
-(ert-deftest register-test-bug27634 ()
-  "Test for https://debbugs.gnu.org/27634 ."
-  (dolist (event (list ?\C-g 'escape ?\C-\[))
-    (cl-letf (((symbol-function 'read-key) #'ignore)
-              (last-input-event event)
-              (register-alist nil))
-      (should (equal 'quit
-                     (condition-case err
-                         (call-interactively 'point-to-register)
-                       (quit (car err)))))
-      (should-not register-alist))))
-
-(provide 'register-tests)
-;;; register-tests.el ends here
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02  5:51                                                   ` Thierry Volpiatto
@ 2023-12-02  7:50                                                     ` Eli Zaretskii
  2023-12-02  8:08                                                       ` Thierry Volpiatto
                                                                         ` (2 more replies)
  0 siblings, 3 replies; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-02  7:50 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, 66394, monnier, stefankangas

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>   stefankangas@gmail.com,  66394@debbugs.gnu.org
> Date: Sat, 02 Dec 2023 05:51:45 +0000
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > Anyway, I trust you to do what is needed here, I just want the test
> > suite to keep running successfully, and I don't have time to work on
> > this myself.  TIA.
> 
> Here again the patchs (0002 with a little modification).
> Let me know if I can commit them.

Please install on the master branch, and thanks.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02  7:50                                                     ` Eli Zaretskii
@ 2023-12-02  8:08                                                       ` Thierry Volpiatto
  2023-12-03 14:35                                                       ` Thierry Volpiatto
  2023-12-11  9:30                                                       ` Thierry Volpiatto
  2 siblings, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-02  8:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas

[-- Attachment #1: Type: text/plain, Size: 662 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Thierry Volpiatto <thievol@posteo.net>
>> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>>   stefankangas@gmail.com,  66394@debbugs.gnu.org
>> Date: Sat, 02 Dec 2023 05:51:45 +0000
>> 
>> Eli Zaretskii <eliz@gnu.org> writes:
>> 
>> > Anyway, I trust you to do what is needed here, I just want the test
>> > suite to keep running successfully, and I don't have time to work on
>> > this myself.  TIA.
>> 
>> Here again the patchs (0002 with a little modification).
>> Let me know if I can commit them.
>
> Please install on the master branch, and thanks.

Done, thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-11-20  6:00                               ` Thierry Volpiatto
  2023-11-20 17:33                                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-02  9:24                                 ` Bastien
  2023-12-02  9:52                                   ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Bastien @ 2023-12-02  9:24 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: Michael Heerdegen, 66394, stefankangas, monnier

I use registers ~100 times a day, so enhancements here are very
welcome, thanks!

Thierry Volpiatto <thievol@posteo.net> writes:

> A minibuffer is used now instead of read-key.

I wonder about this, though. It badly hinders my usual flow, where I
do remember what registers I use and like to store new ones quickly.

When a register is empty, I believe it's more efficient to just read
the key and store the content in the register directly.

E.g. if the "a" contains "A string" and "b" is an empty register:

- C-x r s would display the preview and copy the region to the "b"
  register as soon as the "b" key is hit (using read-key).

- C-x r s would display the preview and if the user hits "a", it will
  warn about overwriting the existing register and RET can confirm.

This supposes using read-key by default and switch to using a
minibuffer when the user hits keys for existing registers.

What do you think?

-- 
 Bastien





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02  9:24                                 ` Bastien
@ 2023-12-02  9:52                                   ` Thierry Volpiatto
  2023-12-02 10:37                                     ` Bastien Guerry
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-02  9:52 UTC (permalink / raw)
  To: Bastien; +Cc: Michael Heerdegen, 66394, stefankangas, monnier

[-- Attachment #1: Type: text/plain, Size: 1742 bytes --]

Bastien <bzg@gnu.org> writes:

> I use registers ~100 times a day, so enhancements here are very
> welcome, thanks!
>
> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> A minibuffer is used now instead of read-key.
>
> I wonder about this, though. It badly hinders my usual flow, where I
> do remember what registers I use and like to store new ones quickly.
>
> When a register is empty, I believe it's more efficient to just read
> the key and store the content in the register directly.
>
> E.g. if the "a" contains "A string" and "b" is an empty register:
>
> - C-x r s would display the preview and copy the region to the "b"
>   register as soon as the "b" key is hit (using read-key).

I suggest you use M-n RET instead if you want to be sure you don't
overwrite a register.
Also don't forget you can now use C-n/p or <up>/<down> to navigate in preview.

> - C-x r s would display the preview and if the user hits "a", it will
>   warn about overwriting the existing register and RET can confirm.

It is what it is doing actually with minibuffer.  Hitting "a" highlight
register "a" and send a message "overwriting register", then you can hit
RET if you want to overwrite.

> This supposes using read-key by default and switch to using a
> minibuffer when the user hits keys for existing registers.
>
> What do you think?

I think using read-key+minibuffer would be very complicated and would
need much more code, this for a small benefit: Saving one key (RET).
Also I think hitting RET in any case is better as it does a kind of
"confirm I want to do this".
Also using read-key leads to bug like we had previously as we must mimic
a keymap which is often wrong.

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02  9:52                                   ` Thierry Volpiatto
@ 2023-12-02 10:37                                     ` Bastien Guerry
  2023-12-02 10:54                                       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-02 11:55                                       ` Thierry Volpiatto
  0 siblings, 2 replies; 121+ messages in thread
From: Bastien Guerry @ 2023-12-02 10:37 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: Michael Heerdegen, jonas, 66394, stefankangas, monnier

Hi Thierry,

thanks for your anwer.

Thierry Volpiatto <thievol@posteo.net> writes:

>> - C-x r s would display the preview and copy the region to the "b"
>>   register as soon as the "b" key is hit (using read-key).
>
> I suggest you use M-n RET instead if you want to be sure you don't
> overwrite a register.

What I am suggesting is to store the register _as soon as_ the user
hits the "b" key.

Since the recent changes, I need to hit one additional keystroke for
zero benefit, which is a net less when you use registers a lot.

I use "a", "b", "c" registers for quick copy and paste and can easily
remember them; when I need more, I use register-list.el.

> It is what it is doing actually with minibuffer.  Hitting "a" highlight
> register "a" and send a message "overwriting register", then you can hit
> RET if you want to overwrite.

This might be useful in some cases. I don't suggest to change this. I
suggest to allow the previous behavior for empty registers.

> I think using read-key+minibuffer would be very complicated and would
> need much more code, this for a small benefit: Saving one key (RET).

I would say this is not a small benefit.

> Also I think hitting RET in any case is better as it does a kind of
> "confirm I want to do this".

IMHO confirmation is good for cases where mistakes can have bad
consequences.  I don't see them when using an empty register.

> Also using read-key leads to bug like we had previously as we must mimic
> a keymap which is often wrong.

I know there are always trade-offs. I just wanted to report the slight
"eww" moment I had wrt this UX change, which I still think is wrong.

If we set this issue aside, I wonder if read-key could be augmented so
that certain keystrokes let the user enter in "editing mode" (a bit
like when users hit C-s then C-e to edit the search string.) I can see
several situations where a read-key prompt would benefit from allowing
to switch to a minibuffer prompt with all the flexibility it provides:

- Allowing for confirmation when overwriting a register is one;

- Allowing to hit two keystrokes to facilitate navigation for C-h:
  e.g. `C-h k l' would list keybindings; `C-h k d` would describe a
  keybinding, etc.

This touches explorations that perhaps Jonas made while designing
transient, so I'm adding him to this conversation.
  
-- 
 Bastien Guerry





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02 10:37                                     ` Bastien Guerry
@ 2023-12-02 10:54                                       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-02 11:55                                       ` Thierry Volpiatto
  1 sibling, 0 replies; 121+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-02 10:54 UTC (permalink / raw)
  To: Bastien Guerry
  Cc: jonas, Michael Heerdegen, stefankangas, Thierry Volpiatto, 66394,
	monnier

Bastien Guerry <bzg@gnu.org> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>>> - C-x r s would display the preview and copy the region to the "b"
>>>   register as soon as the "b" key is hit (using read-key).
>>
>> I suggest you use M-n RET instead if you want to be sure you don't
>> overwrite a register.
>
> What I am suggesting is to store the register _as soon as_ the user
> hits the "b" key.
>
> Since the recent changes, I need to hit one additional keystroke for
> zero benefit, which is a net less when you use registers a lot.
>
> I use "a", "b", "c" registers for quick copy and paste and can easily
> remember them; when I need more, I use register-list.el.
>
>> It is what it is doing actually with minibuffer.  Hitting "a" highlight
>> register "a" and send a message "overwriting register", then you can hit
>> RET if you want to overwrite.
>
> This might be useful in some cases. I don't suggest to change this. I
> suggest to allow the previous behavior for empty registers.
>
>> I think using read-key+minibuffer would be very complicated and would
>> need much more code, this for a small benefit: Saving one key (RET).
>
> I would say this is not a small benefit.

FWIW, I second Bastien's request to restore the existing behavior as the
default, or at least provide it as an option.  I think Michael requested
that as well in the beginning of this thread.

This patch brings some nice benefits, but it also presents a regression
in terms of UX, perhaps we could avoid that or make it opt-in?  It would
also be great if there were a NEWS entry that clearly describes the user
visible changes.


Thanks,

Eshel





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02 10:37                                     ` Bastien Guerry
  2023-12-02 10:54                                       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-02 11:55                                       ` Thierry Volpiatto
  2023-12-02 12:43                                         ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-02 11:55 UTC (permalink / raw)
  To: Bastien Guerry; +Cc: Michael Heerdegen, jonas, 66394, stefankangas, monnier

[-- Attachment #1: Type: text/plain, Size: 1908 bytes --]


Hi Bastien and Eshel,

Bastien Guerry <bzg@gnu.org> writes:

> Hi Thierry,
>
> thanks for your anwer.
>
> Thierry Volpiatto <thievol@posteo.net> writes:
>
>>> - C-x r s would display the preview and copy the region to the "b"
>>>   register as soon as the "b" key is hit (using read-key).
>>
>> I suggest you use M-n RET instead if you want to be sure you don't
>> overwrite a register.
>
> What I am suggesting is to store the register _as soon as_ the user
> hits the "b" key.
>
> Since the recent changes, I need to hit one additional keystroke for
> zero benefit, which is a net less when you use registers a lot.
>
> I use "a", "b", "c" registers for quick copy and paste and can easily
> remember them; when I need more, I use register-list.el.

I see, you want to go fast.
Using read-key+minibuffer, as I said would be a pain to implement,
hopefully (IIUC) we can use only minibuffer and exit immediately and it
is simple to implement (3 lines):

1) Set register-use-preview to nil.
2) Apply this patch on register.el:

@@ -388,6 +388,3 @@
-                              (if (member pat strs)
-                                  (with-selected-window (minibuffer-window)
-                                    (minibuffer-message msg pat))
-                                (with-selected-window (minibuffer-window)
-                                  (minibuffer-message
-                                   "Register `%s' is empty" pat)))))))))
+                              (with-selected-window (minibuffer-window)
+                                (setq result pat)
+                                (exit-minibuffer))))))))

3) Try your "a", "b", "c" registers and also to set a new register, if
needed you can call C-h to have a preview, in this case you will have to
hit RET.

Let me know if this is acceptable for you.

Thanks.


-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02 11:55                                       ` Thierry Volpiatto
@ 2023-12-02 12:43                                         ` Thierry Volpiatto
  2023-12-02 13:02                                           ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-02 13:50                                           ` Bastien Guerry
  0 siblings, 2 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-02 12:43 UTC (permalink / raw)
  To: Bastien Guerry; +Cc: Michael Heerdegen, jonas, 66394, stefankangas, monnier

[-- Attachment #1: Type: text/plain, Size: 3308 bytes --]

Thierry Volpiatto <thievol@posteo.net> writes:

> Hi Bastien and Eshel,
>
> Bastien Guerry <bzg@gnu.org> writes:
>
>> Hi Thierry,
>>
>> thanks for your anwer.
>>
>> Thierry Volpiatto <thievol@posteo.net> writes:
>>
>>>> - C-x r s would display the preview and copy the region to the "b"
>>>>   register as soon as the "b" key is hit (using read-key).
>>>
>>> I suggest you use M-n RET instead if you want to be sure you don't
>>> overwrite a register.
>>
>> What I am suggesting is to store the register _as soon as_ the user
>> hits the "b" key.
>>
>> Since the recent changes, I need to hit one additional keystroke for
>> zero benefit, which is a net less when you use registers a lot.
>>
>> I use "a", "b", "c" registers for quick copy and paste and can easily
>> remember them; when I need more, I use register-list.el.
>
> I see, you want to go fast.
> Using read-key+minibuffer, as I said would be a pain to implement,
> hopefully (IIUC) we can use only minibuffer and exit immediately and it
> is simple to implement (3 lines):
>
> 1) Set register-use-preview to nil.
> 2) Apply this patch on register.el:
>
> @@ -388,6 +388,3 @@
> -                              (if (member pat strs)
> -                                  (with-selected-window (minibuffer-window)
> -                                    (minibuffer-message msg pat))
> -                                (with-selected-window (minibuffer-window)
> -                                  (minibuffer-message
> -                                   "Register `%s' is empty" pat)))))))))
> +                              (with-selected-window (minibuffer-window)
> +                                (setq result pat)
> +                                (exit-minibuffer))))))))
>
> 3) Try your "a", "b", "c" registers and also to set a new register, if
> needed you can call C-h to have a preview, in this case you will have to
> hit RET.
>
> Let me know if this is acceptable for you.
>
> Thanks.

Even better is this patch which ask for confirmation when overwriting a
register but not when jumping, inserting or setting a new register:

@@ -388,6 +388,10 @@
-                              (if (member pat strs)
-                                  (with-selected-window (minibuffer-window)
-                                    (minibuffer-message msg pat))
-                                (with-selected-window (minibuffer-window)
-                                  (minibuffer-message
-                                   "Register `%s' is empty" pat)))))))))
+                              (with-selected-window (minibuffer-window)
+                                (if (and (member pat strs) (memq act '(set modify)))
+                                    (with-selected-window (minibuffer-window)
+                                      (minibuffer-message msg pat))
+                                  ;; An empty register or an existing
+                                  ;; one but the action is insert or
+                                  ;; jump, don't ask for confirmation
+                                  ;; and exit immediately.
+                                  (setq result pat)
+                                  (exit-minibuffer)))))))))


-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02 12:43                                         ` Thierry Volpiatto
@ 2023-12-02 13:02                                           ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-02 13:50                                           ` Bastien Guerry
  1 sibling, 0 replies; 121+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-02 13:02 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: jonas, Michael Heerdegen, Bastien Guerry, stefankangas, 66394,
	monnier

Thierry Volpiatto <thievol@posteo.net> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> Hi Bastien and Eshel,
>>
>> I see, you want to go fast.

Thanks, but this not only about speed.
Using a minibuffer to read a key has other disadvantages: it limits
the range of keys that can be easily used as registers since now
specifying the `C-a` register is much harder (as Michael mentioned).
This also makes register commands less convenient or and even
impossible (when `enable-recursive-minibuffers` is nil) to use inside
an existing minibuffer.

>> Using read-key+minibuffer, as I said would be a pain to implement,
>> hopefully (IIUC) we can use only minibuffer and exit immediately and it
>> is simple to implement (3 lines):
>>
>> 1) Set register-use-preview to nil.

Hmm, but this disables the automatic register preview, which I still want
to see, preferably after a short delay, just like before.

>> 2) Apply this patch on register.el:
>> ...
>>
>> Let me know if this is acceptable for you.
>
> Even better is this patch which ask for confirmation when overwriting a
> register but not when jumping, inserting or setting a new register:
>
> ...

That's improves things a bit, but see above.  I can see how confirmation
could be helpful for some people, but not everyone would appreciate the
added friction.  I basically suggest reverting to the previous behavior
(or otherwise restoring full compatibility), and making any involvement
of the minibuffer in reading registers optional, for example by
providing a new user option `register-read-from-minibuffer`.


Best,

Eshel





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02 12:43                                         ` Thierry Volpiatto
  2023-12-02 13:02                                           ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-02 13:50                                           ` Bastien Guerry
  2023-12-02 15:01                                             ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Bastien Guerry @ 2023-12-02 13:50 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: Michael Heerdegen, jonas, 66394, stefankangas, monnier

Thierry Volpiatto <thievol@posteo.net> writes:

> Even better is this patch which ask for confirmation when overwriting a
> register but not when jumping, inserting or setting a new register:

Yes, this goes in the right direction, thanks!

The patch works fine when `register-use-preview' is nil. (I wonder if
the prompt "Register `%s' is empty" is not still displayed, though: I
believe I've seen it flash.)

When `register-use-preview' is t (the default), it skips confirmation
only when setting the _first_ empty register: when setting another
empty register, confirmation reappears.  Can you reproduce this bug?

-- 
 Bastien Guerry





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02 13:50                                           ` Bastien Guerry
@ 2023-12-02 15:01                                             ` Thierry Volpiatto
  0 siblings, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-02 15:01 UTC (permalink / raw)
  To: Bastien Guerry; +Cc: Michael Heerdegen, jonas, 66394, stefankangas, monnier

[-- Attachment #1: Type: text/plain, Size: 753 bytes --]

Bastien Guerry <bzg@gnu.org> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> Even better is this patch which ask for confirmation when overwriting a
>> register but not when jumping, inserting or setting a new register:
>
> Yes, this goes in the right direction, thanks!
>
> The patch works fine when `register-use-preview' is nil. (I wonder if
> the prompt "Register `%s' is empty" is not still displayed, though: I
> believe I've seen it flash.)
>
> When `register-use-preview' is t (the default), it skips confirmation
> only when setting the _first_ empty register: when setting another
> empty register, confirmation reappears.  Can you reproduce this bug?

No, can you give me a recipe.

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02  7:50                                                     ` Eli Zaretskii
  2023-12-02  8:08                                                       ` Thierry Volpiatto
@ 2023-12-03 14:35                                                       ` Thierry Volpiatto
  2023-12-03 15:05                                                         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-11  9:30                                                       ` Thierry Volpiatto
  2 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-03 14:35 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas


[-- Attachment #1.1: Type: text/plain, Size: 788 bytes --]


Hello Eli,

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Thierry Volpiatto <thievol@posteo.net>
>> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>>   stefankangas@gmail.com,  66394@debbugs.gnu.org
>> Date: Sat, 02 Dec 2023 05:51:45 +0000
>> 
>> Eli Zaretskii <eliz@gnu.org> writes:
>> 
>> > Anyway, I trust you to do what is needed here, I just want the test
>> > suite to keep running successfully, and I don't have time to work on
>> > this myself.  TIA.
>> 
>> Here again the patchs (0002 with a little modification).
>> Let me know if I can commit them.
>
> Please install on the master branch, and thanks.

Here another change related to the discussion in previous posts.
If no objections I will merge it in next days.

Thanks.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Exit-with-no-confirmation-RET-when-register-use-prev.patch --]
[-- Type: text/x-diff, Size: 2247 bytes --]

From ff8f43a39e2cee1f71629194d44c7459f2b90d79 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Sun, 3 Dec 2023 15:21:50 +0100
Subject: [PATCH] Exit with no confirmation (RET) when register-use-preview

is non nil and .

This is done by exiting minibuffer when selected register is empty or
when just jumping or inserting.

* lisp/register.el (register-read-with-preview): Do it.
---
 lisp/register.el | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index 46ec38821e5..a38b531dfc9 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -385,12 +385,16 @@ display such a window regardless."
                                         (minibuffer-message
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
-                              (if (member pat strs)
-                                  (with-selected-window (minibuffer-window)
-                                    (minibuffer-message msg pat))
-                                (with-selected-window (minibuffer-window)
-                                  (minibuffer-message
-                                   "Register `%s' is empty" pat)))))))))
+                              (with-selected-window (minibuffer-window)
+                                (if (and (member pat strs) (memq act '(set modify)))
+                                    (with-selected-window (minibuffer-window)
+                                      (minibuffer-message msg pat))
+                                  ;; An empty register or an existing
+                                  ;; one but the action is insert or
+                                  ;; jump, don't ask for confirmation
+                                  ;; and exit immediately (bug#66394).
+                                  (setq result pat)
+                                  (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
                            prompt nil map nil nil (register-preview-get-defaults act))))
            (cl-assert (and result (not (string= result "")))
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-03 14:35                                                       ` Thierry Volpiatto
@ 2023-12-03 15:05                                                         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-03 16:48                                                           ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-03 15:05 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394

Hi Thierry,

Thierry Volpiatto <thievol@posteo.net> writes:

> Here another change related to the discussion in previous posts.
> If no objections I will merge it in next days.

This seems to disregard my comments entirely, I'm sure that's not
intentional, but I'd appreciate it if you could consider them.

To reiterate, I wrote:

> Using a minibuffer to read a key has other disadvantages [beyond the
> extra friction of confirming with RET]: it limits the range of keys
> that can be easily used as registers since now specifying the `C-a`
> register is much harder (as Michael mentioned).  This also makes
> register commands less convenient and even impossible (when
> `enable-recursive-minibuffers` is nil) to use inside an existing
> minibuffer.

So it'd be great to have the previous behavior available in Emacs 30.


Thanks,

Eshel





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-03 15:05                                                         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-03 16:48                                                           ` Thierry Volpiatto
  2023-12-03 18:29                                                             ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-03 16:48 UTC (permalink / raw)
  To: Eshel Yaron
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394

[-- Attachment #1: Type: text/plain, Size: 1220 bytes --]

Eshel Yaron <me@eshelyaron.com> writes:

> Hi Thierry,
>
> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> Here another change related to the discussion in previous posts.
>> If no objections I will merge it in next days.
>
> This seems to disregard my comments entirely,

It doesn't.

> I'm sure that's not intentional, but I'd appreciate it if you could
> consider them.

This finish to fix the version of register-preview I wrote (the one you
don't like) regarding what bastien asked for.

> So it'd be great to have the previous behavior available in Emacs 30.

Sorry but I wont write this, it is not complicated to write but needs
works and attention and I spent enough time on this.

The only thing you mentionned I agree with is the necessity now to use C-q
to insert key sequence (note that C-n/p will insert it alone), but it is
not a big annoyance right? (most people don't use this, I don't for
one).  For the preview buffer not visible, note that you can pop to it
at any moment with C-h.  Perhaps you will get used to the new behavior
after some time, otherwise it is easy to revert completely my commits
(it is the development branch of emacs after all).

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-03 16:48                                                           ` Thierry Volpiatto
@ 2023-12-03 18:29                                                             ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-03 18:39                                                               ` Eli Zaretskii
  0 siblings, 1 reply; 121+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-03 18:29 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, Eli Zaretskii, 66394, stefankangas, monnier

Thierry Volpiatto <thievol@posteo.net> writes:

> Eshel Yaron <me@eshelyaron.com> writes:
>
>> So it'd be great to have the previous behavior available in Emacs 30.
>
> Sorry but I wont write this, it is not complicated to write but needs
> works and attention and I spent enough time on this.
>
> The only thing you mentionned I agree with is the necessity now to use C-q
> to insert key sequence (note that C-n/p will insert it alone), but it is
> not a big annoyance right? (most people don't use this, I don't for
> one).  For the preview buffer not visible, note that you can pop to it
> at any moment with C-h.

What about the fact that `C-x r s` and friends by default no longer work
in the minibuffer?

> Perhaps you will get used to the new behavior after some time,

Why can't I, and other users, have the previous behavior, though?  It's
great to innovate with new alternatives, but why should we break user
workflows in the process, without as much as a NEWS entry to warn them?

> otherwise it is easy to revert completely my commits (it is the
> development branch of emacs after all).

Seeing as you are not willing to make this change backward compatible, I
think that would make sense.  I don't have commit rights to emacs.git,
so I can't do that myself, though.

I do think it shouldn't be that hard to extend the previous
implementation to _optionally_ ask for confirmation before overwriting
register contents, without using the minibuffer.  That way we'd have the
new behavior that you want to introduce without the added breakage.
Would you be willing to test such a patch if I write it?


Thanks,

Eshel





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-03 18:29                                                             ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-03 18:39                                                               ` Eli Zaretskii
  2023-12-03 21:23                                                                 ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-11  6:55                                                                 ` Thierry Volpiatto
  0 siblings, 2 replies; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-03 18:39 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: thievol, michael_heerdegen, 66394, stefankangas, monnier

> From: Eshel Yaron <me@eshelyaron.com>
> Cc: michael_heerdegen@web.de,  Eli Zaretskii <eliz@gnu.org>,
>   stefankangas@gmail.com,  monnier@iro.umontreal.ca,  66394@debbugs.gnu.org
> Date: Sun, 03 Dec 2023 19:29:19 +0100
> 
> > otherwise it is easy to revert completely my commits (it is the
> > development branch of emacs after all).
> 
> Seeing as you are not willing to make this change backward compatible, I
> think that would make sense.  I don't have commit rights to emacs.git,
> so I can't do that myself, though.

Thierry also said:

> > So it'd be great to have the previous behavior available in Emacs 30.
> 
> Sorry but I wont write this, it is not complicated to write but needs
> works and attention and I spent enough time on this.

So maybe a better way forward is for someone, perhaps you Eshel, to
add whatever is needed to provide optionally the previous behavior?

Would you like to work on that?





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-03 18:39                                                               ` Eli Zaretskii
@ 2023-12-03 21:23                                                                 ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-04  7:30                                                                   ` Thierry Volpiatto
  2023-12-11  6:55                                                                 ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-03 21:23 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: thievol, michael_heerdegen, stefankangas, monnier, 66394

[-- Attachment #1: Type: text/plain, Size: 1437 bytes --]

Hi Eli,

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Eshel Yaron <me@eshelyaron.com>
>> Cc: michael_heerdegen@web.de,  Eli Zaretskii <eliz@gnu.org>,
>>   stefankangas@gmail.com,  monnier@iro.umontreal.ca,  66394@debbugs.gnu.org
>> Date: Sun, 03 Dec 2023 19:29:19 +0100
>> 
>> > otherwise it is easy to revert completely my commits (it is the
>> > development branch of emacs after all).
>> 
>> Seeing as you are not willing to make this change backward compatible, I
>> think that would make sense.  I don't have commit rights to emacs.git,
>> so I can't do that myself, though.
>
> Thierry also said:
>
>> > So it'd be great to have the previous behavior available in Emacs 30.
>> 
>> Sorry but I wont write this, it is not complicated to write but needs
>> works and attention and I spent enough time on this.
>
> So maybe a better way forward is for someone, perhaps you Eshel, to
> add whatever is needed to provide optionally the previous behavior?
>
> Would you like to work on that?

Sure.  I'm attaching two patches, the first reverts to the previous
implementation, and the second adds optional (on by default)
confirmation and highlighting in the *Register Preview* buffer when you
are about to overwrite the contents of a register.

The idea is to provide the nice of enhancements from Thierry's patch via
more minimal changes, without switching to a minibuffer based approach,
and without breaking any existing behavior.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Revert-recent-register-preview-changes.patch --]
[-- Type: text/x-patch, Size: 19163 bytes --]

From 220c600dd8b57de5ff44974ecfddd6f36dc9c3cd Mon Sep 17 00:00:00 2001
From: Eshel Yaron <me@eshelyaron.com>
Date: Sun, 3 Dec 2023 20:02:42 +0100
Subject: [PATCH 1/2] Revert recent register preview changes

This reverts commits cd6e66f955d20d31686a617ed8a5cd043585c71f,
408126b6d56a0cc36f621348212e16d0715fd671,
0fa70dad21d3475d3a5dae54a09d8a9e60b668ae,
3df81fb5dc5809cab7843e5358c17d0039b55eb1,
589e6ae1fb983bfba42f20906773555037246e45.
---
 doc/emacs/regs.texi           |   5 +-
 etc/NEWS                      |   5 -
 lisp/emacs-lisp/cl-generic.el |   1 -
 lisp/register.el              | 298 +++++-----------------------------
 test/lisp/register-tests.el   |  43 +++++
 5 files changed, 84 insertions(+), 268 deletions(-)
 create mode 100644 test/lisp/register-tests.el

diff --git a/doc/emacs/regs.texi b/doc/emacs/regs.texi
index 5e5b7ae2b16..e52f68dd18e 100644
--- a/doc/emacs/regs.texi
+++ b/doc/emacs/regs.texi
@@ -16,8 +16,9 @@ Registers
 we will denote by @var{r}; @var{r} can be a letter (such as @samp{a})
 or a number (such as @samp{1}); case matters, so register @samp{a} is
 not the same as register @samp{A}.  You can also set a register in
-non-alphanumeric characters, for instance @samp{C-d} by using for
-example @key{C-q} @samp{C-d}.
+non-alphanumeric characters, for instance @samp{*} or @samp{C-d}.
+Note, it's not possible to set a register in @samp{C-g} or @samp{ESC},
+because these keys are reserved for quitting (@pxref{Quitting}).
 
 @findex view-register
   A register can store a position, a piece of text, a rectangle, a
diff --git a/etc/NEWS b/etc/NEWS
index 29f4e5c0b66..af8e1049483 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1154,11 +1154,6 @@ showcases all their customization options.
 \f
 * Incompatible Lisp Changes in Emacs 30.1
 
----
-** 'register-preview-delay' is no longer used.
-Register preview is no more delayed.  If you want to disable it use
-'register-use-preview' instead with a boolean value.
-
 +++
 ** 'M-TAB' now invokes 'completion-at-point' also in Text mode.
 Text mode no longer binds 'M-TAB' to 'ispell-complete-word', and
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 0ef0d1e192a..56eb83e6f75 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -1379,7 +1379,6 @@ cl-generic-generalizers
 (cl--generic-prefill-dispatchers 0 integer)
 (cl--generic-prefill-dispatchers 1 integer)
 (cl--generic-prefill-dispatchers 0 cl--generic-generalizer integer)
-(cl--generic-prefill-dispatchers 0 (eql 'x) integer)
 
 ;;; Dispatch on major mode.
 
diff --git a/lisp/register.el b/lisp/register.el
index 46ec38821e5..ca6de450993 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -35,8 +35,6 @@
 
 ;; FIXME: Clean up namespace usage!
 
-(declare-function frameset-register-p "frameset")
-
 (cl-defstruct
   (registerv (:constructor nil)
 	     (:constructor registerv--make (&optional data print-func
@@ -100,15 +98,6 @@ register-preview-delay
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
-
-(defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
-  "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
-  "Always show register preview when non nil."
-  :type 'boolean)
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -131,8 +120,7 @@ register-describe-oneline
 (defun register-preview-default (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
-	  (propertize (string (car r))
-                      'display (single-key-description (car r)))
+	  (single-key-description (car r))
 	  (register-describe-oneline (car r))))
 
 (defvar register-preview-function #'register-preview-default
@@ -140,263 +128,53 @@ register-preview-function
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
 The function should return a string, the description of the argument.")
 
-(cl-defstruct register-preview-info
-  "Store data for a specific register command.
-TYPES are the types of register supported.
-MSG is the minibuffer message to send when a register is selected.
-ACT is the type of action the command is doing on register.
-SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
-
-(cl-defgeneric register-command-info (command)
-  "Returns a `register-preview-info' object storing data for COMMAND."
-  (ignore command))
-(cl-defmethod register-command-info ((_command (eql insert-register)))
-  (make-register-preview-info
-   :types '(string number)
-   :msg "Insert register `%s'"
-   :act 'insert
-   :smatch t))
-(cl-defmethod register-command-info ((_command (eql jump-to-register)))
-  (make-register-preview-info
-   :types  '(window frame marker kmacro
-             file buffer file-query)
-   :msg "Jump to register `%s'"
-   :act 'jump
-   :smatch t))
-(cl-defmethod register-command-info ((_command (eql view-register)))
-  (make-register-preview-info
-   :types '(all)
-   :msg "View register `%s'"
-   :act 'view
-   :smatch t))
-(cl-defmethod register-command-info ((_command (eql append-to-register)))
-  (make-register-preview-info
-   :types '(string number)
-   :msg "Append to register `%s'"
-   :act 'modify
-   :smatch t))
-(cl-defmethod register-command-info ((_command (eql prepend-to-register)))
-  (make-register-preview-info
-   :types '(string number)
-   :msg "Prepend to register `%s'"
-   :act 'modify
-   :smatch t))
-(cl-defmethod register-command-info ((_command (eql increment-register)))
-  (make-register-preview-info
-   :types '(string number)
-   :msg "Increment register `%s'"
-   :act 'modify
-   :smatch t))
-
-(defun register-preview-forward-line (arg)
-  "Move to next or previous line in register preview buffer.
-If ARG is positive goto next line, if negative to previous.
-Do nothing when defining or executing kmacros."
-  ;; Ensure user enter manually key in minibuffer when recording a macro.
-  (unless (or defining-kbd-macro executing-kbd-macro
-              (not (get-buffer-window "*Register Preview*" 'visible)))
-    (let ((fn (if (> arg 0) #'eobp #'bobp))
-          (posfn (if (> arg 0)
-                     #'point-min
-                     (lambda () (1- (point-max)))))
-          str)
-      (with-current-buffer "*Register Preview*"
-        (let ((ovs (overlays-in (point-min) (point-max)))
-              pos)
-          (goto-char (if ovs
-                         (overlay-start (car ovs))
-                         (point-min)))
-          (setq pos (point))
-          (and ovs (forward-line arg))
-          (when (and (funcall fn)
-                     (or (> arg 0) (eql pos (point))))
-            (goto-char (funcall posfn)))
-          (setq str (buffer-substring-no-properties
-                     (pos-bol) (1+ (pos-bol))))
-          (remove-overlays)
-          (with-selected-window (minibuffer-window)
-            (delete-minibuffer-contents)
-            (insert str)))))))
-
-(defun register-preview-next ()
-  "Goto next line in register preview buffer."
-  (interactive)
-  (register-preview-forward-line 1))
-
-(defun register-preview-previous ()
-  "Goto previous line in register preview buffer."
-  (interactive)
-  (register-preview-forward-line -1))
-
-(defun register-type (register)
-  "Return REGISTER type.
-Current register types actually returned are one of:
-- string
-- number
-- marker
-- buffer
-- file
-- file-query
-- window
-- frame
-- kmacro
-
-One can add new types to a specific command by defining a new `cl-defmethod'
-matching this command. Predicate for type in new `cl-defmethod' should
-satisfy `cl-typep' otherwise the new type should be defined with
-`cl-deftype'."
-  ;; Call register--type against the register value.
-  (register--type (if (consp (cdr register))
-                     (cadr register)
-                   (cdr register))))
-
-(cl-defgeneric register--type (regval)
-  "Returns type of register value REGVAL."
-  (ignore regval))
-
-(cl-defmethod register--type ((_regval string)) 'string)
-(cl-defmethod register--type ((_regval number)) 'number)
-(cl-defmethod register--type ((_regval marker)) 'marker)
-(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer)
-(cl-defmethod register--type ((_regval (eql 'file))) 'file)
-(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query)
-(cl-defmethod register--type ((_regval window-configuration)) 'window)
-(cl-deftype frame-register () '(satisfies frameset-register-p))
-(cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
-(cl-deftype kmacro-register () '(satisfies kmacro-register-p))
-(cl-defmethod register--type :extra "kmacro-register" (_regval) 'kmacro)
-
-(defun register-of-type-alist (types)
-  "Filter `register-alist' according to TYPES."
-  (if (memq 'all types)
-      register-alist
-    (cl-loop for register in register-alist
-             when (memq (register-type register) types)
-             collect register)))
-
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
   "Pop up a window showing the registers preview in BUFFER.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
-Argument TYPES (a list) specify the types of register to show, when nil show all
-registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
-  (let ((registers (register-of-type-alist (or types '(all)))))
-    (when (or show-empty (consp registers))
-      (with-current-buffer-window
-        buffer
-        (cons 'display-buffer-below-selected
-	      '((window-height . fit-window-to-buffer)
-	        (preserve-size . (nil . t))))
-        nil
-        (with-current-buffer standard-output
-          (setq cursor-in-non-selected-windows nil)
-          (mapc (lambda (elem)
-                  (when (get-register (car elem))
-                    (insert (funcall register-preview-function elem))))
-                registers))))))
-
-(cl-defgeneric register-preview-get-defaults (action)
-  "Returns default registers according to ACTION."
-  (ignore action))
-(cl-defmethod register-preview-get-defaults ((_action (eql set)))
-  (cl-loop for s in register-preview-default-keys
-           unless (assoc (string-to-char s) register-alist)
-           collect s))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
 
 (defun register-read-with-preview (prompt)
   "Read and return a register name, possibly showing existing registers.
-Prompt with the string PROMPT.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
 If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
-         (pat "")
-         (map (let ((m (make-sparse-keymap)))
-                (set-keymap-parent m minibuffer-local-map)
-                m))
-         (data (register-command-info this-command))
-         types msg result timer act win strs smatch)
-    (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
-      (setq types '(all)
-            msg   "Overwrite register `%s'"
-            act   'set))
-    (setq strs (mapcar (lambda (x)
-                         (string (car x)))
-                       (register-of-type-alist types)))
-    (when (and (memq act '(insert jump view)) (null strs))
-      (error "No register suitable for `%s'" act))
-    (dolist (k (cons help-char help-event-list))
-      (define-key map
-          (vector k) (lambda ()
-                       (interactive)
-                       (unless (get-buffer-window buffer)
-                         (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
-    (define-key map (kbd "<down>") 'register-preview-next)
-    (define-key map (kbd "<up>")   'register-preview-previous)
-    (define-key map (kbd "C-n")    'register-preview-next)
-    (define-key map (kbd "C-p")    'register-preview-previous)
-    (unless (or executing-kbd-macro (null register-use-preview))
-      (register-preview buffer nil types))
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
     (unwind-protect
-         (progn
-           (minibuffer-with-setup-hook
-               (lambda ()
-                 (setq timer
-                       (run-with-idle-timer
-                        0.01 'repeat
-                        (lambda ()
-                          (with-selected-window (minibuffer-window)
-                            (let ((input (minibuffer-contents)))
-                              (when (> (length input) 1)
-                                (let ((new (substring input 1))
-                                      (old (substring input 0 1)))
-                                  (setq input (if (or (null smatch)
-                                                      (member new strs))
-                                                  new old))
-                                  (delete-minibuffer-contents)
-                                  (insert input)))
-                              (when (and smatch (not (string= input ""))
-                                         (not (member input strs)))
-                                (setq input "")
-                                (delete-minibuffer-contents)
-                                (minibuffer-message "Not matching"))
-                              (when (not (string= input pat))
-                                (setq pat input))))
-                          (if (setq win (get-buffer-window buffer))
-                              (with-selected-window win
-                                (let ((ov (make-overlay (point-min) (point-min))))
-                                  (goto-char (point-min))
-                                  (remove-overlays)
-                                  (unless (string= pat "")
-                                    (if (re-search-forward (concat "^" pat) nil t)
-                                        (progn (move-overlay
-                                                ov
-                                                (match-beginning 0) (pos-eol))
-                                               (overlay-put ov 'face 'match)
-                                               (when msg
-                                                 (with-selected-window (minibuffer-window)
-                                                   (minibuffer-message msg pat))))
-                                      (with-selected-window (minibuffer-window)
-                                        (minibuffer-message
-                                         "Register `%s' is empty" pat))))))
-                            (unless (string= pat "")
-                              (if (member pat strs)
-                                  (with-selected-window (minibuffer-window)
-                                    (minibuffer-message msg pat))
-                                (with-selected-window (minibuffer-window)
-                                  (minibuffer-message
-                                   "Register `%s' is empty" pat)))))))))
-             (setq result (read-from-minibuffer
-                           prompt nil map nil nil (register-preview-get-defaults act))))
-           (cl-assert (and result (not (string= result "")))
-                      nil "No register specified")
-           (string-to-char result))
-      (when timer (cancel-timer timer))
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
       (let ((w (get-buffer-window buffer)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buffer) (kill-buffer buffer)))))
diff --git a/test/lisp/register-tests.el b/test/lisp/register-tests.el
new file mode 100644
index 00000000000..6283d1c31e0
--- /dev/null
+++ b/test/lisp/register-tests.el
@@ -0,0 +1,43 @@
+;;; register-tests.el --- tests for register.el  -*- lexical-binding: t-*-
+
+;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+
+;; Author: Tino Calancha <tino.calancha@gmail.com>
+;; Keywords:
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+\f
+;;; Code:
+(require 'ert)
+(require 'cl-lib)
+
+(ert-deftest register-test-bug27634 ()
+  "Test for https://debbugs.gnu.org/27634 ."
+  (dolist (event (list ?\C-g 'escape ?\C-\[))
+    (cl-letf (((symbol-function 'read-key) #'ignore)
+              (last-input-event event)
+              (register-alist nil))
+      (should (equal 'quit
+                     (condition-case err
+                         (call-interactively 'point-to-register)
+                       (quit (car err)))))
+      (should-not register-alist))))
+
+(provide 'register-tests)
+;;; register-tests.el ends here
-- 
2.42.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Optionally-ask-for-confirmation-before-overwriting-r.patch --]
[-- Type: text/x-patch, Size: 13524 bytes --]

From d1538aadc4f3d0da6a8c550248f8d348edb96116 Mon Sep 17 00:00:00 2001
From: Eshel Yaron <me@eshelyaron.com>
Date: Sun, 3 Dec 2023 20:44:16 +0100
Subject: [PATCH 2/2] Optionally ask for confirmation before overwriting
 registers

Commands can now call 'register-read-with-preview' with optional
argument CONFIRM to ask the user for confirmation if they choose a
register that is already in use, subject to new user option
'register-confirm-overwrite'.  Commands that write to registers are
adapted to make use of this new argument.  When asking for
confirmation, Emacs also highlights the selected register in
the *Register Preview* buffer.

* lisp/register.el (register-confirm-overwrite): New user option.
(register-preview): New optional argument HIGHLIGHT.
(register-read-with-preview): Use them.  New optional arg CONFIRM.
(point-to-register,window-configuration-to-register)
(frame-configuration-to-register,number-to-register)
(copy-to-register,copy-rectangle-to-register)
* lisp/textmodes/picture.el (picture-clear-rectangle-to-register)
* lisp/calc/calc-yank.el (calc-copy-to-register)
* lisp/cedet/semantic/senator.el (senator-copy-tag-to-register)
* lisp/frameset.el (frameset-to-register)
* lisp/kmacro.el (kmacro-to-register)
* lisp/play/gametree.el (gametree-layout-to-register): Use new arg.
* doc/lispref/text.texi (Registers): Update.
* etc/NEWS: Announce.
---
 doc/lispref/text.texi          |  8 +++--
 etc/NEWS                       |  6 ++++
 lisp/calc/calc-yank.el         |  2 +-
 lisp/cedet/semantic/senator.el |  2 +-
 lisp/frameset.el               |  2 +-
 lisp/kmacro.el                 |  2 +-
 lisp/play/gametree.el          |  2 +-
 lisp/register.el               | 62 ++++++++++++++++++++++++----------
 lisp/textmodes/picture.el      |  2 +-
 9 files changed, 61 insertions(+), 27 deletions(-)

diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 5d05ef18d4f..9f5b846b92d 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -4710,7 +4710,7 @@ Registers
 changed in the future.
 @end deffn
 
-@defun register-read-with-preview prompt
+@defun register-read-with-preview prompt &optional confirm
 @cindex register preview
 This function reads and returns a register name, prompting with
 @var{prompt} and possibly showing a preview of the existing registers
@@ -4718,8 +4718,10 @@ Registers
 the delay specified by the user option @code{register-preview-delay},
 if its value and @code{register-alist} are both non-@code{nil}.  The
 preview is also shown if the user requests help (e.g., by typing the
-help character).  We recommend that all interactive commands which
-read register names use this function.
+help character).  If optional argument @var{confirm} is
+non-@code{nil}, this function asks for confirmation before returning a
+register that is already in use.  We recommend that all interactive
+commands which read register names use this function.
 @end defun
 
 @node Transposition
diff --git a/etc/NEWS b/etc/NEWS
index af8e1049483..0617c8dc218 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1085,6 +1085,12 @@ macros with many lines, such as from 'kmacro-edit-lossage'.
 
 ** Miscellaneous
 
++++
+*** New user option 'register-confirm-overwrite'.
+Emacs now defaults to asking for confirmation before overwriting
+registers with existing contents.  To disable such confirmation,
+customize this option to nil.
+
 ---
 *** Webjump now assumes URIs are HTTPS instead of HTTP.
 For links in 'webjump-sites' without an explicit URI scheme, it was
diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el
index a2a91dc8fb8..ed1a8e1c046 100644
--- a/lisp/calc/calc-yank.el
+++ b/lisp/calc/calc-yank.el
@@ -281,7 +281,7 @@ calc-copy-to-register
 With prefix arg, delete as well.
 
 Interactively, reads the register using `register-read-with-preview'."
-  (interactive (list (register-read-with-preview "Copy to register: ")
+  (interactive (list (register-read-with-preview "Copy to register: " t)
 		     (region-beginning) (region-end)
 		     current-prefix-arg))
   (if (eq major-mode 'calc-mode)
diff --git a/lisp/cedet/semantic/senator.el b/lisp/cedet/semantic/senator.el
index ca4334eaff5..2c1fc4fda3b 100644
--- a/lisp/cedet/semantic/senator.el
+++ b/lisp/cedet/semantic/senator.el
@@ -736,7 +736,7 @@ senator-copy-tag-to-register
 kill ring.
 
 Interactively, reads the register using `register-read-with-preview'."
-  (interactive (list (register-read-with-preview "Tag to register: ")
+  (interactive (list (register-read-with-preview "Tag to register: " t)
                      current-prefix-arg))
   (semantic-fetch-tags)
   (let ((ft (semantic-obtain-foreign-tag)))
diff --git a/lisp/frameset.el b/lisp/frameset.el
index 224746bbfe3..63ff4668541 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -1451,7 +1451,7 @@ frameset-to-register
 Argument is a character, naming the register.
 
 Interactively, reads the register using `register-read-with-preview'."
-  (interactive (list (register-read-with-preview "Frameset to register: ")))
+  (interactive (list (register-read-with-preview "Frameset to register: " t)))
   (set-register register
 		(frameset-make-register
                  (frameset-save nil
diff --git a/lisp/kmacro.el b/lisp/kmacro.el
index 588b2d14943..a7aa2c88508 100644
--- a/lisp/kmacro.el
+++ b/lisp/kmacro.el
@@ -967,7 +967,7 @@ kmacro-to-register
   (interactive
    (progn
      (or last-kbd-macro (error "No keyboard macro defined"))
-     (list (register-read-with-preview "Save to register: "))))
+     (list (register-read-with-preview "Save to register: " t))))
   (set-register r (kmacro-ring-head)))
 
 
diff --git a/lisp/play/gametree.el b/lisp/play/gametree.el
index 971d8ea70ca..e46770af2da 100644
--- a/lisp/play/gametree.el
+++ b/lisp/play/gametree.el
@@ -523,7 +523,7 @@ gametree-layout-to-register
 Argument is a character, naming the register.
 
 Interactively, reads the register using `register-read-with-preview'."
-  (interactive (list (register-read-with-preview "Layout to register: ")))
+  (interactive (list (register-read-with-preview "Layout to register: " t)))
   (save-excursion
     (goto-char (point-min))
     (set-register register
diff --git a/lisp/register.el b/lisp/register.el
index ca6de450993..4e400fbff2c 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -99,6 +99,12 @@ register-preview-delay
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
 
+(defcustom register-confirm-overwrite t
+  "Whether to ask for confirmation before overwriting register contents."
+  :version "30.1"
+  :type 'boolean
+  :group 'register)
+
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
   (alist-get register register-alist))
@@ -128,10 +134,12 @@ register-preview-function
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
 The function should return a string, the description of the argument.")
 
-(defun register-preview (buffer &optional show-empty)
+(defun register-preview (buffer &optional show-empty highlight)
   "Pop up a window showing the registers preview in BUFFER.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
-Format of each entry is controlled by the variable `register-preview-function'."
+Optional argument HIGHLIGHT says to highlight the description of
+a register with that name.  Format of each entry is controlled by
+the variable `register-preview-function'."
   (when (or show-empty (consp register-alist))
     (with-current-buffer-window
      buffer
@@ -140,19 +148,26 @@ register-preview
 	     (preserve-size . (nil . t))))
      nil
      (with-current-buffer standard-output
+       (delete-region (point-min) (point-max))
        (setq cursor-in-non-selected-windows nil)
        (mapc (lambda (elem)
-               (when (get-register (car elem))
-                 (insert (funcall register-preview-function elem))))
+               (when-let ((name (car elem))
+                          (reg (get-register name))
+                          (desc (funcall register-preview-function elem)))
+                 (when (equal highlight name)
+                   (add-face-text-property 0 (length desc) 'match nil desc))
+                 (insert desc)))
              register-alist)))))
 
-(defun register-read-with-preview (prompt)
+(defun register-read-with-preview (prompt &optional confirm)
   "Read and return a register name, possibly showing existing registers.
-Prompt with the string PROMPT.  If `register-alist' and
+Prompt with the string PROMPT.  Optional argument CONFIRM says to
+ask for confirmation if the register is already in use and
+`register-confirm-overwrite' is non-nil.  If `register-alist' and
 `register-preview-delay' are both non-nil, display a window
-listing existing registers after `register-preview-delay' seconds.
-If `help-char' (or a member of `help-event-list') is pressed,
-display such a window regardless."
+listing existing registers after `register-preview-delay'
+seconds.  If `help-char' (or a member of `help-event-list') is
+pressed, display such a window regardless."
   (let* ((buffer "*Register Preview*")
 	 (timer (when (numberp register-preview-delay)
 		  (run-with-timer register-preview-delay nil
@@ -168,10 +183,20 @@ register-read-with-preview
 		       help-chars)
 	    (unless (get-buffer-window buffer)
 	      (register-preview buffer 'show-empty)))
-          (when (or (eq ?\C-g last-input-event)
-                    (eq 'escape last-input-event)
-                    (eq ?\C-\[ last-input-event))
+          (cond
+           ((or (eq ?\C-g last-input-event)
+                (eq 'escape last-input-event)
+                (eq ?\C-\[ last-input-event))
             (keyboard-quit))
+           ((and (get-register last-input-event)
+                 confirm register-confirm-overwrite
+                 (not (progn
+                        (register-preview buffer nil last-input-event)
+                        (y-or-n-p (substitute-quotes
+                                   (format "Overwrite register `%s'?"
+                                           (single-key-description
+                                            last-input-event))))))
+                 (user-error "Register already in use"))))
 	  (if (characterp last-input-event) last-input-event
 	    (error "Non-character input-event")))
       (and (timerp timer) (cancel-timer timer))
@@ -189,7 +214,8 @@ point-to-register
   (interactive (list (register-read-with-preview
                       (if current-prefix-arg
                           "Frame configuration to register: "
-                        "Point to register: "))
+                        "Point to register: ")
+                      t)
                      current-prefix-arg))
   ;; Turn the marker into a file-ref if the buffer is killed.
   (add-hook 'kill-buffer-hook 'register-swap-out nil t)
@@ -204,7 +230,7 @@ window-configuration-to-register
 
 Interactively, prompt for REGISTER using `register-read-with-preview'."
   (interactive (list (register-read-with-preview
-		      "Window configuration to register: ")
+		      "Window configuration to register: " t)
 		     current-prefix-arg))
   ;; current-window-configuration does not include the value
   ;; of point in the current buffer, so record that separately.
@@ -222,7 +248,7 @@ frame-configuration-to-register
 
 Interactively, prompt for REGISTER using `register-read-with-preview'."
   (interactive (list (register-read-with-preview
-		      "Frame configuration to register: ")
+		      "Frame configuration to register: " t)
 		     current-prefix-arg))
   ;; current-frame-configuration does not include the value
   ;; of point in the current buffer, so record that separately.
@@ -316,7 +342,7 @@ number-to-register
 
 Interactively, prompt for REGISTER using `register-read-with-preview'."
   (interactive (list current-prefix-arg
-		     (register-read-with-preview "Number to register: ")))
+		     (register-read-with-preview "Number to register: " t)))
   (set-register register
 		(if number
 		    (prefix-numeric-value number)
@@ -527,7 +553,7 @@ copy-to-register
 Interactively, prompt for REGISTER using `register-read-with-preview'
 and use mark and point as START and END; REGION is always non-nil in
 this case."
-  (interactive (list (register-read-with-preview "Copy to register: ")
+  (interactive (list (register-read-with-preview "Copy to register: " t)
 		     (region-beginning)
 		     (region-end)
 		     current-prefix-arg
@@ -605,7 +631,7 @@ copy-rectangle-to-register
 Interactively, prompt for REGISTER using `register-read-with-preview',
 and use mark and point as START and END."
   (interactive (list (register-read-with-preview
-		      "Copy rectangle to register: ")
+		      "Copy rectangle to register: " t)
 		     (region-beginning)
 		     (region-end)
 		     current-prefix-arg))
diff --git a/lisp/textmodes/picture.el b/lisp/textmodes/picture.el
index f98c3963b6f..efa59e0682f 100644
--- a/lisp/textmodes/picture.el
+++ b/lisp/textmodes/picture.el
@@ -503,7 +503,7 @@ picture-clear-rectangle-to-register
 
 Interactively, reads the register using `register-read-with-preview'."
   (interactive (list (region-beginning) (region-end)
-		     (register-read-with-preview "Rectangle to register: ")
+		     (register-read-with-preview "Rectangle to register: " t)
 		     current-prefix-arg))
   (set-register register (picture-snarf-rectangle start end killp)))
 
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-03 21:23                                                                 ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-04  7:30                                                                   ` Thierry Volpiatto
  2023-12-04  7:57                                                                     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-04  7:30 UTC (permalink / raw)
  To: Eshel Yaron
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394

[-- Attachment #1: Type: text/plain, Size: 560 bytes --]

Eshel Yaron <me@eshelyaron.com> writes:

> The idea is to provide the nice of enhancements from Thierry's patch via
> more minimal changes,

Your patch fails to provide all the enhancements I had provided.

- No filtering.
- No navigation.
- No default registers.
- No possibility to configure a new command added to register.
- You reintroduced the old implementation which was not wrote correctly
about handling various keys, particularly C-g.
- About overwriting, now you have to press "y" to confirm instead of
pressing RET.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-04  7:30                                                                   ` Thierry Volpiatto
@ 2023-12-04  7:57                                                                     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 121+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-04  7:57 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394

Hi Thierry,


Thierry Volpiatto <thievol@posteo.net> writes:

> Eshel Yaron <me@eshelyaron.com> writes:
>
>> The idea is to provide the nice of enhancements from Thierry's patch via
>> more minimal changes,
>
> Your patch fails to provide all the enhancements I had provided.

Thanks for testing.

Indeed, I only reimplemented the parts I saw as clearly beneficial.
Most importantly, my patch improves stuff without breaking other stuff.

Perhaps you can explain your use case for the rest of the changes, and
if there's a good and compatible way to add them I'll be happy to look
into it at some point.

> - No filtering.
> - No navigation.
> - No default registers.
> - No possibility to configure a new command added to register.

If you could elaborate about these bullets, and explain their use,
that'd be great.

> - You reintroduced the old implementation which was not wrote correctly
> about handling various keys, particularly C-g.

How so?  Works well over here, AFAICT, as it did in Emacs 29.

> - About overwriting, now you have to press "y" to confirm instead of
> pressing RET.

Yes, I think `y-or-n-p` is more user friendly here, don't you?


Cheers,

Eshel





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-07 19:03 bug#66394: 29.1; Make register-read-with-preview more useful Thierry Volpiatto
                   ` (2 preceding siblings ...)
  2023-10-19  2:42 ` bug#66394: 29.1; " Michael Heerdegen
@ 2023-12-05  7:34 ` Tino Calancha
  2023-12-05  7:38 ` Tino Calancha
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 121+ messages in thread
From: Tino Calancha @ 2023-12-05  7:34 UTC (permalink / raw)
  To: 66394


Michael Heerdegen <michael_heerdegen <at> web.de>  writes:

>> There is only RET as additional key and it is a good thing IMO as it 
>> let the time to user to see what he is doing.

> But wait: What I find confusing is that I also need need to confirm for
>`jump-to-register'.  Is this intended?

Please consider revising the patch to maintain backward compatibility. I 
find the fact that jump-to-register works without confirmation to be a 
very useful feature.

Thank you!
Tino





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-07 19:03 bug#66394: 29.1; Make register-read-with-preview more useful Thierry Volpiatto
                   ` (3 preceding siblings ...)
  2023-12-05  7:34 ` Tino Calancha
@ 2023-12-05  7:38 ` Tino Calancha
  2023-12-05  7:43 ` Tino Calancha
  2023-12-12  5:46 ` Pedro Andres Aranda Gutierrez
  6 siblings, 0 replies; 121+ messages in thread
From: Tino Calancha @ 2023-12-05  7:38 UTC (permalink / raw)
  To: 66394


Michael Heerdegen <michael_heerdegen <at> web.de>

>> There is only RET as additional key and it is a good thing IMO as it 
>> let the time to user to see what he is doing.

>But wait: What I find confusing is that I also need need to confirm for
>`jump-to-register'.  Is this intended?

Please consider revising the patch to maintain backward compatibility. I 
consider the fact that jump-to-register works without confirmation to be 
an important feature.

Thank you!
Tino






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-10-07 19:03 bug#66394: 29.1; Make register-read-with-preview more useful Thierry Volpiatto
                   ` (4 preceding siblings ...)
  2023-12-05  7:38 ` Tino Calancha
@ 2023-12-05  7:43 ` Tino Calancha
  2023-12-12  5:46 ` Pedro Andres Aranda Gutierrez
  6 siblings, 0 replies; 121+ messages in thread
From: Tino Calancha @ 2023-12-05  7:43 UTC (permalink / raw)
  To: 66394


Tino Calancha <tino.calancha <at> gmail.com> writes:

> Please consider revising the patch to maintain backward compatibility. I
> consider the fact that jump-to-register works without confirmation to be
> an important feature.

Same for `point-to-register`. I prefer the bahavior w/o a confirmation 
need.
Thank you!
Tino





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-03 18:39                                                               ` Eli Zaretskii
  2023-12-03 21:23                                                                 ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-11  6:55                                                                 ` Thierry Volpiatto
  1 sibling, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-11  6:55 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, stefankangas, monnier


[-- Attachment #1.1: Type: text/plain, Size: 1828 bytes --]


Hello Eli,

I tried to fullfill the requests on Emacs-devel about overwriting a
register with no confirmation, this will happen when
register-use-preview is nil or 'never.  Even with this configuration we
still have filtering when preview buffer is visible and in any case we
have defaults with M-n available when the register command is of type
'set'.

So now to resume the situation:

1) register-use-preview == t

We have a register-preview buffer with navigation and selected register
highlighted, when the register is selected we have to press RET to do
the action on this register.  Defaults are provided for registers of
type set.  Registers are filtered depending on the command used.

2) register-use-preview == nil

We have a register-preview buffer with no navigation and no
highlighting.  No confirmation with RET is requested, as soon as you
enter the register name, minibuffer is exited immediately.  Filtering
and defaults for register of type set are still provided.

3) register-use-preview == 'never

Same behavior as 2) but there is no preview buffer at all, however if
user type C-h, a preview buffer is provided behaving like 1) i.e. RET is
requested when selecting a register.

4) For registers which are key sequence e.g. C-a

For entering manually in minibuffer such a register one have to hit C-d
C-a.  This is now the only thing that differ from Emacs-29.1 behavior.

Let me know if I can push this patch.

I think all this is a real improvement for Emacs despite the several
complaints we had recently, however if all the arrangements I did are
not enough, we could add a new variable register-read-preview-function
and reinstall the old code exactly as it was (it's easy, let me know if
you want this I will provide the patch).

Thanks.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch --]
[-- Type: text/x-diff, Size: 6629 bytes --]

From f5ded67a4e3dfe8ef96971f8018b12cf26c13af2 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 07:02:40 +0100
Subject: [PATCH] Don't confirm with RET even when overwriting in register
 commands

This happen when register-use-preview is nil or never.
This reproduce what we had previously in 29.1 but with filtering in
the preview and default registers are provided for the commands of
type 'set'.

This is implemented with cl-defmethod to keep the code as much as
possible configurable.

* lisp/register.el (register-preview-info): New slot.
(register-command-info): Add new methods for copy-to-register,
point-to-register, number-to-register,
window-configuration-to-register, frameset-to-register and
copy-rectangle-to-register.
(register-read-with-preview): Bind noconfirm.
---
 lisp/register.el | 67 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index ade65b5bdc2..2f2f5682e34 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -155,7 +155,7 @@ TYPES are the types of register supported.
 MSG is the minibuffer message to send when a register is selected.
 ACT is the type of action the command is doing on register.
 SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
   "Returns a `register-preview-info' object storing data for COMMAND."
@@ -178,24 +178,66 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-preview-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-preview-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-preview-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-preview-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-preview-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
@@ -327,12 +369,13 @@ display such a window regardless."
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result timer act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -399,13 +442,15 @@ display such a window regardless."
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
                               (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs) (memq act '(set modify)))
+                                (if (and (member pat strs)
+                                         (memq act '(set modify))
+                                         (null noconfirm))
                                     (with-selected-window (minibuffer-window)
                                       (minibuffer-message msg pat))
-                                  ;; An empty register or an existing
-                                  ;; one but the action is insert or
-                                  ;; jump, don't ask for confirmation
-                                  ;; and exit immediately (bug#66394).
+                                  ;; The action is insert or
+                                  ;; jump or noconfirm is specifed
+                                  ;; explicitely, don't ask for
+                                  ;; confirmation and exit immediately (bug#66394).
                                   (setq result pat)
                                   (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-02  7:50                                                     ` Eli Zaretskii
  2023-12-02  8:08                                                       ` Thierry Volpiatto
  2023-12-03 14:35                                                       ` Thierry Volpiatto
@ 2023-12-11  9:30                                                       ` Thierry Volpiatto
  2023-12-11  9:58                                                         ` Thierry Volpiatto
                                                                           ` (3 more replies)
  2 siblings, 4 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-11  9:30 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas


[-- Attachment #1.1: Type: text/plain, Size: 675 bytes --]


Hello Eli, 

here the last patch that provide Emacs-29 previous behavior as asked on emacs-dev,
I made it the default for now.
The only customization one have to do to make a change is through
register-use-preview which have now three options:

- basic (default - same as Emacs-29- )
- nil (simple preview with filtering, default and no confirm)
- never (same as nil but without any preview)
- t  (the improved version with navigation etc...)

I don't know if you want to restore previous behavior (emacs-29), if so this patch
will apply against the previous one.
(0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch).

Thanks.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Provide-emacs-29-behavior-for-register-preview.patch --]
[-- Type: text/x-diff, Size: 10845 bytes --]

From 1b85a30f0150b0427b8efb3dee9ea4d740f3254b Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 09:02:58 +0100
Subject: [PATCH] Provide emacs-29 behavior for register-preview

It is now the default with a value of register-use-preview eq to
basic.
To change this one have now to customize register-use-preview to
another value.

* lisp/register.el (register-preview-delay): Remove obsolescence.
(register--read-with-preview-function): New.
(register-use-preview): New option basic, it is now the default.
(register-preview-default-1): New the register-preview-default used by
`register-read-with-preview-fancy`.
(register-preview-default): Restored (same as Emacs-29).
(register--preview-function): Generic fn that return the right
function for register--preview-function.
(register-preview): Restored (same behavior as Emacs-29).
(register-preview-1): Used by `register-read-with-preview-fancy'.
(register-read-with-preview-basic): The old
register-read-with-preview.
(register-read-with-preview-fancy): The new
register-read-with-preview.
---
 lisp/register.el | 133 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 121 insertions(+), 12 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index 2f2f5682e34..5818e818787 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -100,24 +100,49 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
+  :type '(repeat string)
+  :version 30.1)
+
+(defvar register--read-with-preview-function nil
+  "The register read preview function to use.
+Two functions are provided, one that provide navigation and
+highlighting of the register selected, filtering of register
+according to command in use, defaults register to use when
+setting a new register, confirmation and notification when you
+are about to overwrite a register and generic functions to
+configure how each existing commands behave.  The other function
+provided is the same as what was used in Emacs-29, no filtering,
+no navigation, no defaults.")
+
+(defcustom register-use-preview 'basic
   "Maybe show register preview.
 
+This have no effect when `register--read-with-preview-function' value
+is `register-read-with-preview-basic'.
+
 When set to `t' show a preview buffer with navigation and highlighting.
 When nil show a basic preview buffer and exit minibuffer
 immediately after insertion in minibuffer.
 When set to \\='never behave as above but with no preview buffer at
-all."
+all.
+When set to \\='basic provide a much more basic preview according to
+`register-preview-delay', it have the exact same behavior as in Emacs-29."
   :type '(choice
           (const :tag "Use preview" t)
           (const :tag "Use quick preview" nil)
-          (const :tag "Never use preview" never)))
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" basic))
+  :version 30.1
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'basic)
+                   #'register-read-with-preview-basic
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -137,17 +162,34 @@ See the documentation of the variable `register-alist' for possible VALUEs."
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
+(defun register-preview-default-1 (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
 	  (propertize (string (car r))
                       'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
+(defun register-preview-default (r)
+  "Function that is the default value of the variable `register-preview-function'."
+  (format "%s: %s\n"
+	  (single-key-description (car r))
+	  (register-describe-oneline (car r))))
+
+(defvar register-preview-function nil
   "Function to format a register for previewing.
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+The function should return a string, the description of the argument.
+It is set according to the value of `register--read-with-preview-function'.")
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Returns a function to format a register for previewing.
+This accorfing to the value of read-preview-function.")
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-basic)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
@@ -326,12 +368,39 @@ satisfy `cl-typep' otherwise the new type should be defined with
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
+  "Pop up a window showing the registers preview in BUFFER.
+If SHOW-EMPTY is non-nil, show the window even if no registers.
+Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
+
+(defun register-preview-1 (buffer &optional show-empty types)
   "Pop up a window showing the registers preview in BUFFER.
+
+This is the preview function use with
+`register-read-with-preview-fancy' function.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
 Argument TYPES (a list) specify the types of register to show, when nil show all
 registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
@@ -359,6 +428,46 @@ Format of each entry is controlled by the variable `register-preview-function'."
   "Read and return a register name, possibly showing existing registers.
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-basic (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
+    (unwind-protect
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.
+If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
          (buffer1 "*Register quick preview*")
@@ -391,13 +500,13 @@ display such a window regardless."
                        ;; Do nothing when buffer1 is in use.
                        (unless (get-buffer-window buf)
                          (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+                           (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
     (unless (or executing-kbd-macro (eq register-use-preview 'never))
-      (register-preview buf nil types))
+      (register-preview-1 buf nil types))
     (unwind-protect
          (progn
            (minibuffer-with-setup-hook
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-11  9:30                                                       ` Thierry Volpiatto
@ 2023-12-11  9:58                                                         ` Thierry Volpiatto
  2023-12-11 12:30                                                         ` Eli Zaretskii
                                                                           ` (2 subsequent siblings)
  3 siblings, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-11  9:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas

[-- Attachment #1: Type: text/plain, Size: 1077 bytes --]

Thierry Volpiatto <thievol@posteo.net> writes:

> Hello Eli, 
>
> here the last patch that provide Emacs-29 previous behavior as asked on emacs-dev,
> I made it the default for now.
> The only customization one have to do to make a change is through
> register-use-preview which have now three options:
>
> - basic (default - same as Emacs-29- )
> - nil (simple preview with filtering, default and no confirm)
> - never (same as nil but without any preview)
> - t  (the improved version with navigation etc...)
>
> I don't know if you want to restore previous behavior (emacs-29), if so this patch
> will apply against the previous one.
> (0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch).
>
> Thanks.

BTW I saw the thread on Reddit just now.  I have no more account there
to reply, but may be it is better to no reply to those people.
Even if it's easier to say than doing it, you should ignore all this
(and the usual trolls on emacs-dev) and continue the good job as you
always did, change nothing.

Respectfully,

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-11  9:30                                                       ` Thierry Volpiatto
  2023-12-11  9:58                                                         ` Thierry Volpiatto
@ 2023-12-11 12:30                                                         ` Eli Zaretskii
  2023-12-11 13:10                                                           ` Thierry Volpiatto
  2023-12-12  6:06                                                         ` Alfred M. Szmidt
  2023-12-12  9:37                                                         ` Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors
  3 siblings, 1 reply; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-11 12:30 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, 66394, monnier, stefankangas

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>   stefankangas@gmail.com,  66394@debbugs.gnu.org
> Date: Mon, 11 Dec 2023 09:30:50 +0000
> 
> here the last patch that provide Emacs-29 previous behavior as asked on emacs-dev,
> I made it the default for now.
> The only customization one have to do to make a change is through
> register-use-preview which have now three options:
> 
> - basic (default - same as Emacs-29- )
> - nil (simple preview with filtering, default and no confirm)
> - never (same as nil but without any preview)
> - t  (the improved version with navigation etc...)
> 
> I don't know if you want to restore previous behavior (emacs-29), if so this patch
> will apply against the previous one.
> (0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch).

Thank you for all your efforts in this matter.

I asked on emacs-devel that people try this and your previous
proposal, and provide opinions.  (Those CC'ed here are also invited,
of course.)  Let's wait for their responses for a couple of days
before we make the decision how to proceed.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-11 12:30                                                         ` Eli Zaretskii
@ 2023-12-11 13:10                                                           ` Thierry Volpiatto
  2023-12-11 17:32                                                             ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-11 13:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas

[-- Attachment #1: Type: text/plain, Size: 1405 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Thierry Volpiatto <thievol@posteo.net>
>> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>>   stefankangas@gmail.com,  66394@debbugs.gnu.org
>> Date: Mon, 11 Dec 2023 09:30:50 +0000
>> 
>> here the last patch that provide Emacs-29 previous behavior as asked on emacs-dev,
>> I made it the default for now.
>> The only customization one have to do to make a change is through
>> register-use-preview which have now three options:
>> 
>> - basic (default - same as Emacs-29- )
>> - nil (simple preview with filtering, default and no confirm)
>> - never (same as nil but without any preview)
>> - t  (the improved version with navigation etc...)
>> 
>> I don't know if you want to restore previous behavior (emacs-29), if so this patch
>> will apply against the previous one.
>> (0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch).
>
> Thank you for all your efforts in this matter.
>
> I asked on emacs-devel that people try this and your previous
> proposal, and provide opinions.  (Those CC'ed here are also invited,
> of course.)  Let's wait for their responses for a couple of days
> before we make the decision how to proceed.

Thanks, there is no hurry, let me know if something else is needed, I
will make the needed changes in NEWS and regs.texi once the changes will be
accepted.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-11 13:10                                                           ` Thierry Volpiatto
@ 2023-12-11 17:32                                                             ` Thierry Volpiatto
  2023-12-11 23:36                                                               ` Dmitry Gutov
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-11 17:32 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, 66394, monnier, stefankangas


[-- Attachment #1.1: Type: text/plain, Size: 1736 bytes --]

Thierry Volpiatto <thievol@posteo.net> writes:

> Eli Zaretskii <eliz@gnu.org> writes:
>
>>> From: Thierry Volpiatto <thievol@posteo.net>
>>> Cc: monnier@iro.umontreal.ca,  michael_heerdegen@web.de,
>>>   stefankangas@gmail.com,  66394@debbugs.gnu.org
>>> Date: Mon, 11 Dec 2023 09:30:50 +0000
>>> 
>>> here the last patch that provide Emacs-29 previous behavior as asked on emacs-dev,
>>> I made it the default for now.
>>> The only customization one have to do to make a change is through
>>> register-use-preview which have now three options:
>>> 
>>> - basic (default - same as Emacs-29- )
>>> - nil (simple preview with filtering, default and no confirm)
>>> - never (same as nil but without any preview)
>>> - t  (the improved version with navigation etc...)
>>> 
>>> I don't know if you want to restore previous behavior (emacs-29), if so this patch
>>> will apply against the previous one.
>>> (0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch).
>>
>> Thank you for all your efforts in this matter.
>>
>> I asked on emacs-devel that people try this and your previous
>> proposal, and provide opinions.  (Those CC'ed here are also invited,
>> of course.)  Let's wait for their responses for a couple of days
>> before we make the decision how to proceed.
>
> Thanks, there is no hurry, let me know if something else is needed, I
> will make the needed changes in NEWS and regs.texi once the changes will be
> accepted.

I made a little error in one of the patch when merging from a working
file for emacs-29.1, attaching here the two patches again with error
corrected (read `register-use-preview` instead of
`register-preview-use-preview`), sorry for this.


-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch --]
[-- Type: text/x-diff, Size: 6507 bytes --]

From 792ca690f24913d39ca24c8e0088de4ce60533a7 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 07:02:40 +0100
Subject: [PATCH 1/2] Don't confirm with RET even when overwriting in register
 commands

This happen when register-use-preview is nil or never.
This reproduce what we had previously in 29.1 but with filtering in
the preview and default registers are provided for the commands of
type 'set'.

This is implemented with cl-defmethod to keep the code as much as
possible configurable.

* lisp/register.el (register-preview-info): New slot.
(register-command-info): Add new methods for copy-to-register,
point-to-register, number-to-register,
window-configuration-to-register, frameset-to-register and
copy-rectangle-to-register.
(register-read-with-preview): Bind noconfirm.
---
 lisp/register.el | 67 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index ade65b5bdc2..734f351299e 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -155,7 +155,7 @@ register-preview-info
 MSG is the minibuffer message to send when a register is selected.
 ACT is the type of action the command is doing on register.
 SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
   "Returns a `register-preview-info' object storing data for COMMAND."
@@ -178,24 +178,66 @@ register-command-info
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-preview-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
@@ -327,12 +369,13 @@ register-read-with-preview
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result timer act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -399,13 +442,15 @@ register-read-with-preview
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
                               (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs) (memq act '(set modify)))
+                                (if (and (member pat strs)
+                                         (memq act '(set modify))
+                                         (null noconfirm))
                                     (with-selected-window (minibuffer-window)
                                       (minibuffer-message msg pat))
-                                  ;; An empty register or an existing
-                                  ;; one but the action is insert or
-                                  ;; jump, don't ask for confirmation
-                                  ;; and exit immediately (bug#66394).
+                                  ;; The action is insert or
+                                  ;; jump or noconfirm is specifed
+                                  ;; explicitely, don't ask for
+                                  ;; confirmation and exit immediately (bug#66394).
                                   (setq result pat)
                                   (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Provide-emacs-29-behavior-for-register-preview.patch --]
[-- Type: text/x-diff, Size: 10643 bytes --]

From 3833b91b7f332e5c9461746ce88cc008ad21778a Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 18:25:25 +0100
Subject: [PATCH 2/2] Provide emacs-29 behavior for register-preview

It is now the default with a value of register-use-preview eq to
basic.
To change this one have now to customize register-use-preview to
another value.

* lisp/register.el (register-preview-delay): Remove obsolescence.
(register--read-with-preview-function): New.
(register-use-preview): New option basic, it is now the default.
(register-preview-default-1): New the register-preview-default used by
`register-read-with-preview-fancy`.
(register-preview-default): Restored (same as Emacs-29).
(register--preview-function): Generic fn that return the right
function for register--preview-function.
(register-preview): Restored (same behavior as Emacs-29).
(register-preview-1): Used by `register-read-with-preview-fancy'.
(register-read-with-preview-basic): The old
register-read-with-preview.
(register-read-with-preview-fancy): The new
register-read-with-preview.
---
 lisp/register.el | 133 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 121 insertions(+), 12 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index 734f351299e..fd6c9af060e 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -100,24 +100,49 @@ register-preview-delay
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
+  :type '(repeat string)
+  :version 30.1)
+
+(defvar register--read-with-preview-function nil
+  "The register read preview function to use.
+Two functions are provided, one that provide navigation and
+highlighting of the register selected, filtering of register
+according to command in use, defaults register to use when
+setting a new register, confirmation and notification when you
+are about to overwrite a register and generic functions to
+configure how each existing commands behave.  The other function
+provided is the same as what was used in Emacs-29, no filtering,
+no navigation, no defaults.")
+
+(defcustom register-use-preview 'basic
   "Maybe show register preview.
 
+This have no effect when `register--read-with-preview-function' value
+is `register-read-with-preview-basic'.
+
 When set to `t' show a preview buffer with navigation and highlighting.
 When nil show a basic preview buffer and exit minibuffer
 immediately after insertion in minibuffer.
 When set to \\='never behave as above but with no preview buffer at
-all."
+all.
+When set to \\='basic provide a much more basic preview according to
+`register-preview-delay', it have the exact same behavior as in Emacs-29."
   :type '(choice
           (const :tag "Use preview" t)
           (const :tag "Use quick preview" nil)
-          (const :tag "Never use preview" never)))
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" basic))
+  :version 30.1
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'basic)
+                   #'register-read-with-preview-basic
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -137,17 +162,34 @@ register-describe-oneline
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
+(defun register-preview-default-1 (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
 	  (propertize (string (car r))
                       'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
+(defun register-preview-default (r)
+  "Function that is the default value of the variable `register-preview-function'."
+  (format "%s: %s\n"
+	  (single-key-description (car r))
+	  (register-describe-oneline (car r))))
+
+(defvar register-preview-function nil
   "Function to format a register for previewing.
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+The function should return a string, the description of the argument.
+It is set according to the value of `register--read-with-preview-function'.")
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Returns a function to format a register for previewing.
+This accorfing to the value of read-preview-function.")
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-basic)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
@@ -326,12 +368,39 @@ register-of-type-alist
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
+  "Pop up a window showing the registers preview in BUFFER.
+If SHOW-EMPTY is non-nil, show the window even if no registers.
+Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
+
+(defun register-preview-1 (buffer &optional show-empty types)
   "Pop up a window showing the registers preview in BUFFER.
+
+This is the preview function use with
+`register-read-with-preview-fancy' function.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
 Argument TYPES (a list) specify the types of register to show, when nil show all
 registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
@@ -359,6 +428,46 @@ register-read-with-preview
   "Read and return a register name, possibly showing existing registers.
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-basic (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
+    (unwind-protect
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.
+If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
          (buffer1 "*Register quick preview*")
@@ -391,13 +500,13 @@ register-read-with-preview
                        ;; Do nothing when buffer1 is in use.
                        (unless (get-buffer-window buf)
                          (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+                           (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
     (unless (or executing-kbd-macro (eq register-use-preview 'never))
-      (register-preview buf nil types))
+      (register-preview-1 buf nil types))
     (unwind-protect
          (progn
            (minibuffer-with-setup-hook
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-11 17:32                                                             ` Thierry Volpiatto
@ 2023-12-11 23:36                                                               ` Dmitry Gutov
  2023-12-12  6:29                                                                 ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Dmitry Gutov @ 2023-12-11 23:36 UTC (permalink / raw)
  To: Thierry Volpiatto, Eli Zaretskii
  Cc: michael_heerdegen, stefankangas, monnier, 66394

On 11/12/2023 19:32, Thierry Volpiatto wrote:
> I made a little error in one of the patch when merging from a working
> file for emacs-29.1, attaching here the two patches again with error
> corrected (read `register-use-preview` instead of
> `register-preview-use-preview`), sorry for this.

JFYI, the second patch doesn't apply cleanly, which may make testing 
them a bit more difficult.

It's because of commit 598ab9ca10d35d6 by Eli with documentation 
updates. When reverted, the second patch applies without problem.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
@ 2023-12-12  5:46 ` Pedro Andres Aranda Gutierrez
  2023-12-12 12:01   ` Eli Zaretskii
  0 siblings, 1 reply; 121+ messages in thread
From: Pedro Andres Aranda Gutierrez @ 2023-12-12  5:46 UTC (permalink / raw)
  To: emacs-devel, bug-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 528 bytes --]

Hi,

I could live with the patch proposed in
  https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-12/msg00644.html
if the default value for

was 'never. The new behaviour would be opt-in and I might be tempted to
test it out
and eventually switch in the future.

Thx, /PA

-- 
Fragen sind nicht da, um beantwortet zu werden,
Fragen sind da um gestellt zu werden
Georg Kreisler

Headaches with a Juju log:
unit-basic-16: 09:17:36 WARNING juju.worker.uniter.operation we should run
a leader-deposed hook here, but we can't yet

[-- Attachment #2: Type: text/html, Size: 1064 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-11  9:30                                                       ` Thierry Volpiatto
  2023-12-11  9:58                                                         ` Thierry Volpiatto
  2023-12-11 12:30                                                         ` Eli Zaretskii
@ 2023-12-12  6:06                                                         ` Alfred M. Szmidt
  2023-12-12  9:37                                                         ` Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors
  3 siblings, 0 replies; 121+ messages in thread
From: Alfred M. Szmidt @ 2023-12-12  6:06 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, eliz, stefankangas, monnier, 66394

Confirmation, we already have bookmarks which are the "longer"
variants.  Making registers confirm by default, makes registers on
par, as slow to use as bookmarks to use.  If those who wish to use
registers with confirmation, why not use bookmarks?

What becomes the difference between registers and bookmarks with this
change (confirmation part) other than bookmarks being saved to a file?

Some people seemed to have lots and lots (dozens if not more) of
registers, what heppens if you restart Emacs?  Do you save registers
between invocations of Emacs?  In that case, it sounds like one should
be using bookmarks and not registers.

TLDR: Making the default to "confirm" (preview is not the main
problem) makes registers just like bookmarks.  

   here the last patch that provide Emacs-29 previous behavior as asked on emacs-dev,
   I made it the default for now.
   The only customization one have to do to make a change is through
   register-use-preview which have now three options:

   - basic (default - same as Emacs-29- )
   - nil (simple preview with filtering, default and no confirm)
   - never (same as nil but without any preview)
   - t  (the improved version with navigation etc...)

I think the variable is being overloaded.  Shouldn't this just control
the usage of preview, not how interactive the behaviour of registers
are?

People seem to be confusing what it does already, since they think
that registers did not have preview before this change (and that being
the main feaature that they seem to be after -- not confirmation).
Which makes it hard to disucss this change, since it conflates
multiple topics into one thread.

"basic" seems to not be the same behaviour as in 29 (from the looks --
I cannot apply the patch), even Emacs 25 has register preview by
default, which is a useful feature, which seems to correspond to
'nil'.


The discussion of this change is strange and why people are upset, we
first change the behaviour silently and then try to justify the old
one.  It should be the other way round.  

Why is confirmation in registers so important to break old trusted
behaviour, when we already have a similar feature (bookmarks) that
those who wish to be "sure" can't use that instead?





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-11 23:36                                                               ` Dmitry Gutov
@ 2023-12-12  6:29                                                                 ` Thierry Volpiatto
  2023-12-12  9:31                                                                   ` Thierry Volpiatto
  2023-12-14 19:39                                                                   ` Stefan Kangas
  0 siblings, 2 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-12  6:29 UTC (permalink / raw)
  To: Dmitry Gutov
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394


[-- Attachment #1.1: Type: text/plain, Size: 664 bytes --]

Dmitry Gutov <dmitry@gutov.dev> writes:

> On 11/12/2023 19:32, Thierry Volpiatto wrote:
>> I made a little error in one of the patch when merging from a working
>> file for emacs-29.1, attaching here the two patches again with error
>> corrected (read `register-use-preview` instead of
>> `register-preview-use-preview`), sorry for this.
>
> JFYI, the second patch doesn't apply cleanly, which may make testing
> them a bit more difficult.
>
> It's because of commit 598ab9ca10d35d6 by Eli with documentation
> updates. When reverted, the second patch applies without problem.

Dmitry thanks, here the patches again after rebasing.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch --]
[-- Type: text/x-diff, Size: 6601 bytes --]

From 386457b493e3d2ebdb605dd8a8ce3c323847f537 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 07:02:40 +0100
Subject: [PATCH 1/2] Don't confirm with RET even when overwriting in register
 commands

This happen when register-use-preview is nil or never.
This reproduce what we had previously in 29.1 but with filtering in
the preview and default registers are provided for the commands of
type 'set'.

This is implemented with cl-defmethod to keep the code as much as
possible configurable.

* lisp/register.el (register-preview-info): New slot.
(register-command-info): Add new methods for copy-to-register,
point-to-register, number-to-register,
window-configuration-to-register, frameset-to-register and
copy-rectangle-to-register.
(register-read-with-preview): Bind noconfirm.
---
 lisp/register.el | 67 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index fa4bbcf483f..b7f4658055a 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -156,7 +156,7 @@ TYPES are the types of register supported.
 MSG is the minibuffer message to send when a register is selected.
 ACT is the type of action the command is doing on register.
 SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
   "Returns a `register-preview-info' object storing data for COMMAND."
@@ -179,24 +179,66 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-preview-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-preview-command-info ((_command (eql copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
@@ -328,12 +370,13 @@ display such a window regardless."
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result timer act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -400,13 +443,15 @@ display such a window regardless."
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
                               (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs) (memq act '(set modify)))
+                                (if (and (member pat strs)
+                                         (memq act '(set modify))
+                                         (null noconfirm))
                                     (with-selected-window (minibuffer-window)
                                       (minibuffer-message msg pat))
-                                  ;; An empty register or an existing
-                                  ;; one but the action is insert or
-                                  ;; jump, don't ask for confirmation
-                                  ;; and exit immediately (bug#66394).
+                                  ;; The action is insert or
+                                  ;; jump or noconfirm is specifed
+                                  ;; explicitely, don't ask for
+                                  ;; confirmation and exit immediately (bug#66394).
                                   (setq result pat)
                                   (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Provide-emacs-29-behavior-for-register-preview.patch --]
[-- Type: text/x-diff, Size: 11208 bytes --]

From 7b634a3359565dea755392324055443eb02aa070 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Tue, 12 Dec 2023 07:24:32 +0100
Subject: [PATCH 2/2] Provide emacs-29 behavior for register-preview

It is now the default with a value of register-use-preview eq to
basic.
To change this one have now to customize register-use-preview to
another value.

* lisp/register.el (register-preview-delay): Remove obsolescence.
(register--read-with-preview-function): New.
(register-use-preview): New option basic, it is now the default.
(register-preview-default-1): New the register-preview-default used by
`register-read-with-preview-fancy`.
(register-preview-default): Restored (same as Emacs-29).
(register--preview-function): Generic fn that return the right
function for register--preview-function.
(register-preview): Restored (same behavior as Emacs-29).
(register-preview-1): Used by `register-read-with-preview-fancy'.
(register-read-with-preview-basic): The old
register-read-with-preview.
(register-read-with-preview-fancy): The new
register-read-with-preview.
---
 lisp/register.el | 146 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 127 insertions(+), 19 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index b7f4658055a..fd6c9af060e 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -100,25 +100,49 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
-  "Whether to show preview of registers.
-
-If the value is t, show a preview buffer with navigation and highlighting.
-If the value is nil, show a basic preview buffer and exit minibuffer
-immediately after the register name is inserted into minibuffer.
-If the value is \\='never, behave as for nil, but with no preview buffer
-at all."
+  :type '(repeat string)
+  :version 30.1)
+
+(defvar register--read-with-preview-function nil
+  "The register read preview function to use.
+Two functions are provided, one that provide navigation and
+highlighting of the register selected, filtering of register
+according to command in use, defaults register to use when
+setting a new register, confirmation and notification when you
+are about to overwrite a register and generic functions to
+configure how each existing commands behave.  The other function
+provided is the same as what was used in Emacs-29, no filtering,
+no navigation, no defaults.")
+
+(defcustom register-use-preview 'basic
+  "Maybe show register preview.
+
+This have no effect when `register--read-with-preview-function' value
+is `register-read-with-preview-basic'.
+
+When set to `t' show a preview buffer with navigation and highlighting.
+When nil show a basic preview buffer and exit minibuffer
+immediately after insertion in minibuffer.
+When set to \\='never behave as above but with no preview buffer at
+all.
+When set to \\='basic provide a much more basic preview according to
+`register-preview-delay', it have the exact same behavior as in Emacs-29."
   :type '(choice
           (const :tag "Use preview" t)
           (const :tag "Use quick preview" nil)
-          (const :tag "Never use preview" never))
-  :version "30.1")
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" basic))
+  :version 30.1
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'basic)
+                   #'register-read-with-preview-basic
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -138,17 +162,34 @@ See the documentation of the variable `register-alist' for possible VALUEs."
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
+(defun register-preview-default-1 (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
 	  (propertize (string (car r))
                       'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
+(defun register-preview-default (r)
+  "Function that is the default value of the variable `register-preview-function'."
+  (format "%s: %s\n"
+	  (single-key-description (car r))
+	  (register-describe-oneline (car r))))
+
+(defvar register-preview-function nil
   "Function to format a register for previewing.
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+The function should return a string, the description of the argument.
+It is set according to the value of `register--read-with-preview-function'.")
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Returns a function to format a register for previewing.
+This accorfing to the value of read-preview-function.")
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-basic)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
@@ -327,12 +368,39 @@ satisfy `cl-typep' otherwise the new type should be defined with
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
+  "Pop up a window showing the registers preview in BUFFER.
+If SHOW-EMPTY is non-nil, show the window even if no registers.
+Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
+
+(defun register-preview-1 (buffer &optional show-empty types)
   "Pop up a window showing the registers preview in BUFFER.
+
+This is the preview function use with
+`register-read-with-preview-fancy' function.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
 Argument TYPES (a list) specify the types of register to show, when nil show all
 registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
@@ -360,6 +428,46 @@ Format of each entry is controlled by the variable `register-preview-function'."
   "Read and return a register name, possibly showing existing registers.
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-basic (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
+    (unwind-protect
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.
+If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
          (buffer1 "*Register quick preview*")
@@ -392,13 +500,13 @@ display such a window regardless."
                        ;; Do nothing when buffer1 is in use.
                        (unless (get-buffer-window buf)
                          (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+                           (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
     (unless (or executing-kbd-macro (eq register-use-preview 'never))
-      (register-preview buf nil types))
+      (register-preview-1 buf nil types))
     (unwind-protect
          (progn
            (minibuffer-with-setup-hook
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-12  6:29                                                                 ` Thierry Volpiatto
@ 2023-12-12  9:31                                                                   ` Thierry Volpiatto
  2023-12-12 10:16                                                                     ` Thierry Volpiatto
  2023-12-14  2:10                                                                     ` Dmitry Gutov
  2023-12-14 19:39                                                                   ` Stefan Kangas
  1 sibling, 2 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-12  9:31 UTC (permalink / raw)
  To: Dmitry Gutov
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394


[-- Attachment #1.1: Type: text/plain, Size: 1031 bytes --]

Thierry Volpiatto <thievol@posteo.net> writes:

> Dmitry Gutov <dmitry@gutov.dev> writes:
>
>> On 11/12/2023 19:32, Thierry Volpiatto wrote:
>>> I made a little error in one of the patch when merging from a working
>>> file for emacs-29.1, attaching here the two patches again with error
>>> corrected (read `register-use-preview` instead of
>>> `register-preview-use-preview`), sorry for this.
>>
>> JFYI, the second patch doesn't apply cleanly, which may make testing
>> them a bit more difficult.
>>
>> It's because of commit 598ab9ca10d35d6 by Eli with documentation
>> updates. When reverted, the second patch applies without problem.
>
> Dmitry thanks, here the patches again after rebasing.

I found another (merge) error in patch 0001 with defmethod names (read
register-command-info instead of register-preview-command-info), here
the patches corrected.  Without this changes, and with
register-use-preview == nil, confirmation is needed for copy-to-register
and friends, now fixed.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch --]
[-- Type: text/x-diff, Size: 6553 bytes --]

From c83e6132f33c1ab7f6baf63f85aed32f32e8177c Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 07:02:40 +0100
Subject: [PATCH 1/2] Don't confirm with RET even when overwriting in register
 commands

This happen when register-use-preview is nil or never.
This reproduce what we had previously in 29.1 but with filtering in
the preview and default registers are provided for the commands of
type 'set'.

This is implemented with cl-defmethod to keep the code as much as
possible configurable.

* lisp/register.el (register-preview-info): New slot.
(register-command-info): Add new methods for copy-to-register,
point-to-register, number-to-register,
window-configuration-to-register, frameset-to-register and
copy-rectangle-to-register.
(register-read-with-preview): Bind noconfirm.
---
 lisp/register.el | 67 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index fa4bbcf483f..cc4770579ee 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -156,7 +156,7 @@ TYPES are the types of register supported.
 MSG is the minibuffer message to send when a register is selected.
 ACT is the type of action the command is doing on register.
 SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
   "Returns a `register-preview-info' object storing data for COMMAND."
@@ -179,24 +179,66 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
@@ -328,12 +370,13 @@ display such a window regardless."
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result timer act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -400,13 +443,15 @@ display such a window regardless."
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
                               (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs) (memq act '(set modify)))
+                                (if (and (member pat strs)
+                                         (memq act '(set modify))
+                                         (null noconfirm))
                                     (with-selected-window (minibuffer-window)
                                       (minibuffer-message msg pat))
-                                  ;; An empty register or an existing
-                                  ;; one but the action is insert or
-                                  ;; jump, don't ask for confirmation
-                                  ;; and exit immediately (bug#66394).
+                                  ;; The action is insert or
+                                  ;; jump or noconfirm is specifed
+                                  ;; explicitely, don't ask for
+                                  ;; confirmation and exit immediately (bug#66394).
                                   (setq result pat)
                                   (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Provide-emacs-29-behavior-for-register-preview.patch --]
[-- Type: text/x-diff, Size: 11208 bytes --]

From 08cecb72eea866933941036718eb7af7f8d05ee9 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Tue, 12 Dec 2023 07:24:32 +0100
Subject: [PATCH 2/2] Provide emacs-29 behavior for register-preview

It is now the default with a value of register-use-preview eq to
basic.
To change this one have now to customize register-use-preview to
another value.

* lisp/register.el (register-preview-delay): Remove obsolescence.
(register--read-with-preview-function): New.
(register-use-preview): New option basic, it is now the default.
(register-preview-default-1): New the register-preview-default used by
`register-read-with-preview-fancy`.
(register-preview-default): Restored (same as Emacs-29).
(register--preview-function): Generic fn that return the right
function for register--preview-function.
(register-preview): Restored (same behavior as Emacs-29).
(register-preview-1): Used by `register-read-with-preview-fancy'.
(register-read-with-preview-basic): The old
register-read-with-preview.
(register-read-with-preview-fancy): The new
register-read-with-preview.
---
 lisp/register.el | 146 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 127 insertions(+), 19 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index cc4770579ee..8dbddf1bc9a 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -100,25 +100,49 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
-  "Whether to show preview of registers.
-
-If the value is t, show a preview buffer with navigation and highlighting.
-If the value is nil, show a basic preview buffer and exit minibuffer
-immediately after the register name is inserted into minibuffer.
-If the value is \\='never, behave as for nil, but with no preview buffer
-at all."
+  :type '(repeat string)
+  :version 30.1)
+
+(defvar register--read-with-preview-function nil
+  "The register read preview function to use.
+Two functions are provided, one that provide navigation and
+highlighting of the register selected, filtering of register
+according to command in use, defaults register to use when
+setting a new register, confirmation and notification when you
+are about to overwrite a register and generic functions to
+configure how each existing commands behave.  The other function
+provided is the same as what was used in Emacs-29, no filtering,
+no navigation, no defaults.")
+
+(defcustom register-use-preview 'basic
+  "Maybe show register preview.
+
+This have no effect when `register--read-with-preview-function' value
+is `register-read-with-preview-basic'.
+
+When set to `t' show a preview buffer with navigation and highlighting.
+When nil show a basic preview buffer and exit minibuffer
+immediately after insertion in minibuffer.
+When set to \\='never behave as above but with no preview buffer at
+all.
+When set to \\='basic provide a much more basic preview according to
+`register-preview-delay', it have the exact same behavior as in Emacs-29."
   :type '(choice
           (const :tag "Use preview" t)
           (const :tag "Use quick preview" nil)
-          (const :tag "Never use preview" never))
-  :version "30.1")
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" basic))
+  :version 30.1
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'basic)
+                   #'register-read-with-preview-basic
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -138,17 +162,34 @@ See the documentation of the variable `register-alist' for possible VALUEs."
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
+(defun register-preview-default-1 (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
 	  (propertize (string (car r))
                       'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
+(defun register-preview-default (r)
+  "Function that is the default value of the variable `register-preview-function'."
+  (format "%s: %s\n"
+	  (single-key-description (car r))
+	  (register-describe-oneline (car r))))
+
+(defvar register-preview-function nil
   "Function to format a register for previewing.
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+The function should return a string, the description of the argument.
+It is set according to the value of `register--read-with-preview-function'.")
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Returns a function to format a register for previewing.
+This accorfing to the value of read-preview-function.")
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-basic)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
@@ -327,12 +368,39 @@ satisfy `cl-typep' otherwise the new type should be defined with
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
+  "Pop up a window showing the registers preview in BUFFER.
+If SHOW-EMPTY is non-nil, show the window even if no registers.
+Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
+
+(defun register-preview-1 (buffer &optional show-empty types)
   "Pop up a window showing the registers preview in BUFFER.
+
+This is the preview function use with
+`register-read-with-preview-fancy' function.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
 Argument TYPES (a list) specify the types of register to show, when nil show all
 registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
@@ -360,6 +428,46 @@ Format of each entry is controlled by the variable `register-preview-function'."
   "Read and return a register name, possibly showing existing registers.
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-basic (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
+    (unwind-protect
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.
+If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
          (buffer1 "*Register quick preview*")
@@ -392,13 +500,13 @@ display such a window regardless."
                        ;; Do nothing when buffer1 is in use.
                        (unless (get-buffer-window buf)
                          (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+                           (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
     (unless (or executing-kbd-macro (eq register-use-preview 'never))
-      (register-preview buf nil types))
+      (register-preview-1 buf nil types))
     (unwind-protect
          (progn
            (minibuffer-with-setup-hook
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-11  9:30                                                       ` Thierry Volpiatto
                                                                           ` (2 preceding siblings ...)
  2023-12-12  6:06                                                         ` Alfred M. Szmidt
@ 2023-12-12  9:37                                                         ` Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-12 12:15                                                           ` Eli Zaretskii
  3 siblings, 1 reply; 121+ messages in thread
From: Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-12  9:37 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, eliz, stefankangas, monnier, 66394

Thierry Volpiatto <thievol@posteo.net> writes:
>
> ...
>
> I don't know if you want to restore previous behavior (emacs-29), if so this patch
> will apply against the previous one.
> (0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch).
>
> Thanks.

Hi - I'd love to give this patch a try but I can't get it to apply
against master, either with or without the other patch:

Don't Panic! ~/src/emacs $ patch -p1 < 0001-Provide-emacs-29-behavior-for-register-preview.patch 
patching file lisp/register.el
Hunk #1 FAILED at 100.
Hunk #2 succeeded at 138 (offset 1 line).
Hunk #3 succeeded at 302 (offset -41 lines).
Hunk #4 succeeded at 362 (offset -41 lines).
Hunk #5 succeeded at 433 (offset -42 lines).
1 out of 5 hunks FAILED -- saving rejects to file lisp/register.el.rej

I assume I'm doing something wrong somewhere but don't know what :-(


Many thanks!





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-12  9:31                                                                   ` Thierry Volpiatto
@ 2023-12-12 10:16                                                                     ` Thierry Volpiatto
  2023-12-12 16:44                                                                       ` Thierry Volpiatto
  2023-12-14  1:46                                                                       ` Dmitry Gutov
  2023-12-14  2:10                                                                     ` Dmitry Gutov
  1 sibling, 2 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-12 10:16 UTC (permalink / raw)
  To: Dmitry Gutov
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394


[-- Attachment #1.1: Type: text/plain, Size: 1991 bytes --]

Thierry Volpiatto <thievol@posteo.net> writes:

> Thierry Volpiatto <thievol@posteo.net> writes:
>
>> Dmitry Gutov <dmitry@gutov.dev> writes:
>>
>>> On 11/12/2023 19:32, Thierry Volpiatto wrote:
>>>> I made a little error in one of the patch when merging from a working
>>>> file for emacs-29.1, attaching here the two patches again with error
>>>> corrected (read `register-use-preview` instead of
>>>> `register-preview-use-preview`), sorry for this.
>>>
>>> JFYI, the second patch doesn't apply cleanly, which may make testing
>>> them a bit more difficult.
>>>
>>> It's because of commit 598ab9ca10d35d6 by Eli with documentation
>>> updates. When reverted, the second patch applies without problem.
>>
>> Dmitry thanks, here the patches again after rebasing.
>
> I found another (merge) error in patch 0001 with defmethod names (read
> register-command-info instead of register-preview-command-info), here
> the patches corrected.  Without this changes, and with
> register-use-preview == nil, confirmation is needed for copy-to-register
> and friends, now fixed.

Here a third patch that allows more precise configuration if needed.
For example if you have register-use-preview == nil, no confirmation
with RET is needed everywhere, even when overwriting a register.  If you
want to have a confirmation when overwriting but no confirmation when
jumping/inserting you can use this in addition of register-use-preview
== nil:

    (cl-defmethod register-command-info :after ((_command (eql copy-to-register)))
      (make-register-preview-info
       :types '(all)
       :msg "Copy to register `%s'"
       :act 'set))

You can modify other commands as well to your needs (point-to-register
etc...) with same method.

Sending here the serie of 3 patches to avoid errors when applying
patches.

I have also some minor errors (english in docstring, unnneded quotes
etc...) that I will fix later when polishing final patches.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch --]
[-- Type: text/x-diff, Size: 6553 bytes --]

From c83e6132f33c1ab7f6baf63f85aed32f32e8177c Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 07:02:40 +0100
Subject: [PATCH 1/3] Don't confirm with RET even when overwriting in register
 commands

This happen when register-use-preview is nil or never.
This reproduce what we had previously in 29.1 but with filtering in
the preview and default registers are provided for the commands of
type 'set'.

This is implemented with cl-defmethod to keep the code as much as
possible configurable.

* lisp/register.el (register-preview-info): New slot.
(register-command-info): Add new methods for copy-to-register,
point-to-register, number-to-register,
window-configuration-to-register, frameset-to-register and
copy-rectangle-to-register.
(register-read-with-preview): Bind noconfirm.
---
 lisp/register.el | 67 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index fa4bbcf483f..cc4770579ee 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -156,7 +156,7 @@ TYPES are the types of register supported.
 MSG is the minibuffer message to send when a register is selected.
 ACT is the type of action the command is doing on register.
 SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
   "Returns a `register-preview-info' object storing data for COMMAND."
@@ -179,24 +179,66 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
@@ -328,12 +370,13 @@ display such a window regardless."
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result timer act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -400,13 +443,15 @@ display such a window regardless."
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
                               (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs) (memq act '(set modify)))
+                                (if (and (member pat strs)
+                                         (memq act '(set modify))
+                                         (null noconfirm))
                                     (with-selected-window (minibuffer-window)
                                       (minibuffer-message msg pat))
-                                  ;; An empty register or an existing
-                                  ;; one but the action is insert or
-                                  ;; jump, don't ask for confirmation
-                                  ;; and exit immediately (bug#66394).
+                                  ;; The action is insert or
+                                  ;; jump or noconfirm is specifed
+                                  ;; explicitely, don't ask for
+                                  ;; confirmation and exit immediately (bug#66394).
                                   (setq result pat)
                                   (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Provide-emacs-29-behavior-for-register-preview.patch --]
[-- Type: text/x-diff, Size: 11208 bytes --]

From 08cecb72eea866933941036718eb7af7f8d05ee9 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Tue, 12 Dec 2023 07:24:32 +0100
Subject: [PATCH 2/3] Provide emacs-29 behavior for register-preview

It is now the default with a value of register-use-preview eq to
basic.
To change this one have now to customize register-use-preview to
another value.

* lisp/register.el (register-preview-delay): Remove obsolescence.
(register--read-with-preview-function): New.
(register-use-preview): New option basic, it is now the default.
(register-preview-default-1): New the register-preview-default used by
`register-read-with-preview-fancy`.
(register-preview-default): Restored (same as Emacs-29).
(register--preview-function): Generic fn that return the right
function for register--preview-function.
(register-preview): Restored (same behavior as Emacs-29).
(register-preview-1): Used by `register-read-with-preview-fancy'.
(register-read-with-preview-basic): The old
register-read-with-preview.
(register-read-with-preview-fancy): The new
register-read-with-preview.
---
 lisp/register.el | 146 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 127 insertions(+), 19 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index cc4770579ee..8dbddf1bc9a 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -100,25 +100,49 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
-  "Whether to show preview of registers.
-
-If the value is t, show a preview buffer with navigation and highlighting.
-If the value is nil, show a basic preview buffer and exit minibuffer
-immediately after the register name is inserted into minibuffer.
-If the value is \\='never, behave as for nil, but with no preview buffer
-at all."
+  :type '(repeat string)
+  :version 30.1)
+
+(defvar register--read-with-preview-function nil
+  "The register read preview function to use.
+Two functions are provided, one that provide navigation and
+highlighting of the register selected, filtering of register
+according to command in use, defaults register to use when
+setting a new register, confirmation and notification when you
+are about to overwrite a register and generic functions to
+configure how each existing commands behave.  The other function
+provided is the same as what was used in Emacs-29, no filtering,
+no navigation, no defaults.")
+
+(defcustom register-use-preview 'basic
+  "Maybe show register preview.
+
+This have no effect when `register--read-with-preview-function' value
+is `register-read-with-preview-basic'.
+
+When set to `t' show a preview buffer with navigation and highlighting.
+When nil show a basic preview buffer and exit minibuffer
+immediately after insertion in minibuffer.
+When set to \\='never behave as above but with no preview buffer at
+all.
+When set to \\='basic provide a much more basic preview according to
+`register-preview-delay', it have the exact same behavior as in Emacs-29."
   :type '(choice
           (const :tag "Use preview" t)
           (const :tag "Use quick preview" nil)
-          (const :tag "Never use preview" never))
-  :version "30.1")
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" basic))
+  :version 30.1
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'basic)
+                   #'register-read-with-preview-basic
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -138,17 +162,34 @@ See the documentation of the variable `register-alist' for possible VALUEs."
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
+(defun register-preview-default-1 (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
 	  (propertize (string (car r))
                       'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
+(defun register-preview-default (r)
+  "Function that is the default value of the variable `register-preview-function'."
+  (format "%s: %s\n"
+	  (single-key-description (car r))
+	  (register-describe-oneline (car r))))
+
+(defvar register-preview-function nil
   "Function to format a register for previewing.
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+The function should return a string, the description of the argument.
+It is set according to the value of `register--read-with-preview-function'.")
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Returns a function to format a register for previewing.
+This accorfing to the value of read-preview-function.")
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-basic)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((read-preview-function
+                                           (eql 'register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
@@ -327,12 +368,39 @@ satisfy `cl-typep' otherwise the new type should be defined with
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
+  "Pop up a window showing the registers preview in BUFFER.
+If SHOW-EMPTY is non-nil, show the window even if no registers.
+Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
+
+(defun register-preview-1 (buffer &optional show-empty types)
   "Pop up a window showing the registers preview in BUFFER.
+
+This is the preview function use with
+`register-read-with-preview-fancy' function.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
 Argument TYPES (a list) specify the types of register to show, when nil show all
 registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
@@ -360,6 +428,46 @@ Format of each entry is controlled by the variable `register-preview-function'."
   "Read and return a register name, possibly showing existing registers.
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-basic (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
+    (unwind-protect
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.
+If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
          (buffer1 "*Register quick preview*")
@@ -392,13 +500,13 @@ display such a window regardless."
                        ;; Do nothing when buffer1 is in use.
                        (unless (get-buffer-window buf)
                          (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+                           (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
     (unless (or executing-kbd-macro (eq register-use-preview 'never))
-      (register-preview buf nil types))
+      (register-preview-1 buf nil types))
     (unwind-protect
          (progn
            (minibuffer-with-setup-hook
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.4: 0003-Allow-users-overriding-register-use-preview-behavior.patch --]
[-- Type: text/x-diff, Size: 4029 bytes --]

From 15839ea11879fb651314c2d45ea4558c5735dcb6 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Tue, 12 Dec 2023 10:48:00 +0100
Subject: [PATCH 3/3] Allow users overriding register-use-preview behavior

This allows a more precise configuration if needed.
For example if one have register-use-preview == nil and want a
confirmation when overwriting a register he can use:

(cl-defmethod register-command-info :after ((_command (eql copy-to-register)))
  (make-register-preview-info
   :types '(all)
   :msg "Copy to register `%s'"
   :act 'set))

which disable the no confirmation when overwriting with such setting
of register-use-preview.

This is done by calling cl-call-next-method.

* lisp/register.el (register-command-info): Call next method where
  needed.
---
 lisp/register.el | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index 8dbddf1bc9a..2bb476cb34c 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -228,59 +228,68 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :msg "Append to register `%s'"
    :act 'modify
    :noconfirm (memq register-use-preview '(nil never))
-   :smatch t))
+   :smatch t)
+  (cl-call-next-method))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
    :noconfirm (memq register-use-preview '(nil never))
-   :smatch t))
+   :smatch t)
+  (cl-call-next-method))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
    :noconfirm (memq register-use-preview '(nil never))
-   :smatch t))
+   :smatch t)
+  (cl-call-next-method))
 (cl-defmethod register-command-info ((_command (eql copy-to-register)))
   (make-register-preview-info
    :types '(all)
    :msg "Copy to register `%s'"
    :act 'set
-   :noconfirm (memq register-use-preview '(nil never))))
+   :noconfirm (memq register-use-preview '(nil never)))
+  (cl-call-next-method))
 (cl-defmethod register-command-info ((_command (eql point-to-register)))
   (make-register-preview-info
    :types '(all)
    :msg "Point to register `%s'"
    :act 'set
-   :noconfirm (memq register-use-preview '(nil never))))
+   :noconfirm (memq register-use-preview '(nil never)))
+  (cl-call-next-method))
 (cl-defmethod register-command-info ((_command (eql number-to-register)))
   (make-register-preview-info
    :types '(all)
    :msg "Number to register `%s'"
    :act 'set
-   :noconfirm (memq register-use-preview '(nil never))))
+   :noconfirm (memq register-use-preview '(nil never)))
+  (cl-call-next-method))
 (cl-defmethod register-command-info
     ((_command (eql window-configuration-to-register)))
   (make-register-preview-info
    :types '(all)
    :msg "Window configuration to register `%s'"
    :act 'set
-   :noconfirm (memq register-use-preview '(nil never))))
+   :noconfirm (memq register-use-preview '(nil never)))
+  (cl-call-next-method))
 (cl-defmethod register-command-info ((_command (eql frameset-to-register)))
   (make-register-preview-info
    :types '(all)
    :msg "Frameset to register `%s'"
    :act 'set
-   :noconfirm (memq register-use-preview '(nil never))))
+   :noconfirm (memq register-use-preview '(nil never)))
+  (cl-call-next-method))
 (cl-defmethod register-command-info ((_command (eql copy-rectangle-to-register)))
   (make-register-preview-info
    :types '(all)
    :msg "Copy rectangle to register `%s'"
    :act 'set
    :noconfirm (memq register-use-preview '(nil never))
-   :smatch t))
+   :smatch t)
+  (cl-call-next-method))
 
 (defun register-preview-forward-line (arg)
   "Move to next or previous line in register preview buffer.
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-12  5:46 ` Pedro Andres Aranda Gutierrez
@ 2023-12-12 12:01   ` Eli Zaretskii
  0 siblings, 0 replies; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-12 12:01 UTC (permalink / raw)
  To: Pedro Andres Aranda Gutierrez; +Cc: 66394, emacs-devel

> From: Pedro Andres Aranda Gutierrez <paaguti@gmail.com>
> Date: Tue, 12 Dec 2023 06:46:51 +0100
> 
> I could live with the patch proposed in
>   https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-12/msg00644.html
> if the default value for 

Thanks, but please don't cross-post.  Post your opinions and
responses either toe emacs-devel or (preferred) 66394@debbugs.gnu.org,
but not to both.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-12  9:37                                                         ` Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-12 12:15                                                           ` Eli Zaretskii
  2023-12-12 17:58                                                             ` Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-12 12:15 UTC (permalink / raw)
  To: Steve Perry; +Cc: thievol, michael_heerdegen, stefankangas, monnier, 66394

> From: Steve Perry <stp@envs.net>
> Cc: eliz@gnu.org, michael_heerdegen@web.de, 66394@debbugs.gnu.org,
>  monnier@iro.umontreal.ca,
>  stefankangas@gmail.com
> Date: Tue, 12 Dec 2023 09:37:45 +0000
> 
> Thierry Volpiatto <thievol@posteo.net> writes:
> >
> > ...
> >
> > I don't know if you want to restore previous behavior (emacs-29), if so this patch
> > will apply against the previous one.
> > (0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch).
> >
> > Thanks.
> 
> Hi - I'd love to give this patch a try but I can't get it to apply
> against master, either with or without the other patch:
> 
> Don't Panic! ~/src/emacs $ patch -p1 < 0001-Provide-emacs-29-behavior-for-register-preview.patch 
> patching file lisp/register.el
> Hunk #1 FAILED at 100.
> Hunk #2 succeeded at 138 (offset 1 line).
> Hunk #3 succeeded at 302 (offset -41 lines).
> Hunk #4 succeeded at 362 (offset -41 lines).
> Hunk #5 succeeded at 433 (offset -42 lines).
> 1 out of 5 hunks FAILED -- saving rejects to file lisp/register.el.rej
> 
> I assume I'm doing something wrong somewhere but don't know what :-(

I don't think it's your fault.  Please try applying the patch named
0002-Provide-emacs-29-behavior-for-register-preview.patch from this
message:

  https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-12/msg00704.html

Thanks.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-12 10:16                                                                     ` Thierry Volpiatto
@ 2023-12-12 16:44                                                                       ` Thierry Volpiatto
  2023-12-14  1:46                                                                       ` Dmitry Gutov
  1 sibling, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-12 16:44 UTC (permalink / raw)
  To: Dmitry Gutov
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394

[-- Attachment #1: Type: text/plain, Size: 728 bytes --]

Thierry Volpiatto <thievol@posteo.net> writes:

> Here a third patch that allows more precise configuration if needed.
> For example if you have register-use-preview == nil, no confirmation
> with RET is needed everywhere, even when overwriting a register.  If you
> want to have a confirmation when overwriting but no confirmation when
> jumping/inserting you can use this in addition of register-use-preview
> == nil:

Finally patch 0003 is not needed, one can override default with:

    (cl-defmethod register-command-info ((_command (eql copy-to-register)))
      (make-register-preview-info
       :types '(all)
       :msg "Copy to register `%s'"
       :act 'set
       :noconfirm nil))

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-12 12:15                                                           ` Eli Zaretskii
@ 2023-12-12 17:58                                                             ` Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 121+ messages in thread
From: Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-12 17:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: thievol, michael_heerdegen, stefankangas, monnier, 66394

Eli Zaretskii <eliz@gnu.org> writes:
>
> I don't think it's your fault.  Please try applying the patch named
> 0002-Provide-emacs-29-behavior-for-register-preview.patch from this
> message:
>
>   https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-12/msg00704.html
>
> Thanks.

Ah, perfect.  Cheers!





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-12 10:16                                                                     ` Thierry Volpiatto
  2023-12-12 16:44                                                                       ` Thierry Volpiatto
@ 2023-12-14  1:46                                                                       ` Dmitry Gutov
  2023-12-14  5:34                                                                         ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Dmitry Gutov @ 2023-12-14  1:46 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394

On 12/12/2023 12:16, Thierry Volpiatto wrote:
> Here a third patch that allows more precise configuration if needed.
> For example if you have register-use-preview == nil, no confirmation
> with RET is needed everywhere, even when overwriting a register.  If you
> want to have a confirmation when overwriting but no confirmation when
> jumping/inserting you can use this in addition of register-use-preview

I was actually thinking this might be a good default behavior: no 
confirmation in all cases except when overwriting. It's a change from 
the current one still, but a smaller one.

But never mind me, I have very little practice using registers.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-12  9:31                                                                   ` Thierry Volpiatto
  2023-12-12 10:16                                                                     ` Thierry Volpiatto
@ 2023-12-14  2:10                                                                     ` Dmitry Gutov
  2023-12-14  5:30                                                                       ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Dmitry Gutov @ 2023-12-14  2:10 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394

On 12/12/2023 11:31, Thierry Volpiatto wrote:
> Thierry Volpiatto<thievol@posteo.net>  writes:
> 
>> Dmitry Gutov<dmitry@gutov.dev>  writes:
>>
>>> On 11/12/2023 19:32, Thierry Volpiatto wrote:
>>>> I made a little error in one of the patch when merging from a working
>>>> file for emacs-29.1, attaching here the two patches again with error
>>>> corrected (read `register-use-preview` instead of
>>>> `register-preview-use-preview`), sorry for this.
>>> JFYI, the second patch doesn't apply cleanly, which may make testing
>>> them a bit more difficult.
>>>
>>> It's because of commit 598ab9ca10d35d6 by Eli with documentation
>>> updates. When reverted, the second patch applies without problem.
>> Dmitry thanks, here the patches again after rebasing.
> I found another (merge) error in patch 0001 with defmethod names (read
> register-command-info instead of register-preview-command-info), here
> the patches corrected.  Without this changes, and with
> register-use-preview == nil, confirmation is needed for copy-to-register
> and friends, now fixed.

I did some testing.

Something I'm seeing with my custom config, but not with 'emacs -Q': the 
register preview is eating my windows. :-) No matter if I choose 
something, or C-g out of it.

To reproduce:

(defun split-window-prefer-side-by-side (&optional window)
   (let ((split-height-threshold (and (< (window-width window)
                                         split-width-threshold)
                                      split-height-threshold)))
     (split-window-sensibly window)))

(setq split-window-preferred-function 'split-window-prefer-side-by-side)

Then split the frame horizontally or vertically, create a register and 
jump to it.

The problem is that with this setup the preview is not creating a new 
window but reuses an existing one. And then deletes it at the end.

Again, I'm not a heavy user of registers, so if this is easy enough to 
fix, great. If not, never mind.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14  2:10                                                                     ` Dmitry Gutov
@ 2023-12-14  5:30                                                                       ` Thierry Volpiatto
  0 siblings, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-14  5:30 UTC (permalink / raw)
  To: Dmitry Gutov
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394

[-- Attachment #1: Type: text/plain, Size: 2191 bytes --]

Dmitry Gutov <dmitry@gutov.dev> writes:

> On 12/12/2023 11:31, Thierry Volpiatto wrote:
>> Thierry Volpiatto<thievol@posteo.net>  writes:
>> 
>>> Dmitry Gutov<dmitry@gutov.dev>  writes:
>>>
>>>> On 11/12/2023 19:32, Thierry Volpiatto wrote:
>>>>> I made a little error in one of the patch when merging from a working
>>>>> file for emacs-29.1, attaching here the two patches again with error
>>>>> corrected (read `register-use-preview` instead of
>>>>> `register-preview-use-preview`), sorry for this.
>>>> JFYI, the second patch doesn't apply cleanly, which may make testing
>>>> them a bit more difficult.
>>>>
>>>> It's because of commit 598ab9ca10d35d6 by Eli with documentation
>>>> updates. When reverted, the second patch applies without problem.
>>> Dmitry thanks, here the patches again after rebasing.
>> I found another (merge) error in patch 0001 with defmethod names (read
>> register-command-info instead of register-preview-command-info), here
>> the patches corrected.  Without this changes, and with
>> register-use-preview == nil, confirmation is needed for copy-to-register
>> and friends, now fixed.
>
> I did some testing.
>
> Something I'm seeing with my custom config, but not with 'emacs -Q':
> the register preview is eating my windows. :-) No matter if I choose
> something, or C-g out of it.
>
> To reproduce:
>
> (defun split-window-prefer-side-by-side (&optional window)
>   (let ((split-height-threshold (and (< (window-width window)
>                                         split-width-threshold)
>                                      split-height-threshold)))
>     (split-window-sensibly window)))
>
> (setq split-window-preferred-function 'split-window-prefer-side-by-side)
>
> Then split the frame horizontally or vertically, create a register and
> jump to it.
>
> The problem is that with this setup the preview is not creating a new
> window but reuses an existing one. And then deletes it at the end.

I think I can fix this, will look at it as soon as possible.

Thanks.

> Again, I'm not a heavy user of registers, so if this is easy enough to
> fix, great. If not, never mind.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14  1:46                                                                       ` Dmitry Gutov
@ 2023-12-14  5:34                                                                         ` Thierry Volpiatto
  2023-12-14  7:38                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-14  7:44                                                                           ` Eli Zaretskii
  0 siblings, 2 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-14  5:34 UTC (permalink / raw)
  To: Dmitry Gutov
  Cc: michael_heerdegen, Eli Zaretskii, stefankangas, monnier, 66394

[-- Attachment #1: Type: text/plain, Size: 713 bytes --]

Dmitry Gutov <dmitry@gutov.dev> writes:

> On 12/12/2023 12:16, Thierry Volpiatto wrote:
>> Here a third patch that allows more precise configuration if needed.
>> For example if you have register-use-preview == nil, no confirmation
>> with RET is needed everywhere, even when overwriting a register.  If you
>> want to have a confirmation when overwriting but no confirmation when
>> jumping/inserting you can use this in addition of register-use-preview
>
> I was actually thinking this might be a good default behavior: no
> confirmation in all cases except when overwriting. It's a change from
> the current one still, but a smaller one.

I think too it would be a good default.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14  5:34                                                                         ` Thierry Volpiatto
@ 2023-12-14  7:38                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-14  8:24                                                                             ` Eli Zaretskii
  2023-12-14  7:44                                                                           ` Eli Zaretskii
  1 sibling, 1 reply; 121+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-14  7:38 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, Dmitry Gutov, Eli Zaretskii, stefankangas,
	66394

>> I was actually thinking this might be a good default behavior: no
>> confirmation in all cases except when overwriting. It's a change from
>> the current one still, but a smaller one.

Note that when used within a keyboard macro, it's annoying if it
sometimes requires confirmation and sometimes not.


        Stefan






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14  5:34                                                                         ` Thierry Volpiatto
  2023-12-14  7:38                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-14  7:44                                                                           ` Eli Zaretskii
  2023-12-14 15:50                                                                             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 1 reply; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-14  7:44 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, dmitry, stefankangas, monnier, 66394

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: Eli Zaretskii <eliz@gnu.org>,  michael_heerdegen@web.de,
>   66394@debbugs.gnu.org,  monnier@iro.umontreal.ca,  stefankangas@gmail.com
> Date: Thu, 14 Dec 2023 05:34:36 +0000
> 
> Dmitry Gutov <dmitry@gutov.dev> writes:
> 
> > On 12/12/2023 12:16, Thierry Volpiatto wrote:
> >> Here a third patch that allows more precise configuration if needed.
> >> For example if you have register-use-preview == nil, no confirmation
> >> with RET is needed everywhere, even when overwriting a register.  If you
> >> want to have a confirmation when overwriting but no confirmation when
> >> jumping/inserting you can use this in addition of register-use-preview
> >
> > I was actually thinking this might be a good default behavior: no
> > confirmation in all cases except when overwriting. It's a change from
> > the current one still, but a smaller one.
> 
> I think too it would be a good default.

What do others think about making this the default?





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14  7:38                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-14  8:24                                                                             ` Eli Zaretskii
  0 siblings, 0 replies; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-14  8:24 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: thievol, dmitry, stefankangas, michael_heerdegen, 66394

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: Dmitry Gutov <dmitry@gutov.dev>,  Eli Zaretskii <eliz@gnu.org>,
>   michael_heerdegen@web.de,  66394@debbugs.gnu.org,  stefankangas@gmail.com
> Date: Thu, 14 Dec 2023 02:38:56 -0500
> 
> >> I was actually thinking this might be a good default behavior: no
> >> confirmation in all cases except when overwriting. It's a change from
> >> the current one still, but a smaller one.
> 
> Note that when used within a keyboard macro, it's annoying if it
> sometimes requires confirmation and sometimes not.

Perhaps we could avoid the confirmation request when the command is
run from a macro?





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14  7:44                                                                           ` Eli Zaretskii
@ 2023-12-14 15:50                                                                             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-14 17:58                                                                               ` Thierry Volpiatto
  2023-12-14 20:29                                                                               ` Stefan Kangas
  0 siblings, 2 replies; 121+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-14 15:50 UTC (permalink / raw)
  To: Eli Zaretskii
  Cc: Thierry Volpiatto, dmitry, stefankangas, michael_heerdegen, 66394

> What do others think about making this the default?

My understanding is that usage style of registers varies a lot, where
some people use them extensively, so any change that makes them
heavier/slower (such a requiring a confirmation) will alienate them.
For that reason I'd opt to keep the defaults as close to the previous
behavior, focusing on making the new features discoverable rather than
enabled by default.


        Stefan






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14 15:50                                                                             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-14 17:58                                                                               ` Thierry Volpiatto
  2023-12-14 19:19                                                                                 ` Andreas Schwab
  2023-12-14 20:29                                                                               ` Stefan Kangas
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-14 17:58 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, stefankangas, 66394

[-- Attachment #1: Type: text/plain, Size: 1486 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> What do others think about making this the default?
>
> My understanding is that usage style of registers varies a lot, where
> some people use them extensively, so any change that makes them
> heavier/slower (such a requiring a confirmation) will alienate them.

My impression is that these people use a workflow based on few register
(I guess maximum 5) because it is hard to read the register preview as
it was before, so they work with for example only "a", "b" and "c", they
always overwrite them and as there is only few registers they can
always remember what they do.

But when you have many registers, the time you spend scrutinizing the
preview buffer is worst than the time you spend hitting RET or even
navigating the preview buffer with C-n/p. 

> 
> For that reason I'd opt to keep the defaults as close to the previous
> behavior, focusing on making the new features discoverable rather than
> enabled by default.

So we could have the default exactly as before (register-use-preview ==
basic) and disable the behavior of register-preview == nil, keeping only
t and 'never.

t would provide the fully featured preview buffer (with RET everywhere to confirm).
And 'never would be the same but with no preview buffer (but still available
with C-h).

As I have actually a problem unsolved with register-use-preview == nil
with kmacros, this would save me some more work.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14 17:58                                                                               ` Thierry Volpiatto
@ 2023-12-14 19:19                                                                                 ` Andreas Schwab
  0 siblings, 0 replies; 121+ messages in thread
From: Andreas Schwab @ 2023-12-14 19:19 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, stefankangas, dmitry, Stefan Monnier,
	Eli Zaretskii, 66394

On Dez 14 2023, Thierry Volpiatto wrote:

> My impression is that these people use a workflow based on few register
> (I guess maximum 5) because it is hard to read the register preview as
> it was before, so they work with for example only "a", "b" and "c", they
> always overwrite them and as there is only few registers they can
> always remember what they do.

The right way to handle that is to use mnemonic letters and punctuation
as registers.

It is even impossible now to use both lower and upper case letters.
That is a serious bug.

Registers need to be fast and accessible.  The current interface is slow
and cumbersome.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-12  6:29                                                                 ` Thierry Volpiatto
  2023-12-12  9:31                                                                   ` Thierry Volpiatto
@ 2023-12-14 19:39                                                                   ` Stefan Kangas
  1 sibling, 0 replies; 121+ messages in thread
From: Stefan Kangas @ 2023-12-14 19:39 UTC (permalink / raw)
  To: Thierry Volpiatto, Dmitry Gutov
  Cc: michael_heerdegen, Eli Zaretskii, monnier, 66394

Thierry Volpiatto <thievol@posteo.net> writes:

> From 386457b493e3d2ebdb605dd8a8ce3c323847f537 Mon Sep 17 00:00:00 2001
> From: Thierry Volpiatto <thievol@posteo.net>
> Date: Mon, 11 Dec 2023 07:02:40 +0100
> Subject: [PATCH 1/2] Don't confirm with RET even when overwriting in register
>  commands

The preview here when copying to and inserting from registers is really
nice.

However, I think we should do what Stefan Monnier suggested: keep the
old default (with regards to which keys to press), and make it
discoverable for those that want it.

That said, I think the new feature, if made optional, will clearly be
popular among at least a section of users.  So it's a nice addition and
extension of Emacs' capabilities.

> From 7b634a3359565dea755392324055443eb02aa070 Mon Sep 17 00:00:00 2001
> From: Thierry Volpiatto <thievol@posteo.net>
> Date: Tue, 12 Dec 2023 07:24:32 +0100
> Subject: [PATCH 2/2] Provide emacs-29 behavior for register-preview

This one is okay in terms of the keys I need to press (i.e. there is no
change from emacs-29, by default), but why not keep the preview from the
first one?  That part I think was a really good addition, and also
non-intrusive.  It makes me feel more in control, as I'm not inserting
or overwriting stuff blindly.  We might want an option to turn it off,
though.

I hope that helps.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14 15:50                                                                             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-14 17:58                                                                               ` Thierry Volpiatto
@ 2023-12-14 20:29                                                                               ` Stefan Kangas
  2023-12-15 14:45                                                                                 ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Stefan Kangas @ 2023-12-14 20:29 UTC (permalink / raw)
  To: Stefan Monnier, Eli Zaretskii
  Cc: Thierry Volpiatto, dmitry, michael_heerdegen, 66394

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> What do others think about making this the default?
>
> My understanding is that usage style of registers varies a lot, where
> some people use them extensively, so any change that makes them
> heavier/slower (such a requiring a confirmation) will alienate them.
> For that reason I'd opt to keep the defaults as close to the previous
> behavior, focusing on making the new features discoverable rather than
> enabled by default.

+1





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-14 20:29                                                                               ` Stefan Kangas
@ 2023-12-15 14:45                                                                                 ` Thierry Volpiatto
  2023-12-15 15:18                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-16 15:07                                                                                   ` Dmitry Gutov
  0 siblings, 2 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-15 14:45 UTC (permalink / raw)
  To: Stefan Kangas
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Monnier, 66394


[-- Attachment #1.1: Type: text/plain, Size: 1029 bytes --]

Stefan Kangas <stefankangas@gmail.com> writes:

> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>>> What do others think about making this the default?
>>
>> My understanding is that usage style of registers varies a lot, where
>> some people use them extensively, so any change that makes them
>> heavier/slower (such a requiring a confirmation) will alienate them.
>> For that reason I'd opt to keep the defaults as close to the previous
>> behavior, focusing on making the new features discoverable rather than
>> enabled by default.
>
> +1

I just fixed a bug with register-use-preview = nil about its usage
with kmacros.
So I guess it is now possible to make it the default.
In these patches (attached) I also fixed the problem of Dmitri with windows
configuration (let me know if it works), BTW I guess this bug was
already here before these changes.

Thanks all for your feedback.

PS: I didn't have the time to look in delayed preview request, will do
as soon as possible.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch --]
[-- Type: text/x-diff, Size: 6553 bytes --]

From c83e6132f33c1ab7f6baf63f85aed32f32e8177c Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 07:02:40 +0100
Subject: [PATCH 1/4] Don't confirm with RET even when overwriting in register
 commands

This happen when register-use-preview is nil or never.
This reproduce what we had previously in 29.1 but with filtering in
the preview and default registers are provided for the commands of
type 'set'.

This is implemented with cl-defmethod to keep the code as much as
possible configurable.

* lisp/register.el (register-preview-info): New slot.
(register-command-info): Add new methods for copy-to-register,
point-to-register, number-to-register,
window-configuration-to-register, frameset-to-register and
copy-rectangle-to-register.
(register-read-with-preview): Bind noconfirm.
---
 lisp/register.el | 67 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index fa4bbcf483f..cc4770579ee 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -156,7 +156,7 @@ TYPES are the types of register supported.
 MSG is the minibuffer message to send when a register is selected.
 ACT is the type of action the command is doing on register.
 SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
   "Returns a `register-preview-info' object storing data for COMMAND."
@@ -179,24 +179,66 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
@@ -328,12 +370,13 @@ display such a window regardless."
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result timer act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -400,13 +443,15 @@ display such a window regardless."
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
                               (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs) (memq act '(set modify)))
+                                (if (and (member pat strs)
+                                         (memq act '(set modify))
+                                         (null noconfirm))
                                     (with-selected-window (minibuffer-window)
                                       (minibuffer-message msg pat))
-                                  ;; An empty register or an existing
-                                  ;; one but the action is insert or
-                                  ;; jump, don't ask for confirmation
-                                  ;; and exit immediately (bug#66394).
+                                  ;; The action is insert or
+                                  ;; jump or noconfirm is specifed
+                                  ;; explicitely, don't ask for
+                                  ;; confirmation and exit immediately (bug#66394).
                                   (setq result pat)
                                   (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Provide-emacs-29-behavior-for-register-preview.patch --]
[-- Type: text/x-diff, Size: 12216 bytes --]

From 31effd1956d78810bd197abd746b84a48474911d Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Tue, 12 Dec 2023 07:24:32 +0100
Subject: [PATCH 2/4] Provide emacs-29 behavior for register-preview

It is now the default with a value of register-use-preview eq to
basic.
To change this one have now to customize register-use-preview to
another value.

* lisp/register.el (register-preview-delay): Remove obsolescence.
(register--read-with-preview-function): New.
(register-use-preview): New option basic, it is now the default.
(register-preview-default-1): New the register-preview-default used by
`register-read-with-preview-fancy`.
(register-preview-default): Restored (same as Emacs-29).
(register--preview-function): Generic fn that return the right
function for register--preview-function.
(register-preview): Restored (same behavior as Emacs-29).
(register-preview-1): Used by `register-read-with-preview-fancy'.
(register-read-with-preview-basic): The old
register-read-with-preview.
(register-read-with-preview-fancy): The new
register-read-with-preview.
---
 lisp/register.el | 156 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 132 insertions(+), 24 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index cc4770579ee..1ef6189682e 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -100,25 +100,55 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
-  "Whether to show preview of registers.
-
-If the value is t, show a preview buffer with navigation and highlighting.
-If the value is nil, show a basic preview buffer and exit minibuffer
-immediately after the register name is inserted into minibuffer.
-If the value is \\='never, behave as for nil, but with no preview buffer
-at all."
+  :type '(repeat string)
+  :version 30.1)
+
+(defvar register--read-with-preview-function nil
+  "The register read preview function to use.
+Two functions are provided, one that provide navigation and
+highlighting of the register selected, filtering of register
+according to command in use, defaults register to use when
+setting a new register, confirmation and notification when you
+are about to overwrite a register and generic functions to
+configure how each existing commands behave.  The other function
+provided is the same as what was used in Emacs-29, no filtering,
+no navigation, no defaults.")
+
+(defvar register-preview-function nil
+  "Function to format a register for previewing.
+Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
+The function should return a string, the description of the argument.
+It is set according to the value of `register--read-with-preview-function'.")
+
+(defcustom register-use-preview 'basic
+  "Maybe show register preview.
+
+This has no effect when `register--read-with-preview-function' value
+is `register-read-with-preview-basic'.
+
+When set to `t' show a preview buffer with navigation and highlighting.
+When nil show a basic preview buffer and exit minibuffer
+immediately after insertion in minibuffer.
+When set to \\='never behave as above but with no preview buffer at
+all.
+When set to \\='basic provide a much more basic preview according to
+`register-preview-delay', it has the exact same behavior as in Emacs-29."
   :type '(choice
           (const :tag "Use preview" t)
           (const :tag "Use quick preview" nil)
-          (const :tag "Never use preview" never))
-  :version "30.1")
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" basic))
+  :version 30.1
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'basic)
+                   #'register-read-with-preview-basic
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -138,17 +168,28 @@ See the documentation of the variable `register-alist' for possible VALUEs."
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
+(defun register-preview-default-1 (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
 	  (propertize (string (car r))
                       'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
-  "Function to format a register for previewing.
-Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+(defun register-preview-default (r)
+  "Function that is the default value of the variable `register-preview-function'."
+  (format "%s: %s\n"
+	  (single-key-description (car r))
+	  (register-describe-oneline (car r))))
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Returns a function to format a register for previewing.
+This according to the value of READ-PREVIEW-FUNCTION.")
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql register-read-with-preview-basic)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
@@ -310,9 +351,9 @@ satisfy `cl-typep' otherwise the new type should be defined with
 (cl-defmethod register--type ((_regval string)) 'string)
 (cl-defmethod register--type ((_regval number)) 'number)
 (cl-defmethod register--type ((_regval marker)) 'marker)
-(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer)
-(cl-defmethod register--type ((_regval (eql 'file))) 'file)
-(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query)
+(cl-defmethod register--type ((_regval (eql buffer))) 'buffer)
+(cl-defmethod register--type ((_regval (eql file))) 'file)
+(cl-defmethod register--type ((_regval (eql file-query))) 'file-query)
 (cl-defmethod register--type ((_regval window-configuration)) 'window)
 (cl-deftype frame-register () '(satisfies frameset-register-p))
 (cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
@@ -327,12 +368,39 @@ satisfy `cl-typep' otherwise the new type should be defined with
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
   "Pop up a window showing the registers preview in BUFFER.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
+Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
+
+(defun register-preview-1 (buffer &optional show-empty types)
+  "Pop up a window showing the registers preview in BUFFER.
+
+This is the preview function use with
+`register-read-with-preview-fancy' function.
+If SHOW-EMPTY is non-nil, show the window even if no registers.
 Argument TYPES (a list) specify the types of register to show, when nil show all
 registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
@@ -360,6 +428,46 @@ Format of each entry is controlled by the variable `register-preview-function'."
   "Read and return a register name, possibly showing existing registers.
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-basic (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
+    (unwind-protect
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.
+If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
          (buffer1 "*Register quick preview*")
@@ -392,13 +500,13 @@ display such a window regardless."
                        ;; Do nothing when buffer1 is in use.
                        (unless (get-buffer-window buf)
                          (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+                           (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
     (unless (or executing-kbd-macro (eq register-use-preview 'never))
-      (register-preview buf nil types))
+      (register-preview-1 buf nil types))
     (unwind-protect
          (progn
            (minibuffer-with-setup-hook
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.4: 0003-Save-and-restore-win-confs-after-register-commands.patch --]
[-- Type: text/x-diff, Size: 1381 bytes --]

From 8d81687b7e58ae9e36a2a405f98976b05aaffe28 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 14 Dec 2023 16:23:26 +0100
Subject: [PATCH 3/4] Save and restore win confs after register commands

When several windows are open, the register preview may eat other
windows and break the current window configuration.

* lisp/register.el (register-read-with-preview-fancy): Do it.
---
 lisp/register.el | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lisp/register.el b/lisp/register.el
index 1ef6189682e..43dad90778c 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -473,6 +473,7 @@ display such a window regardless."
          (buffer1 "*Register quick preview*")
          (buf (if register-use-preview buffer buffer1))
          (pat "")
+         (winconf (current-window-configuration))
          (map (let ((m (make-sparse-keymap)))
                 (set-keymap-parent m minibuffer-local-map)
                 m))
@@ -568,6 +569,7 @@ display such a window regardless."
                       nil "No register specified")
            (string-to-char result))
       (when timer (cancel-timer timer))
+      (set-window-configuration winconf)
       (let ((w (get-buffer-window buf)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buf) (kill-buffer buf)))))
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.5: 0004-Fix-register-commands-in-kmacros.patch --]
[-- Type: text/x-diff, Size: 1742 bytes --]

From 382feaaa808946cde7fc3aa4fa20520e009fcaf3 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Fri, 15 Dec 2023 06:41:46 +0100
Subject: [PATCH 4/4] Fix register commands in kmacros

When register-use-preview is nil we are exiting minibuffer with no
confirmation after an idle delay.  This cause a problem when executing
kmacros because the commands in macro that should run outside the
minibuffer run inside the minibuffer and BTW have no effect in current
buffer.

By using a preview fn that is not delayed we exit immediately with no
delay and the commands are executed in the good order and in the main
buffer.

* lisp/register.el (register-read-with-preview): Use basic fn while
executing kmacros.
---
 lisp/register.el | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lisp/register.el b/lisp/register.el
index 43dad90778c..15ed5c0a53b 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -429,7 +429,12 @@ Format of each entry is controlled by the variable `register-preview-function'."
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
-  (funcall register--read-with-preview-function prompt))
+  (let ((register--read-with-preview-function
+         (if (and executing-kbd-macro
+                  (memq register-use-preview '(nil never)))
+             #'register-read-with-preview-basic
+           (default-value 'register--read-with-preview-function))))
+    (funcall register--read-with-preview-function prompt)))
 
 (defun register-read-with-preview-basic (prompt)
   "Read and return a register name, possibly showing existing registers.
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-15 14:45                                                                                 ` Thierry Volpiatto
@ 2023-12-15 15:18                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-15 18:36                                                                                     ` Thierry Volpiatto
  2023-12-16 15:07                                                                                   ` Dmitry Gutov
  1 sibling, 1 reply; 121+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-15 15:18 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

> @@ -429,7 +429,12 @@ Format of each entry is controlled by the variable `register-preview-function'."
>  Prompt with the string PROMPT.
>  If `help-char' (or a member of `help-event-list') is pressed,
>  display such a window regardless."
> -  (funcall register--read-with-preview-function prompt))
> +  (let ((register--read-with-preview-function
> +         (if (and executing-kbd-macro
> +                  (memq register-use-preview '(nil never)))
> +             #'register-read-with-preview-basic
> +           (default-value 'register--read-with-preview-function))))
> +    (funcall register--read-with-preview-function prompt)))

Questions/comments:

- Why did you change from using
  `register--read-with-preview-function` to using
  (default-value 'register--read-with-preview-function) ?
  [ The answer should presumably be in the commit message but
    I couldn't find it there.  ]

- Why let-bind `register--read-with-preview-function`
  rather than using a local lexical var?
  [ The answer should probably be in a comment in the code.  ]

- Making the behavior dependent on `executing-kbd-macro` is generally
  undesirable, so it should be accompanied with a comment in the code
  explaining why we need it (with enough detail that someone
  sufficiently motivated could potentially "fix" the code to remove this
  dependency, or alternatively to convince that someone else that this
  dependency is actually desirable here).


-- Stefan






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-15 15:18                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-15 18:36                                                                                     ` Thierry Volpiatto
  2023-12-15 23:30                                                                                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-15 18:36 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

[-- Attachment #1: Type: text/plain, Size: 3938 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> @@ -429,7 +429,12 @@ Format of each entry is controlled by the variable `register-preview-function'."
>>  Prompt with the string PROMPT.
>>  If `help-char' (or a member of `help-event-list') is pressed,
>>  display such a window regardless."
>> -  (funcall register--read-with-preview-function prompt))
>> +  (let ((register--read-with-preview-function
>> +         (if (and executing-kbd-macro
>> +                  (memq register-use-preview '(nil never)))
>> +             #'register-read-with-preview-basic
>> +           (default-value 'register--read-with-preview-function))))
>> +    (funcall register--read-with-preview-function prompt)))
>
> Questions/comments:
>
> - Why did you change from using
>   `register--read-with-preview-function` to using
>   (default-value 'register--read-with-preview-function) ?
>   [ The answer should presumably be in the commit message but
>     I couldn't find it there.  ]
>
> - Why let-bind `register--read-with-preview-function`
>   rather than using a local lexical var?
>   [ The answer should probably be in a comment in the code.  ]

To answer to your 1) and 2) questions, I guess what you
suggest is something like this (indeed better):

    diff --git a/lisp/register.el b/lisp/register.el
    index 15ed5c0a53b..2444f88794e 100644
    --- a/lisp/register.el
    +++ b/lisp/register.el
    @@ -429,12 +429,11 @@ Format of each entry is controlled by the variable `register-preview-function'."
     Prompt with the string PROMPT.
     If `help-char' (or a member of `help-event-list') is pressed,
     display such a window regardless."
    -  (let ((register--read-with-preview-function
    -         (if (and executing-kbd-macro
    -                  (memq register-use-preview '(nil never)))
    -             #'register-read-with-preview-basic
    -           (default-value 'register--read-with-preview-function))))
    -    (funcall register--read-with-preview-function prompt)))
    +  (let ((fn (if (and executing-kbd-macro
    +                     (memq register-use-preview '(nil never)))
    +                #'register-read-with-preview-basic
    +              register--read-with-preview-function)))
    +    (funcall fn prompt)))
     
     (defun register-read-with-preview-basic (prompt)
       "Read and return a register name, possibly showing existing registers.

> - Making the behavior dependent on `executing-kbd-macro` is generally
>   undesirable, so it should be accompanied with a comment in the code
>   explaining why we need it (with enough detail that someone
>   sufficiently motivated could potentially "fix" the code to remove this
>   dependency, or alternatively to convince that someone else that this
>   dependency is actually desirable here).

The explanation is in the commit message. To resume, when we are not
using RET to exit minibuffer, we use `exit-minibuffer` from the timer
function in minibuffer-setup-hook, BTW when you have a macro using
e.g. "C-x r i, C-n, C-a, C-x r +", "C-n and C-a" are running
immediately BEFORE the minibuffer is exited so they run in minibuffer
and have no effect in your macro that run in current-buffer.
Is such a comment sufficiently explicit? (will add in next patch if so).

If you have a better fix for this I take ;-).

The problem with such a fix (as I did) is that we can't have an hybrid
version of preview i.e. one that use RET to confirm overwrite and no RET
for other things.
For example if one add a configuration like below to modify behavior
with *-use-preview == nil the macro will fail to execute properly. 

(cl-defmethod register-command-info ((_command (eql increment-register)))
  (make-register-preview-info
   :types '(all)
   :msg "Increment to register `%s'"
   :act 'set
   :noconfirm nil))


Thanks Stefan for reviewing this.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-15 18:36                                                                                     ` Thierry Volpiatto
@ 2023-12-15 23:30                                                                                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-16 13:18                                                                                         ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-15 23:30 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

>> - Why did you change from using
>>   `register--read-with-preview-function` to using
>>   (default-value 'register--read-with-preview-function) ?
>>   [ The answer should presumably be in the commit message but
>>     I couldn't find it there.  ]
>>
>> - Why let-bind `register--read-with-preview-function`
>>   rather than using a local lexical var?
>>   [ The answer should probably be in a comment in the code.  ]
>
> To answer to your 1) and 2) questions, I guess what you
> suggest is something like this (indeed better):
>
>     diff --git a/lisp/register.el b/lisp/register.el
>     index 15ed5c0a53b..2444f88794e 100644
>     --- a/lisp/register.el
>     +++ b/lisp/register.el
>     @@ -429,12 +429,11 @@ Format of each entry is controlled by the variable `register-preview-function'."
>      Prompt with the string PROMPT.
>      If `help-char' (or a member of `help-event-list') is pressed,
>      display such a window regardless."
>     -  (let ((register--read-with-preview-function
>     -         (if (and executing-kbd-macro
>     -                  (memq register-use-preview '(nil never)))
>     -             #'register-read-with-preview-basic
>     -           (default-value 'register--read-with-preview-function))))
>     -    (funcall register--read-with-preview-function prompt)))
>     +  (let ((fn (if (and executing-kbd-macro
>     +                     (memq register-use-preview '(nil never)))
>     +                #'register-read-with-preview-basic
>     +              register--read-with-preview-function)))
>     +    (funcall fn prompt)))
>      
>      (defun register-read-with-preview-basic (prompt)
>        "Read and return a register name, possibly showing existing registers.

LGTM, thanks.

>> - Making the behavior dependent on `executing-kbd-macro` is generally
>>   undesirable, so it should be accompanied with a comment in the code
>>   explaining why we need it (with enough detail that someone
>>   sufficiently motivated could potentially "fix" the code to remove this
>>   dependency, or alternatively to convince that someone else that this
>>   dependency is actually desirable here).
>
> The explanation is in the commit message.

Then please move it into a comment in the code.

> To resume, when we are not
> using RET to exit minibuffer, we use `exit-minibuffer` from the timer
> function in minibuffer-setup-hook, BTW when you have a macro using
> e.g. "C-x r i, C-n, C-a, C-x r +", "C-n and C-a" are running
> immediately BEFORE the minibuffer is exited so they run in minibuffer
> and have no effect in your macro that run in current-buffer.
> Is such a comment sufficiently explicit? (will add in next patch if so).

Sounds good, yes.

> If you have a better fix for this I take ;-).

I haven't looked enough at the code to have a better suggestion.
From what I see the only way to have a "better fix" would be to forego
the use of asynchronous code (i.e. of a timer).  I don't know why you're
using a timer, but usually people don't use timer just because they're
pretty, so I assume you've considered other options already (such as
using an `after-change-function` or a `post-command-hook` instead of
a timer).

[ FWIW, I suspect we have a similar problem in `read-key`.
  Maybe that's the reason why people refrain from using `read-key`?
  I can't see any comment in `read-key` mentioning that it doesn't work
  in kmacros, but indeed it uses a timer just like you do, so it
  probably fails in the exact same way.  ]

> The problem with such a fix (as I did) is that we can't have an hybrid
> version of preview i.e. one that use RET to confirm overwrite and no RET
> for other things.
> For example if one add a configuration like below to modify behavior
> with *-use-preview == nil the macro will fail to execute properly.

You might want to add a short hint about that problem in the comment.

> Thanks Stefan for reviewing this.

I looked only at the kmacro part (because I thought maybe it had to do
with kmacro's use of OClosures), sorry.


        Stefan






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-15 23:30                                                                                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-16 13:18                                                                                         ` Thierry Volpiatto
  2023-12-16 15:31                                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-16 13:18 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

[-- Attachment #1: Type: text/plain, Size: 4536 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>>> - Why did you change from using
>>>   `register--read-with-preview-function` to using
>>>   (default-value 'register--read-with-preview-function) ?
>>>   [ The answer should presumably be in the commit message but
>>>     I couldn't find it there.  ]
>>>
>>> - Why let-bind `register--read-with-preview-function`
>>>   rather than using a local lexical var?
>>>   [ The answer should probably be in a comment in the code.  ]
>>
>> To answer to your 1) and 2) questions, I guess what you
>> suggest is something like this (indeed better):
>>
>>     diff --git a/lisp/register.el b/lisp/register.el
>>     index 15ed5c0a53b..2444f88794e 100644
>>     --- a/lisp/register.el
>>     +++ b/lisp/register.el
>>     @@ -429,12 +429,11 @@ Format of each entry is controlled by the variable `register-preview-function'."
>>      Prompt with the string PROMPT.
>>      If `help-char' (or a member of `help-event-list') is pressed,
>>      display such a window regardless."
>>     -  (let ((register--read-with-preview-function
>>     -         (if (and executing-kbd-macro
>>     -                  (memq register-use-preview '(nil never)))
>>     -             #'register-read-with-preview-basic
>>     -           (default-value 'register--read-with-preview-function))))
>>     -    (funcall register--read-with-preview-function prompt)))
>>     +  (let ((fn (if (and executing-kbd-macro
>>     +                     (memq register-use-preview '(nil never)))
>>     +                #'register-read-with-preview-basic
>>     +              register--read-with-preview-function)))
>>     +    (funcall fn prompt)))
>>      
>>      (defun register-read-with-preview-basic (prompt)
>>        "Read and return a register name, possibly showing existing registers.
>
> LGTM, thanks.
>
>>> - Making the behavior dependent on `executing-kbd-macro` is generally
>>>   undesirable, so it should be accompanied with a comment in the code
>>>   explaining why we need it (with enough detail that someone
>>>   sufficiently motivated could potentially "fix" the code to remove this
>>>   dependency, or alternatively to convince that someone else that this
>>>   dependency is actually desirable here).
>>
>> The explanation is in the commit message.
>
> Then please move it into a comment in the code.

Done.

>> To resume, when we are not
>> using RET to exit minibuffer, we use `exit-minibuffer` from the timer
>> function in minibuffer-setup-hook, BTW when you have a macro using
>> e.g. "C-x r i, C-n, C-a, C-x r +", "C-n and C-a" are running
>> immediately BEFORE the minibuffer is exited so they run in minibuffer
>> and have no effect in your macro that run in current-buffer.
>> Is such a comment sufficiently explicit? (will add in next patch if so).
>
> Sounds good, yes.
>
>> If you have a better fix for this I take ;-).
>
> I haven't looked enough at the code to have a better suggestion.
> From what I see the only way to have a "better fix" would be to forego
> the use of asynchronous code (i.e. of a timer).  I don't know why you're
> using a timer, but usually people don't use timer just because they're
> pretty, so I assume you've considered other options already (such as
> using an `after-change-function` or a `post-command-hook` instead of
> a timer).

It should be possible to use post-command-hook, I didn't use it because
it makes harder the communication between the minibuffer and the preview
buffer.


> [ FWIW, I suspect we have a similar problem in `read-key`.
>   Maybe that's the reason why people refrain from using `read-key`?
>   I can't see any comment in `read-key` mentioning that it doesn't work
>   in kmacros, but indeed it uses a timer just like you do, so it
>   probably fails in the exact same way.  ]
>
>> The problem with such a fix (as I did) is that we can't have an hybrid
>> version of preview i.e. one that use RET to confirm overwrite and no RET
>> for other things.
>> For example if one add a configuration like below to modify behavior
>> with *-use-preview == nil the macro will fail to execute properly.
>
> You might want to add a short hint about that problem in the comment.

Ok, will add this in next patch.

>> Thanks Stefan for reviewing this.
>
> I looked only at the kmacro part (because I thought maybe it had to do
> with kmacro's use of OClosures), sorry.

Anyway your comments were useful, as always, thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-15 14:45                                                                                 ` Thierry Volpiatto
  2023-12-15 15:18                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-16 15:07                                                                                   ` Dmitry Gutov
  2023-12-16 20:20                                                                                     ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Dmitry Gutov @ 2023-12-16 15:07 UTC (permalink / raw)
  To: Thierry Volpiatto, Stefan Kangas
  Cc: michael_heerdegen, Eli Zaretskii, Stefan Monnier, 66394

On 15/12/2023 16:45, Thierry Volpiatto wrote:
> In these patches (attached) I also fixed the problem of Dmitri with windows
> configuration (let me know if it works), BTW I guess this bug was
> already here before these changes.

My bad: it is indeed present in Emacs 29 as well.

It's still there in the new patches (just tested a couple of times), but 
since it's not a regression, it might not be your problem to handle.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-16 13:18                                                                                         ` Thierry Volpiatto
@ 2023-12-16 15:31                                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-16 20:39                                                                                             ` Thierry Volpiatto
  2023-12-19 17:40                                                                                             ` Thierry Volpiatto
  0 siblings, 2 replies; 121+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-16 15:31 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

> It should be possible to use post-command-hook, I didn't use it because
> it makes harder the communication between the minibuffer and the preview
> buffer.

The patch below seems to work for my extremely limited testing.


        Stefan


diff --git a/lisp/register.el b/lisp/register.el
index fa4bbcf483f..31466a42b0a 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -328,7 +328,7 @@ register-read-with-preview
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result act win strs smatch)
     (if data
         (setq types  (register-preview-info-types data)
               msg    (register-preview-info-msg   data)
@@ -360,9 +360,7 @@ register-read-with-preview
          (progn
            (minibuffer-with-setup-hook
                (lambda ()
-                 (setq timer
-                       (run-with-idle-timer
-                        0.01 'repeat
+                 (add-hook 'post-command-hook
                         (lambda ()
                           (with-selected-window (minibuffer-window)
                             (let ((input (minibuffer-contents)))
@@ -408,13 +406,13 @@ register-read-with-preview
                                   ;; jump, don't ask for confirmation
                                   ;; and exit immediately (bug#66394).
                                   (setq result pat)
-                                  (exit-minibuffer)))))))))
+                                  (exit-minibuffer))))))
+                        nil 'local))
              (setq result (read-from-minibuffer
                            prompt nil map nil nil (register-preview-get-defaults act))))
            (cl-assert (and result (not (string= result "")))
                       nil "No register specified")
            (string-to-char result))
-      (when timer (cancel-timer timer))
       (let ((w (get-buffer-window buf)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buf) (kill-buffer buf)))))






^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-16 15:07                                                                                   ` Dmitry Gutov
@ 2023-12-16 20:20                                                                                     ` Thierry Volpiatto
  2023-12-16 23:28                                                                                       ` Dmitry Gutov
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-16 20:20 UTC (permalink / raw)
  To: Dmitry Gutov
  Cc: michael_heerdegen, Eli Zaretskii, 66394, Stefan Kangas,
	Stefan Monnier

[-- Attachment #1: Type: text/plain, Size: 708 bytes --]

Dmitry Gutov <dmitry@gutov.dev> writes:

> On 15/12/2023 16:45, Thierry Volpiatto wrote:
>> In these patches (attached) I also fixed the problem of Dmitri with windows
>> configuration (let me know if it works), BTW I guess this bug was
>> already here before these changes.
>
> My bad: it is indeed present in Emacs 29 as well.
>
> It's still there in the new patches (just tested a couple of times),

Really? I tested it from emacs -Q with your recipe and it was working.
Hmm, I will try again as soon as possible.

> but since it's not a regression, it might not be your problem to
> handle.

Yes indeed, but while we are at it, if we can fix it it is better.

Thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-16 15:31                                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-16 20:39                                                                                             ` Thierry Volpiatto
  2023-12-17 23:20                                                                                               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-19 17:40                                                                                             ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-16 20:39 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394


[-- Attachment #1.1: Type: text/plain, Size: 504 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> It should be possible to use post-command-hook, I didn't use it because
>> it makes harder the communication between the minibuffer and the preview
>> buffer.
>
> The patch below seems to work for my extremely limited testing.

Here the serie of patches with your patch included.
Let me know if the commit is incorrect (patch 0004).
I will test this extensively next week, too tired now to do something
useful.

Thanks.

-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch --]
[-- Type: text/x-diff, Size: 6553 bytes --]

From f28f38f51af62325213bdf7c9e85ee031b405f4c Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 07:02:40 +0100
Subject: [PATCH 1/4] Don't confirm with RET even when overwriting in register
 commands

This happen when register-use-preview is nil or never.
This reproduce what we had previously in 29.1 but with filtering in
the preview and default registers are provided for the commands of
type 'set'.

This is implemented with cl-defmethod to keep the code as much as
possible configurable.

* lisp/register.el (register-preview-info): New slot.
(register-command-info): Add new methods for copy-to-register,
point-to-register, number-to-register,
window-configuration-to-register, frameset-to-register and
copy-rectangle-to-register.
(register-read-with-preview): Bind noconfirm.
---
 lisp/register.el | 67 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index ef529cd67e5..cd6f2861315 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -156,7 +156,7 @@ TYPES are the types of register supported.
 MSG is the minibuffer message to send when a register is selected.
 ACT is the type of action the command is doing on register.
 SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
   "Returns a `register-preview-info' object storing data for COMMAND."
@@ -179,24 +179,66 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
@@ -328,12 +370,13 @@ display such a window regardless."
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result timer act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -405,13 +448,15 @@ display such a window regardless."
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
                               (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs) (memq act '(set modify)))
+                                (if (and (member pat strs)
+                                         (memq act '(set modify))
+                                         (null noconfirm))
                                     (with-selected-window (minibuffer-window)
                                       (minibuffer-message msg pat))
-                                  ;; An empty register or an existing
-                                  ;; one but the action is insert or
-                                  ;; jump, don't ask for confirmation
-                                  ;; and exit immediately (bug#66394).
+                                  ;; The action is insert or
+                                  ;; jump or noconfirm is specifed
+                                  ;; explicitely, don't ask for
+                                  ;; confirmation and exit immediately (bug#66394).
                                   (setq result pat)
                                   (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Provide-emacs-29-behavior-for-register-preview.patch --]
[-- Type: text/x-diff, Size: 12216 bytes --]

From 99cb6d4d1e85b85a60e26ddc22a54a0a9b029d43 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Tue, 12 Dec 2023 07:24:32 +0100
Subject: [PATCH 2/4] Provide emacs-29 behavior for register-preview

It is now the default with a value of register-use-preview eq to
basic.
To change this one have now to customize register-use-preview to
another value.

* lisp/register.el (register-preview-delay): Remove obsolescence.
(register--read-with-preview-function): New.
(register-use-preview): New option basic, it is now the default.
(register-preview-default-1): New the register-preview-default used by
`register-read-with-preview-fancy`.
(register-preview-default): Restored (same as Emacs-29).
(register--preview-function): Generic fn that return the right
function for register--preview-function.
(register-preview): Restored (same behavior as Emacs-29).
(register-preview-1): Used by `register-read-with-preview-fancy'.
(register-read-with-preview-basic): The old
register-read-with-preview.
(register-read-with-preview-fancy): The new
register-read-with-preview.
---
 lisp/register.el | 156 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 132 insertions(+), 24 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index cd6f2861315..8f0c6a7105d 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -100,25 +100,55 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
-  "Whether to show preview of registers.
-
-If the value is t, show a preview buffer with navigation and highlighting.
-If the value is nil, show a basic preview buffer and exit minibuffer
-immediately after the register name is inserted into minibuffer.
-If the value is \\='never, behave as for nil, but with no preview buffer
-at all."
+  :type '(repeat string)
+  :version 30.1)
+
+(defvar register--read-with-preview-function nil
+  "The register read preview function to use.
+Two functions are provided, one that provide navigation and
+highlighting of the register selected, filtering of register
+according to command in use, defaults register to use when
+setting a new register, confirmation and notification when you
+are about to overwrite a register and generic functions to
+configure how each existing commands behave.  The other function
+provided is the same as what was used in Emacs-29, no filtering,
+no navigation, no defaults.")
+
+(defvar register-preview-function nil
+  "Function to format a register for previewing.
+Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
+The function should return a string, the description of the argument.
+It is set according to the value of `register--read-with-preview-function'.")
+
+(defcustom register-use-preview 'basic
+  "Maybe show register preview.
+
+This has no effect when `register--read-with-preview-function' value
+is `register-read-with-preview-basic'.
+
+When set to `t' show a preview buffer with navigation and highlighting.
+When nil show a basic preview buffer and exit minibuffer
+immediately after insertion in minibuffer.
+When set to \\='never behave as above but with no preview buffer at
+all.
+When set to \\='basic provide a much more basic preview according to
+`register-preview-delay', it has the exact same behavior as in Emacs-29."
   :type '(choice
           (const :tag "Use preview" t)
           (const :tag "Use quick preview" nil)
-          (const :tag "Never use preview" never))
-  :version "30.1")
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" basic))
+  :version 30.1
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'basic)
+                   #'register-read-with-preview-basic
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -138,17 +168,28 @@ See the documentation of the variable `register-alist' for possible VALUEs."
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
+(defun register-preview-default-1 (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
 	  (propertize (string (car r))
                       'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
-  "Function to format a register for previewing.
-Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+(defun register-preview-default (r)
+  "Function that is the default value of the variable `register-preview-function'."
+  (format "%s: %s\n"
+	  (single-key-description (car r))
+	  (register-describe-oneline (car r))))
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Returns a function to format a register for previewing.
+This according to the value of READ-PREVIEW-FUNCTION.")
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql register-read-with-preview-basic)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
@@ -310,9 +351,9 @@ satisfy `cl-typep' otherwise the new type should be defined with
 (cl-defmethod register--type ((_regval string)) 'string)
 (cl-defmethod register--type ((_regval number)) 'number)
 (cl-defmethod register--type ((_regval marker)) 'marker)
-(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer)
-(cl-defmethod register--type ((_regval (eql 'file))) 'file)
-(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query)
+(cl-defmethod register--type ((_regval (eql buffer))) 'buffer)
+(cl-defmethod register--type ((_regval (eql file))) 'file)
+(cl-defmethod register--type ((_regval (eql file-query))) 'file-query)
 (cl-defmethod register--type ((_regval window-configuration)) 'window)
 (cl-deftype frame-register () '(satisfies frameset-register-p))
 (cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
@@ -327,12 +368,39 @@ satisfy `cl-typep' otherwise the new type should be defined with
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
   "Pop up a window showing the registers preview in BUFFER.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
+Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
+
+(defun register-preview-1 (buffer &optional show-empty types)
+  "Pop up a window showing the registers preview in BUFFER.
+
+This is the preview function use with
+`register-read-with-preview-fancy' function.
+If SHOW-EMPTY is non-nil, show the window even if no registers.
 Argument TYPES (a list) specify the types of register to show, when nil show all
 registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
@@ -360,6 +428,46 @@ Format of each entry is controlled by the variable `register-preview-function'."
   "Read and return a register name, possibly showing existing registers.
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-basic (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
+    (unwind-protect
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.
+If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
          (buffer1 "*Register quick preview*")
@@ -392,13 +500,13 @@ display such a window regardless."
                        ;; Do nothing when buffer1 is in use.
                        (unless (get-buffer-window buf)
                          (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+                           (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
     (unless (or executing-kbd-macro (eq register-use-preview 'never))
-      (register-preview buf nil types))
+      (register-preview-1 buf nil types))
     (unwind-protect
          (progn
            (minibuffer-with-setup-hook
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.4: 0003-Save-and-restore-win-confs-after-register-commands.patch --]
[-- Type: text/x-diff, Size: 1381 bytes --]

From 6a15a8b7b795b8377ef3537dc7bbd5ba26c0e159 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Thu, 14 Dec 2023 16:23:26 +0100
Subject: [PATCH 3/4] Save and restore win confs after register commands

When several windows are open, the register preview may eat other
windows and break the current window configuration.

* lisp/register.el (register-read-with-preview-fancy): Do it.
---
 lisp/register.el | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lisp/register.el b/lisp/register.el
index 8f0c6a7105d..1fadbe81056 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -473,6 +473,7 @@ display such a window regardless."
          (buffer1 "*Register quick preview*")
          (buf (if register-use-preview buffer buffer1))
          (pat "")
+         (winconf (current-window-configuration))
          (map (let ((m (make-sparse-keymap)))
                 (set-keymap-parent m minibuffer-local-map)
                 m))
@@ -573,6 +574,7 @@ display such a window regardless."
                       nil "No register specified")
            (string-to-char result))
       (when timer (cancel-timer timer))
+      (set-window-configuration winconf)
       (let ((w (get-buffer-window buf)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buf) (kill-buffer buf)))))
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.5: 0004-Fix-issue-with-register-commands-in-kmacro.patch --]
[-- Type: text/x-diff, Size: 8797 bytes --]

From 84dac0537fb033c51f86c6920f2cc6b086632331 Mon Sep 17 00:00:00 2001
From: Stefan Monnier <monnier@iro.umontreal.ca>
Date: Sat, 16 Dec 2023 21:25:08 +0100
Subject: [PATCH 4/4] Fix issue with register commands in kmacro

Using post-command-hook in minibuffer-setup-hook instead of a timer
allow running exit-minibuffer without delay and ensure the serie of
commands used in a kmacro run synchronously.

* lisp/register.el (register-read-with-preview-fancy): Do it.
---
 lisp/register.el | 112 +++++++++++++++++++++++------------------------
 1 file changed, 55 insertions(+), 57 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index 1fadbe81056..8dffb301c0e 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -512,68 +512,66 @@ display such a window regardless."
          (progn
            (minibuffer-with-setup-hook
                (lambda ()
-                 (setq timer
-                       (run-with-idle-timer
-                        0.01 'repeat
-                        (lambda ()
-                          (with-selected-window (minibuffer-window)
-                            (let ((input (minibuffer-contents)))
-                              (when (> (length input) 1)
-                                (let ((new (substring input 1))
-                                      (old (substring input 0 1)))
-                                  (setq input (if (or (null smatch)
-                                                      (member new strs))
-                                                  new old))
-                                  (delete-minibuffer-contents)
-                                  (insert input)))
-                              (when (and smatch (not (string= input ""))
-                                         (not (member input strs)))
-                                (setq input "")
-                                (delete-minibuffer-contents)
-                                (minibuffer-message "Not matching"))
-                              (when (not (string= input pat))
-                                (setq pat input))))
-                          (if (setq win (get-buffer-window buffer))
-                              (with-selected-window win
-                                (let ((ov (make-overlay
-                                           (point-min) (point-min)))
-                                      ;; Allow upper-case and
-                                      ;; lower-case letters to refer
-                                      ;; to different registers.
-                                      (case-fold-search nil))
-                                  (goto-char (point-min))
-                                  (remove-overlays)
-                                  (unless (string= pat "")
-                                    (if (re-search-forward (concat "^" pat) nil t)
-                                        (progn (move-overlay
-                                                ov
-                                                (match-beginning 0) (pos-eol))
-                                               (overlay-put ov 'face 'match)
-                                               (when msg
-                                                 (with-selected-window (minibuffer-window)
-                                                   (minibuffer-message msg pat))))
-                                      (with-selected-window (minibuffer-window)
-                                        (minibuffer-message
-                                         "Register `%s' is empty" pat))))))
-                            (unless (string= pat "")
-                              (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs)
-                                         (memq act '(set modify))
-                                         (null noconfirm))
-                                    (with-selected-window (minibuffer-window)
-                                      (minibuffer-message msg pat))
-                                  ;; The action is insert or
-                                  ;; jump or noconfirm is specifed
-                                  ;; explicitely, don't ask for
-                                  ;; confirmation and exit immediately (bug#66394).
-                                  (setq result pat)
-                                  (exit-minibuffer)))))))))
+                 (add-hook 'post-command-hook
+                           (lambda ()
+                             (with-selected-window (minibuffer-window)
+                               (let ((input (minibuffer-contents)))
+                                 (when (> (length input) 1)
+                                   (let ((new (substring input 1))
+                                         (old (substring input 0 1)))
+                                     (setq input (if (or (null smatch)
+                                                         (member new strs))
+                                                     new old))
+                                     (delete-minibuffer-contents)
+                                     (insert input)))
+                                 (when (and smatch (not (string= input ""))
+                                            (not (member input strs)))
+                                   (setq input "")
+                                   (delete-minibuffer-contents)
+                                   (minibuffer-message "Not matching"))
+                                 (when (not (string= input pat))
+                                   (setq pat input))))
+                             (if (setq win (get-buffer-window buffer))
+                                 (with-selected-window win
+                                   (let ((ov (make-overlay
+                                              (point-min) (point-min)))
+                                         ;; Allow upper-case and
+                                         ;; lower-case letters to refer
+                                         ;; to different registers.
+                                         (case-fold-search nil))
+                                     (goto-char (point-min))
+                                     (remove-overlays)
+                                     (unless (string= pat "")
+                                       (if (re-search-forward (concat "^" pat) nil t)
+                                           (progn (move-overlay
+                                                   ov
+                                                   (match-beginning 0) (pos-eol))
+                                                  (overlay-put ov 'face 'match)
+                                                  (when msg
+                                                    (with-selected-window (minibuffer-window)
+                                                      (minibuffer-message msg pat))))
+                                         (with-selected-window (minibuffer-window)
+                                           (minibuffer-message
+                                            "Register `%s' is empty" pat))))))
+                               (unless (string= pat "")
+                                 (with-selected-window (minibuffer-window)
+                                   (if (and (member pat strs)
+                                            (memq act '(set modify))
+                                            (null noconfirm))
+                                       (with-selected-window (minibuffer-window)
+                                         (minibuffer-message msg pat))
+                                     ;; The action is insert or
+                                     ;; jump or noconfirm is specifed
+                                     ;; explicitely, don't ask for
+                                     ;; confirmation and exit immediately (bug#66394).
+                                     (setq result pat)
+                                     (exit-minibuffer))))))
+                           nil 'local))
              (setq result (read-from-minibuffer
                            prompt nil map nil nil (register-preview-get-defaults act))))
            (cl-assert (and result (not (string= result "")))
                       nil "No register specified")
            (string-to-char result))
-      (when timer (cancel-timer timer))
       (set-window-configuration winconf)
       (let ((w (get-buffer-window buf)))
         (and (window-live-p w) (delete-window w)))
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-16 20:20                                                                                     ` Thierry Volpiatto
@ 2023-12-16 23:28                                                                                       ` Dmitry Gutov
  0 siblings, 0 replies; 121+ messages in thread
From: Dmitry Gutov @ 2023-12-16 23:28 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, Eli Zaretskii, 66394, Stefan Kangas,
	Stefan Monnier

On 16/12/2023 22:20, Thierry Volpiatto wrote:
> Dmitry Gutov<dmitry@gutov.dev>  writes:
> 
>> On 15/12/2023 16:45, Thierry Volpiatto wrote:
>>> In these patches (attached) I also fixed the problem of Dmitri with windows
>>> configuration (let me know if it works), BTW I guess this bug was
>>> already here before these changes.
>> My bad: it is indeed present in Emacs 29 as well.
>>
>> It's still there in the new patches (just tested a couple of times),
> Really? I tested it from emacs -Q with your recipe and it was working.
> Hmm, I will try again as soon as possible.

Thanks.

The problem occurs whenever an existing window is reused to show the 
registers' preview, rather than split.






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-16 20:39                                                                                             ` Thierry Volpiatto
@ 2023-12-17 23:20                                                                                               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-18  5:15                                                                                                 ` Thierry Volpiatto
  2023-12-18  6:18                                                                                                 ` Thierry Volpiatto
  0 siblings, 2 replies; 121+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-17 23:20 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

> From 6a15a8b7b795b8377ef3537dc7bbd5ba26c0e159 Mon Sep 17 00:00:00 2001
> From: Thierry Volpiatto <thievol@posteo.net>
> Date: Thu, 14 Dec 2023 16:23:26 +0100
> Subject: [PATCH 3/4] Save and restore win confs after register commands
>
> When several windows are open, the register preview may eat other
> windows and break the current window configuration.
>
> * lisp/register.el (register-read-with-preview-fancy): Do it.
> ---
>  lisp/register.el | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/lisp/register.el b/lisp/register.el
> index 8f0c6a7105d..1fadbe81056 100644
> --- a/lisp/register.el
> +++ b/lisp/register.el
> @@ -473,6 +473,7 @@ display such a window regardless."
>           (buffer1 "*Register quick preview*")
>           (buf (if register-use-preview buffer buffer1))
>           (pat "")
> +         (winconf (current-window-configuration))
>           (map (let ((m (make-sparse-keymap)))
>                  (set-keymap-parent m minibuffer-local-map)
>                  m))
> @@ -573,6 +574,7 @@ display such a window regardless."
>                        nil "No register specified")
>             (string-to-char result))
>        (when timer (cancel-timer timer))
> +      (set-window-configuration winconf)
>        (let ((w (get-buffer-window buf)))
>          (and (window-live-p w) (delete-window w)))
>        (and (get-buffer buf) (kill-buffer buf)))))

While save&restore of window configuration often works well, it
misbehaves in various cases (such as when the buffer is displayed in
another frame, which case case `set-window-configuration` will do you
no good).

The official way to undo a `display-buffer` is with
`quit-(restore-)window`.  See (info "(elisp)Quitting Windows").


        Stefan






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-17 23:20                                                                                               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-18  5:15                                                                                                 ` Thierry Volpiatto
  2023-12-18 13:20                                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-18  6:18                                                                                                 ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-18  5:15 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

[-- Attachment #1: Type: text/plain, Size: 2887 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> From 6a15a8b7b795b8377ef3537dc7bbd5ba26c0e159 Mon Sep 17 00:00:00 2001
>> From: Thierry Volpiatto <thievol@posteo.net>
>> Date: Thu, 14 Dec 2023 16:23:26 +0100
>> Subject: [PATCH 3/4] Save and restore win confs after register commands
>>
>> When several windows are open, the register preview may eat other
>> windows and break the current window configuration.
>>
>> * lisp/register.el (register-read-with-preview-fancy): Do it.
>> ---
>>  lisp/register.el | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/lisp/register.el b/lisp/register.el
>> index 8f0c6a7105d..1fadbe81056 100644
>> --- a/lisp/register.el
>> +++ b/lisp/register.el
>> @@ -473,6 +473,7 @@ display such a window regardless."
>>           (buffer1 "*Register quick preview*")
>>           (buf (if register-use-preview buffer buffer1))
>>           (pat "")
>> +         (winconf (current-window-configuration))
>>           (map (let ((m (make-sparse-keymap)))
>>                  (set-keymap-parent m minibuffer-local-map)
>>                  m))
>> @@ -573,6 +574,7 @@ display such a window regardless."
>>                        nil "No register specified")
>>             (string-to-char result))
>>        (when timer (cancel-timer timer))
>> +      (set-window-configuration winconf)
>>        (let ((w (get-buffer-window buf)))
>>          (and (window-live-p w) (delete-window w)))
>>        (and (get-buffer buf) (kill-buffer buf)))))
>
> While save&restore of window configuration often works well, it
> misbehaves in various cases (such as when the buffer is displayed in
> another frame, which case case `set-window-configuration` will do you
> no good).

Yes, I thought this would be enough, but no, there is as well another
problem in register-preview and register-preview-1 with this code which
is as well not working well if there is multiple windows.

      (with-current-buffer-window
        buffer
        (cons 'display-buffer-below-selected
	      '((window-height . fit-window-to-buffer)
	        (preserve-size . (nil . t))))

[...]

At least it should use display-buffer-at-bottom, but I guess the best
would be to make this configurable in one way or the other.

>
> The official way to undo a `display-buffer` is with
> `quit-(restore-)window`.  See (info "(elisp)Quitting Windows").

Yes, this is not what the current code is using, see the last unwind
form of register-read-with-preview-basic/fancy.

But as Dmitri said, it is not bugs introduced by these patches, I
thought it would be simple to fix while we were at it but no.  I guess I
will follow Dmitri advice and not fix this in this serie of patches.
Perhaps we could make another bug report once these patches are applied
(I will remove the patch doing save/restore win conf) ?
 
-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-17 23:20                                                                                               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-18  5:15                                                                                                 ` Thierry Volpiatto
@ 2023-12-18  6:18                                                                                                 ` Thierry Volpiatto
  1 sibling, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-18  6:18 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394


[-- Attachment #1.1: Type: text/plain, Size: 500 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> While save&restore of window configuration often works well, it
> misbehaves in various cases (such as when the buffer is displayed in
> another frame, which case case `set-window-configuration` will do you
> no good).
>
> The official way to undo a `display-buffer` is with
> `quit-(restore-)window`.  See (info "(elisp)Quitting Windows").

So here the serie of patches updated (save/restore winconf patch
dropped).


-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch --]
[-- Type: text/x-diff, Size: 6553 bytes --]

From f28f38f51af62325213bdf7c9e85ee031b405f4c Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 07:02:40 +0100
Subject: [PATCH 1/3] Don't confirm with RET even when overwriting in register
 commands

This happen when register-use-preview is nil or never.
This reproduce what we had previously in 29.1 but with filtering in
the preview and default registers are provided for the commands of
type 'set'.

This is implemented with cl-defmethod to keep the code as much as
possible configurable.

* lisp/register.el (register-preview-info): New slot.
(register-command-info): Add new methods for copy-to-register,
point-to-register, number-to-register,
window-configuration-to-register, frameset-to-register and
copy-rectangle-to-register.
(register-read-with-preview): Bind noconfirm.
---
 lisp/register.el | 67 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index ef529cd67e5..cd6f2861315 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -156,7 +156,7 @@ TYPES are the types of register supported.
 MSG is the minibuffer message to send when a register is selected.
 ACT is the type of action the command is doing on register.
 SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
   "Returns a `register-preview-info' object storing data for COMMAND."
@@ -179,24 +179,66 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
@@ -328,12 +370,13 @@ display such a window regardless."
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result timer act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -405,13 +448,15 @@ display such a window regardless."
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
                               (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs) (memq act '(set modify)))
+                                (if (and (member pat strs)
+                                         (memq act '(set modify))
+                                         (null noconfirm))
                                     (with-selected-window (minibuffer-window)
                                       (minibuffer-message msg pat))
-                                  ;; An empty register or an existing
-                                  ;; one but the action is insert or
-                                  ;; jump, don't ask for confirmation
-                                  ;; and exit immediately (bug#66394).
+                                  ;; The action is insert or
+                                  ;; jump or noconfirm is specifed
+                                  ;; explicitely, don't ask for
+                                  ;; confirmation and exit immediately (bug#66394).
                                   (setq result pat)
                                   (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Provide-emacs-29-behavior-for-register-preview.patch --]
[-- Type: text/x-diff, Size: 12216 bytes --]

From 99cb6d4d1e85b85a60e26ddc22a54a0a9b029d43 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Tue, 12 Dec 2023 07:24:32 +0100
Subject: [PATCH 2/3] Provide emacs-29 behavior for register-preview

It is now the default with a value of register-use-preview eq to
basic.
To change this one have now to customize register-use-preview to
another value.

* lisp/register.el (register-preview-delay): Remove obsolescence.
(register--read-with-preview-function): New.
(register-use-preview): New option basic, it is now the default.
(register-preview-default-1): New the register-preview-default used by
`register-read-with-preview-fancy`.
(register-preview-default): Restored (same as Emacs-29).
(register--preview-function): Generic fn that return the right
function for register--preview-function.
(register-preview): Restored (same behavior as Emacs-29).
(register-preview-1): Used by `register-read-with-preview-fancy'.
(register-read-with-preview-basic): The old
register-read-with-preview.
(register-read-with-preview-fancy): The new
register-read-with-preview.
---
 lisp/register.el | 156 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 132 insertions(+), 24 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index cd6f2861315..8f0c6a7105d 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -100,25 +100,55 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
-  "Whether to show preview of registers.
-
-If the value is t, show a preview buffer with navigation and highlighting.
-If the value is nil, show a basic preview buffer and exit minibuffer
-immediately after the register name is inserted into minibuffer.
-If the value is \\='never, behave as for nil, but with no preview buffer
-at all."
+  :type '(repeat string)
+  :version 30.1)
+
+(defvar register--read-with-preview-function nil
+  "The register read preview function to use.
+Two functions are provided, one that provide navigation and
+highlighting of the register selected, filtering of register
+according to command in use, defaults register to use when
+setting a new register, confirmation and notification when you
+are about to overwrite a register and generic functions to
+configure how each existing commands behave.  The other function
+provided is the same as what was used in Emacs-29, no filtering,
+no navigation, no defaults.")
+
+(defvar register-preview-function nil
+  "Function to format a register for previewing.
+Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
+The function should return a string, the description of the argument.
+It is set according to the value of `register--read-with-preview-function'.")
+
+(defcustom register-use-preview 'basic
+  "Maybe show register preview.
+
+This has no effect when `register--read-with-preview-function' value
+is `register-read-with-preview-basic'.
+
+When set to `t' show a preview buffer with navigation and highlighting.
+When nil show a basic preview buffer and exit minibuffer
+immediately after insertion in minibuffer.
+When set to \\='never behave as above but with no preview buffer at
+all.
+When set to \\='basic provide a much more basic preview according to
+`register-preview-delay', it has the exact same behavior as in Emacs-29."
   :type '(choice
           (const :tag "Use preview" t)
           (const :tag "Use quick preview" nil)
-          (const :tag "Never use preview" never))
-  :version "30.1")
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" basic))
+  :version 30.1
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'basic)
+                   #'register-read-with-preview-basic
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -138,17 +168,28 @@ See the documentation of the variable `register-alist' for possible VALUEs."
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
+(defun register-preview-default-1 (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
 	  (propertize (string (car r))
                       'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
-  "Function to format a register for previewing.
-Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+(defun register-preview-default (r)
+  "Function that is the default value of the variable `register-preview-function'."
+  (format "%s: %s\n"
+	  (single-key-description (car r))
+	  (register-describe-oneline (car r))))
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Returns a function to format a register for previewing.
+This according to the value of READ-PREVIEW-FUNCTION.")
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql register-read-with-preview-basic)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
@@ -310,9 +351,9 @@ satisfy `cl-typep' otherwise the new type should be defined with
 (cl-defmethod register--type ((_regval string)) 'string)
 (cl-defmethod register--type ((_regval number)) 'number)
 (cl-defmethod register--type ((_regval marker)) 'marker)
-(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer)
-(cl-defmethod register--type ((_regval (eql 'file))) 'file)
-(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query)
+(cl-defmethod register--type ((_regval (eql buffer))) 'buffer)
+(cl-defmethod register--type ((_regval (eql file))) 'file)
+(cl-defmethod register--type ((_regval (eql file-query))) 'file-query)
 (cl-defmethod register--type ((_regval window-configuration)) 'window)
 (cl-deftype frame-register () '(satisfies frameset-register-p))
 (cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
@@ -327,12 +368,39 @@ satisfy `cl-typep' otherwise the new type should be defined with
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
   "Pop up a window showing the registers preview in BUFFER.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
+Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
+
+(defun register-preview-1 (buffer &optional show-empty types)
+  "Pop up a window showing the registers preview in BUFFER.
+
+This is the preview function use with
+`register-read-with-preview-fancy' function.
+If SHOW-EMPTY is non-nil, show the window even if no registers.
 Argument TYPES (a list) specify the types of register to show, when nil show all
 registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
@@ -360,6 +428,46 @@ Format of each entry is controlled by the variable `register-preview-function'."
   "Read and return a register name, possibly showing existing registers.
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-basic (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
+    (unwind-protect
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.
+If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
          (buffer1 "*Register quick preview*")
@@ -392,13 +500,13 @@ display such a window regardless."
                        ;; Do nothing when buffer1 is in use.
                        (unless (get-buffer-window buf)
                          (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+                           (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
     (unless (or executing-kbd-macro (eq register-use-preview 'never))
-      (register-preview buf nil types))
+      (register-preview-1 buf nil types))
     (unwind-protect
          (progn
            (minibuffer-with-setup-hook
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.4: 0003-Fix-issue-with-register-commands-in-kmacro.patch --]
[-- Type: text/x-diff, Size: 8803 bytes --]

From f1105b7266788a93e03f837db172351b25020964 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 18 Dec 2023 07:11:42 +0100
Subject: [PATCH 3/3] Fix issue with register commands in kmacro

Using post-command-hook in minibuffer-setup-hook instead of a timer
allow running exit-minibuffer without delay and ensure the serie of
commands used in a kmacro run synchronously.

* lisp/register.el (register-read-with-preview-fancy): Do it.
---
 lisp/register.el | 112 +++++++++++++++++++++++------------------------
 1 file changed, 55 insertions(+), 57 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index 8f0c6a7105d..4ffbd460a5b 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -511,68 +511,66 @@ display such a window regardless."
          (progn
            (minibuffer-with-setup-hook
                (lambda ()
-                 (setq timer
-                       (run-with-idle-timer
-                        0.01 'repeat
-                        (lambda ()
-                          (with-selected-window (minibuffer-window)
-                            (let ((input (minibuffer-contents)))
-                              (when (> (length input) 1)
-                                (let ((new (substring input 1))
-                                      (old (substring input 0 1)))
-                                  (setq input (if (or (null smatch)
-                                                      (member new strs))
-                                                  new old))
-                                  (delete-minibuffer-contents)
-                                  (insert input)))
-                              (when (and smatch (not (string= input ""))
-                                         (not (member input strs)))
-                                (setq input "")
-                                (delete-minibuffer-contents)
-                                (minibuffer-message "Not matching"))
-                              (when (not (string= input pat))
-                                (setq pat input))))
-                          (if (setq win (get-buffer-window buffer))
-                              (with-selected-window win
-                                (let ((ov (make-overlay
-                                           (point-min) (point-min)))
-                                      ;; Allow upper-case and
-                                      ;; lower-case letters to refer
-                                      ;; to different registers.
-                                      (case-fold-search nil))
-                                  (goto-char (point-min))
-                                  (remove-overlays)
-                                  (unless (string= pat "")
-                                    (if (re-search-forward (concat "^" pat) nil t)
-                                        (progn (move-overlay
-                                                ov
-                                                (match-beginning 0) (pos-eol))
-                                               (overlay-put ov 'face 'match)
-                                               (when msg
-                                                 (with-selected-window (minibuffer-window)
-                                                   (minibuffer-message msg pat))))
-                                      (with-selected-window (minibuffer-window)
-                                        (minibuffer-message
-                                         "Register `%s' is empty" pat))))))
-                            (unless (string= pat "")
-                              (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs)
-                                         (memq act '(set modify))
-                                         (null noconfirm))
-                                    (with-selected-window (minibuffer-window)
-                                      (minibuffer-message msg pat))
-                                  ;; The action is insert or
-                                  ;; jump or noconfirm is specifed
-                                  ;; explicitely, don't ask for
-                                  ;; confirmation and exit immediately (bug#66394).
-                                  (setq result pat)
-                                  (exit-minibuffer)))))))))
+                 (add-hook 'post-command-hook
+                           (lambda ()
+                             (with-selected-window (minibuffer-window)
+                               (let ((input (minibuffer-contents)))
+                                 (when (> (length input) 1)
+                                   (let ((new (substring input 1))
+                                         (old (substring input 0 1)))
+                                     (setq input (if (or (null smatch)
+                                                         (member new strs))
+                                                     new old))
+                                     (delete-minibuffer-contents)
+                                     (insert input)))
+                                 (when (and smatch (not (string= input ""))
+                                            (not (member input strs)))
+                                   (setq input "")
+                                   (delete-minibuffer-contents)
+                                   (minibuffer-message "Not matching"))
+                                 (when (not (string= input pat))
+                                   (setq pat input))))
+                             (if (setq win (get-buffer-window buffer))
+                                 (with-selected-window win
+                                   (let ((ov (make-overlay
+                                              (point-min) (point-min)))
+                                         ;; Allow upper-case and
+                                         ;; lower-case letters to refer
+                                         ;; to different registers.
+                                         (case-fold-search nil))
+                                     (goto-char (point-min))
+                                     (remove-overlays)
+                                     (unless (string= pat "")
+                                       (if (re-search-forward (concat "^" pat) nil t)
+                                           (progn (move-overlay
+                                                   ov
+                                                   (match-beginning 0) (pos-eol))
+                                                  (overlay-put ov 'face 'match)
+                                                  (when msg
+                                                    (with-selected-window (minibuffer-window)
+                                                      (minibuffer-message msg pat))))
+                                         (with-selected-window (minibuffer-window)
+                                           (minibuffer-message
+                                            "Register `%s' is empty" pat))))))
+                               (unless (string= pat "")
+                                 (with-selected-window (minibuffer-window)
+                                   (if (and (member pat strs)
+                                            (memq act '(set modify))
+                                            (null noconfirm))
+                                       (with-selected-window (minibuffer-window)
+                                         (minibuffer-message msg pat))
+                                     ;; The action is insert or
+                                     ;; jump or noconfirm is specifed
+                                     ;; explicitely, don't ask for
+                                     ;; confirmation and exit immediately (bug#66394).
+                                     (setq result pat)
+                                     (exit-minibuffer))))))
+                           nil 'local))
              (setq result (read-from-minibuffer
                            prompt nil map nil nil (register-preview-get-defaults act))))
            (cl-assert (and result (not (string= result "")))
                       nil "No register specified")
            (string-to-char result))
-      (when timer (cancel-timer timer))
       (let ((w (get-buffer-window buf)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buf) (kill-buffer buf)))))
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-18  5:15                                                                                                 ` Thierry Volpiatto
@ 2023-12-18 13:20                                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-18 18:11                                                                                                     ` Thierry Volpiatto
  2023-12-18 18:22                                                                                                     ` Dmitry Gutov
  0 siblings, 2 replies; 121+ messages in thread
From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-12-18 13:20 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

> But as Dmitri said, it is not bugs introduced by these patches, I
> thought it would be simple to fix while we were at it but no.  I guess I
> will follow Dmitri advice and not fix this in this serie of patches.

Wise choice :-)

> Perhaps we could make another bug report once these patches are applied
> (I will remove the patch doing save/restore win conf) ?

Dmitry, can you do the honors (since you mentioned the bug first)?


        Stefan






^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-18 13:20                                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-12-18 18:11                                                                                                     ` Thierry Volpiatto
  2023-12-18 18:22                                                                                                     ` Dmitry Gutov
  1 sibling, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-18 18:11 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

[-- Attachment #1: Type: text/plain, Size: 479 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> But as Dmitri said, it is not bugs introduced by these patches, I
>> thought it would be simple to fix while we were at it but no.  I guess I
>> will follow Dmitri advice and not fix this in this serie of patches.
>
> Wise choice :-)

When dropping this change while rebasing I didn't realize the author
name of the last patch has changed (from Stefan to Thierry), it is fixed
(git amend) here.
 

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-18 13:20                                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-18 18:11                                                                                                     ` Thierry Volpiatto
@ 2023-12-18 18:22                                                                                                     ` Dmitry Gutov
  1 sibling, 0 replies; 121+ messages in thread
From: Dmitry Gutov @ 2023-12-18 18:22 UTC (permalink / raw)
  To: Stefan Monnier, Thierry Volpiatto
  Cc: michael_heerdegen, Eli Zaretskii, Stefan Kangas, 66394

On 18/12/2023 15:20, Stefan Monnier wrote:
>> But as Dmitri said, it is not bugs introduced by these patches, I
>> thought it would be simple to fix while we were at it but no.  I guess I
>> will follow Dmitri advice and not fix this in this serie of patches.
> Wise choice 😄
> 
>> Perhaps we could make another bug report once these patches are applied
>> (I will remove the patch doing save/restore win conf) ?
> Dmitry, can you do the honors (since you mentioned the bug first)?

No problem: bug#67882.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-16 15:31                                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-12-16 20:39                                                                                             ` Thierry Volpiatto
@ 2023-12-19 17:40                                                                                             ` Thierry Volpiatto
  2023-12-19 17:47                                                                                               ` Thierry Volpiatto
  2023-12-20 12:05                                                                                               ` Eli Zaretskii
  1 sibling, 2 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-19 17:40 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394


[-- Attachment #1.1: Type: text/plain, Size: 1710 bytes --]


Hello Stefan,

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> It should be possible to use post-command-hook, I didn't use it because
>> it makes harder the communication between the minibuffer and the preview
>> buffer.
>
> The patch below seems to work for my extremely limited testing.

Could have some time to test register with your post-command-hook patch.
I had to make on more little change to make it working in all
conditions, here what I tried so far:

1) (customize-set-variable 'register-use-preview t)
We have here confirmation with RET everywhere, works fine in all
commands and test macro.

2) (customize-set-variable 'register-use-preview nil)
We have here no confirmation (RET) at all, works fine in all commands
and test macro.

3) (customize-set-variable 'register-use-preview nil) and modification
with a defmethod so that we have no confirmation in insert/jump and
confirmation with increment-register:

    (cl-defmethod register-command-info ((_command (eql increment-register)))
      (make-register-preview-info
       :types '(all)
       :msg "Increment to register `%s'"
       :act 'set
       :smatch t
       :noconfirm t))

Works fine everywhere and in test macro as well.

4) (customize-set-variable 'register-use-preview 'never)

Same behavior as in 2) and 3) in same conditions.


[The test macro was adding a number at beginning and end of each lines in
a text and increment this number at every turn, this involve
insert-register (twice) and increment-register (once).]

So it seems we have now something working fine in all conditions :-)

Here the serie of patches (the first 3 are unchanged). 


-- 
Thierry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-Don-t-confirm-with-RET-even-when-overwriting-in-regi.patch --]
[-- Type: text/x-diff, Size: 6553 bytes --]

From f28f38f51af62325213bdf7c9e85ee031b405f4c Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Mon, 11 Dec 2023 07:02:40 +0100
Subject: [PATCH 1/4] Don't confirm with RET even when overwriting in register
 commands

This happen when register-use-preview is nil or never.
This reproduce what we had previously in 29.1 but with filtering in
the preview and default registers are provided for the commands of
type 'set'.

This is implemented with cl-defmethod to keep the code as much as
possible configurable.

* lisp/register.el (register-preview-info): New slot.
(register-command-info): Add new methods for copy-to-register,
point-to-register, number-to-register,
window-configuration-to-register, frameset-to-register and
copy-rectangle-to-register.
(register-read-with-preview): Bind noconfirm.
---
 lisp/register.el | 67 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index ef529cd67e5..cd6f2861315 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -156,7 +156,7 @@ TYPES are the types of register supported.
 MSG is the minibuffer message to send when a register is selected.
 ACT is the type of action the command is doing on register.
 SMATCH accept a boolean value to say if command accept non matching register."
-  types msg act smatch)
+  types msg act smatch noconfirm)
 
 (cl-defgeneric register-command-info (command)
   "Returns a `register-preview-info' object storing data for COMMAND."
@@ -179,24 +179,66 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :types '(all)
    :msg "View register `%s'"
    :act 'view
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql append-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Append to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql prepend-to-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Prepend to register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 (cl-defmethod register-command-info ((_command (eql increment-register)))
   (make-register-preview-info
    :types '(string number)
    :msg "Increment register `%s'"
    :act 'modify
+   :noconfirm (memq register-use-preview '(nil never))
+   :smatch t))
+(cl-defmethod register-command-info ((_command (eql copy-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql point-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Point to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql number-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Number to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info
+    ((_command (eql window-configuration-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Window configuration to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql frameset-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Frameset to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql copy-rectangle-to-register)))
+  (make-register-preview-info
+   :types '(all)
+   :msg "Copy rectangle to register `%s'"
+   :act 'set
+   :noconfirm (memq register-use-preview '(nil never))
    :smatch t))
 
 (defun register-preview-forward-line (arg)
@@ -328,12 +370,13 @@ display such a window regardless."
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch)
+         types msg result timer act win strs smatch noconfirm)
     (if data
-        (setq types  (register-preview-info-types data)
-              msg    (register-preview-info-msg   data)
-              act    (register-preview-info-act   data)
-              smatch (register-preview-info-smatch data))
+        (setq types     (register-preview-info-types data)
+              msg       (register-preview-info-msg   data)
+              act       (register-preview-info-act   data)
+              smatch    (register-preview-info-smatch data)
+              noconfirm (register-preview-info-noconfirm data))
       (setq types '(all)
             msg   "Overwrite register `%s'"
             act   'set))
@@ -405,13 +448,15 @@ display such a window regardless."
                                          "Register `%s' is empty" pat))))))
                             (unless (string= pat "")
                               (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs) (memq act '(set modify)))
+                                (if (and (member pat strs)
+                                         (memq act '(set modify))
+                                         (null noconfirm))
                                     (with-selected-window (minibuffer-window)
                                       (minibuffer-message msg pat))
-                                  ;; An empty register or an existing
-                                  ;; one but the action is insert or
-                                  ;; jump, don't ask for confirmation
-                                  ;; and exit immediately (bug#66394).
+                                  ;; The action is insert or
+                                  ;; jump or noconfirm is specifed
+                                  ;; explicitely, don't ask for
+                                  ;; confirmation and exit immediately (bug#66394).
                                   (setq result pat)
                                   (exit-minibuffer)))))))))
              (setq result (read-from-minibuffer
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-Provide-emacs-29-behavior-for-register-preview.patch --]
[-- Type: text/x-diff, Size: 12216 bytes --]

From 99cb6d4d1e85b85a60e26ddc22a54a0a9b029d43 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Tue, 12 Dec 2023 07:24:32 +0100
Subject: [PATCH 2/4] Provide emacs-29 behavior for register-preview

It is now the default with a value of register-use-preview eq to
basic.
To change this one have now to customize register-use-preview to
another value.

* lisp/register.el (register-preview-delay): Remove obsolescence.
(register--read-with-preview-function): New.
(register-use-preview): New option basic, it is now the default.
(register-preview-default-1): New the register-preview-default used by
`register-read-with-preview-fancy`.
(register-preview-default): Restored (same as Emacs-29).
(register--preview-function): Generic fn that return the right
function for register--preview-function.
(register-preview): Restored (same behavior as Emacs-29).
(register-preview-1): Used by `register-read-with-preview-fancy'.
(register-read-with-preview-basic): The old
register-read-with-preview.
(register-read-with-preview-fancy): The new
register-read-with-preview.
---
 lisp/register.el | 156 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 132 insertions(+), 24 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index cd6f2861315..8f0c6a7105d 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -100,25 +100,55 @@ If nil, do not show register previews, unless `help-char' (or a member of
   :version "24.4"
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
-(make-obsolete-variable 'register-preview-delay "No longer used." "30.1")
 
 (defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
   "Default keys for setting a new register."
-  :type '(repeat string))
-
-(defcustom register-use-preview t
-  "Whether to show preview of registers.
-
-If the value is t, show a preview buffer with navigation and highlighting.
-If the value is nil, show a basic preview buffer and exit minibuffer
-immediately after the register name is inserted into minibuffer.
-If the value is \\='never, behave as for nil, but with no preview buffer
-at all."
+  :type '(repeat string)
+  :version 30.1)
+
+(defvar register--read-with-preview-function nil
+  "The register read preview function to use.
+Two functions are provided, one that provide navigation and
+highlighting of the register selected, filtering of register
+according to command in use, defaults register to use when
+setting a new register, confirmation and notification when you
+are about to overwrite a register and generic functions to
+configure how each existing commands behave.  The other function
+provided is the same as what was used in Emacs-29, no filtering,
+no navigation, no defaults.")
+
+(defvar register-preview-function nil
+  "Function to format a register for previewing.
+Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
+The function should return a string, the description of the argument.
+It is set according to the value of `register--read-with-preview-function'.")
+
+(defcustom register-use-preview 'basic
+  "Maybe show register preview.
+
+This has no effect when `register--read-with-preview-function' value
+is `register-read-with-preview-basic'.
+
+When set to `t' show a preview buffer with navigation and highlighting.
+When nil show a basic preview buffer and exit minibuffer
+immediately after insertion in minibuffer.
+When set to \\='never behave as above but with no preview buffer at
+all.
+When set to \\='basic provide a much more basic preview according to
+`register-preview-delay', it has the exact same behavior as in Emacs-29."
   :type '(choice
           (const :tag "Use preview" t)
           (const :tag "Use quick preview" nil)
-          (const :tag "Never use preview" never))
-  :version "30.1")
+          (const :tag "Never use preview" never)
+          (const :tag "Basic preview like Emacs-29" basic))
+  :version 30.1
+  :set (lambda (var val)
+         (set var val)
+         (setq register--read-with-preview-function
+               (if (eq val 'basic)
+                   #'register-read-with-preview-basic
+                 #'register-read-with-preview-fancy))
+         (setq register-preview-function nil)))
 
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
@@ -138,17 +168,28 @@ See the documentation of the variable `register-alist' for possible VALUEs."
         (substring d (match-end 0))
       d)))
 
-(defun register-preview-default (r)
+(defun register-preview-default-1 (r)
   "Function that is the default value of the variable `register-preview-function'."
   (format "%s: %s\n"
 	  (propertize (string (car r))
                       'display (single-key-description (car r)))
 	  (register-describe-oneline (car r))))
 
-(defvar register-preview-function #'register-preview-default
-  "Function to format a register for previewing.
-Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+(defun register-preview-default (r)
+  "Function that is the default value of the variable `register-preview-function'."
+  (format "%s: %s\n"
+	  (single-key-description (car r))
+	  (register-describe-oneline (car r))))
+
+(cl-defgeneric register--preview-function (read-preview-function)
+  "Returns a function to format a register for previewing.
+This according to the value of READ-PREVIEW-FUNCTION.")
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql register-read-with-preview-basic)))
+  #'register-preview-default)
+(cl-defmethod register--preview-function ((_read-preview-function
+                                           (eql register-read-with-preview-fancy)))
+  #'register-preview-default-1)
 
 (cl-defstruct register-preview-info
   "Store data for a specific register command.
@@ -310,9 +351,9 @@ satisfy `cl-typep' otherwise the new type should be defined with
 (cl-defmethod register--type ((_regval string)) 'string)
 (cl-defmethod register--type ((_regval number)) 'number)
 (cl-defmethod register--type ((_regval marker)) 'marker)
-(cl-defmethod register--type ((_regval (eql 'buffer))) 'buffer)
-(cl-defmethod register--type ((_regval (eql 'file))) 'file)
-(cl-defmethod register--type ((_regval (eql 'file-query))) 'file-query)
+(cl-defmethod register--type ((_regval (eql buffer))) 'buffer)
+(cl-defmethod register--type ((_regval (eql file))) 'file)
+(cl-defmethod register--type ((_regval (eql file-query))) 'file-query)
 (cl-defmethod register--type ((_regval window-configuration)) 'window)
 (cl-deftype frame-register () '(satisfies frameset-register-p))
 (cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
@@ -327,12 +368,39 @@ satisfy `cl-typep' otherwise the new type should be defined with
              when (memq (register-type register) types)
              collect register)))
 
-(defun register-preview (buffer &optional show-empty types)
+(defun register-preview (buffer &optional show-empty)
   "Pop up a window showing the registers preview in BUFFER.
 If SHOW-EMPTY is non-nil, show the window even if no registers.
+Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
+  (when (or show-empty (consp register-alist))
+    (with-current-buffer-window
+     buffer
+     (cons 'display-buffer-below-selected
+	   '((window-height . fit-window-to-buffer)
+	     (preserve-size . (nil . t))))
+     nil
+     (with-current-buffer standard-output
+       (setq cursor-in-non-selected-windows nil)
+       (mapc (lambda (elem)
+               (when (get-register (car elem))
+                 (insert (funcall register-preview-function elem))))
+             register-alist)))))
+
+(defun register-preview-1 (buffer &optional show-empty types)
+  "Pop up a window showing the registers preview in BUFFER.
+
+This is the preview function use with
+`register-read-with-preview-fancy' function.
+If SHOW-EMPTY is non-nil, show the window even if no registers.
 Argument TYPES (a list) specify the types of register to show, when nil show all
 registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-function'."
+  (unless register-preview-function
+    (setq register-preview-function (register--preview-function
+                                     register--read-with-preview-function)))
   (let ((registers (register-of-type-alist (or types '(all)))))
     (when (or show-empty (consp registers))
       (with-current-buffer-window
@@ -360,6 +428,46 @@ Format of each entry is controlled by the variable `register-preview-function'."
   "Read and return a register name, possibly showing existing registers.
 Prompt with the string PROMPT.
 If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-basic (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.  If `register-alist' and
+`register-preview-delay' are both non-nil, display a window
+listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display such a window regardless."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  (lambda ()
+				    (unless (get-buffer-window buffer)
+				      (register-preview buffer))))))
+	 (help-chars (cl-loop for c in (cons help-char help-event-list)
+			      when (not (get-register c))
+			      collect c)))
+    (unwind-protect
+	(progn
+	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
+		       help-chars)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer 'show-empty)))
+          (when (or (eq ?\C-g last-input-event)
+                    (eq 'escape last-input-event)
+                    (eq ?\C-\[ last-input-event))
+            (keyboard-quit))
+	  (if (characterp last-input-event) last-input-event
+	    (error "Non-character input-event")))
+      (and (timerp timer) (cancel-timer timer))
+      (let ((w (get-buffer-window buffer)))
+        (and (window-live-p w) (delete-window w)))
+      (and (get-buffer buffer) (kill-buffer buffer)))))
+
+(defun register-read-with-preview-fancy (prompt)
+  "Read and return a register name, possibly showing existing registers.
+Prompt with the string PROMPT.
+If `help-char' (or a member of `help-event-list') is pressed,
 display such a window regardless."
   (let* ((buffer "*Register Preview*")
          (buffer1 "*Register quick preview*")
@@ -392,13 +500,13 @@ display such a window regardless."
                        ;; Do nothing when buffer1 is in use.
                        (unless (get-buffer-window buf)
                          (with-selected-window (minibuffer-selected-window)
-                           (register-preview buffer 'show-empty types))))))
+                           (register-preview-1 buffer 'show-empty types))))))
     (define-key map (kbd "<down>") 'register-preview-next)
     (define-key map (kbd "<up>")   'register-preview-previous)
     (define-key map (kbd "C-n")    'register-preview-next)
     (define-key map (kbd "C-p")    'register-preview-previous)
     (unless (or executing-kbd-macro (eq register-use-preview 'never))
-      (register-preview buf nil types))
+      (register-preview-1 buf nil types))
     (unwind-protect
          (progn
            (minibuffer-with-setup-hook
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.4: 0003-Fix-issue-with-register-commands-in-kmacro.patch --]
[-- Type: text/x-diff, Size: 9244 bytes --]

From 0fe75f80172bb02a082e786264f21e69e09a96dd Mon Sep 17 00:00:00 2001
From: Stefan Monnier <monnier@iro.umontreal.ca>
Date: Mon, 18 Dec 2023 07:11:42 +0100
Subject: [PATCH 3/4] Fix issue with register commands in kmacro

Using post-command-hook in minibuffer-setup-hook instead of a timer
allow running exit-minibuffer without delay and ensure the serie of
commands used in a kmacro run synchronously.

* lisp/register.el (register-read-with-preview-fancy): Do it.
---
 lisp/register.el | 114 +++++++++++++++++++++++------------------------
 1 file changed, 56 insertions(+), 58 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index 8f0c6a7105d..19b207960d6 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -478,7 +478,7 @@ display such a window regardless."
                 m))
          (data (register-command-info this-command))
          (enable-recursive-minibuffers t)
-         types msg result timer act win strs smatch noconfirm)
+         types msg result act win strs smatch noconfirm)
     (if data
         (setq types     (register-preview-info-types data)
               msg       (register-preview-info-msg   data)
@@ -511,68 +511,66 @@ display such a window regardless."
          (progn
            (minibuffer-with-setup-hook
                (lambda ()
-                 (setq timer
-                       (run-with-idle-timer
-                        0.01 'repeat
-                        (lambda ()
-                          (with-selected-window (minibuffer-window)
-                            (let ((input (minibuffer-contents)))
-                              (when (> (length input) 1)
-                                (let ((new (substring input 1))
-                                      (old (substring input 0 1)))
-                                  (setq input (if (or (null smatch)
-                                                      (member new strs))
-                                                  new old))
-                                  (delete-minibuffer-contents)
-                                  (insert input)))
-                              (when (and smatch (not (string= input ""))
-                                         (not (member input strs)))
-                                (setq input "")
-                                (delete-minibuffer-contents)
-                                (minibuffer-message "Not matching"))
-                              (when (not (string= input pat))
-                                (setq pat input))))
-                          (if (setq win (get-buffer-window buffer))
-                              (with-selected-window win
-                                (let ((ov (make-overlay
-                                           (point-min) (point-min)))
-                                      ;; Allow upper-case and
-                                      ;; lower-case letters to refer
-                                      ;; to different registers.
-                                      (case-fold-search nil))
-                                  (goto-char (point-min))
-                                  (remove-overlays)
-                                  (unless (string= pat "")
-                                    (if (re-search-forward (concat "^" pat) nil t)
-                                        (progn (move-overlay
-                                                ov
-                                                (match-beginning 0) (pos-eol))
-                                               (overlay-put ov 'face 'match)
-                                               (when msg
-                                                 (with-selected-window (minibuffer-window)
-                                                   (minibuffer-message msg pat))))
-                                      (with-selected-window (minibuffer-window)
-                                        (minibuffer-message
-                                         "Register `%s' is empty" pat))))))
-                            (unless (string= pat "")
-                              (with-selected-window (minibuffer-window)
-                                (if (and (member pat strs)
-                                         (memq act '(set modify))
-                                         (null noconfirm))
-                                    (with-selected-window (minibuffer-window)
-                                      (minibuffer-message msg pat))
-                                  ;; The action is insert or
-                                  ;; jump or noconfirm is specifed
-                                  ;; explicitely, don't ask for
-                                  ;; confirmation and exit immediately (bug#66394).
-                                  (setq result pat)
-                                  (exit-minibuffer)))))))))
+                 (add-hook 'post-command-hook
+                           (lambda ()
+                             (with-selected-window (minibuffer-window)
+                               (let ((input (minibuffer-contents)))
+                                 (when (> (length input) 1)
+                                   (let ((new (substring input 1))
+                                         (old (substring input 0 1)))
+                                     (setq input (if (or (null smatch)
+                                                         (member new strs))
+                                                     new old))
+                                     (delete-minibuffer-contents)
+                                     (insert input)))
+                                 (when (and smatch (not (string= input ""))
+                                            (not (member input strs)))
+                                   (setq input "")
+                                   (delete-minibuffer-contents)
+                                   (minibuffer-message "Not matching"))
+                                 (when (not (string= input pat))
+                                   (setq pat input))))
+                             (if (setq win (get-buffer-window buffer))
+                                 (with-selected-window win
+                                   (let ((ov (make-overlay
+                                              (point-min) (point-min)))
+                                         ;; Allow upper-case and
+                                         ;; lower-case letters to refer
+                                         ;; to different registers.
+                                         (case-fold-search nil))
+                                     (goto-char (point-min))
+                                     (remove-overlays)
+                                     (unless (string= pat "")
+                                       (if (re-search-forward (concat "^" pat) nil t)
+                                           (progn (move-overlay
+                                                   ov
+                                                   (match-beginning 0) (pos-eol))
+                                                  (overlay-put ov 'face 'match)
+                                                  (when msg
+                                                    (with-selected-window (minibuffer-window)
+                                                      (minibuffer-message msg pat))))
+                                         (with-selected-window (minibuffer-window)
+                                           (minibuffer-message
+                                            "Register `%s' is empty" pat))))))
+                               (unless (string= pat "")
+                                 (with-selected-window (minibuffer-window)
+                                   (if (and (member pat strs)
+                                            (memq act '(set modify))
+                                            (null noconfirm))
+                                       (with-selected-window (minibuffer-window)
+                                         (minibuffer-message msg pat))
+                                     ;; The action is insert or
+                                     ;; jump or noconfirm is specifed
+                                     ;; explicitely, don't ask for
+                                     ;; confirmation and exit immediately (bug#66394).
+                                     (setq result pat)
+                                     (exit-minibuffer))))))
+                           nil 'local))
              (setq result (read-from-minibuffer
                            prompt nil map nil nil (register-preview-get-defaults act))))
            (cl-assert (and result (not (string= result "")))
                       nil "No register specified")
            (string-to-char result))
-      (when timer (cancel-timer timer))
       (let ((w (get-buffer-window buf)))
         (and (window-live-p w) (delete-window w)))
       (and (get-buffer buf) (kill-buffer buf)))))
-- 
2.34.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.5: 0004-Fix-condition-in-register-read-with-preview-fancy.patch --]
[-- Type: text/x-diff, Size: 2528 bytes --]

From 777c6c7e821d44faa970655c04e9eba8e5b11498 Mon Sep 17 00:00:00 2001
From: Thierry Volpiatto <thievol@posteo.net>
Date: Tue, 19 Dec 2023 17:45:22 +0100
Subject: [PATCH 4/4] Fix condition in register-read-with-preview-fancy

Now with have :noconfirm no need to check for '(set modify) otherwise
we fail as well in kmacros when register-use-preview is t.
The conditions should not be hard coded in
register-read-with-preview-fancy but in the cl-defmethod
register-command-info for each command.

* lisp/register.el (register-read-with-preview-fancy): Remove now
unneeded condition.
---
 lisp/register.el | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lisp/register.el b/lisp/register.el
index 19b207960d6..c2b10a91adb 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -207,14 +207,16 @@ SMATCH accept a boolean value to say if command accept non matching register."
    :types '(string number)
    :msg "Insert register `%s'"
    :act 'insert
-   :smatch t))
+   :smatch t
+   :noconfirm (memq register-use-preview '(nil never))))
 (cl-defmethod register-command-info ((_command (eql jump-to-register)))
   (make-register-preview-info
    :types  '(window frame marker kmacro
              file buffer file-query)
    :msg "Jump to register `%s'"
    :act 'jump
-   :smatch t))
+   :smatch t
+   :noconfirm (memq register-use-preview '(nil never))))
 (cl-defmethod register-command-info ((_command (eql view-register)))
   (make-register-preview-info
    :types '(all)
@@ -555,12 +557,10 @@ display such a window regardless."
                                (unless (string= pat "")
                                  (with-selected-window (minibuffer-window)
                                    (if (and (member pat strs)
-                                            (memq act '(set modify))
                                             (null noconfirm))
                                        (with-selected-window (minibuffer-window)
                                          (minibuffer-message msg pat))
-                                     ;; The action is insert or
-                                     ;; jump or noconfirm is specifed
+                                     ;; :noconfirm is specifed
                                      ;; explicitely, don't ask for
                                      ;; confirmation and exit immediately (bug#66394).
                                      (setq result pat)
-- 
2.34.1


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply related	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-19 17:40                                                                                             ` Thierry Volpiatto
@ 2023-12-19 17:47                                                                                               ` Thierry Volpiatto
  2023-12-20 12:05                                                                                               ` Eli Zaretskii
  1 sibling, 0 replies; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-19 17:47 UTC (permalink / raw)
  To: Stefan Monnier
  Cc: michael_heerdegen, dmitry, Eli Zaretskii, Stefan Kangas, 66394

[-- Attachment #1: Type: text/plain, Size: 945 bytes --]

Thierry Volpiatto <thievol@posteo.net> writes:

> Hello Stefan,
>
> Stefan Monnier <monnier@iro.umontreal.ca> writes:
>
>>> It should be possible to use post-command-hook, I didn't use it because
>>> it makes harder the communication between the minibuffer and the preview
>>> buffer.
>>
>> The patch below seems to work for my extremely limited testing.

>     (cl-defmethod register-command-info ((_command (eql increment-register)))
>       (make-register-preview-info
>        :types '(all)
>        :msg "Increment to register `%s'"
>        :act 'set
>        :smatch t
>        :noconfirm t))

Copied the wrong one, the test was with :noconfirm == nil:

     (cl-defmethod register-command-info ((_command (eql increment-register)))
       (make-register-preview-info
        :types '(all)
        :msg "Increment to register `%s'"
        :act 'set
        :smatch t
        :noconfirm nil))

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-19 17:40                                                                                             ` Thierry Volpiatto
  2023-12-19 17:47                                                                                               ` Thierry Volpiatto
@ 2023-12-20 12:05                                                                                               ` Eli Zaretskii
  2023-12-20 17:23                                                                                                 ` Thierry Volpiatto
  1 sibling, 1 reply; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-20 12:05 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, dmitry, 66394, monnier, stefankangas

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: Stefan Kangas <stefankangas@gmail.com>,  Eli Zaretskii <eliz@gnu.org>,
>   dmitry@gutov.dev,  michael_heerdegen@web.de,  66394@debbugs.gnu.org
> Date: Tue, 19 Dec 2023 17:40:59 +0000
> 
> So it seems we have now something working fine in all conditions :-)
> 
> Here the serie of patches (the first 3 are unchanged). 

Thank you for all your efforts in this matter.

I have only 2 minor comments:

  . I suggest to rename all the "*basic" symbols to "*traditional"
    instead (including such words in some doc strings)
  . I think we need to update the NEWS entry, and in particular
    describe there the two different "styles" of entering the register
    names and the preview modes

(I'm okay with doing these minor changes myself, once you install the
changes.)

Thanks again.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-20 12:05                                                                                               ` Eli Zaretskii
@ 2023-12-20 17:23                                                                                                 ` Thierry Volpiatto
  2023-12-21 11:47                                                                                                   ` Eli Zaretskii
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-20 17:23 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, dmitry, 66394, monnier, stefankangas

[-- Attachment #1: Type: text/plain, Size: 1120 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Thierry Volpiatto <thievol@posteo.net>
>> Cc: Stefan Kangas <stefankangas@gmail.com>,  Eli Zaretskii <eliz@gnu.org>,
>>   dmitry@gutov.dev,  michael_heerdegen@web.de,  66394@debbugs.gnu.org
>> Date: Tue, 19 Dec 2023 17:40:59 +0000
>> 
>> So it seems we have now something working fine in all conditions :-)
>> 
>> Here the serie of patches (the first 3 are unchanged). 
>
> Thank you for all your efforts in this matter.

You are welcome.

> I have only 2 minor comments:
>
>   . I suggest to rename all the "*basic" symbols to "*traditional"
>     instead (including such words in some doc strings)

Ok, done.  Have a look though to verify if docstring is correct.

>   . I think we need to update the NEWS entry, and in particular
>     describe there the two different "styles" of entering the register
>     names and the preview modes

I would prefer you do this, it will be better written.

> (I'm okay with doing these minor changes myself, once you install the
> changes.)

Ok, now merged, Thanks.

> Thanks again.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-20 17:23                                                                                                 ` Thierry Volpiatto
@ 2023-12-21 11:47                                                                                                   ` Eli Zaretskii
  2023-12-21 18:04                                                                                                     ` Thierry Volpiatto
  0 siblings, 1 reply; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-21 11:47 UTC (permalink / raw)
  To: Thierry Volpiatto; +Cc: michael_heerdegen, dmitry, 66394, monnier, stefankangas

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: monnier@iro.umontreal.ca,  stefankangas@gmail.com,  dmitry@gutov.dev,
>   michael_heerdegen@web.de,  66394@debbugs.gnu.org
> Date: Wed, 20 Dec 2023 17:23:14 +0000
> 
> >   . I suggest to rename all the "*basic" symbols to "*traditional"
> >     instead (including such words in some doc strings)
> 
> Ok, done.  Have a look though to verify if docstring is correct.
> 
> >   . I think we need to update the NEWS entry, and in particular
> >     describe there the two different "styles" of entering the register
> >     names and the preview modes
> 
> I would prefer you do this, it will be better written.
> 
> > (I'm okay with doing these minor changes myself, once you install the
> > changes.)
> 
> Ok, now merged, Thanks.

Thanks, I have a question:

The doc string of register-use-preview says:

  This has no effect when the value of `register--read-with-preview-function'
  is `register-read-with-preview-traditional'.

However, customizing register-use-preview to the value 'traditional
has the exact effect of setting register--read-with-preview-function
to register-read-with-preview-traditional.  OTOH, when
register-use-preview is set to 'traditional, one can set it to a
different value, and then the behavior will change.  So I wonder what
that sentence is about and what I missed?  Is that perhaps a leftover
from previous versions, and should now be deleted?

I updated the documentation and NEWS.  I'd appreciate if you could
spare a few minutes to review the changes and point out any
inaccuracies or mistakes.





^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-21 11:47                                                                                                   ` Eli Zaretskii
@ 2023-12-21 18:04                                                                                                     ` Thierry Volpiatto
  2023-12-23 10:49                                                                                                       ` Eli Zaretskii
  0 siblings, 1 reply; 121+ messages in thread
From: Thierry Volpiatto @ 2023-12-21 18:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, dmitry, 66394, monnier, stefankangas

[-- Attachment #1: Type: text/plain, Size: 3244 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Thierry Volpiatto <thievol@posteo.net>
>> Cc: monnier@iro.umontreal.ca,  stefankangas@gmail.com,  dmitry@gutov.dev,
>>   michael_heerdegen@web.de,  66394@debbugs.gnu.org
>> Date: Wed, 20 Dec 2023 17:23:14 +0000
>> 
>> >   . I suggest to rename all the "*basic" symbols to "*traditional"
>> >     instead (including such words in some doc strings)
>> 
>> Ok, done.  Have a look though to verify if docstring is correct.
>> 
>> >   . I think we need to update the NEWS entry, and in particular
>> >     describe there the two different "styles" of entering the register
>> >     names and the preview modes
>> 
>> I would prefer you do this, it will be better written.
>> 
>> > (I'm okay with doing these minor changes myself, once you install the
>> > changes.)
>> 
>> Ok, now merged, Thanks.
>
> Thanks, I have a question:
>
> The doc string of register-use-preview says:
>
>   This has no effect when the value of `register--read-with-preview-function'
>   is `register-read-with-preview-traditional'.
>
> However, customizing register-use-preview to the value 'traditional
> has the exact effect of setting register--read-with-preview-function
> to register-read-with-preview-traditional.  OTOH, when
> register-use-preview is set to 'traditional, one can set it to a
> different value, and then the behavior will change.  So I wonder what
> that sentence is about and what I missed?  Is that perhaps a leftover
> from previous versions, and should now be deleted?

Yes exactly, it can be deleted.

> I updated the documentation and NEWS.  I'd appreciate if you could
> spare a few minutes to review the changes and point out any
> inaccuracies or mistakes.

About the documentation or register-use-preview in the manual:

Another difference with the old behavior (traditional) is that the
preview is filtered according to type of registers used by command.  For
example insert-register show only the registers that can be inserted,
not windows, markers etc... Same for jump.

    -  "Returns a function to format a register for previewing.
    -This according to the value of READ-PREVIEW-FUNCTION.")
    +  "Return a function to format a register for previewing.
    +This is according to the value of `read-preview-function'.")

Here READ-PREVIEW-FUNCTION is the argument of function and not a
variable, so IMO it should be upcased and not quoted.

     (cl-defstruct register-preview-info
       "Store data for a specific register command.
    -TYPES are the types of register supported.
    -MSG is the minibuffer message to send when a register is selected.
    +TYPES are the supported types of registers.
    +MSG is the minibuffer message to show when a register is selected.
     ACT is the type of action the command is doing on register.
    -SMATCH accept a boolean value to say if command accept non matching register."
    +SMATCH accept a boolean value to say if the command accepts non-matching
    +registers."
       types msg act smatch noconfirm)

NOCONFIRM is not documented (my fault).
When set to nil don't request confirmation with RET.

Otherwise all looks good to me, thanks.

-- 
Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 686 bytes --]

^ permalink raw reply	[flat|nested] 121+ messages in thread

* bug#66394: 29.1; Make register-read-with-preview more useful
  2023-12-21 18:04                                                                                                     ` Thierry Volpiatto
@ 2023-12-23 10:49                                                                                                       ` Eli Zaretskii
  0 siblings, 0 replies; 121+ messages in thread
From: Eli Zaretskii @ 2023-12-23 10:49 UTC (permalink / raw)
  To: Thierry Volpiatto
  Cc: michael_heerdegen, dmitry, 66394-done, monnier, stefankangas

> From: Thierry Volpiatto <thievol@posteo.net>
> Cc: monnier@iro.umontreal.ca,  stefankangas@gmail.com,  dmitry@gutov.dev,
>   michael_heerdegen@web.de,  66394@debbugs.gnu.org
> Date: Thu, 21 Dec 2023 18:04:02 +0000
> 
> > Thanks, I have a question:
> >
> > The doc string of register-use-preview says:
> >
> >   This has no effect when the value of `register--read-with-preview-function'
> >   is `register-read-with-preview-traditional'.
> >
> > However, customizing register-use-preview to the value 'traditional
> > has the exact effect of setting register--read-with-preview-function
> > to register-read-with-preview-traditional.  OTOH, when
> > register-use-preview is set to 'traditional, one can set it to a
> > different value, and then the behavior will change.  So I wonder what
> > that sentence is about and what I missed?  Is that perhaps a leftover
> > from previous versions, and should now be deleted?
> 
> Yes exactly, it can be deleted.
> 
> > I updated the documentation and NEWS.  I'd appreciate if you could
> > spare a few minutes to review the changes and point out any
> > inaccuracies or mistakes.
> 
> About the documentation or register-use-preview in the manual:
> 
> Another difference with the old behavior (traditional) is that the
> preview is filtered according to type of registers used by command.  For
> example insert-register show only the registers that can be inserted,
> not windows, markers etc... Same for jump.
> 
>     -  "Returns a function to format a register for previewing.
>     -This according to the value of READ-PREVIEW-FUNCTION.")
>     +  "Return a function to format a register for previewing.
>     +This is according to the value of `read-preview-function'.")
> 
> Here READ-PREVIEW-FUNCTION is the argument of function and not a
> variable, so IMO it should be upcased and not quoted.
> 
>      (cl-defstruct register-preview-info
>        "Store data for a specific register command.
>     -TYPES are the types of register supported.
>     -MSG is the minibuffer message to send when a register is selected.
>     +TYPES are the supported types of registers.
>     +MSG is the minibuffer message to show when a register is selected.
>      ACT is the type of action the command is doing on register.
>     -SMATCH accept a boolean value to say if command accept non matching register."
>     +SMATCH accept a boolean value to say if the command accepts non-matching
>     +registers."
>        types msg act smatch noconfirm)
> 
> NOCONFIRM is not documented (my fault).
> When set to nil don't request confirmation with RET.
> 
> Otherwise all looks good to me, thanks.

Thanks, I fixed all of the above, and I'm therefore closing this bug.





^ permalink raw reply	[flat|nested] 121+ messages in thread

end of thread, other threads:[~2023-12-23 10:49 UTC | newest]

Thread overview: 121+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-07 19:03 bug#66394: 29.1; Make register-read-with-preview more useful Thierry Volpiatto
2023-10-08  6:45 ` bug#66394: [RE] " Thierry Volpiatto
2023-10-12  6:43 ` Thierry Volpiatto
2023-10-14  2:04   ` Richard Stallman
2023-10-14  5:59     ` Thierry Volpiatto
2023-10-16  2:04       ` Richard Stallman
2023-10-15  7:56     ` Thierry Volpiatto
2023-10-15  8:18       ` Stefan Kangas
2023-10-15 10:05         ` Thierry Volpiatto
2023-10-15 12:55           ` Stefan Kangas
2023-11-18 18:39             ` Thierry Volpiatto
2023-10-19  2:42 ` bug#66394: 29.1; " Michael Heerdegen
2023-10-19  6:16   ` Thierry Volpiatto
2023-10-20  5:00     ` Michael Heerdegen
2023-10-20  5:49       ` Thierry Volpiatto
2023-10-21  1:09         ` Michael Heerdegen
2023-10-21  3:34           ` Thierry Volpiatto
2023-10-23  4:09             ` Michael Heerdegen
2023-10-23  5:14               ` Thierry Volpiatto
2023-10-24  3:42                 ` Michael Heerdegen
2023-10-24  3:54                   ` Michael Heerdegen
2023-10-24  5:30                   ` Thierry Volpiatto
2023-10-25  3:54                     ` Michael Heerdegen
2023-10-24  7:19               ` Thierry Volpiatto
2023-10-25  4:10                 ` Michael Heerdegen
2023-10-25  6:38                   ` Thierry Volpiatto
2023-10-26  4:18                     ` Michael Heerdegen
2023-10-26  6:17                       ` Thierry Volpiatto
2023-10-27  1:27                         ` Michael Heerdegen
2023-10-27  4:24                           ` Thierry Volpiatto
2023-11-03  4:58                             ` Michael Heerdegen
2023-11-19 19:37                               ` Thierry Volpiatto
2023-11-20  6:00                               ` Thierry Volpiatto
2023-11-20 17:33                                 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-11-20 18:51                                   ` Thierry Volpiatto
2023-11-25 10:23                                     ` Eli Zaretskii
2023-11-25 19:59                                       ` Thierry Volpiatto
2023-11-25 20:10                                         ` Eli Zaretskii
2023-11-25 21:14                                           ` Thierry Volpiatto
2023-11-26 10:38                                             ` Eli Zaretskii
2023-11-26 16:46                                               ` Thierry Volpiatto
2023-11-29 14:04                                             ` Eli Zaretskii
2023-11-29 18:18                                               ` Thierry Volpiatto
2023-11-30  6:00                                                 ` Eli Zaretskii
2023-11-30 10:21                                                   ` Thierry Volpiatto
2023-12-02  5:51                                                   ` Thierry Volpiatto
2023-12-02  7:50                                                     ` Eli Zaretskii
2023-12-02  8:08                                                       ` Thierry Volpiatto
2023-12-03 14:35                                                       ` Thierry Volpiatto
2023-12-03 15:05                                                         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-03 16:48                                                           ` Thierry Volpiatto
2023-12-03 18:29                                                             ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-03 18:39                                                               ` Eli Zaretskii
2023-12-03 21:23                                                                 ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-04  7:30                                                                   ` Thierry Volpiatto
2023-12-04  7:57                                                                     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-11  6:55                                                                 ` Thierry Volpiatto
2023-12-11  9:30                                                       ` Thierry Volpiatto
2023-12-11  9:58                                                         ` Thierry Volpiatto
2023-12-11 12:30                                                         ` Eli Zaretskii
2023-12-11 13:10                                                           ` Thierry Volpiatto
2023-12-11 17:32                                                             ` Thierry Volpiatto
2023-12-11 23:36                                                               ` Dmitry Gutov
2023-12-12  6:29                                                                 ` Thierry Volpiatto
2023-12-12  9:31                                                                   ` Thierry Volpiatto
2023-12-12 10:16                                                                     ` Thierry Volpiatto
2023-12-12 16:44                                                                       ` Thierry Volpiatto
2023-12-14  1:46                                                                       ` Dmitry Gutov
2023-12-14  5:34                                                                         ` Thierry Volpiatto
2023-12-14  7:38                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-14  8:24                                                                             ` Eli Zaretskii
2023-12-14  7:44                                                                           ` Eli Zaretskii
2023-12-14 15:50                                                                             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-14 17:58                                                                               ` Thierry Volpiatto
2023-12-14 19:19                                                                                 ` Andreas Schwab
2023-12-14 20:29                                                                               ` Stefan Kangas
2023-12-15 14:45                                                                                 ` Thierry Volpiatto
2023-12-15 15:18                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-15 18:36                                                                                     ` Thierry Volpiatto
2023-12-15 23:30                                                                                       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-16 13:18                                                                                         ` Thierry Volpiatto
2023-12-16 15:31                                                                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-16 20:39                                                                                             ` Thierry Volpiatto
2023-12-17 23:20                                                                                               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-18  5:15                                                                                                 ` Thierry Volpiatto
2023-12-18 13:20                                                                                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-18 18:11                                                                                                     ` Thierry Volpiatto
2023-12-18 18:22                                                                                                     ` Dmitry Gutov
2023-12-18  6:18                                                                                                 ` Thierry Volpiatto
2023-12-19 17:40                                                                                             ` Thierry Volpiatto
2023-12-19 17:47                                                                                               ` Thierry Volpiatto
2023-12-20 12:05                                                                                               ` Eli Zaretskii
2023-12-20 17:23                                                                                                 ` Thierry Volpiatto
2023-12-21 11:47                                                                                                   ` Eli Zaretskii
2023-12-21 18:04                                                                                                     ` Thierry Volpiatto
2023-12-23 10:49                                                                                                       ` Eli Zaretskii
2023-12-16 15:07                                                                                   ` Dmitry Gutov
2023-12-16 20:20                                                                                     ` Thierry Volpiatto
2023-12-16 23:28                                                                                       ` Dmitry Gutov
2023-12-14  2:10                                                                     ` Dmitry Gutov
2023-12-14  5:30                                                                       ` Thierry Volpiatto
2023-12-14 19:39                                                                   ` Stefan Kangas
2023-12-12  6:06                                                         ` Alfred M. Szmidt
2023-12-12  9:37                                                         ` Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-12 12:15                                                           ` Eli Zaretskii
2023-12-12 17:58                                                             ` Steve Perry via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-11-25 21:38                                           ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-02  9:24                                 ` Bastien
2023-12-02  9:52                                   ` Thierry Volpiatto
2023-12-02 10:37                                     ` Bastien Guerry
2023-12-02 10:54                                       ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-02 11:55                                       ` Thierry Volpiatto
2023-12-02 12:43                                         ` Thierry Volpiatto
2023-12-02 13:02                                           ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-12-02 13:50                                           ` Bastien Guerry
2023-12-02 15:01                                             ` Thierry Volpiatto
2023-12-05  7:34 ` Tino Calancha
2023-12-05  7:38 ` Tino Calancha
2023-12-05  7:43 ` Tino Calancha
2023-12-12  5:46 ` Pedro Andres Aranda Gutierrez
2023-12-12 12:01   ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).