]> git.eshelyaron.com Git - emacs.git/commitdiff
* lisp/keymap.el (defvar-keymap): Add support for repeat-mode.
authorJuri Linkov <juri@linkov.net>
Thu, 17 Nov 2022 07:25:42 +0000 (09:25 +0200)
committerJuri Linkov <juri@linkov.net>
Thu, 17 Nov 2022 07:28:32 +0000 (09:28 +0200)
Put symbol properties 'repeat-map' on commands from the keymap
when a ':repeat' keyword is non-nil.  Also include/exclude commands
according to ':repeat (:enter (commands ...) :exit (commands ...))'.
https://lists.gnu.org/archive/html/emacs-devel/2022-11/msg00968.html

etc/NEWS
lisp/keymap.el

index bb2bd52134e1662cc2363fa4a36dfb31a2c24af5..47fc9f1e8e3670d445637bc85d0cdd8dfa4a41de 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -4075,6 +4075,10 @@ This function allows defining a number of keystrokes with one form.
 ** New macro 'defvar-keymap'.
 This macro allows defining keymap variables more conveniently.
 
+** 'repeat-map' can be defined in the macro 'defvar-keymap'.
+This is possible either by using ':repeat t' or more advanced
+':repeat (:enter (commands ...) :exit (commands ...))'.
+
 ---
 ** 'kbd' can now be used in built-in, preloaded libraries.
 It no longer depends on edmacro.el and cl-lib.el.
index 107565590c14314bf7099488213521734e8e7a48..953fb233cbc52ca1fa626c89d5015f000077ebfd 100644 (file)
@@ -559,22 +559,37 @@ In addition to the keywords accepted by `define-keymap', this
 macro also accepts a `:doc' keyword, which (if present) is used
 as the variable documentation string.
 
-\(fn VARIABLE-NAME &key DOC FULL PARENT SUPPRESS NAME PREFIX KEYMAP &rest [KEY DEFINITION]...)"
+When a `:repeat' keyword is non-nil, put `repeat-map' symbol
+properties on commands in this map for `repeat-mode'.  The value
+could also be a property list with properties `:enter' and `:exit',
+for example, :repeat (:enter (commands ...) :exit (commands ...)).
+`:enter' is a list of additional commands that only enter `repeat-mode'.
+When the list is empty then by default all commands in the map enter
+`repeat-mode'.  This is applicable when a command has the `repeat-map'
+symbol property on its symbol, but doesn't exist in the map.  `:exit'
+is a list of commands that exit `repeat-mode'.  When the list is
+empty, no commands in the map exit `repeat-mode'.  This is applicable
+when a command exists in the map, but doesn't have the `repeat-map'
+symbol property on its symbol.
+
+\(fn VARIABLE-NAME &key DOC FULL PARENT SUPPRESS NAME PREFIX KEYMAP REPEAT &rest [KEY DEFINITION]...)"
   (declare (indent 1))
   (let ((opts nil)
-        doc)
+        doc repeat props)
     (while (and defs
                 (keywordp (car defs))
                 (not (eq (car defs) :menu)))
       (let ((keyword (pop defs)))
         (unless defs
           (error "Uneven number of keywords"))
-        (if (eq keyword :doc)
-            (setq doc (pop defs))
-          (push keyword opts)
-          (push (pop defs) opts))))
+        (pcase keyword
+          (:doc (setq doc (pop defs)))
+          (:repeat (setq repeat (pop defs)))
+          (_ (push keyword opts)
+             (push (pop defs) opts)))))
     (unless (zerop (% (length defs) 2))
       (error "Uneven number of key/definition pairs: %s" defs))
+
     (let ((defs defs)
           key seen-keys)
       (while defs
@@ -585,9 +600,28 @@ as the variable documentation string.
               (error "Duplicate definition for key '%s' in keymap '%s'"
                      key variable-name)
             (push key seen-keys)))))
-    `(defvar ,variable-name
-       (define-keymap ,@(nreverse opts) ,@defs)
-       ,@(and doc (list doc)))))
+
+    (when repeat
+      (let ((defs defs)
+            def)
+        (dolist (def (plist-get repeat :enter))
+          (push `(put ',def 'repeat-map ',variable-name) props))
+        (while defs
+          (pop defs)
+          (setq def (pop defs))
+          (when (and (memq (car def) '(function quote))
+                     (not (memq (cadr def) (plist-get repeat :exit))))
+            (push `(put ,def 'repeat-map ',variable-name) props)))))
+
+    (let ((defvar-form
+           `(defvar ,variable-name
+              (define-keymap ,@(nreverse opts) ,@defs)
+              ,@(and doc (list doc)))))
+      (if repeat
+          `(progn
+             ,defvar-form
+             ,@(nreverse props))
+        defvar-form))))
 
 (defun make-non-key-event (symbol)
   "Mark SYMBOL as an event that shouldn't be returned from `where-is'."