GNU bug report logs - #15525
24.3; register-read-with-preview

Previous Next

Package: emacs;

Reported by: Leo Liu <sdl.web <at> gmail.com>

Date: Fri, 4 Oct 2013 05:59:02 UTC

Severity: wishlist

Tags: patch

Found in version 24.3

Fixed in version 24.4

Done: Glenn Morris <rgm <at> gnu.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 15525 in the body.
You can then email your comments to 15525 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to monnier <at> iro.umontreal.ca, ofv <at> wanadoo.es, bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Fri, 04 Oct 2013 05:59:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Leo Liu <sdl.web <at> gmail.com>:
New bug report received and forwarded. Copy sent to monnier <at> iro.umontreal.ca, ofv <at> wanadoo.es, bug-gnu-emacs <at> gnu.org. (Fri, 04 Oct 2013 05:59:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Leo Liu <sdl.web <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 24.3; register-read-with-preview
Date: Fri, 04 Oct 2013 13:57:26 +0800
[Message part 1 (text/plain, inline)]
register-read-with-preview pops up a window showing existing registers
and brief description. Any comments?

[reg.diff (text/x-patch, inline)]
=== modified file 'lisp/register.el'
--- lisp/register.el	2013-08-09 00:30:24 +0000
+++ lisp/register.el	2013-10-04 05:48:34 +0000
@@ -89,6 +89,11 @@
   :type '(choice (const :tag "None" nil)
 		 (character :tag "Use register" :value ?+)))
 
+(defcustom register-preview-delay 0.5
+  "Delay in seconds before popping up the preview window."
+  :type 'number
+  :group 'register)
+
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
   (cdr (assq register register-alist)))
@@ -102,12 +107,54 @@
       (push (cons register value) register-alist))
     value))
 
+(defun register-describe-oneline (c)
+  (let ((d (replace-regexp-in-string
+            "\n[ \t]*" " "
+            (with-output-to-string (describe-register-1 c)))))
+    (if (string-match "Register.+? contains \\(?:an? \\|the \\)?" d)
+        (substring d (match-end 0))
+      d)))
+
+(defvar register-preview-functions nil)
+
+(defun register-preview (buffer)
+  "Pop up a window to show register preview in BUFFER."
+  (when (consp register-alist)
+    (let ((split-height-threshold 0))
+      (with-temp-buffer-window
+       buffer
+       (cons 'display-buffer-below-selected
+	     '((window-height . fit-window-to-buffer)))
+       nil
+       (with-current-buffer standard-output
+	 (setq cursor-in-non-selected-windows nil)
+	 (mapc (lambda (r)
+		 (insert
+		  (format
+		   "%s %s\n"
+		   (concat (single-key-description (car r)) ":")
+		   (or (run-hook-with-args 'register-preview-functions (cdr r))
+		       (register-describe-oneline (car r))))))
+	       register-alist))))))
+
+(defun register-read-with-preview (prompt)
+  (let* ((buffer "*Register Preview*")
+	 (timer (run-with-timer register-preview-delay nil
+				#'register-preview buffer)))
+    (unwind-protect
+	(read-event (propertize prompt 'face 'minibuffer-prompt))
+      (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 point-to-register (register &optional arg)
   "Store current location of point in register REGISTER.
 With prefix argument, store current frame configuration.
 Use \\[jump-to-register] to go to that location or restore that configuration.
 Argument is a character, naming the register."
-  (interactive "cPoint to register: \nP")
+  (interactive (list (register-read-with-preview "Point to register: ")
+		     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)
   (set-register register
@@ -118,7 +165,9 @@
   "Store the window configuration of the selected frame in register REGISTER.
 Use \\[jump-to-register] to restore the configuration.
 Argument is a character, naming the register."
-  (interactive "cWindow configuration to register: \nP")
+  (interactive (list (register-read-with-preview
+		      "Window configuration to register: ")
+		     current-prefix-arg))
   ;; current-window-configuration does not include the value
   ;; of point in the current buffer, so record that separately.
   (set-register register (list (current-window-configuration) (point-marker))))
@@ -127,7 +176,9 @@
   "Store the window configuration of all frames in register REGISTER.
 Use \\[jump-to-register] to restore the configuration.
 Argument is a character, naming the register."
-  (interactive "cFrame configuration to register: \nP")
+  (interactive (list (register-read-with-preview
+		      "Frame configuration to register: ")
+		     current-prefix-arg))
   ;; current-frame-configuration does not include the value
   ;; of point in the current buffer, so record that separately.
   (set-register register (list (current-frame-configuration) (point-marker))))
@@ -143,7 +194,8 @@
 Optional second arg non-nil (interactively, prefix argument) says to
 delete any existing frames that the frameset doesn't mention.
 \(Otherwise, these frames are iconified.)"
-  (interactive "cJump to register: \nP")
+  (interactive (list (register-read-with-preview "Jump to register: ")
+		     current-prefix-arg))
   (let ((val (get-register register)))
     (cond
      ((registerv-p val)
@@ -190,7 +242,8 @@
 If NUMBER is nil, a decimal number is read from the buffer starting
 at point, and point moves to the end of that number.
 Interactively, NUMBER is the prefix arg (none means nil)."
-  (interactive "P\ncNumber to register: ")
+  (interactive (list current-prefix-arg
+		     (register-read-with-preview "Number to register: ")))
   (set-register register
 		(if number
 		    (prefix-numeric-value number)
@@ -222,7 +275,7 @@
 (defun view-register (register)
   "Display what is contained in register named REGISTER.
 The Lisp value REGISTER is a character."
-  (interactive "cView register: ")
+  (interactive (list (register-read-with-preview "View register: ")))
   (let ((val (get-register register)))
     (if (null val)
 	(message "Register %s is empty" (single-key-description register))
@@ -323,7 +376,10 @@
 Normally puts point before and mark after the inserted text.
 If optional second arg is non-nil, puts mark before and point after.
 Interactively, second arg is non-nil if prefix arg is supplied."
-  (interactive "*cInsert register: \nP")
+  (interactive (progn
+		 (barf-if-buffer-read-only)
+		 (register-read-with-preview "Insert register: ")
+		 current-prefix-arg))
   (push-mark)
   (let ((val (get-register register)))
     (cond
@@ -349,7 +405,10 @@
 With prefix arg, delete as well.
 Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions indicating what to copy."
-  (interactive "cCopy to register: \nr\nP")
+  (interactive (list (register-read-with-preview "Copy to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (set-register register (filter-buffer-substring start end))
   (setq deactivate-mark t)
   (cond (delete-flag
@@ -362,7 +421,10 @@
 With prefix arg, delete as well.
 Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions indicating what to append."
-  (interactive "cAppend to register: \nr\nP")
+  (interactive (list (register-read-with-preview "Append to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (let ((reg (get-register register))
         (text (filter-buffer-substring start end))
 	(separator (and register-separator (get-register register-separator))))
@@ -381,7 +443,10 @@
 With prefix arg, delete as well.
 Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions indicating what to prepend."
-  (interactive "cPrepend to register: \nr\nP")
+  (interactive (list (register-read-with-preview "Prepend to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (let ((reg (get-register register))
         (text (filter-buffer-substring start end))
 	(separator (and register-separator (get-register register-separator))))
@@ -402,7 +467,11 @@
 
 Called from a program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions giving two corners of rectangle."
-  (interactive "cCopy rectangle to register: \nr\nP")
+  (interactive (list (register-read-with-preview
+		      "Copy rectangle to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (let ((rectangle (if delete-flag
 		       (delete-extract-rectangle start end)
 		     (extract-rectangle start end))))
@@ -412,6 +481,5 @@
       (setq deactivate-mark t)
       (indicate-copied-region (length (car rectangle))))))
 
-
 (provide 'register)
 ;;; register.el ends here


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Fri, 04 Oct 2013 13:58:01 GMT) Full text and rfc822 format available.

Message #8 received at 15525 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Leo Liu <sdl.web <at> gmail.com>
Cc: Óscar Fuentes <ofv <at> wanadoo.es>, 15525 <at> debbugs.gnu.org
Subject: Re: bug#15525: 24.3; register-read-with-preview
Date: Fri, 04 Oct 2013 09:57:19 -0400
> register-read-with-preview pops up a window showing existing registers
> and brief description. Any comments?

I like the idea of displaying the available choices, but I'm not sure
"0.5s delay" is a good enough trigger: it's probably a fine choice for
some users, but usually Emacs doesn't like to use such time-dependent
behavior too much.

Could we offer, additionally to the delay, a different trigger
(e.g. help-char and help-event-list)?


        Stefan


PS: How does it compare to register-list?  Could they be consolidated?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Fri, 04 Oct 2013 16:03:02 GMT) Full text and rfc822 format available.

Message #11 received at 15525 <at> debbugs.gnu.org (full text, mbox):

From: Bastien <bzg <at> altern.org>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Óscar Fuentes <ofv <at> wanadoo.es>,
 Leo Liu <sdl.web <at> gmail.com>, 15525 <at> debbugs.gnu.org
Subject: Re: bug#15525: 24.3; register-read-with-preview
Date: Fri, 04 Oct 2013 18:02:10 +0200
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

> PS: How does it compare to register-list?  Could they be
> consolidated?

I hope so.  The Org merge is higher on my todo-list, but working on
register-list.el comes right after.

-- 
 Bastien




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Sat, 05 Oct 2013 03:21:01 GMT) Full text and rfc822 format available.

Message #14 received at 15525 <at> debbugs.gnu.org (full text, mbox):

From: Leo Liu <sdl.web <at> gmail.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Óscar Fuentes <ofv <at> wanadoo.es>, 15525 <at> debbugs.gnu.org
Subject: Re: bug#15525: 24.3; register-read-with-preview
Date: Sat, 05 Oct 2013 11:19:34 +0800
[Message part 1 (text/plain, inline)]
On 2013-10-04 21:57 +0800, Stefan Monnier wrote:
[snipped 3 lines]
> I like the idea of displaying the available choices, but I'm not sure
> "0.5s delay" is a good enough trigger: it's probably a fine choice for
> some users, but usually Emacs doesn't like to use such time-dependent
> behavior too much.
>
> Could we offer, additionally to the delay, a different trigger
> (e.g. help-char and help-event-list)?
>
>
>         Stefan

Good idea. The attached patch implements this. i.e. if one sets
register-preview-delay to t it means forever, i.e. the timer is never
set. Users can customise register-read-help-char to nil if they don't
want any help-char to bring up the preview window.

BTW, the delay is so that if you can remember which register to choose
within some time (0.5s) you shall never see the preview window.

[snipped 10 lines]
>> PS: How does it compare to register-list?  Could they be
>> consolidated?
>
> I hope so.  The Org merge is higher on my todo-list, but working on
> register-list.el comes right after.

I leave a hook i.e. register-preview-functions for customising how the
preview should be presented. I am not sure other ways to have
integration with register-list. Comments welcome.

Best wishes,
Leo

[reg2.diff (text/x-patch, inline)]
=== modified file 'lisp/register.el'
--- lisp/register.el	2013-08-09 00:30:24 +0000
+++ lisp/register.el	2013-10-05 03:08:31 +0000
@@ -89,6 +89,16 @@
   :type '(choice (const :tag "None" nil)
 		 (character :tag "Use register" :value ?+)))
 
+(defcustom register-preview-delay 0.5
+  "Delay in seconds before popping up the preview window."
+  :type '(choice number (const :tag "Indefinitely" t))
+  :group 'register)
+
+(defcustom register-read-help-char help-char
+  "Character to recognize as meaning help."
+  :type '(choice character (const :tag "Never" nil))
+  :group 'register)
+
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
   (cdr (assq register register-alist)))
@@ -102,12 +112,60 @@
       (push (cons register value) register-alist))
     value))
 
+(defun register-describe-oneline (c)
+  (let ((d (replace-regexp-in-string
+            "\n[ \t]*" " "
+            (with-output-to-string (describe-register-1 c)))))
+    (if (string-match "Register.+? contains \\(?:an? \\|the \\)?" d)
+        (substring d (match-end 0))
+      d)))
+
+(defvar register-preview-functions nil)
+
+(defun register-preview (buffer)
+  "Pop up a window to show register preview in BUFFER."
+  (when (consp register-alist)
+    (let ((split-height-threshold 0))
+      (with-temp-buffer-window
+       buffer
+       (cons 'display-buffer-below-selected
+	     '((window-height . fit-window-to-buffer)))
+       nil
+       (with-current-buffer standard-output
+	 (setq cursor-in-non-selected-windows nil)
+	 (mapc (lambda (r)
+		 (insert
+		  (format
+		   "%s %s\n"
+		   (concat (single-key-description (car r)) ":")
+		   (or (run-hook-with-args 'register-preview-functions (cdr r))
+		       (register-describe-oneline (car r))))))
+	       register-alist))))))
+
+(defun register-read-with-preview (prompt)
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  #'register-preview buffer))))
+    (unwind-protect
+	(progn
+	  (while (eq (read-event (propertize prompt 'face 'minibuffer-prompt))
+		     register-read-help-char)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer)))
+	  last-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 point-to-register (register &optional arg)
   "Store current location of point in register REGISTER.
 With prefix argument, store current frame configuration.
 Use \\[jump-to-register] to go to that location or restore that configuration.
 Argument is a character, naming the register."
-  (interactive "cPoint to register: \nP")
+  (interactive (list (register-read-with-preview "Point to register: ")
+		     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)
   (set-register register
@@ -118,7 +176,9 @@
   "Store the window configuration of the selected frame in register REGISTER.
 Use \\[jump-to-register] to restore the configuration.
 Argument is a character, naming the register."
-  (interactive "cWindow configuration to register: \nP")
+  (interactive (list (register-read-with-preview
+		      "Window configuration to register: ")
+		     current-prefix-arg))
   ;; current-window-configuration does not include the value
   ;; of point in the current buffer, so record that separately.
   (set-register register (list (current-window-configuration) (point-marker))))
@@ -127,7 +187,9 @@
   "Store the window configuration of all frames in register REGISTER.
 Use \\[jump-to-register] to restore the configuration.
 Argument is a character, naming the register."
-  (interactive "cFrame configuration to register: \nP")
+  (interactive (list (register-read-with-preview
+		      "Frame configuration to register: ")
+		     current-prefix-arg))
   ;; current-frame-configuration does not include the value
   ;; of point in the current buffer, so record that separately.
   (set-register register (list (current-frame-configuration) (point-marker))))
@@ -143,7 +205,8 @@
 Optional second arg non-nil (interactively, prefix argument) says to
 delete any existing frames that the frameset doesn't mention.
 \(Otherwise, these frames are iconified.)"
-  (interactive "cJump to register: \nP")
+  (interactive (list (register-read-with-preview "Jump to register: ")
+		     current-prefix-arg))
   (let ((val (get-register register)))
     (cond
      ((registerv-p val)
@@ -190,7 +253,8 @@
 If NUMBER is nil, a decimal number is read from the buffer starting
 at point, and point moves to the end of that number.
 Interactively, NUMBER is the prefix arg (none means nil)."
-  (interactive "P\ncNumber to register: ")
+  (interactive (list current-prefix-arg
+		     (register-read-with-preview "Number to register: ")))
   (set-register register
 		(if number
 		    (prefix-numeric-value number)
@@ -222,7 +286,7 @@
 (defun view-register (register)
   "Display what is contained in register named REGISTER.
 The Lisp value REGISTER is a character."
-  (interactive "cView register: ")
+  (interactive (list (register-read-with-preview "View register: ")))
   (let ((val (get-register register)))
     (if (null val)
 	(message "Register %s is empty" (single-key-description register))
@@ -323,7 +387,10 @@
 Normally puts point before and mark after the inserted text.
 If optional second arg is non-nil, puts mark before and point after.
 Interactively, second arg is non-nil if prefix arg is supplied."
-  (interactive "*cInsert register: \nP")
+  (interactive (progn
+		 (barf-if-buffer-read-only)
+		 (register-read-with-preview "Insert register: ")
+		 current-prefix-arg))
   (push-mark)
   (let ((val (get-register register)))
     (cond
@@ -349,7 +416,10 @@
 With prefix arg, delete as well.
 Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions indicating what to copy."
-  (interactive "cCopy to register: \nr\nP")
+  (interactive (list (register-read-with-preview "Copy to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (set-register register (filter-buffer-substring start end))
   (setq deactivate-mark t)
   (cond (delete-flag
@@ -362,7 +432,10 @@
 With prefix arg, delete as well.
 Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions indicating what to append."
-  (interactive "cAppend to register: \nr\nP")
+  (interactive (list (register-read-with-preview "Append to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (let ((reg (get-register register))
         (text (filter-buffer-substring start end))
 	(separator (and register-separator (get-register register-separator))))
@@ -381,7 +454,10 @@
 With prefix arg, delete as well.
 Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions indicating what to prepend."
-  (interactive "cPrepend to register: \nr\nP")
+  (interactive (list (register-read-with-preview "Prepend to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (let ((reg (get-register register))
         (text (filter-buffer-substring start end))
 	(separator (and register-separator (get-register register-separator))))
@@ -402,7 +478,11 @@
 
 Called from a program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions giving two corners of rectangle."
-  (interactive "cCopy rectangle to register: \nr\nP")
+  (interactive (list (register-read-with-preview
+		      "Copy rectangle to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (let ((rectangle (if delete-flag
 		       (delete-extract-rectangle start end)
 		     (extract-rectangle start end))))
@@ -412,6 +492,5 @@
       (setq deactivate-mark t)
       (indicate-copied-region (length (car rectangle))))))
 
-
 (provide 'register)
 ;;; register.el ends here


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Sat, 05 Oct 2013 16:31:01 GMT) Full text and rfc822 format available.

Message #17 received at 15525 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Leo Liu <sdl.web <at> gmail.com>
Cc: Óscar Fuentes <ofv <at> wanadoo.es>, 15525 <at> debbugs.gnu.org
Subject: Re: bug#15525: 24.3; register-read-with-preview
Date: Sat, 05 Oct 2013 12:30:10 -0400
> Good idea. The attached patch implements this. i.e. if one sets
> register-preview-delay to t it means forever,

Good (I'd have used nil rather than t, but it doesn't matter).

I wonder if the default shouldn't be "infinite delay", so as to preserve
existing behavior?

> Users can customise register-read-help-char to nil if they don't want
> any help-char to bring up the preview window.

I think the only valid reason to disable the help-char here is if it
prevents access to an existing register.  So we can get rid of this
custom var and instead make sure we only obey help-char if there is no
existing register by that name.


        Stefan




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Sun, 06 Oct 2013 02:02:02 GMT) Full text and rfc822 format available.

Message #20 received at 15525 <at> debbugs.gnu.org (full text, mbox):

From: Leo Liu <sdl.web <at> gmail.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Óscar Fuentes <ofv <at> wanadoo.es>, Bastien <bzg <at> altern.org>,
 15525 <at> debbugs.gnu.org
Subject: Re: bug#15525: 24.3; register-read-with-preview
Date: Sun, 06 Oct 2013 10:01:05 +0800
[Message part 1 (text/plain, inline)]
On 2013-10-06 00:30 +0800, Stefan Monnier wrote:
> Good (I'd have used nil rather than t, but it doesn't matter).

Done.

> I wonder if the default shouldn't be "infinite delay", so as to preserve
> existing behavior?

Done. (If it is OK I like to turn it on for a month or two for some
testing and then turn it off eventually)

> I think the only valid reason to disable the help-char here is if it
> prevents access to an existing register.  So we can get rid of this
> custom var and instead make sure we only obey help-char if there is no
> existing register by that name.

The trouble is when you create new registers. But I remove that custom
variable anyway since it won't be used much. It is unlikely C-h be used
as a register.

If no one objects I would like to install the attached patch.

Thanks,
Leo

[reg3.diff (text/x-patch, inline)]
=== modified file 'lisp/register.el'
--- lisp/register.el	2013-08-09 00:30:24 +0000
+++ lisp/register.el	2013-10-06 01:56:29 +0000
@@ -1,4 +1,4 @@
-;;; register.el --- register commands for Emacs
+;;; register.el --- register commands for Emacs      -*- lexical-binding: t; -*-
 
 ;; Copyright (C) 1985, 1993-1994, 2001-2013 Free Software Foundation,
 ;; Inc.
@@ -89,6 +89,11 @@
   :type '(choice (const :tag "None" nil)
 		 (character :tag "Use register" :value ?+)))
 
+(defcustom register-preview-delay nil
+  "If non-nil delay in seconds to pop up the preview window."
+  :type '(choice number (const :tag "Indefinitely" nil))
+  :group 'register)
+
 (defun get-register (register)
   "Return contents of Emacs register named REGISTER, or nil if none."
   (cdr (assq register register-alist)))
@@ -102,12 +107,66 @@
       (push (cons register value) register-alist))
     value))
 
+(defun register-describe-oneline (c)
+  "One-line description of register C."
+  (let ((d (replace-regexp-in-string
+            "\n[ \t]*" " "
+            (with-output-to-string (describe-register-1 c)))))
+    (if (string-match "Register.+? contains \\(?:an? \\|the \\)?" d)
+        (substring d (match-end 0))
+      d)))
+
+(defvar register-preview-functions nil)
+
+(defun register-preview (buffer)
+  "Pop up a window to show register preview in BUFFER."
+  (when (consp register-alist)
+    (let ((split-height-threshold 0))
+      (with-temp-buffer-window
+       buffer
+       (cons 'display-buffer-below-selected
+	     '((window-height . fit-window-to-buffer)))
+       nil
+       (with-current-buffer standard-output
+	 (setq cursor-in-non-selected-windows nil)
+	 (mapc
+	  (lambda (r)
+	    (insert (or (run-hook-with-args-until-success
+			 'register-preview-functions r)
+			(format "%s %s\n"
+				(concat (single-key-description (car r)) ":")
+				(register-describe-oneline (car r))))))
+	  register-alist))))))
+
+(defun register-read-with-preview (prompt)
+  "Read an event with register preview using PROMPT.
+Pop up a register preview window if the input is help-char but is
+not a register. Alternatively if `register-preview-delay' is a
+number the preview window is popped up after some delay."
+  (let* ((buffer "*Register Preview*")
+	 (timer (when (numberp register-preview-delay)
+		  (run-with-timer register-preview-delay nil
+				  #'register-preview buffer)))
+	 (help-char (and (not (get-register help-char)) help-char)))
+    (unwind-protect
+	(progn
+	  (while (eq (read-event (propertize prompt 'face 'minibuffer-prompt))
+		     help-char)
+	    (unless (get-buffer-window buffer)
+	      (register-preview buffer)))
+	  last-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 point-to-register (register &optional arg)
   "Store current location of point in register REGISTER.
 With prefix argument, store current frame configuration.
 Use \\[jump-to-register] to go to that location or restore that configuration.
 Argument is a character, naming the register."
-  (interactive "cPoint to register: \nP")
+  (interactive (list (register-read-with-preview "Point to register: ")
+		     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)
   (set-register register
@@ -118,7 +177,9 @@
   "Store the window configuration of the selected frame in register REGISTER.
 Use \\[jump-to-register] to restore the configuration.
 Argument is a character, naming the register."
-  (interactive "cWindow configuration to register: \nP")
+  (interactive (list (register-read-with-preview
+		      "Window configuration to register: ")
+		     current-prefix-arg))
   ;; current-window-configuration does not include the value
   ;; of point in the current buffer, so record that separately.
   (set-register register (list (current-window-configuration) (point-marker))))
@@ -127,7 +188,9 @@
   "Store the window configuration of all frames in register REGISTER.
 Use \\[jump-to-register] to restore the configuration.
 Argument is a character, naming the register."
-  (interactive "cFrame configuration to register: \nP")
+  (interactive (list (register-read-with-preview
+		      "Frame configuration to register: ")
+		     current-prefix-arg))
   ;; current-frame-configuration does not include the value
   ;; of point in the current buffer, so record that separately.
   (set-register register (list (current-frame-configuration) (point-marker))))
@@ -143,7 +206,8 @@
 Optional second arg non-nil (interactively, prefix argument) says to
 delete any existing frames that the frameset doesn't mention.
 \(Otherwise, these frames are iconified.)"
-  (interactive "cJump to register: \nP")
+  (interactive (list (register-read-with-preview "Jump to register: ")
+		     current-prefix-arg))
   (let ((val (get-register register)))
     (cond
      ((registerv-p val)
@@ -190,7 +254,8 @@
 If NUMBER is nil, a decimal number is read from the buffer starting
 at point, and point moves to the end of that number.
 Interactively, NUMBER is the prefix arg (none means nil)."
-  (interactive "P\ncNumber to register: ")
+  (interactive (list current-prefix-arg
+		     (register-read-with-preview "Number to register: ")))
   (set-register register
 		(if number
 		    (prefix-numeric-value number)
@@ -222,7 +287,7 @@
 (defun view-register (register)
   "Display what is contained in register named REGISTER.
 The Lisp value REGISTER is a character."
-  (interactive "cView register: ")
+  (interactive (list (register-read-with-preview "View register: ")))
   (let ((val (get-register register)))
     (if (null val)
 	(message "Register %s is empty" (single-key-description register))
@@ -323,7 +388,10 @@
 Normally puts point before and mark after the inserted text.
 If optional second arg is non-nil, puts mark before and point after.
 Interactively, second arg is non-nil if prefix arg is supplied."
-  (interactive "*cInsert register: \nP")
+  (interactive (progn
+		 (barf-if-buffer-read-only)
+		 (register-read-with-preview "Insert register: ")
+		 current-prefix-arg))
   (push-mark)
   (let ((val (get-register register)))
     (cond
@@ -349,7 +417,10 @@
 With prefix arg, delete as well.
 Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions indicating what to copy."
-  (interactive "cCopy to register: \nr\nP")
+  (interactive (list (register-read-with-preview "Copy to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (set-register register (filter-buffer-substring start end))
   (setq deactivate-mark t)
   (cond (delete-flag
@@ -362,7 +433,10 @@
 With prefix arg, delete as well.
 Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions indicating what to append."
-  (interactive "cAppend to register: \nr\nP")
+  (interactive (list (register-read-with-preview "Append to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (let ((reg (get-register register))
         (text (filter-buffer-substring start end))
 	(separator (and register-separator (get-register register-separator))))
@@ -381,7 +455,10 @@
 With prefix arg, delete as well.
 Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions indicating what to prepend."
-  (interactive "cPrepend to register: \nr\nP")
+  (interactive (list (register-read-with-preview "Prepend to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (let ((reg (get-register register))
         (text (filter-buffer-substring start end))
 	(separator (and register-separator (get-register register-separator))))
@@ -402,7 +479,11 @@
 
 Called from a program, takes four args: REGISTER, START, END and DELETE-FLAG.
 START and END are buffer positions giving two corners of rectangle."
-  (interactive "cCopy rectangle to register: \nr\nP")
+  (interactive (list (register-read-with-preview
+		      "Copy rectangle to register: ")
+		     (region-beginning)
+		     (region-end)
+		     current-prefix-arg))
   (let ((rectangle (if delete-flag
 		       (delete-extract-rectangle start end)
 		     (extract-rectangle start end))))
@@ -412,6 +493,5 @@
       (setq deactivate-mark t)
       (indicate-copied-region (length (car rectangle))))))
 
-
 (provide 'register)
 ;;; register.el ends here


Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Sun, 06 Oct 2013 17:00:03 GMT) Full text and rfc822 format available.

Message #23 received at 15525 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Leo Liu <sdl.web <at> gmail.com>
Cc: Óscar Fuentes <ofv <at> wanadoo.es>,
 Bastien <bzg <at> altern.org>, 15525 <at> debbugs.gnu.org
Subject: Re: bug#15525: 24.3; register-read-with-preview
Date: Sun, 06 Oct 2013 12:59:41 -0400
>> I wonder if the default shouldn't be "infinite delay", so as to preserve
>> existing behavior?
> Done. (If it is OK I like to turn it on for a month or two for some
> testing and then turn it off eventually)

I'm OK with enabling it tentatively, and see if people complain.
You might like to use a slightly longer delay, tho.  For me, 0.5s makes
it pop up the list pretty much all the time (I guess I'm slow).

>> I think the only valid reason to disable the help-char here is if it
>> prevents access to an existing register.  So we can get rid of this
>> custom var and instead make sure we only obey help-char if there is no
>> existing register by that name.
> The trouble is when you create new registers.

The code should not let you create new registers that match help-char.

> But I remove that custom variable anyway since it won't be used
> much. It is unlikely C-h be used as a register.

BTW, we could/should also accept help-event-list events.

> If no one objects I would like to install the attached patch.

Go ahead,


        Stefan




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Mon, 07 Oct 2013 02:36:07 GMT) Full text and rfc822 format available.

Message #26 received at 15525 <at> debbugs.gnu.org (full text, mbox):

From: Leo Liu <sdl.web <at> gmail.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Óscar Fuentes <ofv <at> wanadoo.es>, Bastien <bzg <at> altern.org>,
 15525 <at> debbugs.gnu.org
Subject: Re: bug#15525: 24.3; register-read-with-preview
Date: Mon, 07 Oct 2013 10:35:16 +0800
On 2013-10-07 00:59 +0800, Stefan Monnier wrote:
> I'm OK with enabling it tentatively, and see if people complain.
> You might like to use a slightly longer delay, tho.  For me, 0.5s makes
> it pop up the list pretty much all the time (I guess I'm slow).

I have set it to 1s for now and will set it to nil after 60 days.

[snipped 5 lines]
> The code should not let you create new registers that match help-char.
> BTW, we could/should also accept help-event-list events.

OK, though ? is in help-event-list.

> Go ahead,

Installed.

Leo




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Mon, 07 Oct 2013 04:14:01 GMT) Full text and rfc822 format available.

Message #29 received at 15525 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Leo Liu <sdl.web <at> gmail.com>
Cc: Óscar Fuentes <ofv <at> wanadoo.es>,
 Bastien <bzg <at> altern.org>, 15525 <at> debbugs.gnu.org
Subject: Re: bug#15525: 24.3; register-read-with-preview
Date: Mon, 07 Oct 2013 00:13:46 -0400
>> I'm OK with enabling it tentatively, and see if people complain.
>> You might like to use a slightly longer delay, tho.  For me, 0.5s makes
>> it pop up the list pretty much all the time (I guess I'm slow).
> I have set it to 1s for now and will set it to nil after 60 days.

Not sure why you'd want to set it back to nil if noone complains.

>> The code should not let you create new registers that match help-char.
>> BTW, we could/should also accept help-event-list events.
> OK, though ? is in help-event-list.

I know, and I think it's an important trigger key since it's the one
used in completion (i.e. it's the one I'd try instinctively).


        Stefan




bug marked as fixed in version 24.4, send any further explanations to 15525 <at> debbugs.gnu.org and Leo Liu <sdl.web <at> gmail.com> Request was from Glenn Morris <rgm <at> gnu.org> to control <at> debbugs.gnu.org. (Mon, 07 Oct 2013 06:17:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#15525; Package emacs. (Thu, 10 Oct 2013 12:58:02 GMT) Full text and rfc822 format available.

Message #34 received at 15525-done <at> debbugs.gnu.org (full text, mbox):

From: Leo Liu <sdl.web <at> gmail.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 15525-done <at> debbugs.gnu.org
Subject: Re: bug#15525: 24.3; register-read-with-preview
Date: Thu, 10 Oct 2013 20:56:44 +0800
Fixed in 24.4

On 2013-10-07 12:13 +0800, Stefan Monnier wrote:
> Not sure why you'd want to set it back to nil if noone complains.

OK, I'll DTRT.

>> OK, though ? is in help-event-list.
>
> I know, and I think it's an important trigger key since it's the one
> used in completion (i.e. it's the one I'd try instinctively).

OK.

Leo




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Fri, 08 Nov 2013 12:24:03 GMT) Full text and rfc822 format available.

This bug report was last modified 10 years and 191 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.