Merge pull request from killdash9/keymap

:bind-keymap - bind a key prefix to an autoloaded package keymap
GitHub-reference: https://github.com/jwiegley/use-package/issues/142
This commit is contained in:
John Wiegley 2015-01-02 20:09:31 -06:00
commit 60029cb0ab

View file

@ -189,6 +189,8 @@ ARCHIVE can be a string or a symbol or 'manual to indicate a manually updated pa
:pre-init :pre-init
:pre-load :pre-load
:requires :requires
:bind-keymap
:bind-keymap*
) )
"Keywords recognized by `use-package'.") "Keywords recognized by `use-package'.")
@ -274,6 +276,10 @@ For full documentation. please see commentary.
commands. commands.
:bind* Perform key bindings, and define autoload for bound :bind* Perform key bindings, and define autoload for bound
commands, overriding all minor mode bindings. commands, overriding all minor mode bindings.
:bind-keymap Bind key prefix to an auto-loaded keymap that
is defined in the package. Like bind but for keymaps
instead of commands.
:bind-keymap* like bind-keymap, but overrides all minor mode bindings
:commands Define autoloads for given commands. :commands Define autoloads for given commands.
:pre-load Code to run when `use-package' form evals and before :pre-load Code to run when `use-package' form evals and before
anything else. Unlike :init this form runs before the anything else. Unlike :init this form runs before the
@ -308,6 +314,8 @@ For full documentation. please see commentary.
(idle-priority (use-package-plist-get args :idle-priority)) (idle-priority (use-package-plist-get args :idle-priority))
(keybindings-alist (use-package-plist-get args :bind t t)) (keybindings-alist (use-package-plist-get args :bind t t))
(overriding-keybindings-alist (use-package-plist-get args :bind* t t)) (overriding-keybindings-alist (use-package-plist-get args :bind* t t))
(keymap-alist (use-package-plist-get args :bind-keymap t t))
(overriding-keymap-alist (use-package-plist-get args :bind-keymap* t t))
(mode (use-package-plist-get args :mode t t)) (mode (use-package-plist-get args :mode t t))
(mode-alist (mode-alist
(if (stringp mode) (cons mode name) mode)) (if (stringp mode) (cons mode name) mode))
@ -382,9 +390,8 @@ For full documentation. please see commentary.
(use-package-init-on-idle (lambda () ,idle-body) ,idle-priority) (use-package-init-on-idle (lambda () ,idle-body) ,idle-priority)
,init-body))) ,init-body)))
(let ((init-for-commands-or-keymaps
(let ((init-for-commands (lambda (func sym-or-list &optional keymap)
(lambda (func sym-or-list)
(let ((cons-list (if (and (consp sym-or-list) (let ((cons-list (if (and (consp sym-or-list)
(stringp (car sym-or-list))) (stringp (car sym-or-list)))
(list sym-or-list) (list sym-or-list)
@ -394,29 +401,50 @@ For full documentation. please see commentary.
`(progn `(progn
,init-body ,init-body
,@(mapcar (lambda (elem) ,@(mapcar (lambda (elem)
(push (cdr elem) commands) (when (not keymap)
(push (cdr elem) commands))
(funcall func elem)) (funcall func elem))
cons-list)))))))) cons-list))))))))
(funcall init-for-commands (funcall init-for-commands-or-keymaps
(lambda (binding)
`(bind-key ,(car binding)
(lambda () (interactive)
(use-package-autoload-keymap
(quote ,(cdr binding))
,(if (stringp name) name `',name)
nil))))
keymap-alist)
(funcall init-for-commands-or-keymaps
(lambda (binding)
`(bind-key ,(car binding)
(lambda () (interactive)
(use-package-autoload-keymap
(quote ,(cdr binding))
,(if (stringp name) name `',name)
t))))
overriding-keymap-alist)
(funcall init-for-commands-or-keymaps
(lambda (binding) (lambda (binding)
`(bind-key ,(car binding) `(bind-key ,(car binding)
(quote ,(cdr binding)))) (quote ,(cdr binding))))
keybindings-alist) keybindings-alist)
(funcall init-for-commands (funcall init-for-commands-or-keymaps
(lambda (binding) (lambda (binding)
`(bind-key* ,(car binding) `(bind-key* ,(car binding)
(quote ,(cdr binding)))) (quote ,(cdr binding))))
overriding-keybindings-alist) overriding-keybindings-alist)
(funcall init-for-commands (funcall init-for-commands-or-keymaps
(lambda (mode) (lambda (mode)
`(add-to-list 'auto-mode-alist `(add-to-list 'auto-mode-alist
(quote ,mode))) (quote ,mode)))
mode-alist) mode-alist)
(funcall init-for-commands (funcall init-for-commands-or-keymaps
(lambda (interpreter) (lambda (interpreter)
`(add-to-list 'interpreter-mode-alist `(add-to-list 'interpreter-mode-alist
(quote ,interpreter))) (quote ,interpreter)))
@ -446,7 +474,9 @@ For full documentation. please see commentary.
`(require ',name nil t)) `(require ',name nil t))
(error (message "Error requiring %s: %s" ',name err) nil)))) (error (message "Error requiring %s: %s" ',name err) nil))))
,(if (and (or commands (use-package-plist-get args :defer)) ,(if (and (or commands (use-package-plist-get args :defer)
(use-package-plist-get args :bind-keymap)
(use-package-plist-get args :bind-keymap*))
(not (use-package-plist-get args :demand))) (not (use-package-plist-get args :demand)))
(let (form) (let (form)
(mapc (lambda (command) (mapc (lambda (command)
@ -481,6 +511,31 @@ For full documentation. please see commentary.
,config-body ,config-body
t)))))))) t))))))))
(defun use-package-autoload-keymap (keymap-symbol package override)
"Loads PACKAGE and then binds the key sequence used to invoke this function to
KEYMAP-SYMBOL. It then simulates pressing the same key sequence a again, so
that the next key pressed is routed to the newly loaded keymap.
This function supports use-package's :bind-keymap keyword. It works
by binding the given key sequence to an invocation of this function for a
particular keymap. The keymap is expected to be defined by the package. In
this way, loading the package is deferred until the prefix key sequence is
pressed."
(if (if (stringp package) (load package t) (require package nil t))
(if (and (boundp keymap-symbol) (keymapp (symbol-value keymap-symbol)))
(let ((key (key-description (this-command-keys-vector)))
(keymap (symbol-value keymap-symbol)))
(progn
(if override
`(eval `(bind-key* ,key ,keymap)) ; eval form is necessary to avoid compiler error
(bind-key key keymap))
(setq unread-command-events
(listify-key-sequence (this-command-keys-vector)))))
(error
"use-package: package %s failed to define keymap %s"
package keymap-symbol))
(error "Could not load package %s" package)))
(put 'use-package 'lisp-indent-function 'defun) (put 'use-package 'lisp-indent-function 'defun)
(defconst use-package-font-lock-keywords (defconst use-package-font-lock-keywords