aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2025-04-30 12:31:58 -0400
committerStefan Monnier2025-04-30 12:31:58 -0400
commitab9580920278e69ecf1ccbd8dbf3cc1a0f8b019f (patch)
treeb25a6af9b2e4426b6a9cf5d6045ebe480d6da08e
parentcb701f95c61e95298fb7d06f9f98f017dadfbcfe (diff)
parent1284b6f1187be768e1af013339d7a228c6a8e84d (diff)
downloademacs-ab9580920278e69ecf1ccbd8dbf3cc1a0f8b019f.tar.gz
emacs-ab9580920278e69ecf1ccbd8dbf3cc1a0f8b019f.zip
Merge branch 'cleanup-register-preview'
-rw-r--r--lisp/frameset.el11
-rw-r--r--lisp/register.el440
2 files changed, 159 insertions, 292 deletions
diff --git a/lisp/frameset.el b/lisp/frameset.el
index 9de16750c44..ee30f77c3ba 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -1412,15 +1412,15 @@ All keyword parameters default to nil."
1412 :reuse-frames (if arg t 'match) 1412 :reuse-frames (if arg t 'match)
1413 :cleanup-frames (if arg 1413 :cleanup-frames (if arg
1414 ;; delete frames 1414 ;; delete frames
1415 nil 1415 t
1416 ;; iconify frames 1416 ;; iconify frames
1417 (lambda (frame action) 1417 (lambda (frame action)
1418 (pcase action 1418 (pcase action
1419 ('rejected (iconify-frame frame)) 1419 (:rejected (iconify-frame frame))
1420 ;; In the unexpected case that a frame was a candidate 1420 ;; In the unexpected case that a frame was a candidate
1421 ;; (matching frame id) and yet not restored, remove it 1421 ;; (matching frame id) and yet not restored, remove it
1422 ;; because it is in fact a duplicate. 1422 ;; because it is in fact a duplicate.
1423 ('ignored (delete-frame frame)))))) 1423 (:ignored (delete-frame frame))))))
1424 1424
1425 ;; Restore selected frame, buffer and point. 1425 ;; Restore selected frame, buffer and point.
1426 (let ((frame (frameset-frame-with-id (frameset-register-frame-id data))) 1426 (let ((frame (frameset-frame-with-id (frameset-register-frame-id data)))
@@ -1444,11 +1444,6 @@ Called from `list-registers' and `view-register'. Internal use only."
1444 (if (= 1 ns) "" "s") 1444 (if (= 1 ns) "" "s")
1445 (format-time-string "%c" (frameset-timestamp fs)))))) 1445 (format-time-string "%c" (frameset-timestamp fs))))))
1446 1446
1447(cl-defmethod register--type ((_regval frameset-register))
1448 ;; FIXME: Why `frame' rather than `frameset'?
1449 ;; FIXME: We shouldn't need to touch an internal function.
1450 'frame)
1451
1452;;;###autoload 1447;;;###autoload
1453(defun frameset-to-register (register) 1448(defun frameset-to-register (register)
1454 "Store the current frameset in register REGISTER. 1449 "Store the current frameset in register REGISTER.
diff --git a/lisp/register.el b/lisp/register.el
index cdb769991f4..a36d0e6648e 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -90,7 +90,6 @@ A list of the form (FRAME-CONFIGURATION POSITION)
90When collecting text with \\[append-to-register] (or \\[prepend-to-register]), 90When collecting text with \\[append-to-register] (or \\[prepend-to-register]),
91contents of this register is added to the beginning (or end, respectively) 91contents of this register is added to the beginning (or end, respectively)
92of the marked text." 92of the marked text."
93 :group 'register
94 :type '(choice (const :tag "None" nil) 93 :type '(choice (const :tag "None" nil)
95 (character :tag "Use register" :value ?+))) 94 (character :tag "Use register" :value ?+)))
96 95
@@ -100,10 +99,9 @@ If nil, do not show register previews, unless `help-char' (or a member of
100`help-event-list') is pressed. 99`help-event-list') is pressed.
101 100
102This variable has no effect when `register-use-preview' is set to any 101This variable has no effect when `register-use-preview' is set to any
103value except \\='traditional." 102value except `traditional'."
104 :version "24.4" 103 :version "24.4"
105 :type '(choice number (const :tag "No preview unless requested" nil)) 104 :type '(choice number (const :tag "No preview unless requested" nil)))
106 :group 'register)
107 105
108(defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z)) 106(defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
109 "Default keys for setting a new register." 107 "Default keys for setting a new register."
@@ -112,7 +110,8 @@ value except \\='traditional."
112 110
113(defvar register--read-with-preview-function nil 111(defvar register--read-with-preview-function nil
114 "Function to use for reading a register name with preview. 112 "Function to use for reading a register name with preview.
115Two functions are provided, one that provide navigation and highlighting 113Should implement the behavior documented for `register-read-with-preview'.
114Two functions are provided, one that provides navigation and highlighting
116of the selected register, filtering of register according to command in 115of the selected register, filtering of register according to command in
117use, defaults register to use when setting a new register, confirmation 116use, defaults register to use when setting a new register, confirmation
118and notification when you are about to overwrite a register, and generic 117and notification when you are about to overwrite a register, and generic
@@ -122,12 +121,11 @@ provided function, `register-read-with-preview-traditional', behaves
122the same as in Emacs 29 and before: no filtering, no navigation, 121the same as in Emacs 29 and before: no filtering, no navigation,
123and no defaults.") 122and no defaults.")
124 123
125(defvar register-preview-function nil 124(defvar register-preview-function #'register-preview-default
126 "Function to format a register for previewing. 125 "Function to format a register for previewing.
127Called with one argument, a cons (NAME . CONTENTS), as found 126Called with one argument, a cons (NAME . CONTENTS), as found
128in `register-alist'. The function should return a string, the 127in `register-alist'. The function should return a string, the
129description of the argument. The function to use is set according 128description of the argument.")
130to the value of `register--read-with-preview-function'.")
131 129
132(defcustom register-use-preview 'traditional 130(defcustom register-use-preview 'traditional
133 "Whether register commands show preview of registers with non-nil values. 131 "Whether register commands show preview of registers with non-nil values.
@@ -160,8 +158,7 @@ behavior of Emacs 29 and before."
160 (setq register--read-with-preview-function 158 (setq register--read-with-preview-function
161 (if (eq val 'traditional) 159 (if (eq val 'traditional)
162 #'register-read-with-preview-traditional 160 #'register-read-with-preview-traditional
163 #'register-read-with-preview-fancy)) 161 #'register-read-with-preview-fancy))))
164 (setq register-preview-function nil)))
165 162
166(defun get-register (register) 163(defun get-register (register)
167 "Return contents of Emacs register named REGISTER, or nil if none." 164 "Return contents of Emacs register named REGISTER, or nil if none."
@@ -181,139 +178,13 @@ See the documentation of the variable `register-alist' for possible VALUEs."
181 (substring d (match-end 0)) 178 (substring d (match-end 0))
182 d))) 179 d)))
183 180
184(defun register-preview-default-1 (r)
185 "Function used to format a register for fancy previewing.
186This is used as the value of the variable `register-preview-function'
187when `register-use-preview' is set to t or nil."
188 (format "%s: %s\n"
189 (propertize (string (car r))
190 'display (single-key-description (car r)))
191 (register-describe-oneline (car r))))
192
193(defun register-preview-default (r) 181(defun register-preview-default (r)
194 "Function used to format a register for traditional preview. 182 "Function used to format a register for previewing.
195This is the default value of the variable `register-preview-function', 183This is the default value of the variable `register-preview-function'."
196and is used when `register-use-preview' is set to \\='traditional."
197 (format "%s: %s\n" 184 (format "%s: %s\n"
198 (single-key-description (car r)) 185 (single-key-description (car r))
199 (register-describe-oneline (car r)))) 186 (register-describe-oneline (car r))))
200 187
201(cl-defgeneric register--preview-function (read-preview-function)
202 "Return a function to format registers for previewing by READ-PREVIEW-FUNCTION.")
203(cl-defmethod register--preview-function ((_read-preview-function
204 (eql register-read-with-preview-traditional)))
205 #'register-preview-default)
206(cl-defmethod register--preview-function ((_read-preview-function
207 (eql register-read-with-preview-fancy)))
208 #'register-preview-default-1)
209
210(cl-defstruct register-preview-info
211 "Store data for a specific register command.
212TYPES are the supported types of registers.
213MSG is the minibuffer message to show when a register is selected.
214ACT is the type of action the command is doing on register.
215SMATCH accept a boolean value to say if the command accepts non-matching
216registers.
217If NOCONFIRM is non-nil, request confirmation of register name by RET."
218 types msg act smatch noconfirm)
219
220(cl-defgeneric register-command-info (command)
221 "Return a `register-preview-info' object storing data for COMMAND."
222 (ignore command))
223(cl-defmethod register-command-info ((_command (eql insert-register)))
224 (make-register-preview-info
225 :types '(string number)
226 :msg "Insert register `%s'"
227 :act 'insert
228 :smatch t
229 :noconfirm (memq register-use-preview '(nil never))))
230(cl-defmethod register-command-info ((_command (eql jump-to-register)))
231 (make-register-preview-info
232 :types '(window frame marker kmacro
233 file buffer file-query)
234 :msg "Jump to register `%s'"
235 :act 'jump
236 :smatch t
237 :noconfirm (memq register-use-preview '(nil never))))
238(cl-defmethod register-command-info ((_command (eql view-register)))
239 (make-register-preview-info
240 :types '(all)
241 :msg "View register `%s'"
242 :act 'view
243 :noconfirm (memq register-use-preview '(nil never))
244 :smatch t))
245(cl-defmethod register-command-info ((_command (eql append-to-register)))
246 (make-register-preview-info
247 :types '(string number)
248 :msg "Append to register `%s'"
249 :act 'modify
250 :noconfirm (memq register-use-preview '(nil never))
251 :smatch t))
252(cl-defmethod register-command-info ((_command (eql prepend-to-register)))
253 (make-register-preview-info
254 :types '(string number)
255 :msg "Prepend to register `%s'"
256 :act 'modify
257 :noconfirm (memq register-use-preview '(nil never))
258 :smatch t))
259(cl-defmethod register-command-info ((_command (eql increment-register)))
260 (make-register-preview-info
261 :types '(string number)
262 :msg "Increment register `%s'"
263 :act 'modify
264 :noconfirm (memq register-use-preview '(nil never))
265 :smatch t))
266(cl-defmethod register-command-info ((_command (eql copy-to-register)))
267 (make-register-preview-info
268 :types '(all)
269 :msg "Copy to register `%s'"
270 :act 'set
271 :noconfirm (memq register-use-preview '(nil never))))
272(cl-defmethod register-command-info ((_command (eql point-to-register)))
273 (make-register-preview-info
274 :types '(all)
275 :msg "Point to register `%s'"
276 :act 'set
277 :noconfirm (memq register-use-preview '(nil never))))
278(cl-defmethod register-command-info ((_command (eql number-to-register)))
279 (make-register-preview-info
280 :types '(all)
281 :msg "Number to register `%s'"
282 :act 'set
283 :noconfirm (memq register-use-preview '(nil never))))
284(cl-defmethod register-command-info
285 ((_command (eql window-configuration-to-register)))
286 (make-register-preview-info
287 :types '(all)
288 :msg "Window configuration to register `%s'"
289 :act 'set
290 :noconfirm (memq register-use-preview '(nil never))))
291(cl-defmethod register-command-info ((_command (eql frameset-to-register)))
292 (make-register-preview-info
293 :types '(all)
294 :msg "Frameset to register `%s'"
295 :act 'set
296 :noconfirm (memq register-use-preview '(nil never))))
297(cl-defmethod register-command-info ((_command (eql copy-rectangle-to-register)))
298 (make-register-preview-info
299 :types '(all)
300 :msg "Copy rectangle to register `%s'"
301 :act 'set
302 :noconfirm (memq register-use-preview '(nil never))
303 :smatch t))
304(cl-defmethod register-command-info ((_command (eql file-to-register)))
305 (make-register-preview-info
306 :types '(all)
307 :msg "File to register `%s'"
308 :act 'set
309 :noconfirm (memq register-use-preview '(nil never))))
310(cl-defmethod register-command-info ((_command (eql buffer-to-register)))
311 (make-register-preview-info
312 :types '(all)
313 :msg "Buffer to register `%s'"
314 :act 'set
315 :noconfirm (memq register-use-preview '(nil never))))
316
317(defun register-preview-forward-line (arg) 188(defun register-preview-forward-line (arg)
318 "Move to next or previous line in register preview buffer. 189 "Move to next or previous line in register preview buffer.
319If ARG is positive, go to next line; if negative, go to previous line. 190If ARG is positive, go to next line; if negative, go to previous line.
@@ -324,25 +195,23 @@ Do nothing when defining or executing kmacros."
324 (let ((fn (if (> arg 0) #'eobp #'bobp)) 195 (let ((fn (if (> arg 0) #'eobp #'bobp))
325 (posfn (if (> arg 0) 196 (posfn (if (> arg 0)
326 #'point-min 197 #'point-min
327 (lambda () (1- (point-max))))) 198 (lambda () (1- (point-max))))))
328 str)
329 (with-current-buffer "*Register Preview*" 199 (with-current-buffer "*Register Preview*"
330 (let ((ovs (overlays-in (point-min) (point-max))) 200 (let ((ovs (overlays-in (point-min) (point-max)))
331 pos) 201 pos)
332 (goto-char (if ovs 202 (goto-char (if ovs
333 (overlay-start (car ovs)) 203 (overlay-start (car ovs))
334 (point-min))) 204 (point-min)))
335 (setq pos (point)) 205 (setq pos (point))
336 (and ovs (forward-line arg)) 206 (and ovs (forward-line arg))
337 (when (and (funcall fn) 207 (when (and (funcall fn)
338 (or (> arg 0) (eql pos (point)))) 208 (or (> arg 0) (eql pos (point))))
339 (goto-char (funcall posfn))) 209 (goto-char (funcall posfn)))
340 (setq str (buffer-substring-no-properties 210 (let ((reg (get-text-property (pos-bol) 'register--name)))
341 (pos-bol) (1+ (pos-bol)))) 211 (remove-overlays)
342 (remove-overlays) 212 (with-selected-window (minibuffer-window)
343 (with-selected-window (minibuffer-window) 213 (delete-minibuffer-contents)
344 (delete-minibuffer-contents) 214 (insert (string reg)))))))))
345 (insert str)))))))
346 215
347(defun register-preview-next () 216(defun register-preview-next ()
348 "Go to next line in the register preview buffer." 217 "Go to next line in the register preview buffer."
@@ -354,66 +223,41 @@ Do nothing when defining or executing kmacros."
354 (interactive) 223 (interactive)
355 (register-preview-forward-line -1)) 224 (register-preview-forward-line -1))
356 225
357(defun register-type (register) 226(defun register-of-type-alist (pred)
358 "Return REGISTER type. 227 "Filter `register-alist' according to PRED."
359Register type that can be returned is one of the following: 228 (if (null pred)
360 - string
361 - number
362 - marker
363 - buffer
364 - file
365 - file-query
366 - window
367 - frame
368 - kmacro
369
370One can add new types to a specific command by defining a new `cl-defmethod'
371matching that command. Predicates for type in new `cl-defmethod' should
372satisfy `cl-typep', otherwise the new type should be defined with
373`cl-deftype'."
374 ;; Call register--type against the register value.
375 (register--type (if (consp (cdr register))
376 (cadr register)
377 (cdr register))))
378
379(cl-defgeneric register--type (regval)
380 "Return the type of register value REGVAL."
381 (ignore regval))
382
383(cl-defmethod register--type ((_regval string)) 'string)
384(cl-defmethod register--type ((_regval number)) 'number)
385(cl-defmethod register--type ((_regval marker)) 'marker)
386(cl-defmethod register--type ((_regval (eql buffer))) 'buffer)
387(cl-defmethod register--type ((_regval (eql file))) 'file)
388(cl-defmethod register--type ((_regval (eql file-query))) 'file-query)
389(cl-defmethod register--type ((_regval window-configuration)) 'window)
390(cl-defmethod register--type ((regval oclosure)) (oclosure-type regval))
391
392(defun register-of-type-alist (types)
393 "Filter `register-alist' according to TYPES."
394 (if (memq 'all types)
395 register-alist 229 register-alist
396 (cl-loop for register in register-alist 230 (cl-loop for register in register-alist
397 when (memq (register-type register) types) 231 when (funcall pred (cdr register))
398 collect register))) 232 collect register)))
399 233
400(defun register-preview (buffer &optional show-empty) 234(defun register-preview (buffer &optional show-empty pred)
401 "Pop up a window showing the preview of registers in BUFFER. 235 "Pop up a window showing the preview of registers in BUFFER.
402If SHOW-EMPTY is non-nil, show the preview window even if no registers. 236If SHOW-EMPTY is non-nil, show the preview window even if no registers.
237Optional argument PRED specifies the types of register to show;
238if it is nil, show all the registers.
403Format of each entry is controlled by the variable `register-preview-function'." 239Format of each entry is controlled by the variable `register-preview-function'."
404 (unless register-preview-function 240 (let ((registers (register-of-type-alist pred)))
405 (setq register-preview-function (register--preview-function 241 (when (or show-empty (consp registers))
406 register--read-with-preview-function))) 242 (with-current-buffer-window
407 (when (or show-empty (consp register-alist)) 243 buffer
408 (with-current-buffer-window buffer
409 register-preview-display-buffer-alist 244 register-preview-display-buffer-alist
410 nil 245 nil
411 (with-current-buffer standard-output 246 (with-current-buffer standard-output
412 (setq cursor-in-non-selected-windows nil) 247 (setq cursor-in-non-selected-windows nil)
413 (mapc (lambda (elem) 248 (dolist (elem registers)
414 (when (get-register (car elem)) 249 (when (cdr elem)
415 (insert (funcall register-preview-function elem)))) 250 (let ((beg (point)))
416 register-alist))))) 251 (insert (funcall register-preview-function elem))
252 (put-text-property beg (point)
253 'register--name (car elem))))))))))
254
255(defun register--find-preview (regname)
256 (goto-char (point-min))
257 (while (not (or (eobp)
258 (eql regname (get-text-property (point) 'register--name))))
259 (forward-line 1))
260 (not (eobp)))
417 261
418(defcustom register-preview-display-buffer-alist '(display-buffer-at-bottom 262(defcustom register-preview-display-buffer-alist '(display-buffer-at-bottom
419 (window-height . fit-window-to-buffer) 263 (window-height . fit-window-to-buffer)
@@ -422,49 +266,30 @@ Format of each entry is controlled by the variable `register-preview-function'."
422 :type display-buffer--action-custom-type 266 :type display-buffer--action-custom-type
423 :version "30.1") 267 :version "30.1")
424 268
425(defun register-preview-1 (buffer &optional show-empty types) 269(defun register--preview-get-defaults (pred strs)
426 "Pop up a window showing the preview of registers in BUFFER. 270 "Return default registers according to PRED and available registers.
271STRS is the list of non-empty registers that match PRED,"
272 (unless pred
273 (cl-loop for s in register-preview-default-keys
274 unless (member s strs)
275 collect s)))
427 276
428This is the preview function used with the `register-read-with-preview-fancy' 277(defun register-read-with-preview (prompt &optional pred)
429function.
430If SHOW-EMPTY is non-nil, show the preview window even if no registers.
431Optional argument TYPES (a list) specifies the types of register to show;
432if it is nil, show all the registers. See `register-type' for suitable types.
433Format of each entry is controlled by the variable `register-preview-function'."
434 (unless register-preview-function
435 (setq register-preview-function (register--preview-function
436 register--read-with-preview-function)))
437 (let ((registers (register-of-type-alist (or types '(all)))))
438 (when (or show-empty (consp registers))
439 (with-current-buffer-window
440 buffer
441 register-preview-display-buffer-alist
442 nil
443 (with-current-buffer standard-output
444 (setq cursor-in-non-selected-windows nil)
445 (mapc (lambda (elem)
446 (when (get-register (car elem))
447 (insert (funcall register-preview-function elem))))
448 registers))))))
449
450(cl-defgeneric register-preview-get-defaults (action)
451 "Return default registers according to ACTION."
452 (ignore action))
453(cl-defmethod register-preview-get-defaults ((_action (eql set)))
454 (cl-loop for s in register-preview-default-keys
455 unless (assoc (string-to-char s) register-alist)
456 collect s))
457
458(defun register-read-with-preview (prompt)
459 "Read register name, prompting with PROMPT; possibly show existing registers. 278 "Read register name, prompting with PROMPT; possibly show existing registers.
460This reads and returns the name of a register. PROMPT should be a string 279This reads and returns the name of a register. PROMPT should be a string
461to prompt the user for the name. 280to prompt the user for the name.
462If `help-char' (or a member of `help-event-list') is pressed, 281If `help-char' (or a member of `help-event-list') is pressed,
463display preview window unconditionally. 282display preview window unconditionally.
283
284PRED if non-nil should be a function specifying the kinds of registers that
285can be used. It is called with one argument, a register value, and should
286return non-nil if and only if that register value can be used.
287The register value nil represents an empty register.
288
464This calls the function specified by `register--read-with-preview-function'." 289This calls the function specified by `register--read-with-preview-function'."
465 (funcall register--read-with-preview-function prompt)) 290 (funcall register--read-with-preview-function prompt pred))
466 291
467(defun register-read-with-preview-traditional (prompt) 292(defun register-read-with-preview-traditional (prompt &optional _pred)
468 "Read register name, prompting with PROMPT; possibly show existing registers. 293 "Read register name, prompting with PROMPT; possibly show existing registers.
469This reads and returns the name of a register. PROMPT should be a string 294This reads and returns the name of a register. PROMPT should be a string
470to prompt the user for the name. 295to prompt the user for the name.
@@ -474,7 +299,7 @@ If `help-char' (or a member of `help-event-list') is pressed,
474display preview window unconditionally. 299display preview window unconditionally.
475 300
476This function is used as the value of `register--read-with-preview-function' 301This function is used as the value of `register--read-with-preview-function'
477when `register-use-preview' is set to \\='traditional." 302when `register-use-preview' is set to `traditional'."
478 (let* ((buffer "*Register Preview*") 303 (let* ((buffer "*Register Preview*")
479 (timer (when (numberp register-preview-delay) 304 (timer (when (numberp register-preview-delay)
480 (run-with-timer register-preview-delay nil 305 (run-with-timer register-preview-delay nil
@@ -501,7 +326,7 @@ when `register-use-preview' is set to \\='traditional."
501 (and (window-live-p w) (delete-window w))) 326 (and (window-live-p w) (delete-window w)))
502 (and (get-buffer buffer) (kill-buffer buffer))))) 327 (and (get-buffer buffer) (kill-buffer buffer)))))
503 328
504(defun register-read-with-preview-fancy (prompt) 329(defun register-read-with-preview-fancy (prompt &optional pred)
505 "Read register name, prompting with PROMPT; possibly show existing registers. 330 "Read register name, prompting with PROMPT; possibly show existing registers.
506This reads and returns the name of a register. PROMPT should be a string 331This reads and returns the name of a register. PROMPT should be a string
507to prompt the user for the name. 332to prompt the user for the name.
@@ -509,8 +334,8 @@ If `help-char' (or a member of `help-event-list') is pressed,
509display preview window regardless. 334display preview window regardless.
510 335
511This function is used as the value of `register--read-with-preview-function' 336This function is used as the value of `register--read-with-preview-function'
512when `register-use-preview' is set to any value other than \\='traditional 337when `register-use-preview' is set to any value other than `traditional'
513or \\='never." 338or `never'."
514 (let* ((buffer "*Register Preview*") 339 (let* ((buffer "*Register Preview*")
515 (buffer1 "*Register quick preview*") 340 (buffer1 "*Register quick preview*")
516 (buf (if register-use-preview buffer buffer1)) 341 (buf (if register-use-preview buffer buffer1))
@@ -518,23 +343,18 @@ or \\='never."
518 (map (let ((m (make-sparse-keymap))) 343 (map (let ((m (make-sparse-keymap)))
519 (set-keymap-parent m minibuffer-local-map) 344 (set-keymap-parent m minibuffer-local-map)
520 m)) 345 m))
521 (data (register-command-info this-command))
522 (enable-recursive-minibuffers t) 346 (enable-recursive-minibuffers t)
523 types msg result act win strs smatch noconfirm) 347 result win
524 (if data 348 (msg (if (string-match ":? *\\'" prompt)
525 (setq types (register-preview-info-types data) 349 (concat (substring prompt 0 (match-beginning 0))
526 msg (register-preview-info-msg data) 350 " `%s'")
527 act (register-preview-info-act data) 351 "Using register `%s'"))
528 smatch (register-preview-info-smatch data) 352 (noconfirm (memq register-use-preview '(nil never)))
529 noconfirm (register-preview-info-noconfirm data)) 353 (strs (mapcar (lambda (x)
530 (setq types '(all)
531 msg "Overwrite register `%s'"
532 act 'set))
533 (setq strs (mapcar (lambda (x)
534 (string (car x))) 354 (string (car x)))
535 (register-of-type-alist types))) 355 (register-of-type-alist pred))))
536 (when (and (memq act '(insert jump view)) (null strs)) 356 (when (and pred (not (funcall pred nil)) (null strs))
537 (error "No register suitable for `%s'" act)) 357 (error "No suitable register"))
538 (dolist (k (cons help-char help-event-list)) 358 (dolist (k (cons help-char help-event-list))
539 (define-key map (vector k) 359 (define-key map (vector k)
540 (lambda () 360 (lambda ()
@@ -542,23 +362,25 @@ or \\='never."
542 ;; Do nothing when buffer1 is in use. 362 ;; Do nothing when buffer1 is in use.
543 (unless (get-buffer-window buf) 363 (unless (get-buffer-window buf)
544 (with-selected-window (minibuffer-selected-window) 364 (with-selected-window (minibuffer-selected-window)
545 (register-preview-1 buffer 'show-empty types)))))) 365 (register-preview buffer 'show-empty pred))))))
546 (define-key map (kbd "<down>") 'register-preview-next) 366 (define-key map (kbd "<down>") #'register-preview-next)
547 (define-key map (kbd "<up>") 'register-preview-previous) 367 (define-key map (kbd "<up>") #'register-preview-previous)
548 (define-key map (kbd "C-n") 'register-preview-next) 368 (define-key map (kbd "C-n") #'register-preview-next)
549 (define-key map (kbd "C-p") 'register-preview-previous) 369 (define-key map (kbd "C-p") #'register-preview-previous)
550 (unless (or executing-kbd-macro (eq register-use-preview 'never)) 370 (unless (or executing-kbd-macro (eq register-use-preview 'never))
551 (register-preview-1 buf nil types)) 371 (register-preview buf nil pred))
552 (unwind-protect 372 (unwind-protect
553 (let ((setup 373 (let ((setup ;; FIXME: Weird name for a `post-command-hook' function.
554 (lambda () 374 (lambda ()
555 (with-selected-window (minibuffer-window) 375 (with-selected-window (minibuffer-window)
556 (let ((input (minibuffer-contents))) 376 (let ((input (minibuffer-contents)))
557 (when (> (length input) 1) 377 (when (> (length input) 1)
558 (let ((new (substring input 1)) 378 ;; Only keep the first of the new chars.
559 (old (substring input 0 1))) 379 (let* ((new (substring input 1 2))
560 (setq input (if (or (null smatch) 380 (old (substring input 0 1))
561 (member new strs)) 381 (newreg (aref new 0))
382 (regval (cdr (assq newreg register-alist))))
383 (setq input (if (or (null pred) (funcall pred regval))
562 new old)) 384 new old))
563 (delete-minibuffer-contents) 385 (delete-minibuffer-contents)
564 (insert input) 386 (insert input)
@@ -567,19 +389,27 @@ or \\='never."
567 (when (and (string= new old) 389 (when (and (string= new old)
568 (eq register-use-preview 'insist)) 390 (eq register-use-preview 'insist))
569 (setq noconfirm t)))) 391 (setq noconfirm t))))
570 (when (and smatch (not (string= input "")) 392 (when (and pred (not (string= input ""))
571 (not (member input strs))) 393 (let* ((reg (aref input 0))
394 (regval (cdr (assq reg register-alist))))
395 (not (funcall pred regval))))
572 (setq input "") 396 (setq input "")
573 (delete-minibuffer-contents) 397 (delete-minibuffer-contents)
574 (minibuffer-message "Not matching")) 398 (minibuffer-message "Not matching"))
575 (when (not (string= input pat)) 399 (when (not (string= input pat)) ;; FIXME: Why this test?
576 (setq pat input)))) 400 (setq pat input))))
401 (unless (or (string= pat "")
402 (get-text-property (minibuffer-prompt-end)
403 'display))
404 (put-text-property (minibuffer-prompt-end)
405 (1+ (minibuffer-prompt-end))
406 'display (key-description pat)))
577 (if (setq win (get-buffer-window buffer)) 407 (if (setq win (get-buffer-window buffer))
578 (with-selected-window win 408 (with-selected-window win
579 (when (or (eq noconfirm t) ; Using insist 409 (when (or (eq noconfirm t) ; Using insist
580 ;; Don't exit when noconfirm == (never) 410 ;; Don't exit when noconfirm == (never)
581 ;; If we are here user has pressed C-h 411 ;; If we are here user has pressed C-h
582 ;; calling `register-preview-1'. 412 ;; calling `register-preview'.
583 (memq nil noconfirm)) 413 (memq nil noconfirm))
584 ;; Happen only when 414 ;; Happen only when
585 ;; *-use-preview == insist. 415 ;; *-use-preview == insist.
@@ -592,25 +422,26 @@ or \\='never."
592 (goto-char (point-min)) 422 (goto-char (point-min))
593 (remove-overlays) 423 (remove-overlays)
594 (unless (string= pat "") 424 (unless (string= pat "")
595 (if (re-search-forward (concat "^" pat) nil t) 425 (if (register--find-preview (aref pat 0))
596 (progn (move-overlay 426 (progn (move-overlay ov (point) (pos-eol))
597 ov
598 (match-beginning 0) (pos-eol))
599 (overlay-put ov 'face 'match) 427 (overlay-put ov 'face 'match)
600 (when msg 428 (when msg
601 (with-selected-window 429 (with-selected-window
602 (minibuffer-window) 430 (minibuffer-window)
603 (minibuffer-message msg pat)))) 431 (minibuffer-message
432 msg (key-description pat)))))
604 (with-selected-window (minibuffer-window) 433 (with-selected-window (minibuffer-window)
605 (minibuffer-message 434 (minibuffer-message
606 "Register `%s' is empty" pat)))))) 435 "Register `%s' is empty"
436 (key-description pat)))))))
607 (unless (string= pat "") 437 (unless (string= pat "")
608 (with-selected-window (minibuffer-window) 438 (with-selected-window (minibuffer-window)
609 (if (and (member pat strs) 439 (if (and (member pat strs)
610 (null noconfirm)) 440 (null noconfirm))
611 (with-selected-window (minibuffer-window) 441 (with-selected-window (minibuffer-window)
612 (minibuffer-message msg pat)) 442 (minibuffer-message
613 ;; `:noconfirm' is specified explicitly, don't ask for 443 msg (key-description pat)))
444 ;; `noconfirm' is specified explicitly, don't ask for
614 ;; confirmation and exit immediately (bug#66394). 445 ;; confirmation and exit immediately (bug#66394).
615 (setq result pat) 446 (setq result pat)
616 (exit-minibuffer)))))))) 447 (exit-minibuffer))))))))
@@ -618,7 +449,7 @@ or \\='never."
618 (lambda () (add-hook 'post-command-hook setup nil 'local)) 449 (lambda () (add-hook 'post-command-hook setup nil 'local))
619 (setq result (read-from-minibuffer 450 (setq result (read-from-minibuffer
620 prompt nil map nil nil 451 prompt nil map nil nil
621 (register-preview-get-defaults act)))) 452 (register--preview-get-defaults pred strs))))
622 (cl-assert (and result (not (string= result ""))) 453 (cl-assert (and result (not (string= result "")))
623 nil "No register specified") 454 nil "No register specified")
624 (string-to-char result)) 455 (string-to-char result))
@@ -639,7 +470,7 @@ Interactively, prompt for REGISTER using `register-read-with-preview'."
639 "Point to register: ")) 470 "Point to register: "))
640 current-prefix-arg)) 471 current-prefix-arg))
641 ;; Turn the marker into a file-ref if the buffer is killed. 472 ;; Turn the marker into a file-ref if the buffer is killed.
642 (add-hook 'kill-buffer-hook 'register-swap-out nil t) 473 (add-hook 'kill-buffer-hook #'register-swap-out nil t)
643 (set-register register 474 (set-register register
644 ;; FIXME: How does this `current-frame-configuration' differ 475 ;; FIXME: How does this `current-frame-configuration' differ
645 ;; in practice with what `frameset-to-register' does? 476 ;; in practice with what `frameset-to-register' does?
@@ -683,7 +514,7 @@ Interactively, prompt for REGISTER using `register-read-with-preview'."
683 514
684(make-obsolete 'frame-configuration-to-register 'frameset-to-register "24.4") 515(make-obsolete 'frame-configuration-to-register 'frameset-to-register "24.4")
685 516
686(defalias 'register-to-point 'jump-to-register) 517(defalias 'register-to-point #'jump-to-register)
687(defun jump-to-register (register &optional delete) 518(defun jump-to-register (register &optional delete)
688 "Go to location stored in REGISTER, or restore configuration stored there. 519 "Go to location stored in REGISTER, or restore configuration stored there.
689Push the mark if going to the location moves point, unless called in succession. 520Push the mark if going to the location moves point, unless called in succession.
@@ -699,7 +530,9 @@ to delete any existing frames that the frameset doesn't mention.
699ignored if the register contains anything but a frameset. 530ignored if the register contains anything but a frameset.
700 531
701Interactively, prompt for REGISTER using `register-read-with-preview'." 532Interactively, prompt for REGISTER using `register-read-with-preview'."
702 (interactive (list (register-read-with-preview "Jump to register: ") 533 (interactive (list (register-read-with-preview
534 "Jump to register: "
535 #'register--jumpable-p)
703 current-prefix-arg)) 536 current-prefix-arg))
704 (let ((val (get-register register))) 537 (let ((val (get-register register)))
705 (register-val-jump-to val delete))) 538 (register-val-jump-to val delete)))
@@ -742,6 +575,24 @@ With a prefix argument, prompt for BUFFER as well."
742 (add-hook 'kill-buffer-hook #'register-buffer-to-file-query nil t)) 575 (add-hook 'kill-buffer-hook #'register-buffer-to-file-query nil t))
743 (set-register register (cons 'buffer buffer))) 576 (set-register register (cons 'buffer buffer)))
744 577
578(defun register--get-method-type (val genfun)
579 (let* ((type (cl-type-of val))
580 (types (cl--class-allparents (cl-find-class type))))
581 (while (and types (not (cl-find-method genfun nil (list (car types)))))
582 (setq types (cdr types)))
583 (car types)))
584
585(defun register--jumpable-p (regval)
586 "Return non-nil if `register-val-insert' is implemented for REGVAL."
587 (pcase (register--get-method-type regval 'register-val-jump-to)
588 ('t nil)
589 ('registerv (registerv-jump-func regval))
590 ('cons
591 (or (frame-configuration-p (car regval))
592 (window-configuration-p (car regval))
593 (memq (car regval) '(file buffer file-query))))
594 (type type)))
595
745(cl-defgeneric register-val-jump-to (_val _arg) 596(cl-defgeneric register-val-jump-to (_val _arg)
746 "Execute the \"jump\" operation of VAL. 597 "Execute the \"jump\" operation of VAL.
747VAL is the contents of a register as returned by `get-register'. 598VAL is the contents of a register as returned by `get-register'.
@@ -836,7 +687,10 @@ If REGISTER is empty or if it contains text, call
836 687
837Interactively, prompt for REGISTER using `register-read-with-preview'." 688Interactively, prompt for REGISTER using `register-read-with-preview'."
838 (interactive (list current-prefix-arg 689 (interactive (list current-prefix-arg
839 (register-read-with-preview "Increment register: "))) 690 (register-read-with-preview
691 "Increment register: "
692 (lambda (regval)
693 (or (numberp regval) (null regval) (stringp regval))))))
840 (let ((register-val (get-register register))) 694 (let ((register-val (get-register register)))
841 (cond 695 (cond
842 ((numberp register-val) 696 ((numberp register-val)
@@ -851,7 +705,8 @@ Interactively, prompt for REGISTER using `register-read-with-preview'."
851REGISTER is a character, the name of the register. 705REGISTER is a character, the name of the register.
852 706
853Interactively, prompt for REGISTER using `register-read-with-preview'." 707Interactively, prompt for REGISTER using `register-read-with-preview'."
854 (interactive (list (register-read-with-preview "View register: "))) 708 (interactive (list (register-read-with-preview "View register: "
709 (lambda (regval) regval))))
855 (let ((val (get-register register))) 710 (let ((val (get-register register)))
856 (if (null val) 711 (if (null val)
857 (message "Register %s is empty" (single-key-description register)) 712 (message "Register %s is empty" (single-key-description register))
@@ -983,13 +838,24 @@ and t otherwise.
983Interactively, prompt for REGISTER using `register-read-with-preview'." 838Interactively, prompt for REGISTER using `register-read-with-preview'."
984 (interactive (progn 839 (interactive (progn
985 (barf-if-buffer-read-only) 840 (barf-if-buffer-read-only)
986 (list (register-read-with-preview "Insert register: ") 841 (list (register-read-with-preview
842 "Insert register: "
843 #'register--insertable-p)
987 (not current-prefix-arg)))) 844 (not current-prefix-arg))))
988 (push-mark) 845 (push-mark)
989 (let ((val (get-register register))) 846 (let ((val (get-register register)))
990 (register-val-insert val)) 847 (register-val-insert val))
991 (if (not arg) (exchange-point-and-mark))) 848 (if (not arg) (exchange-point-and-mark)))
992 849
850(defun register--insertable-p (regval)
851 "Return non-nil if `register-val-insert' is implemented for REGVAL."
852 (pcase (register--get-method-type regval 'register-val-insert)
853 ;; Only rectangles are currently supported.
854 ('t nil)
855 ('registerv (registerv-insert-func regval))
856 ('cons (stringp (car regval)))
857 (type type)))
858
993(cl-defgeneric register-val-insert (_val) 859(cl-defgeneric register-val-insert (_val)
994 "Insert register value VAL in current buffer at point." 860 "Insert register value VAL in current buffer at point."
995 (user-error "Register does not contain text")) 861 (user-error "Register does not contain text"))
@@ -1048,7 +914,10 @@ START and END are buffer positions indicating what to append.
1048 914
1049Interactively, prompt for REGISTER using `register-read-with-preview', 915Interactively, prompt for REGISTER using `register-read-with-preview',
1050and use mark and point as START and END." 916and use mark and point as START and END."
1051 (interactive (list (register-read-with-preview "Append to register: ") 917 (interactive (list (register-read-with-preview
918 "Append to register: "
919 (lambda (regval)
920 (or (null regval) (stringp regval))))
1052 (region-beginning) 921 (region-beginning)
1053 (region-end) 922 (region-end)
1054 current-prefix-arg)) 923 current-prefix-arg))
@@ -1074,7 +943,10 @@ START and END are buffer positions indicating what to prepend.
1074 943
1075Interactively, prompt for REGISTER using `register-read-with-preview', 944Interactively, prompt for REGISTER using `register-read-with-preview',
1076and use mark and point as START and END." 945and use mark and point as START and END."
1077 (interactive (list (register-read-with-preview "Prepend to register: ") 946 (interactive (list (register-read-with-preview
947 "Prepend to register: "
948 (lambda (regval)
949 (or (null regval) (stringp regval))))
1078 (region-beginning) 950 (region-beginning)
1079 (region-end) 951 (region-end)
1080 current-prefix-arg)) 952 current-prefix-arg))