From mboxrd@z Thu Jan  1 00:00:00 1970
Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail
From: Thierry Volpiatto <thievol@posteo.net>
Newsgroups: gmane.emacs.bugs
Subject: bug#66394: 29.1; Make register-read-with-preview more useful
Date: Sat, 25 Nov 2023 21:14:31 +0000
Message-ID: <87zfz1cz7s.fsf@posteo.net>
References: <87il7ib6cu.fsf@posteo.net> <875y3386ep.fsf@posteo.net>
 <87a5sddh14.fsf@web.de> <8734y5vnj7.fsf@posteo.net>
 <87bkcslr18.fsf@web.de> <87y1fwtyrl.fsf@posteo.net>
 <87y1fut1wp.fsf@web.de> <87ttqgpjiz.fsf@posteo.net>
 <87wmvbibpr.fsf@web.de> <877cnb2n63.fsf@posteo.net>
 <8734xyc8z0.fsf@web.de> <87zg05rewi.fsf@posteo.net>
 <87ttqcg8gw.fsf@web.de> <87h6mcr8ol.fsf@posteo.net>
 <87r0l73029.fsf@web.de> <877cmdx8ud.fsf@posteo.net>
 <jwvjzqcxrnq.fsf-monnier+emacs@gnu.org> <87sf50s1gh.fsf@posteo.net>
 <83o7ficesp.fsf@gnu.org> <878r6leh9d.fsf@posteo.net>
 <83il5pbnmh.fsf@gnu.org>
Mime-Version: 1.0
Content-Type: multipart/signed; boundary="==-=-=";
 micalg=pgp-sha512; protocol="application/pgp-signature"
Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214";
	logging-data="10215"; mail-complaints-to="usenet@ciao.gmane.io"
Cc: michael_heerdegen@web.de, 66394@debbugs.gnu.org, monnier@iro.umontreal.ca,
 stefankangas@gmail.com
To: Eli Zaretskii <eliz@gnu.org>
Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sat Nov 25 22:15:14 2023
Return-path: <bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org>
Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org
Original-Received: from lists.gnu.org ([209.51.188.17])
	by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
	(Exim 4.92)
	(envelope-from <bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org>)
	id 1r6zze-0002Pl-4Q
	for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 25 Nov 2023 22:15:14 +0100
Original-Received: from localhost ([::1] helo=lists1p.gnu.org)
	by lists.gnu.org with esmtp (Exim 4.90_1)
	(envelope-from <bug-gnu-emacs-bounces@gnu.org>)
	id 1r6zzO-0001dr-KM; Sat, 25 Nov 2023 16:14:58 -0500
Original-Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <Debian-debbugs@debbugs.gnu.org>)
 id 1r6zzN-0001dj-Nk
 for bug-gnu-emacs@gnu.org; Sat, 25 Nov 2023 16:14:57 -0500
Original-Received: from debbugs.gnu.org ([2001:470:142:5::43])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)
 (Exim 4.90_1) (envelope-from <Debian-debbugs@debbugs.gnu.org>)
 id 1r6zzN-0000LM-FM
 for bug-gnu-emacs@gnu.org; Sat, 25 Nov 2023 16:14:57 -0500
Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2)
 (envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1r6zzS-00042j-MS
 for bug-gnu-emacs@gnu.org; Sat, 25 Nov 2023 16:15:02 -0500
X-Loop: help-debbugs@gnu.org
Resent-From: Thierry Volpiatto <thievol@posteo.net>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces@debbugs.gnu.org>
Resent-CC: bug-gnu-emacs@gnu.org
Resent-Date: Sat, 25 Nov 2023 21:15:02 +0000
Resent-Message-ID: <handler.66394.B66394.170094689615511@debbugs.gnu.org>
Resent-Sender: help-debbugs@gnu.org
X-GNU-PR-Message: followup 66394
X-GNU-PR-Package: emacs
Original-Received: via spool by 66394-submit@debbugs.gnu.org id=B66394.170094689615511
 (code B ref 66394); Sat, 25 Nov 2023 21:15:02 +0000
Original-Received: (at 66394) by debbugs.gnu.org; 25 Nov 2023 21:14:56 +0000
Original-Received: from localhost ([127.0.0.1]:40366 helo=debbugs.gnu.org)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <debbugs-submit-bounces@debbugs.gnu.org>)
 id 1r6zzL-000426-GY
 for submit@debbugs.gnu.org; Sat, 25 Nov 2023 16:14:56 -0500
Original-Received: from mout02.posteo.de ([185.67.36.66]:59421)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <thievol@posteo.net>) id 1r6zzH-00041p-Ph
 for 66394@debbugs.gnu.org; Sat, 25 Nov 2023 16:14:53 -0500
Original-Received: from submission (posteo.de [185.67.36.169]) 
 by mout02.posteo.de (Postfix) with ESMTPS id 6924F240103
 for <66394@debbugs.gnu.org>; Sat, 25 Nov 2023 22:14:40 +0100 (CET)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017;
 t=1700946880; bh=yOPaBOtIqBzsKQEEcPiPlel2QZUQH+9ZO7CZKo5DZ5c=;
 h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Autocrypt:OpenPGP:
 From;
 b=DUdoPfzRMSsXw7q08pnlZlMRednN2xZmTLR20JSC0P+bokmirKM/Jrbwi3KTyxa8k
 23+FNxtqxw71GwPOHWffFqKHDnhrWDoC96QR+4PBAMfwNWMWqx7NCfeL7IR6tL/KyY
 J8l4U80/HhrlVhCZaDzSKSEAyHoMkkaJ6dvtkCYpx8KpY6rXOFivb03Cn6Zb4tRgdj
 6oDXoAHajIifP8qoUyaOfUBh0axj+ma7EH+abHRkSY63N6vdZx/d9Uh6QbpZHms9pO
 YQRwxQkgC6Czln0rCa8PCCxlVLQ303QMYkCG497h3sQPv91WyEnSLR271JRjxGrowU
 xQvKPIIie9n5Q==
Original-Received: from customer (localhost [127.0.0.1])
 by submission (posteo.de) with ESMTPSA id 4Sd4Nt1VBPz6tsB;
 Sat, 25 Nov 2023 22:14:37 +0100 (CET)
In-Reply-To: <83il5pbnmh.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 25 Nov
 2023 22:10:14 +0200 (53 minutes, 35 seconds ago)")
Autocrypt: addr=thievol@posteo.net; prefer-encrypt=mutual;
 keydata=xsDNBF8ylcIBDADG+hy+zR6L4/vbdDDZuSaMmSrU3A5QZJpeBCvxTr7MpzzruZbhLPW1K3R6N2MA
 edi8Y+C8o27FVRIjpdbaKMGu9je7JV/TbUQYo3SOwCK1vM4LUn4V6ZLzSYkuiEt4eyMoiDdyvN0p
 kcK6P9x9DCetcEVszXzQg+yzCVrQ2hXWDXWT4M18EC3wtO7RHPouMqGiwBFhBAYErCqFWFxQHkfb
 tG/4yGyJ58rglb65O3qijjMWvYwcWZun9/7qm8Z4/4mHopmo2zgU+OrptnLSZfkZGz3Y7Uf452xQ
 GVq0Fv75NPvQru7y+DYVhuVXXyAmGxt+vf4rIiixMBbhKEPjcxEPAa2LTzex2IsTZR+QVG9uDnqC
 WcgaOEQ58fzXNvNhtwwF/Rgio2XWAJVdmFWS59/k9W58CIUSNKBMZh2XeGdEmtHvDtCxW3z6FJha
 36RzOM3fMNNiAGdFZJA84gcdloJR+sHCDTTPT3784fjr+V8An7sI581NGFzkRQqPvEQCZbUAEQEA
 Ac0SdGhpZXZvbEBwb3N0ZW8ubmV0wsEOBBMBCgA4AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA
 FiEEI9twfRN7r3nig/xwDsVtFB0W75MFAmL3HCoACgkQDsVtFB0W75OVEAv/f6XxmtIFz08fUb8h
 Bp/zJP6IC4/rhhh+0GMRIRzLN8DK0jV8JCzYdFHiRJOy2lNIOpmrrCmjRRxferc2G42+ePFIsslx
 hU46VSz1Z83NwIG3mpdYNV5WUTUdgzxExHTNTFCd7NKv0nlHKQaA 
OpenPGP: url=https://posteo.de/keys/thievol@posteo.net.asc; preference=encrypt
X-BeenThere: debbugs-submit@debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
X-BeenThere: bug-gnu-emacs@gnu.org
List-Id: "Bug reports for GNU Emacs,
 the Swiss army knife of text editors" <bug-gnu-emacs.gnu.org>
List-Unsubscribe: <https://lists.gnu.org/mailman/options/bug-gnu-emacs>,
 <mailto:bug-gnu-emacs-request@gnu.org?subject=unsubscribe>
List-Archive: <https://lists.gnu.org/archive/html/bug-gnu-emacs>
List-Post: <mailto:bug-gnu-emacs@gnu.org>
List-Help: <mailto:bug-gnu-emacs-request@gnu.org?subject=help>
List-Subscribe: <https://lists.gnu.org/mailman/listinfo/bug-gnu-emacs>,
 <mailto:bug-gnu-emacs-request@gnu.org?subject=subscribe>
Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org
Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org
Xref: news.gmane.io gmane.emacs.bugs:275019
Archived-At: <http://permalink.gmane.org/gmane.emacs.bugs/275019>

--==-=-=
Content-Type: multipart/mixed; boundary="=-=-="

--=-=-=
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

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.
=20
=2D-=20
Thierry

--=-=-=
Content-Type: text/x-diff
Content-Disposition: attachment;
 filename=0001-Improve-register-preview-Fix-bug-66394.patch
Content-Transfer-Encoding: quoted-printable

From=20ccecd34b8307c7168e89289f933e63590ce6fc9c 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.
=2D--
 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
=2D-- 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)
=20
 ;;; Dispatch on major mode.
=20
diff --git a/lisp/register.el b/lisp/register.el
index ca6de450993..61bef503f91 100644
=2D-- a/lisp/register.el
+++ b/lisp/register.el
@@ -35,6 +35,8 @@
=20
 ;; FIXME: Clean up namespace usage!
=20
+(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 ?+)))
=20
+;; 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-cha=
r' (or a member of
   :type '(choice number (const :tag "No preview unless requested" nil))
   :group 'register)
=20
+(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-alis=
t' for possible VALUEs."
 Called with one argument, a cons (NAME . CONTENTS) as found in `register-a=
list'.
 The function should return a string, the description of the argument.")
=20
=2D(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 regist=
er."
+  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-defmetho=
d'
+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 sh=
ow all
+registers, see `register-type' for suitable types.
 Format of each entry is controlled by the variable `register-preview-funct=
ion'."
=2D  (when (or show-empty (consp register-alist))
=2D    (with-current-buffer-window
=2D     buffer
=2D     (cons 'display-buffer-below-selected
=2D	   '((window-height . fit-window-to-buffer)
=2D	     (preserve-size . (nil . t))))
=2D     nil
=2D     (with-current-buffer standard-output
=2D       (setq cursor-in-non-selected-windows nil)
=2D       (mapc (lambda (elem)
=2D               (when (get-register (car elem))
=2D                 (insert (funcall register-preview-function elem))))
=2D             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))
=20
 (defun register-read-with-preview (prompt)
   "Read and return a register name, possibly showing existing registers.
=2DPrompt with the string PROMPT.  If `register-alist' and
=2D`register-preview-delay' are both non-nil, display a window
=2Dlisting 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*")
=2D	 (timer (when (numberp register-preview-delay)
=2D		  (run-with-timer register-preview-delay nil
=2D				  (lambda ()
=2D				    (unless (get-buffer-window buffer)
=2D				      (register-preview buffer))))))
=2D	 (help-chars (cl-loop for c in (cons help-char help-event-list)
=2D			      when (not (get-register c))
=2D			      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
=2D	(progn
=2D	  (while (memq (read-key (propertize prompt 'face 'minibuffer-prompt))
=2D		       help-chars)
=2D	    (unless (get-buffer-window buffer)
=2D	      (register-preview buffer 'show-empty)))
=2D          (when (or (eq ?\C-g last-input-event)
=2D                    (eq 'escape last-input-event)
=2D                    (eq ?\C-\[ last-input-event))
=2D            (keyboard-quit))
=2D	  (if (characterp last-input-event) last-input-event
=2D	    (error "Non-character input-event")))
=2D      (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=3D input ""))
+                                         (not (member input strs)))
+                                (setq input "")
+                                (delete-minibuffer-contents)
+                                (minibuffer-message "Not matching"))
+                              (when (not (string=3D 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=3D pat "")
+                                    (if (re-search-forward (concat "^" pat=
) nil t)
+                                        (progn (move-overlay
+                                                ov
+                                                (match-beginning 0) (pos-e=
ol))
+                                               (overlay-put ov 'face 'matc=
h)
+                                               (when msg
+                                                 (with-selected-window (mi=
nibuffer-window)
+                                                   (minibuffer-message msg=
 pat))))
+                                      (with-selected-window (minibuffer-wi=
ndow)
+                                        (minibuffer-message
+                                         "Register `%s' is empty" pat))))))
+                            (unless (string=3D 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-de=
faults act))))
+           (cl-assert (and result (not (string=3D 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)))))
=2D-=20
2.34.1


--=-=-=--

--==-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iQHHBAEBCgAxFiEEI9twfRN7r3nig/xwDsVtFB0W75MFAmViY7cTHHRoaWV2b2xA
cG9zdGVvLm5ldAAKCRAOxW0UHRbvkyYKC/9RXiecwTB6vgNE/dlSve2M8NZyTsQ+
QspssF+GAtIZng1uqBtrTkEOP866cFE3OFUvn/FOd6b3J7+/eVRBPmH2+zVu8uNO
c0uEwzP1eho/THvIL5UEnmdrOdcxi48oeTb4ACtIgmPjwtlFQMMPpBwNR6rLkB4Y
fddk2vbZd6N1R16+nEmKM4B+9CsQf2HgRo5OTbPEKo5iQsss0zzubbauQKCdI+tB
7gQ/eAmUf1LZMuO9hvFUkFwXw75gRvcOpzE5aX3j4fMDNI/iRs6/NaG0+dNzmzJY
gzhodHdkc/G+tvxCvHNjwTYuaOMLITVwWl+m4G4Yp/D614yvcvbWMAw60Wp9seM1
qbOb1ELbaBo4+O7E/NnjiDtLMpGDi7GoOlxbzwPfbyd+1VVKfXEPzcMZiBPYCn9M
LgZaS47Mw+OE0LDRx8zjrsX8t5AcmpjjmbKrPVBRN1XkszQbfcYSuZoZt2K02Ryf
r1r6QuDrzkwvu3bN5V7MN9DlPERyPUnSMDA=
=lTkc
-----END PGP SIGNATURE-----
--==-=-=--