(_ (byte-compile-keep-pending form))))
-\f
-;; Key syntax warnings.
-
-(mapc
- (lambda (elem)
- (put (car elem) 'byte-hunk-handler
- (lambda (form)
- (dolist (idx (cdr elem))
- (let ((key (elt form idx)))
- (when (or (vectorp key)
- (and (stringp key)
- (not (key-valid-p key))))
- (byte-compile-warn "Invalid `kbd' syntax: %S" key))))
- form)))
- ;; Functions and the place(s) for the key definition(s).
- '((keymap-set 2)
- (keymap-global-set 1)
- (keymap-local-set 1)
- (keymap-unset 2)
- (keymap-global-unset 1)
- (keymap-local-unset 1)
- (keymap-substitute 2 3)
- (keymap-set-after 2)
- (key-translate 1 2)
- (keymap-lookup 2)
- (keymap-global-lookup 1)
- (keymap-local-lookup 1)))
-
-(put 'define-keymap 'byte-hunk-handler #'byte-compile-define-keymap)
-(defun byte-compile-define-keymap (form)
- (let ((result nil)
- (orig-form form))
- (push (pop form) result)
- (while (and form
- (keywordp (car form))
- (not (eq (car form) :menu)))
- (unless (memq (car form)
- '(:full :keymap :parent :suppress :name :prefix))
- (byte-compile-warn "Invalid keyword: %s" (car form)))
- (push (pop form) result)
- (when (null form)
- (byte-compile-warn "Uneven number of keywords in %S" form))
- (push (pop form) result))
- ;; Bindings.
- (while form
- (let ((key (pop form)))
- (when (stringp key)
- (unless (key-valid-p key)
- (byte-compile-warn "Invalid `kbd' syntax: %S" key)))
- ;; No improvement.
- (push key result))
- (when (null form)
- (byte-compile-warn "Uneven number of key bindings in %S" form))
- (push (pop form) result))
- orig-form))
-
-(put 'define-keymap--define 'byte-hunk-handler
- #'byte-compile-define-keymap--define)
-(defun byte-compile-define-keymap--define (form)
- (when (consp (nth 1 form))
- (byte-compile-define-keymap (nth 1 form)))
- form)
-
\f
;;; tags
(unless (key-valid-p key)
(error "%S is not a valid key definition; see `key-valid-p'" key)))
+(defun keymap--compile-check (&rest keys)
+ (dolist (key keys)
+ (when (or (vectorp key)
+ (and (stringp key) (not (key-valid-p key))))
+ (byte-compile-warn "Invalid `kbd' syntax: %S" key))))
+
(defun keymap-set (keymap key definition)
"Set key sequence KEY to DEFINITION in KEYMAP.
KEY is a string that satisfies `key-valid-p'.
or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP,
or an extended menu item definition.
(See info node `(elisp)Extended Menu Items'.)"
+ (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
(keymap--check key)
(define-key keymap (key-parse key) definition))
Note that if KEY has a local binding in the current buffer,
that local binding will continue to shadow any global binding
that you make with this function."
+ (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
(interactive
(let* ((menu-prompting nil)
(key (read-key-sequence "Set key globally: " nil t)))
The binding goes in the current buffer's local map, which in most
cases is shared with all other buffers in the same major mode."
+ (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
(interactive "KSet key locally: \nCSet key %s locally to command: ")
(let ((map (current-local-map)))
(unless map
If REMOVE (interactively, the prefix arg), remove the binding
instead of unsetting it. See `keymap-unset' for details."
+ (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
(interactive
(list (key-description (read-key-sequence "Set key locally: "))
current-prefix-arg))
If REMOVE (interactively, the prefix arg), remove the binding
instead of unsetting it. See `keymap-unset' for details."
+ (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
(interactive
(list (key-description (read-key-sequence "Unset key locally: "))
current-prefix-arg))
a key in a child map, it will still shadow the same key in the
parent keymap. Removing the binding will allow the key in the
parent keymap to be used."
+ (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
(keymap--check key)
(define-key keymap (key-parse key) nil remove))
in a cleaner way with command remapping, like this:
(define-key KEYMAP [remap OLDDEF] NEWDEF)
\n(fn OLDDEF NEWDEF KEYMAP &optional OLDMAP)"
+ (declare (compiler-macro
+ (lambda (form) (keymap--compile-check olddef newdef) form)))
;; Don't document PREFIX in the doc string because we don't want to
;; advertise it. It's meant for recursive calls only. Here's its
;; meaning
The order of bindings in a keymap matters only when it is used as
a menu, so this function is not useful for non-menu keymaps."
- (declare (indent defun))
+ (declare (indent defun)
+ (compiler-macro (lambda (form) (keymap--compile-check key) form)))
(keymap--check key)
(when after
(keymap--check after))
and then modifies one entry in it.
Both KEY and TO are strings that satisfy `key-valid-p'."
+ (declare (compiler-macro
+ (lambda (form) (keymap--compile-check from to) form)))
(keymap--check from)
(keymap--check to)
(or (char-table-p keyboard-translate-table)
occurs in the keymaps associated with it instead of KEY. It can also
be a number or marker, in which case the keymap properties at the
specified buffer position instead of point are used."
+ (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
(keymap--check key)
(when (and keymap (not position))
(error "Can't pass in both keymap and position"))
If optional argument ACCEPT-DEFAULT is non-nil, recognize default
bindings; see the description of `keymap-lookup' for more details
about this."
+ (declare (compiler-macro (lambda (form) (keymap--compile-check keys) form)))
(when-let ((map (current-local-map)))
(keymap-lookup map keys accept-default)))
about this.
If MESSAGE (and interactively), message the result."
+ (declare (compiler-macro (lambda (form) (keymap--compile-check keys) form)))
(interactive
(list (key-description (read-key-sequence "Look up key in global keymap: "))
nil t))
object
(list object)))
+(defun define-keymap--compile (form &rest args)
+ ;; This compiler macro is only there for compile-time
+ ;; error-checking; it does not change the call in any way.
+ (while (and args
+ (keywordp (car args))
+ (not (eq (car args) :menu)))
+ (unless (memq (car args) '(:full :keymap :parent :suppress :name :prefix))
+ (byte-compile-warn "Invalid keyword: %s" (car args)))
+ (setq args (cdr args))
+ (when (null args)
+ (byte-compile-warn "Uneven number of keywords in %S" form))
+ (setq args (cdr args)))
+ ;; Bindings.
+ (while args
+ (let ((key (pop args)))
+ (when (and (stringp key) (not (key-valid-p key)))
+ (byte-compile-warn "Invalid `kbd' syntax: %S" key)))
+ (when (null args)
+ (byte-compile-warn "Uneven number of key bindings in %S" form))
+ (setq args (cdr args)))
+ form)
+
(defun define-keymap (&rest definitions)
"Create a new keymap and define KEY/DEFEFINITION pairs as key sequences.
The new keymap is returned.
should be a MENU form as accepted by `easy-menu-define'.
\(fn &key FULL PARENT SUPPRESS NAME PREFIX KEYMAP &rest [KEY DEFINITION]...)"
- (declare (indent defun))
- (define-keymap--define definitions))
-
-(defun define-keymap--define (definitions)
+ (declare (indent defun)
+ (compiler-macro define-keymap--compile))
(let (full suppress parent name prefix keymap)
;; Handle keywords.
(while (and definitions
(unless (zerop (% (length defs) 2))
(error "Uneven number of key/definition pairs: %s" defs))
`(defvar ,variable-name
- (define-keymap--define (list ,@(nreverse opts) ,@defs))
+ (define-keymap ,@(nreverse opts) ,@defs)
,@(and doc (list doc)))))
(defmacro with-delayed-message (args &rest body)