[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master af39a98 14/45: Adapt to the new `hydra-set-transient-map'
From: |
Oleh Krehel |
Subject: |
[elpa] master af39a98 14/45: Adapt to the new `hydra-set-transient-map' |
Date: |
Thu, 16 Apr 2015 12:45:44 +0000 |
branch: master
commit af39a9885a2a9b1960ff03a1cdc78dfacf00785c
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>
Adapt to the new `hydra-set-transient-map'
* hydra.el (hydra-set-transient-map): Amend arglist.
(hydra--clearfun): Don't count on there being another transient map.
(hydra-disable): Update.
(internal-push-keymap): Define unless defined.
(internal-pop-keymap): Define unless defined.
(hydra--pred): Remove.
(hydra--universal-argument): Update.
(hydra-last): Remove.
(hydra--aggregate-color): Remove.
(hydra--unalias-var): Remove.
(hydra-pink-fallback): Remove.
(hydra--modify-keymap): Remove.
(hydra--make-defun): Update.
Re #90
---
hydra.el | 266 ++++++++++++++++++++++----------------------------------------
1 files changed, 93 insertions(+), 173 deletions(-)
diff --git a/hydra.el b/hydra.el
index fea0e9a..1234cac 100644
--- a/hydra.el
+++ b/hydra.el
@@ -79,59 +79,77 @@
(require 'cl-lib)
(require 'lv)
+(defvar hydra-curr-map nil
+ "The keymap of the current Hydra called.")
+
(defvar hydra-curr-on-exit nil
"The on-exit predicate for the current Hydra.")
(defvar hydra-curr-foreign-keys nil
"The current :foreign-keys behavior.")
-(defun hydra-clearfun ()
- (with-demoted-errors "set-transient-map PCH: %S"
- (unless (or
- (not (eq hydra-curr-map (cadr overriding-terminal-local-map)))
- ;; There's presumably some other transient-map in
- ;; effect. Wait for that one to terminate before we
- ;; remove ourselves.
- ;; For example, if isearch and C-u both use transient
- ;; maps, then the lifetime of the C-u should be nested
- ;; within isearch's, so the pre-command-hook of
- ;; isearch should be suspended during the C-u one so
- ;; we don't exit isearch just because we hit 1 after
- ;; C-u and that 1 exits isearch whereas it doesn't
- ;; exit C-u.
- (eq this-command
- (lookup-key hydra-curr-map (this-command-keys-vector))))
- (unless (cl-case hydra-curr-foreign-keys
- (warn
- (setq this-command 'hydra-amaranth-warn))
- (run
- t)
- (t nil))
- (remove-hook 'pre-command-hook 'hydra-clearfun)
- (internal-pop-keymap hydra-curr-map 'overriding-terminal-local-map)
- (when hydra-curr-on-exit (funcall hydra-curr-on-exit))))))
+(defun hydra-set-transient-map (keymap on-exit &optional foreign-keys)
+ "Set KEYMAP to the highest priority.
+
+Call ON-EXIT when the KEYMAP is deactivated.
+
+FOREIGN-KEYS determines the deactivation behavior, when a command
+that isn't in KEYMAP is called:
+
+nil: deactivate KEYMAP and run the command.
+run: keep KEYMAP and run the command.
+warn: keep KEYMAP and issue a warning instead of running the command."
+ (setq hydra-curr-map keymap)
+ (setq hydra-curr-on-exit on-exit)
+ (setq hydra-curr-foreign-keys foreign-keys)
+ (add-hook 'pre-command-hook 'hydra--clearfun)
+ (internal-push-keymap keymap 'overriding-terminal-local-map))
+
+(defun hydra--clearfun ()
+ "Disable the current Hydra unless `this-command' is a head."
+ (unless (eq this-command
+ (lookup-key hydra-curr-map (this-command-keys-vector)))
+ (unless (cl-case hydra-curr-foreign-keys
+ (warn
+ (setq this-command 'hydra-amaranth-warn))
+ (run
+ t)
+ (t nil))
+ (hydra-disable))))
+
+(defun hydra-disable ()
+ "Disable the current Hydra."
+ (remove-hook 'pre-command-hook 'hydra--clearfun)
+ (internal-pop-keymap hydra-curr-map 'overriding-terminal-local-map)
+ (when hydra-curr-on-exit
+ (let ((on-exit hydra-curr-on-exit))
+ (setq hydra-curr-on-exit nil)
+ (funcall on-exit))))
+
+(unless (fboundp 'internal-push-keymap)
+ (defun internal-push-keymap (keymap symbol)
+ (let ((map (symbol-value symbol)))
+ (unless (memq keymap map)
+ (unless (memq 'add-keymap-witness (symbol-value symbol))
+ (setq map (make-composed-keymap nil (symbol-value symbol)))
+ (push 'add-keymap-witness (cdr map))
+ (set symbol map))
+ (push keymap (cdr map))))))
+
+(unless (fboundp 'internal-pop-keymap)
+ (defun internal-pop-keymap (keymap symbol)
+ (let ((map (symbol-value symbol)))
+ (when (memq keymap map)
+ (setf (cdr map) (delq keymap (cdr map))))
+ (let ((tail (cddr map)))
+ (and (or (null tail) (keymapp tail))
+ (eq 'add-keymap-witness (nth 1 map))
+ (set symbol tail))))))
(defun hydra-amaranth-warn ()
(interactive)
(message "An amaranth Hydra can only exit through a blue head"))
-(defun hydra-set-transient-map (map on-exit)
- (setq hydra-curr-on-exit on-exit)
- (add-hook 'pre-command-hook 'hydra-clearfun)
- (internal-push-keymap map 'overriding-terminal-local-map))
-
-(defun hydra--pred (on-exit)
- "Generate a predicate on whether to continue the Hydra state.
-Call ON-EXIT for clean-up.
-This is a compatibility code for Emacs older than 24.4."
- `(lambda ()
- (if (lookup-key hydra-curr-map (this-command-keys-vector))
- t
- (hydra-keyboard-quit)
- ,(when on-exit
- `(funcall ,(hydra--make-callable on-exit)))
- nil)))
-
;;* Customize
(defgroup hydra nil
"Make bindings that stick around."
@@ -226,10 +244,6 @@ Vanquishable only through a blue head.")
map)
"Keymap that all Hydras inherit. See `universal-argument-map'.")
-(defvar hydra-curr-map
- (make-sparse-keymap)
- "Keymap of the current Hydra called.")
-
(defun hydra--handle-switch-frame (evt)
"Quit hydra and call old switch-frame event handler for EVT."
(interactive "e")
@@ -243,8 +257,7 @@ Vanquishable only through a blue head.")
(list (* 4 (car arg)))
(if (eq arg '-)
(list -4)
- '(4))))
- (hydra-set-transient-map hydra-curr-map hydra-curr-on-exit))
+ '(4)))))
(defun hydra--digit-argument (arg)
"Forward to (`digit-argument' ARG)."
@@ -260,6 +273,7 @@ Vanquishable only through a blue head.")
(interactive "P")
(let ((universal-argument-map hydra-curr-map))
(negative-argument arg)))
+
;;* Repeat
(defvar hydra-repeat--prefix-arg nil
"Prefix arg to use with `hydra-repeat'.")
@@ -280,9 +294,6 @@ When ARG is non-nil, use that instead."
(funcall hydra-repeat--command))
;;* Misc internals
-(defvar hydra-last nil
- "The result of the last `hydra-set-transient-map' call.")
-
(defun hydra--callablep (x)
"Test if X is callable."
(or (functionp x)
@@ -315,26 +326,6 @@ one of the properties on the list."
Return DEFAULT if PROP is not in H."
(hydra-plist-get-default (cl-cdddr h) prop default))
-(defun hydra--aggregate-color (head-color body-color)
- "Return the resulting head color for HEAD-COLOR and BODY-COLOR."
- (cond ((eq head-color 'red)
- (cl-case body-color
- (red 'red)
- (blue 'red)
- (amaranth 'amaranth)
- (pink 'pink)
- (cyan 'amaranth)))
- ((eq head-color 'blue)
- (cl-case body-color
- (red 'blue)
- (blue 'blue)
- (amaranth 'teal)
- (pink 'blue)
- (cyan 'teal)))
- (t
- (error "Can't aggregate head %S to body %S"
- head-color body-color))))
-
(defun hydra--head-color (h body)
"Return the color of a Hydra head H with BODY."
(let* ((exit (hydra--head-property h :exit 'default))
@@ -439,35 +430,6 @@ BODY is the second argument to `defhydra'"
(message ""))
nil)
-(defun hydra-disable ()
- "Disable the current Hydra."
- (cond
- ;; Emacs 25
- ((functionp hydra-last)
- (funcall hydra-last))
-
- ;; Emacs 24.3 or older
- ((< emacs-minor-version 4)
- (setq emulation-mode-map-alists
- (cl-remove-if
- (lambda (x)
- (and (consp x)
- (consp (car x))
- (equal (cdar x) hydra-curr-map)))
- emulation-mode-map-alists)))
-
- ;; Emacs 24.4.1
- (t
- (setq overriding-terminal-local-map nil))))
-
-(defun hydra--unalias-var (str prefix)
- "Return the symbol named STR if it's bound as a variable.
-Otherwise, add PREFIX to the symbol name."
- (let ((sym (intern-soft str)))
- (if (boundp sym)
- sym
- (intern (concat prefix "/" str)))))
-
(defun hydra--hint (body heads)
"Generate a hint for the echo area.
BODY, and HEADS are parameters to `defhydra'."
@@ -622,79 +584,37 @@ OTHER-POST is an optional extension to the :post key of
BODY."
(interactive)
(hydra-default-pre)
,@(when body-pre (list body-pre))
- (hydra-disable)
- ,@(when (memq color '(blue teal)) '((hydra-keyboard-quit)))
- (catch 'hydra-disable
- ,@(delq nil
- (if (memq color '(blue teal))
- `(,(when cmd `(call-interactively #',cmd))
- ,body-post)
- `(,(when cmd
- `(condition-case err
- (call-interactively #',cmd)
- ((quit error)
- (message "%S" err)
- (unless hydra-lv
- (sit-for 0.8)))))
- (when hydra-is-helpful
- (,hint))
- (setq hydra-curr-map ,keymap)
- (setq hydra-curr-foreign-keys
- ,(cond
- ((memq body-color '(amaranth teal))
- ''warn)
- ((eq body-color 'pink)
- ''run)
- (t
- nil)))
- (setq hydra-curr-on-exit
- (lambda ()
- (hydra-keyboard-quit)
- ,body-post))
- (setq hydra-last
- (hydra-set-transient-map
- hydra-curr-map
- hydra-curr-on-exit))
- ,(or other-post
- (when body-timeout
- (list 'hydra-timeout
- body-timeout
- (when body-post
- (hydra--make-callable
body-post))))))))))))
-
-(defun hydra-pink-fallback ()
- "On intercepting a non-head, try to run it."
- (let ((keys (this-single-command-keys))
- kb)
- (when (equal keys [backspace])
- (setq keys ""))
- (setq kb (key-binding keys))
- (if kb
- (if (commandp kb)
- (condition-case err
- (call-interactively kb)
- ((quit error)
- (message "%S" err)
- (unless hydra-lv
- (sit-for 0.8))))
- (message "Pink Hydra can't currently handle prefixes, continuing"))
- (message "Pink Hydra could not resolve: %S" keys))))
-
-(defun hydra--modify-keymap (keymap def)
- "In KEYMAP, add DEF to each sub-keymap."
- (cl-labels
- ((recur (map)
- (if (atom map)
- map
- (if (eq (car map) 'keymap)
- (cons 'keymap
- (cons
- def
- (recur (cdr map))))
- (cons
- (recur (car map))
- (recur (cdr map)))))))
- (recur keymap)))
+ ,@(if (memq color '(blue teal))
+ `((hydra-keyboard-quit)
+ ,(when cmd `(call-interactively #',cmd))
+ ,body-post)
+ (delq
+ nil
+ `(,(when cmd
+ `(condition-case err
+ (call-interactively #',cmd)
+ ((quit error)
+ (message "%S" err)
+ (unless hydra-lv
+ (sit-for 0.8)))))
+ (when hydra-is-helpful
+ (,hint))
+ (hydra-set-transient-map
+ ,keymap
+ (lambda () (hydra-keyboard-quit) ,body-post)
+ ,(cond
+ ((memq body-color '(amaranth teal))
+ ''warn)
+ ((eq body-color 'pink)
+ ''run)
+ (t
+ nil)))
+ ,(or other-post
+ (when body-timeout
+ `(hydra-timeout
+ ,body-timeout
+ ,(when body-post
+ (hydra--make-callable body-post)))))))))))
(defmacro hydra--make-funcall (sym)
"Transform SYM into a `funcall' that calls it."
- [elpa] master e4cae0a 03/45: hydra.el (defhydra): Simplify :cmd-name part, (continued)
- [elpa] master e4cae0a 03/45: hydra.el (defhydra): Simplify :cmd-name part, Oleh Krehel, 2015/04/16
- [elpa] master c06c006 02/45: Use set/defvar for keymap, Oleh Krehel, 2015/04/16
- [elpa] master e7aaafb 07/45: hydra.el (hydra-pink-fallback): Allow prefix arguments, Oleh Krehel, 2015/04/16
- [elpa] master d0cc1c5 01/45: Define a keymap var for each hydra and re-use it, Oleh Krehel, 2015/04/16
- [elpa] master 666048c 10/45: Update testing setup, Oleh Krehel, 2015/04/16
- [elpa] master f9bf8fe 08/45: hydra.el (hydra-set-transient-map): Update, Oleh Krehel, 2015/04/16
- [elpa] master 60483cb 09/45: Add integration testing, Oleh Krehel, 2015/04/16
- [elpa] master 4dde4f7 11/45: hydra.el (hydra--format): Add some more symbols, Oleh Krehel, 2015/04/16
- [elpa] master 3fce2bd 12/45: Try to re-encode the input in the terminal, Oleh Krehel, 2015/04/16
- [elpa] master fa5643f 15/45: Quit Hydra for `handle-switch-frame', Oleh Krehel, 2015/04/16
- [elpa] master af39a98 14/45: Adapt to the new `hydra-set-transient-map',
Oleh Krehel <=
- [elpa] master acdec5b 27/45: Add an integration test for digit args in amaranth, Oleh Krehel, 2015/04/16
- [elpa] master 1a54e09 05/45: hydra.el (hydra--make-funcall): Update location, Oleh Krehel, 2015/04/16
- [elpa] master b351b7c 24/45: hydra.el (hydra--body-color): Remove, Oleh Krehel, 2015/04/16
- [elpa] master 5787a4d 13/45: Move away from setting "t" in keymaps, Oleh Krehel, 2015/04/16
- [elpa] master 5379642 06/45: Use `hydra-keyboard-quit' instead of `hydra-cleanup', Oleh Krehel, 2015/04/16
- [elpa] master e88839c 17/45: Don't double-call :post, Oleh Krehel, 2015/04/16
- [elpa] master 2f07e50 26/45: Account for digit argument, Oleh Krehel, 2015/04/16
- [elpa] master 8875bf1 28/45: Make digit and negative arguments work in 24.3, Oleh Krehel, 2015/04/16
- [elpa] master 0ae639f 22/45: Use a variable instead of a function for the hint, Oleh Krehel, 2015/04/16
- [elpa] master d71386b 29/45: hydra.el (hydra--head-color): Simplify, Oleh Krehel, 2015/04/16