aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Wiegley2022-08-07 08:30:25 -0700
committerGitHub2022-08-07 08:30:25 -0700
commitde0c8c36c7c4bb68b2c881b0449dcee050b19e63 (patch)
tree4bc14e50f4119ddb674b132329458e20d8d20cfd
parent015c921a2e0fdf5f17f095235dd96d8080b0e6eb (diff)
parent1143f14d650c7201d7ddbcb7012dc2c9bf3b1824 (diff)
downloademacs-de0c8c36c7c4bb68b2c881b0449dcee050b19e63.tar.gz
emacs-de0c8c36c7c4bb68b2c881b0449dcee050b19e63.zip
Merge pull request from Hugo-Heagren/bind-keys-repeat-map
GitHub-reference: https://github.com/jwiegley/use-package/issues/974
-rw-r--r--lisp/use-package/bind-key.el74
-rw-r--r--lisp/use-package/use-package-bind-key.el7
2 files changed, 72 insertions, 9 deletions
diff --git a/lisp/use-package/bind-key.el b/lisp/use-package/bind-key.el
index 9a2ddcd8437..3169e24412f 100644
--- a/lisp/use-package/bind-key.el
+++ b/lisp/use-package/bind-key.el
@@ -258,30 +258,60 @@ Accepts keyword arguments:
258 for these bindings 258 for these bindings
259:prefix-docstring STR - docstring for the prefix-map variable 259:prefix-docstring STR - docstring for the prefix-map variable
260:menu-name NAME - optional menu string for prefix map 260:menu-name NAME - optional menu string for prefix map
261:repeat-docstring STR - docstring for the repeat-map variable
262:repeat-map MAP - name of the repeat map that should be created
263 for these bindings. If specified, the
264 'repeat-map property of each command bound
265 (within the scope of the :repeat-map keyword)
266 is set to this map.
267:exit BINDINGS - Within the scope of :repeat-map will bind the
268 key in the repeat map, but will not set the
269 'repeat-map property of the bound command.
270:continue BINDINGS - Within the scope of :repeat-map forces the
271 same behaviour as if no special keyword had
272 been used (that is, the command is bound, and
273 it's 'repeat-map property set)
261:filter FORM - optional form to determine when bindings apply 274:filter FORM - optional form to determine when bindings apply
262 275
263The rest of the arguments are conses of keybinding string and a 276The rest of the arguments are conses of keybinding string and a
264function symbol (unquoted)." 277function symbol (unquoted)."
265 (let (map 278 (let (map
266 doc 279 prefix-doc
267 prefix-map 280 prefix-map
268 prefix 281 prefix
282 repeat-map
283 repeat-doc
284 repeat-type ;; Only used internally
269 filter 285 filter
270 menu-name 286 menu-name
271 pkg) 287 pkg)
272 288
273 ;; Process any initial keyword arguments 289 ;; Process any initial keyword arguments
274 (let ((cont t)) 290 (let ((cont t)
291 (arg-change-func 'cddr))
275 (while (and cont args) 292 (while (and cont args)
276 (if (cond ((and (eq :map (car args)) 293 (if (cond ((and (eq :map (car args))
277 (not prefix-map)) 294 (not prefix-map))
278 (setq map (cadr args))) 295 (setq map (cadr args)))
279 ((eq :prefix-docstring (car args)) 296 ((eq :prefix-docstring (car args))
280 (setq doc (cadr args))) 297 (setq prefix-doc (cadr args)))
281 ((and (eq :prefix-map (car args)) 298 ((and (eq :prefix-map (car args))
282 (not (memq map '(global-map 299 (not (memq map '(global-map
283 override-global-map)))) 300 override-global-map))))
284 (setq prefix-map (cadr args))) 301 (setq prefix-map (cadr args)))
302 ((eq :repeat-docstring (car args))
303 (setq repeat-doc (cadr args)))
304 ((and (eq :repeat-map (car args))
305 (not (memq map '(global-map
306 override-global-map))))
307 (setq repeat-map (cadr args))
308 (setq map repeat-map))
309 ((eq :continue (car args))
310 (setq repeat-type :continue
311 arg-change-func 'cdr))
312 ((eq :exit (car args))
313 (setq repeat-type :exit
314 arg-change-func 'cdr))
285 ((eq :prefix (car args)) 315 ((eq :prefix (car args))
286 (setq prefix (cadr args))) 316 (setq prefix (cadr args)))
287 ((eq :filter (car args)) 317 ((eq :filter (car args))
@@ -290,13 +320,17 @@ function symbol (unquoted)."
290 (setq menu-name (cadr args))) 320 (setq menu-name (cadr args)))
291 ((eq :package (car args)) 321 ((eq :package (car args))
292 (setq pkg (cadr args)))) 322 (setq pkg (cadr args))))
293 (setq args (cddr args)) 323 (setq args (funcall arg-change-func args))
294 (setq cont nil)))) 324 (setq cont nil))))
295 325
296 (when (or (and prefix-map (not prefix)) 326 (when (or (and prefix-map (not prefix))
297 (and prefix (not prefix-map))) 327 (and prefix (not prefix-map)))
298 (error "Both :prefix-map and :prefix must be supplied")) 328 (error "Both :prefix-map and :prefix must be supplied"))
299 329
330 (when repeat-type
331 (unless repeat-map
332 (error ":continue and :exit require specifying :repeat-map")))
333
300 (when (and menu-name (not prefix)) 334 (when (and menu-name (not prefix))
301 (error "If :menu-name is supplied, :prefix must be too")) 335 (error "If :menu-name is supplied, :prefix must be too"))
302 336
@@ -328,13 +362,16 @@ function symbol (unquoted)."
328 (append 362 (append
329 (when prefix-map 363 (when prefix-map
330 `((defvar ,prefix-map) 364 `((defvar ,prefix-map)
331 ,@(when doc `((put ',prefix-map 'variable-documentation ,doc))) 365 ,@(when prefix-doc `((put ',prefix-map 'variable-documentation ,prefix-doc)))
332 ,@(if menu-name 366 ,@(if menu-name
333 `((define-prefix-command ',prefix-map nil ,menu-name)) 367 `((define-prefix-command ',prefix-map nil ,menu-name))
334 `((define-prefix-command ',prefix-map))) 368 `((define-prefix-command ',prefix-map)))
335 ,@(if (and map (not (eq map 'global-map))) 369 ,@(if (and map (not (eq map 'global-map)))
336 (wrap map `((bind-key ,prefix ',prefix-map ,map ,filter))) 370 (wrap map `((bind-key ,prefix ',prefix-map ,map ,filter)))
337 `((bind-key ,prefix ',prefix-map nil ,filter))))) 371 `((bind-key ,prefix ',prefix-map nil ,filter)))))
372 (when repeat-map
373 `((defvar ,repeat-map (make-sparse-keymap)
374 ,@(when repeat-doc `(,repeat-doc)))))
338 (wrap map 375 (wrap map
339 (cl-mapcan 376 (cl-mapcan
340 (lambda (form) 377 (lambda (form)
@@ -342,13 +379,19 @@ function symbol (unquoted)."
342 (if prefix-map 379 (if prefix-map
343 `((bind-key ,(car form) ,fun ,prefix-map ,filter)) 380 `((bind-key ,(car form) ,fun ,prefix-map ,filter))
344 (if (and map (not (eq map 'global-map))) 381 (if (and map (not (eq map 'global-map)))
345 `((bind-key ,(car form) ,fun ,map ,filter)) 382 ;; Only needed in this branch, since when
383 ;; repeat-map is non-nil, map is always
384 ;; non-nil
385 `(,@(when (and repeat-map (not (eq repeat-type :exit)))
386 `((put ,fun 'repeat-map ',repeat-map)))
387 (bind-key ,(car form) ,fun ,map ,filter))
346 `((bind-key ,(car form) ,fun nil ,filter)))))) 388 `((bind-key ,(car form) ,fun nil ,filter))))))
347 first)) 389 first))
348 (when next 390 (when next
349 (bind-keys-form (if pkg 391 (bind-keys-form `(,@(when repeat-map `(:repeat-map ,repeat-map))
350 (cons :package (cons pkg next)) 392 ,@(if pkg
351 next) map))))))) 393 (cons :package (cons pkg next))
394 next)) map)))))))
352 395
353;;;###autoload 396;;;###autoload
354(defmacro bind-keys (&rest args) 397(defmacro bind-keys (&rest args)
@@ -362,6 +405,19 @@ Accepts keyword arguments:
362 for these bindings 405 for these bindings
363:prefix-docstring STR - docstring for the prefix-map variable 406:prefix-docstring STR - docstring for the prefix-map variable
364:menu-name NAME - optional menu string for prefix map 407:menu-name NAME - optional menu string for prefix map
408:repeat-docstring STR - docstring for the repeat-map variable
409:repeat-map MAP - name of the repeat map that should be created
410 for these bindings. If specified, the
411 'repeat-map property of each command bound
412 (within the scope of the :repeat-map keyword)
413 is set to this map.
414:exit BINDINGS - Within the scope of :repeat-map will bind the
415 key in the repeat map, but will not set the
416 'repeat-map property of the bound command.
417:continue BINDINGS - Within the scope of :repeat-map forces the
418 same behaviour as if no special keyword had
419 been used (that is, the command is bound, and
420 it's 'repeat-map property set)
365:filter FORM - optional form to determine when bindings apply 421:filter FORM - optional form to determine when bindings apply
366 422
367The rest of the arguments are conses of keybinding string and a 423The rest of the arguments are conses of keybinding string and a
diff --git a/lisp/use-package/use-package-bind-key.el b/lisp/use-package/use-package-bind-key.el
index e476b060ad6..9642f311750 100644
--- a/lisp/use-package/use-package-bind-key.el
+++ b/lisp/use-package/use-package-bind-key.el
@@ -86,13 +86,20 @@ deferred until the prefix key sequence is pressed."
86 ;; :prefix-docstring STRING 86 ;; :prefix-docstring STRING
87 ;; :prefix-map SYMBOL 87 ;; :prefix-map SYMBOL
88 ;; :prefix STRING 88 ;; :prefix STRING
89 ;; :repeat-docstring STRING
90 ;; :repeat-map SYMBOL
89 ;; :filter SEXP 91 ;; :filter SEXP
90 ;; :menu-name STRING 92 ;; :menu-name STRING
91 ;; :package SYMBOL 93 ;; :package SYMBOL
94 ;; :continue and :exit are used within :repeat-map
92 ((or (and (eq x :map) (symbolp (cadr arg))) 95 ((or (and (eq x :map) (symbolp (cadr arg)))
93 (and (eq x :prefix) (stringp (cadr arg))) 96 (and (eq x :prefix) (stringp (cadr arg)))
94 (and (eq x :prefix-map) (symbolp (cadr arg))) 97 (and (eq x :prefix-map) (symbolp (cadr arg)))
95 (and (eq x :prefix-docstring) (stringp (cadr arg))) 98 (and (eq x :prefix-docstring) (stringp (cadr arg)))
99 (and (eq x :repeat-map) (symbolp (cadr arg)))
100 (eq x :continue)
101 (eq x :exit)
102 (and (eq x :repeat-docstring) (stringp (cadr arg)))
96 (eq x :filter) 103 (eq x :filter)
97 (and (eq x :menu-name) (stringp (cadr arg))) 104 (and (eq x :menu-name) (stringp (cadr arg)))
98 (and (eq x :package) (symbolp (cadr arg)))) 105 (and (eq x :package) (symbolp (cadr arg))))