@end defun
-@defmac defvar-keymap name options &rest defs
+@defmac defvar-keymap name &key options... &rest pairs...
By far, the most common thing to do with a keymap is to bind it to a
variable. This is what virtually all modes do---a mode called
@code{foo} almost always has a variable called @code{foo-mode-map}.
This macro defines @var{name} as a variable, and passes @var{options}
-and @var{defs} to @code{define-keymap}, and uses the result as the
+and @var{pars} to @code{define-keymap}, and uses the result as the
default value for the variable.
@var{options} is like the keywords in @code{define-keymap}, but adds a
Here's an example:
@lisp
-(defvar-keymap eww-textarea-map (:parent text-mode-map)
+(defvar-keymap eww-textarea-map
+ :parent text-mode-map
"\r" #'forward-line
[?\t] #'shr-next-link)
@end lisp
(goto-char (scan-lists (point) -1 0))
(point)))))))))))
-(defun lisp-indent--defvar-keymap (state)
- "Return the indent position in the options part of a `defvar-keymap' form."
- (save-excursion
- (let ((parens (ppss-open-parens state)))
- (and (equal (nth 1 parens) (ppss-innermost-start state))
- (progn
- (goto-char (nth 0 parens))
- (looking-at-p "(defvar-keymap"))
- (progn
- (goto-char (ppss-innermost-start state))
- (1+ (current-column)))))))
-
(defun lisp-indent-function (indent-point state)
"This function is the normal value of the variable `lisp-indent-function'.
The function `calculate-lisp-indent' calls this to determine
(if (and (elt state 2)
(not (looking-at "\\sw\\|\\s_")))
;; car of form doesn't seem to be a symbol
- (cond
- ((lisp--local-defform-body-p state)
- ;; We nevertheless check whether we are in flet-like form
- ;; as we presume local function names could be non-symbols.
- (lisp-indent-defform state indent-point))
- (t
+ (if (lisp--local-defform-body-p state)
+ ;; We nevertheless check whether we are in flet-like form
+ ;; as we presume local function names could be non-symbols.
+ (lisp-indent-defform state indent-point)
(if (not (> (save-excursion (forward-line 1) (point))
calculate-lisp-indent-last-sexp))
(progn (goto-char calculate-lisp-indent-last-sexp)
;; thing on that line has to be complete sexp since we are
;; inside the innermost containing sexp.
(backward-prefix-chars)
- (current-column)))
- ;; Indent `defvar-keymap' arguments.
- (or (lisp-indent--defvar-keymap state)
- ;; Other forms.
- (let ((function (buffer-substring (point)
- (progn (forward-sexp 1) (point))))
- method)
- (setq method (or (function-get (intern-soft function)
- 'lisp-indent-function)
- (get (intern-soft function) 'lisp-indent-hook)))
- (cond ((or (eq method 'defun)
- (and (null method)
- (> (length function) 3)
- (string-match "\\`def" function))
- ;; Check whether we are in flet-like form.
- (lisp--local-defform-body-p state))
- (lisp-indent-defform state indent-point))
- ((integerp method)
- (lisp-indent-specform method state
- indent-point normal-indent))
- (method
- (funcall method indent-point state))))))))
+ (current-column))
+ (let ((function (buffer-substring (point)
+ (progn (forward-sexp 1) (point))))
+ method)
+ (setq method (or (function-get (intern-soft function)
+ 'lisp-indent-function)
+ (get (intern-soft function) 'lisp-indent-hook)))
+ (cond ((or (eq method 'defun)
+ (and (null method)
+ (> (length function) 3)
+ (string-match "\\`def" function))
+ ;; Check whether we are in flet-like form.
+ (lisp--local-defform-body-p state))
+ (lisp-indent-defform state indent-point))
+ ((integerp method)
+ (lisp-indent-specform method state
+ indent-point normal-indent))
+ (method
+ (funcall method indent-point state)))))))
(defcustom lisp-body-indent 2
"Number of columns to indent the second line of a `(def...)' form."
(defvar gnus-bookmark-bmenu-bookmark-column nil)
(defvar gnus-bookmark-bmenu-hidden-bookmarks ())
-(defvar-keymap gnus-bookmark-bmenu-mode-map (:full t
- :suppress 'nodigits)
+(defvar-keymap gnus-bookmark-bmenu-mode-map
+ :full t
+ :suppress 'nodigits
"q" #'quit-window
"\C-m" #'gnus-bookmark-bmenu-select
"v" #'gnus-bookmark-bmenu-select
(autoload 'message-buffers "message")
(autoload 'gnus-print-buffer "gnus-sum")
-(defvar-keymap gnus-dired-mode-map ()
+(defvar-keymap gnus-dired-mode-map
"\C-c\C-m\C-a" #'gnus-dired-attach
"\C-c\C-m\C-l" #'gnus-dired-find-file-mailcap
"\C-c\C-m\C-p" #'gnus-dired-print)
(defvar gnus-edit-form-buffer "*Gnus edit form*")
(defvar gnus-edit-form-done-function nil)
-(defvar-keymap gnus-edit-form-mode-map (:parent emacs-lisp-mode-map)
+(defvar-keymap gnus-edit-form-mode-map
+ :parent emacs-lisp-mode-map
"\C-c\C-c" #'gnus-edit-form-done
"\C-c\C-k" #'gnus-edit-form-exit)
:group 'gnus-art
:type 'float)
-(defvar-keymap gnus-html-image-map ()
+(defvar-keymap gnus-html-image-map
"u" #'gnus-article-copy-string
"i" #'gnus-html-insert-image
"v" #'gnus-html-browse-url)
-(defvar-keymap gnus-html-displayed-image-map ()
+(defvar-keymap gnus-html-displayed-image-map
"a" #'gnus-html-show-alt-text
"i" #'gnus-html-browse-image
"\r" #'gnus-html-browse-url
;;; Set up keymap.
-(defvar-keymap message-mode-map (:full t :parent text-mode-map
- :doc "Message Mode keymap.")
+(defvar-keymap message-mode-map
+ :full t :parent text-mode-map
+ :doc "Message Mode keymap."
"\C-c?" #'describe-mode
"\C-c\C-f\C-t" #'message-goto-to
"text/html, text/plain, text/sgml, text/css, application/xhtml+xml, */*;q=0.01"
"Value used for the HTTP 'Accept' header.")
-(defvar-keymap eww-link-keymap (:parent shr-map)
+(defvar-keymap eww-link-keymap
+ :parent shr-map
"\r" #'eww-follow-link)
-(defvar-keymap eww-image-link-keymap (:parent shr-map)
+(defvar-keymap eww-image-link-keymap
+ :parent shr-map
"\r" #'eww-follow-link)
(defun eww-suggested-uris nil
(setq result highest))))
result))
-(defvar-keymap eww-mode-map ()
+(defvar-keymap eww-mode-map
"g" #'eww-reload ;FIXME: revert-buffer-function instead!
"G" #'eww
[?\M-\r] #'eww-open-in-new-buffer
(defvar eww-form nil)
-(defvar-keymap eww-submit-map ()
+(defvar-keymap eww-submit-map
"\r" #'eww-submit
[(control c) (control c)] #'eww-submit)
-(defvar-keymap eww-submit-file ()
+(defvar-keymap eww-submit-file
"\r" #'eww-select-file
[(control c) (control c)] #'eww-submit)
-(defvar-keymap eww-checkbox-map ()
+(defvar-keymap eww-checkbox-map
" " #'eww-toggle-checkbox
"\r" #'eww-toggle-checkbox
[(control c) (control c)] #'eww-submit)
-(defvar-keymap eww-text-map (:full t :parent text-mode-map)
+(defvar-keymap eww-text-map
+ :full t :parent text-mode-map
"\r" #'eww-submit
[(control a)] #'eww-beginning-of-text
[(control c) (control c)] #'eww-submit
[?\M-\t] #'shr-previous-link
[backtab] #'shr-previous-link)
-(defvar-keymap eww-textarea-map (:full t :parent text-mode-map)
+(defvar-keymap eww-textarea-map
+ :full t :parent text-mode-map
"\r" #'forward-line
[(control c) (control c)] #'eww-submit
[?\t] #'shr-next-link
[?\M-\t] #'shr-previous-link
[backtab] #'shr-previous-link)
-(defvar-keymap eww-select-map (:doc "Map for select buttons")
+(defvar-keymap eww-select-map
+ :doc "Map for select buttons"
"\r" #'eww-change-select
[follow-link] 'mouse-face
[mouse-2] #'eww-change-select
'eww-bookmark)))
(eww-browse-url (plist-get bookmark :url))))
-(defvar-keymap eww-bookmark-mode-map ()
+(defvar-keymap eww-bookmark-mode-map
[(control k)] #'eww-bookmark-kill
[(control y)] #'eww-bookmark-yank
"\r" #'eww-bookmark-browse
(pop-to-buffer-same-window buffer)))
(eww-restore-history history)))
-(defvar-keymap eww-history-mode-map ()
+(defvar-keymap eww-history-mode-map
"\r" #'eww-history-browse
"n" #'next-line
"p" #'previous-line
(forward-line -1))
(eww-buffer-show))
-(defvar-keymap eww-buffers-mode-map ()
+(defvar-keymap eww-buffers-mode-map
[(control k)] #'eww-buffer-kill
"\r" #'eww-buffer-select
"n" #'eww-buffer-show-next
(defvar shr-target-id nil
"Target fragment identifier anchor.")
-(defvar-keymap shr-map ()
+(defvar-keymap shr-map
"a" #'shr-show-alt-text
"i" #'shr-browse-image
"z" #'shr-zoom-image
;; Special major modes to view specially formatted data rather than files.
-(defvar-keymap special-mode-map (:suppress t)
+(defvar-keymap special-mode-map
+ :suppress t
"q" #'quit-window
" " #'scroll-up-command
[?\S-\ ] #'scroll-down-command
also be the special symbol `:menu', in which case DEFINITION
should be a MENU form as accepted by `easy-menu-define'.
-\(fn (&key FULL PARENT SUPPRESS NAME PREFIX KEYMAP) &rest [KEY DEFINITION]...)"
- ;; Handle keywords.
- (let ((options nil))
+\(fn &key FULL PARENT SUPPRESS NAME PREFIX KEYMAP &rest [KEY DEFINITION]...)"
+ (define-keymap--define definitions))
+
+(defun define-keymap--define (definitions)
+ (let (full suppress parent name prefix keymap)
+ ;; Handle keywords.
(while (and definitions
- (keywordp (car definitions)))
+ (keywordp (car definitions))
+ (not (eq (car definitions) :menu)))
(let ((keyword (pop definitions)))
(unless definitions
(error "Missing keyword value for %s" keyword))
- (push keyword options)
- (push (pop definitions) options)))
- (define-keymap--define (nreverse options) definitions)))
-
-(defun define-keymap--define (options definitions)
- (let (full suppress parent name prefix keymap)
- (while options
- (let ((keyword (pop options))
- (value (pop options)))
- (pcase keyword
- (:full (setq full value))
- (:keymap (setq keymap value))
- (:parent (setq parent value))
- (:suppress (setq suppress value))
- (:name (setq name value))
- (:prefix (setq prefix value)))))
+ (let ((value (pop definitions)))
+ (pcase keyword
+ (:full (setq full value))
+ (:keymap (setq keymap value))
+ (:parent (setq parent value))
+ (:suppress (setq suppress value))
+ (:name (setq name value))
+ (:prefix (setq prefix value))))))
(when (and prefix
(or full parent suppress keymap))
(define-key keymap key def)))))
keymap)))
-(defmacro defvar-keymap (name options &rest defs)
- "Define NAME as a variable with a keymap definition.
-See `define-keymap' for an explanation of OPTIONS. In addition,
-the :doc keyword can be used in OPTIONS to add a doc string to NAME.
+(defmacro defvar-keymap (variable-name &rest defs)
+ "Define VARIABLE-NAME as a variable with a keymap definition.
+See `define-keymap' for an explanation of the keywords and KEY/DEFINITION.
+
+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.
-DEFS is passed to `define-keymap' and should be a plist of
-key/definition pairs."
+\(fn VARIABLE-NAME &key DOC FULL PARENT SUPPRESS NAME PREFIX KEYMAP &rest [KEY DEFINITION]...)"
(let ((opts nil)
doc)
- (while options
- (let ((keyword (pop options)))
- (unless options
- (error "Uneven number of options"))
+ (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 options))
+ (setq doc (pop defs))
(push keyword opts)
- (push (pop options) opts))))
+ (push (pop defs) opts))))
(unless (zerop (% (length defs) 2))
- (error "Uneven number of key definitions: %s" defs))
- `(defvar ,name
- (define-keymap--define (list ,@(nreverse opts)) (list ,@defs))
+ (error "Uneven number of key/definition pairs: %s" defs))
+ `(defvar ,variable-name
+ (define-keymap--define (list ,@(nreverse opts) ,@defs))
,@(and doc (list doc)))))
;;; subr.el ends here
Name: defvar-keymap
=-=
-(defvar-keymap eww-link-keymap (:copy shr-map
- :foo bar)
+(defvar-keymap eww-link-keymap
+ :copy shr-map
+ :foo bar
"\r" #'eww-follow-link)
=-=-=