[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master 3c57fa9 6/6: Merge commit 'b963c70dcf211c86d4bb03bfd4a20c6
From: |
Oleh Krehel |
Subject: |
[elpa] master 3c57fa9 6/6: Merge commit 'b963c70dcf211c86d4bb03bfd4a20c6807cbe679' from hydra |
Date: |
Wed, 04 Feb 2015 18:51:22 +0000 |
branch: master
commit 3c57fa96866983e1cf20ca2ab2f0db7c140ccd4d
Merge: d44f2ad b963c70
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>
Merge commit 'b963c70dcf211c86d4bb03bfd4a20c6807cbe679' from hydra
---
packages/hydra/Makefile | 8 +-
packages/hydra/README.md | 8 +
packages/hydra/hydra-examples.el | 32 ++--
packages/hydra/hydra-test.el | 300 +++++++++++++++++++++++++-------------
packages/hydra/hydra.el | 178 ++++++++++++++++-------
5 files changed, 357 insertions(+), 169 deletions(-)
diff --git a/packages/hydra/Makefile b/packages/hydra/Makefile
index 97bcea6..b2d473d 100644
--- a/packages/hydra/Makefile
+++ b/packages/hydra/Makefile
@@ -1,12 +1,18 @@
EMACS = emacs
# EMACS = emacs-24.3
+LOAD = -l hydra.el -l hydra-test.el
+
.PHONY: all test clean
all: test
test:
- $(EMACS) -batch -l hydra.el -l hydra-test.el -f
ert-run-tests-batch-and-exit
+ $(EMACS) -batch $(LOAD) -f ert-run-tests-batch-and-exit
+
+compile:
+ $(EMACS) -q $(LOAD) -l init.el --eval "(progn (mapc #'byte-compile-file
'(\"hydra.el\" \"init.el\")) (switch-to-buffer \"*Compile-Log*\") (ert t))"
+ make clean
clean:
rm -f *.elc
diff --git a/packages/hydra/README.md b/packages/hydra/README.md
index 79175bd..0686965 100644
--- a/packages/hydra/README.md
+++ b/packages/hydra/README.md
@@ -163,3 +163,11 @@ However, there are two important differences:
- you can cancel <kbd>C-c C-v</kbd> with a command while executing that
command, instead of e.g.
getting an error `C-c C-v C-n is undefined` for <kbd>C-c C-v C-n</kbd>.
+
+## Hydras and numeric arguments
+
+Since version `0.6.0`, for any Hydra:
+
+- `digit-argment` can be called with <kbd>0</kbd>-<kbd>9</kbd>.
+- `negative-argument` can be called with <kbd>-</kbd>
+- `universal-argument` can be called with <kbd>C-u</kbd>
diff --git a/packages/hydra/hydra-examples.el b/packages/hydra/hydra-examples.el
index 834db70..3dfc836 100644
--- a/packages/hydra/hydra-examples.el
+++ b/packages/hydra/hydra-examples.el
@@ -43,37 +43,37 @@
(require 'windmove)
-(defun hydra-move-splitter-left ()
+(defun hydra-move-splitter-left (arg)
"Move window splitter left."
- (interactive)
+ (interactive "p")
(if (let ((windmove-wrap-around))
(windmove-find-other-window 'right))
- (shrink-window-horizontally 1)
- (enlarge-window-horizontally 1)))
+ (shrink-window-horizontally arg)
+ (enlarge-window-horizontally arg)))
-(defun hydra-move-splitter-right ()
+(defun hydra-move-splitter-right (arg)
"Move window splitter right."
- (interactive)
+ (interactive "p")
(if (let ((windmove-wrap-around))
(windmove-find-other-window 'right))
- (enlarge-window-horizontally 1)
- (shrink-window-horizontally 1)))
+ (enlarge-window-horizontally arg)
+ (shrink-window-horizontally arg)))
-(defun hydra-move-splitter-up ()
+(defun hydra-move-splitter-up (arg)
"Move window splitter up."
- (interactive)
+ (interactive "p")
(if (let ((windmove-wrap-around))
(windmove-find-other-window 'up))
- (enlarge-window 1)
- (shrink-window 1)))
+ (enlarge-window arg)
+ (shrink-window arg)))
-(defun hydra-move-splitter-down ()
+(defun hydra-move-splitter-down (arg)
"Move window splitter down."
- (interactive)
+ (interactive "p")
(if (let ((windmove-wrap-around))
(windmove-find-other-window 'up))
- (shrink-window 1)
- (enlarge-window 1)))
+ (shrink-window arg)
+ (enlarge-window arg)))
(defvar hydra-example-move-window-splitter
'(("h" hydra-move-splitter-left)
diff --git a/packages/hydra/hydra-test.el b/packages/hydra/hydra-test.el
index f3b3c27..07d0a74 100644
--- a/packages/hydra/hydra-test.el
+++ b/packages/hydra/hydra-test.el
@@ -36,8 +36,7 @@
("j" next-error "next")
("k" previous-error "prev")))
'(progn
- (defun hydra-error/first-error ()
- "Create a hydra with a \"M-g\" body and the heads:
+ (defun hydra-error/first-error nil "Create a hydra with a \"M-g\" body
and the heads:
\"h\": `first-error',
\"j\": `next-error',
@@ -46,22 +45,41 @@
The body can be accessed via `hydra-error/body'.
Call the head: `first-error'."
- (interactive)
- (call-interactively #'first-error)
- (when hydra-is-helpful
- (message #("error: [h]: first, [j]: next, [k]: prev."
- 8 9 (face font-lock-keyword-face)
- 20 21 (face font-lock-keyword-face)
- 31 32 (face font-lock-keyword-face))))
- (setq hydra-last
- (hydra-set-transient-map
- '(keymap
- (107 . hydra-error/previous-error)
- (106 . hydra-error/next-error)
- (104 . hydra-error/first-error)) t)))
-
- (defun hydra-error/next-error ()
- "Create a hydra with a \"M-g\" body and the heads:
+ (interactive)
+ (when hydra-is-helpful (message #("error: [h]: first, [j]: next,
[k]: prev." 8 9 (face hydra-face-red)
+ 20 21 (face hydra-face-red)
+ 31 32 (face hydra-face-red))))
+ (setq hydra-last
+ (hydra-set-transient-map
+ (setq hydra-curr-map '(keymap (107 .
hydra-error/previous-error)
+ (106 . hydra-error/next-error)
+ (104 . hydra-error/first-error)
+ (kp-subtract .
hydra--negative-argument)
+ (kp-9 . hydra--digit-argument)
+ (kp-8 . hydra--digit-argument)
+ (kp-7 . hydra--digit-argument)
+ (kp-6 . hydra--digit-argument)
+ (kp-5 . hydra--digit-argument)
+ (kp-4 . hydra--digit-argument)
+ (kp-3 . hydra--digit-argument)
+ (kp-2 . hydra--digit-argument)
+ (kp-1 . hydra--digit-argument)
+ (kp-0 . hydra--digit-argument)
+ (57 . hydra--digit-argument)
+ (56 . hydra--digit-argument)
+ (55 . hydra--digit-argument)
+ (54 . hydra--digit-argument)
+ (53 . hydra--digit-argument)
+ (52 . hydra--digit-argument)
+ (51 . hydra--digit-argument)
+ (50 . hydra--digit-argument)
+ (49 . hydra--digit-argument)
+ (48 . hydra--digit-argument)
+ (45 . hydra--negative-argument)
+ (21 . hydra--universal-argument)))
+ t))
+ (call-interactively (function first-error)))
+ (defun hydra-error/next-error nil "Create a hydra with a \"M-g\" body
and the heads:
\"h\": `first-error',
\"j\": `next-error',
@@ -70,22 +88,41 @@ Call the head: `first-error'."
The body can be accessed via `hydra-error/body'.
Call the head: `next-error'."
- (interactive)
- (call-interactively #'next-error)
- (when hydra-is-helpful
- (message #("error: [h]: first, [j]: next, [k]: prev."
- 8 9 (face font-lock-keyword-face)
- 20 21 (face font-lock-keyword-face)
- 31 32 (face font-lock-keyword-face))))
- (setq hydra-last
- (hydra-set-transient-map
- '(keymap
- (107 . hydra-error/previous-error)
- (106 . hydra-error/next-error)
- (104 . hydra-error/first-error)) t)))
-
- (defun hydra-error/previous-error ()
- "Create a hydra with a \"M-g\" body and the heads:
+ (interactive)
+ (when hydra-is-helpful (message #("error: [h]: first, [j]: next,
[k]: prev." 8 9 (face hydra-face-red)
+ 20 21 (face hydra-face-red)
+ 31 32 (face hydra-face-red))))
+ (setq hydra-last
+ (hydra-set-transient-map
+ (setq hydra-curr-map '(keymap (107 .
hydra-error/previous-error)
+ (106 . hydra-error/next-error)
+ (104 . hydra-error/first-error)
+ (kp-subtract .
hydra--negative-argument)
+ (kp-9 . hydra--digit-argument)
+ (kp-8 . hydra--digit-argument)
+ (kp-7 . hydra--digit-argument)
+ (kp-6 . hydra--digit-argument)
+ (kp-5 . hydra--digit-argument)
+ (kp-4 . hydra--digit-argument)
+ (kp-3 . hydra--digit-argument)
+ (kp-2 . hydra--digit-argument)
+ (kp-1 . hydra--digit-argument)
+ (kp-0 . hydra--digit-argument)
+ (57 . hydra--digit-argument)
+ (56 . hydra--digit-argument)
+ (55 . hydra--digit-argument)
+ (54 . hydra--digit-argument)
+ (53 . hydra--digit-argument)
+ (52 . hydra--digit-argument)
+ (51 . hydra--digit-argument)
+ (50 . hydra--digit-argument)
+ (49 . hydra--digit-argument)
+ (48 . hydra--digit-argument)
+ (45 . hydra--negative-argument)
+ (21 . hydra--universal-argument)))
+ t))
+ (call-interactively (function next-error)))
+ (defun hydra-error/previous-error nil "Create a hydra with a \"M-g\"
body and the heads:
\"h\": `first-error',
\"j\": `next-error',
@@ -94,46 +131,89 @@ Call the head: `next-error'."
The body can be accessed via `hydra-error/body'.
Call the head: `previous-error'."
- (interactive)
- (call-interactively #'previous-error)
- (when hydra-is-helpful
- (message #("error: [h]: first, [j]: next, [k]: prev."
- 8 9 (face font-lock-keyword-face)
- 20 21 (face font-lock-keyword-face)
- 31 32 (face font-lock-keyword-face))))
- (setq hydra-last
- (hydra-set-transient-map
- '(keymap
- (107 . hydra-error/previous-error)
- (106 . hydra-error/next-error)
- (104 . hydra-error/first-error)) t)))
-
+ (interactive)
+ (when hydra-is-helpful (message #("error: [h]: first, [j]: next,
[k]: prev." 8 9 (face hydra-face-red)
+ 20 21 (face hydra-face-red)
+ 31 32 (face hydra-face-red))))
+ (setq hydra-last
+ (hydra-set-transient-map
+ (setq hydra-curr-map '(keymap (107 .
hydra-error/previous-error)
+ (106 . hydra-error/next-error)
+ (104 . hydra-error/first-error)
+ (kp-subtract .
hydra--negative-argument)
+ (kp-9 . hydra--digit-argument)
+ (kp-8 . hydra--digit-argument)
+ (kp-7 . hydra--digit-argument)
+ (kp-6 . hydra--digit-argument)
+ (kp-5 . hydra--digit-argument)
+ (kp-4 . hydra--digit-argument)
+ (kp-3 . hydra--digit-argument)
+ (kp-2 . hydra--digit-argument)
+ (kp-1 . hydra--digit-argument)
+ (kp-0 . hydra--digit-argument)
+ (57 . hydra--digit-argument)
+ (56 . hydra--digit-argument)
+ (55 . hydra--digit-argument)
+ (54 . hydra--digit-argument)
+ (53 . hydra--digit-argument)
+ (52 . hydra--digit-argument)
+ (51 . hydra--digit-argument)
+ (50 . hydra--digit-argument)
+ (49 . hydra--digit-argument)
+ (48 . hydra--digit-argument)
+ (45 . hydra--negative-argument)
+ (21 . hydra--universal-argument)))
+ t))
+ (call-interactively (function previous-error)))
(unless (keymapp (lookup-key global-map (kbd "M-g")))
- (define-key global-map (kbd "M-g") nil))
- (define-key global-map [134217831 104] #'hydra-error/first-error)
- (define-key global-map [134217831 106] #'hydra-error/next-error)
- (define-key global-map [134217831 107] #'hydra-error/previous-error)
-
- (defun hydra-error/body ()
- "Create a hydra with a \"M-g\" body and the heads:
+ (define-key global-map (kbd "M-g")
+ nil))
+ (define-key global-map [134217831 104]
+ (function hydra-error/first-error))
+ (define-key global-map [134217831 106]
+ (function hydra-error/next-error))
+ (define-key global-map [134217831 107]
+ (function hydra-error/previous-error))
+ (defun hydra-error/body nil "Create a hydra with a \"M-g\" body and the
heads:
\"h\": `first-error',
\"j\": `next-error',
\"k\": `previous-error'
The body can be accessed via `hydra-error/body'."
- (interactive)
- (when hydra-is-helpful
- (message #("error: [h]: first, [j]: next, [k]: prev."
- 8 9 (face font-lock-keyword-face)
- 20 21 (face font-lock-keyword-face)
- 31 32 (face font-lock-keyword-face))))
- (setq hydra-last
- (hydra-set-transient-map
- '(keymap
- (107 . hydra-error/previous-error)
- (106 . hydra-error/next-error)
- (104 . hydra-error/first-error)) t)))))))
+ (interactive)
+ (when hydra-is-helpful (message #("error: [h]: first, [j]: next,
[k]: prev." 8 9 (face hydra-face-red)
+ 20 21 (face hydra-face-red)
+ 31 32 (face hydra-face-red))))
+ (setq hydra-last
+ (hydra-set-transient-map
+ '(keymap (107 . hydra-error/previous-error)
+ (106 . hydra-error/next-error)
+ (104 . hydra-error/first-error)
+ (kp-subtract . hydra--negative-argument)
+ (kp-9 . hydra--digit-argument)
+ (kp-8 . hydra--digit-argument)
+ (kp-7 . hydra--digit-argument)
+ (kp-6 . hydra--digit-argument)
+ (kp-5 . hydra--digit-argument)
+ (kp-4 . hydra--digit-argument)
+ (kp-3 . hydra--digit-argument)
+ (kp-2 . hydra--digit-argument)
+ (kp-1 . hydra--digit-argument)
+ (kp-0 . hydra--digit-argument)
+ (57 . hydra--digit-argument)
+ (56 . hydra--digit-argument)
+ (55 . hydra--digit-argument)
+ (54 . hydra--digit-argument)
+ (53 . hydra--digit-argument)
+ (52 . hydra--digit-argument)
+ (51 . hydra--digit-argument)
+ (50 . hydra--digit-argument)
+ (49 . hydra--digit-argument)
+ (48 . hydra--digit-argument)
+ (45 . hydra--negative-argument)
+ (21 . hydra--universal-argument))
+ t)))))))
(ert-deftest hydra-blue-toggle ()
(should
@@ -146,8 +226,7 @@ The body can be accessed via `hydra-error/body'."
("a" abbrev-mode "abbrev")
("q" nil "cancel")))
'(progn
- (defun toggle/toggle-truncate-lines ()
- "Create a hydra with no body and the heads:
+ (defun toggle/toggle-truncate-lines nil "Create a hydra with no body and
the heads:
\"t\": `toggle-truncate-lines',
\"f\": `auto-fill-mode',
@@ -157,11 +236,10 @@ The body can be accessed via `hydra-error/body'."
The body can be accessed via `toggle/body'.
Call the head: `toggle-truncate-lines'."
- (interactive)
- (hydra-disable)
- (call-interactively #'toggle-truncate-lines))
- (defun toggle/auto-fill-mode ()
- "Create a hydra with no body and the heads:
+ (interactive)
+ (hydra-disable)
+ (call-interactively (function toggle-truncate-lines)))
+ (defun toggle/auto-fill-mode nil "Create a hydra with no body and the
heads:
\"t\": `toggle-truncate-lines',
\"f\": `auto-fill-mode',
@@ -171,11 +249,10 @@ Call the head: `toggle-truncate-lines'."
The body can be accessed via `toggle/body'.
Call the head: `auto-fill-mode'."
- (interactive)
- (hydra-disable)
- (call-interactively #'auto-fill-mode))
- (defun toggle/abbrev-mode ()
- "Create a hydra with no body and the heads:
+ (interactive)
+ (hydra-disable)
+ (call-interactively (function auto-fill-mode)))
+ (defun toggle/abbrev-mode nil "Create a hydra with no body and the heads:
\"t\": `toggle-truncate-lines',
\"f\": `auto-fill-mode',
@@ -185,11 +262,10 @@ Call the head: `auto-fill-mode'."
The body can be accessed via `toggle/body'.
Call the head: `abbrev-mode'."
- (interactive)
- (hydra-disable)
- (call-interactively #'abbrev-mode))
- (defun toggle/nil ()
- "Create a hydra with no body and the heads:
+ (interactive)
+ (hydra-disable)
+ (call-interactively (function abbrev-mode)))
+ (defun toggle/nil nil "Create a hydra with no body and the heads:
\"t\": `toggle-truncate-lines',
\"f\": `auto-fill-mode',
@@ -199,10 +275,9 @@ Call the head: `abbrev-mode'."
The body can be accessed via `toggle/body'.
Call the head: `nil'."
- (interactive)
- (hydra-disable))
- (defun toggle/body ()
- "Create a hydra with no body and the heads:
+ (interactive)
+ (hydra-disable))
+ (defun toggle/body nil "Create a hydra with no body and the heads:
\"t\": `toggle-truncate-lines',
\"f\": `auto-fill-mode',
@@ -210,20 +285,41 @@ Call the head: `nil'."
\"q\": `nil'
The body can be accessed via `toggle/body'."
- (interactive)
- (when hydra-is-helpful
- (message #("toggle: [t]: truncate, [f]: fill, [a]: abbrev, [q]:
cancel."
- 9 10 (face hydra-face-blue)
- 24 25 (face hydra-face-blue)
- 35 36 (face hydra-face-blue)
- 48 49 (face hydra-face-blue))))
- (setq hydra-last
- (hydra-set-transient-map
- '(keymap (113 . toggle/nil)
- (97 . toggle/abbrev-mode)
- (102 . toggle/auto-fill-mode)
- (116 . toggle/toggle-truncate-lines))
- t)))))))
+ (interactive)
+ (when hydra-is-helpful (message #("toggle: [t]: truncate, [f]:
fill, [a]: abbrev, [q]: cancel." 9 10 (face hydra-face-blue)
+ 24 25 (face hydra-face-blue)
+ 35 36 (face hydra-face-blue)
+ 48 49 (face hydra-face-blue))))
+ (setq hydra-last
+ (hydra-set-transient-map
+ '(keymap (113 . toggle/nil)
+ (97 . toggle/abbrev-mode)
+ (102 . toggle/auto-fill-mode)
+ (116 . toggle/toggle-truncate-lines)
+ (kp-subtract . hydra--negative-argument)
+ (kp-9 . hydra--digit-argument)
+ (kp-8 . hydra--digit-argument)
+ (kp-7 . hydra--digit-argument)
+ (kp-6 . hydra--digit-argument)
+ (kp-5 . hydra--digit-argument)
+ (kp-4 . hydra--digit-argument)
+ (kp-3 . hydra--digit-argument)
+ (kp-2 . hydra--digit-argument)
+ (kp-1 . hydra--digit-argument)
+ (kp-0 . hydra--digit-argument)
+ (57 . hydra--digit-argument)
+ (56 . hydra--digit-argument)
+ (55 . hydra--digit-argument)
+ (54 . hydra--digit-argument)
+ (53 . hydra--digit-argument)
+ (52 . hydra--digit-argument)
+ (51 . hydra--digit-argument)
+ (50 . hydra--digit-argument)
+ (49 . hydra--digit-argument)
+ (48 . hydra--digit-argument)
+ (45 . hydra--negative-argument)
+ (21 . hydra--universal-argument))
+ t)))))))
(provide 'hydra-test)
diff --git a/packages/hydra/hydra.el b/packages/hydra/hydra.el
index 95d3a42..738b77c 100644
--- a/packages/hydra/hydra.el
+++ b/packages/hydra/hydra.el
@@ -5,7 +5,7 @@
;; Author: Oleh Krehel <address@hidden>
;; Maintainer: Oleh Krehel <address@hidden>
;; URL: https://github.com/abo-abo/hydra
-;; Version: 0.5.0
+;; Version: 0.6.1
;; Keywords: bindings
;; Package-Requires: ((cl-lib "0.5"))
@@ -61,8 +61,15 @@
;; ("l" text-scale-decrease "out"))
;;; Code:
+;;* Requires
(require 'cl-lib)
+(defalias 'hydra-set-transient-map
+ (if (fboundp 'set-transient-map)
+ 'set-transient-map
+ 'set-temporary-overlay-map))
+
+;;* Customize
(defgroup hydra nil
"Make bindings that stick around."
:group 'bindings
@@ -82,43 +89,65 @@
'((t (:foreground "#758BC6" :bold t)))
"Blue Hydra heads will vanquish the Hydra.")
-(defalias 'hydra-set-transient-map
- (if (fboundp 'set-transient-map)
- 'set-transient-map
- 'set-temporary-overlay-map))
-
+;;* Universal Argument
+(defvar hydra-base-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [?\C-u] 'hydra--universal-argument)
+ (define-key map [?-] 'hydra--negative-argument)
+ (define-key map [?0] 'hydra--digit-argument)
+ (define-key map [?1] 'hydra--digit-argument)
+ (define-key map [?2] 'hydra--digit-argument)
+ (define-key map [?3] 'hydra--digit-argument)
+ (define-key map [?4] 'hydra--digit-argument)
+ (define-key map [?5] 'hydra--digit-argument)
+ (define-key map [?6] 'hydra--digit-argument)
+ (define-key map [?7] 'hydra--digit-argument)
+ (define-key map [?8] 'hydra--digit-argument)
+ (define-key map [?9] 'hydra--digit-argument)
+ (define-key map [kp-0] 'hydra--digit-argument)
+ (define-key map [kp-1] 'hydra--digit-argument)
+ (define-key map [kp-2] 'hydra--digit-argument)
+ (define-key map [kp-3] 'hydra--digit-argument)
+ (define-key map [kp-4] 'hydra--digit-argument)
+ (define-key map [kp-5] 'hydra--digit-argument)
+ (define-key map [kp-6] 'hydra--digit-argument)
+ (define-key map [kp-7] 'hydra--digit-argument)
+ (define-key map [kp-8] 'hydra--digit-argument)
+ (define-key map [kp-9] 'hydra--digit-argument)
+ (define-key map [kp-subtract] 'hydra--negative-argument)
+ 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--universal-argument (arg)
+ "Forward to (`universal-argument' ARG)."
+ (interactive "P")
+ (setq prefix-arg (if (consp arg)
+ (list (* 4 (car arg)))
+ (if (eq arg '-)
+ (list -4)
+ '(4))))
+ (hydra-set-transient-map hydra-curr-map))
+
+(defun hydra--digit-argument (arg)
+ "Forward to (`digit-argument' ARG)."
+ (interactive "P")
+ (let ((universal-argument-map hydra-curr-map))
+ (digit-argument arg)))
+
+(defun hydra--negative-argument (arg)
+ "Forward to (`negative-argument' ARG)."
+ (interactive "P")
+ (let ((universal-argument-map hydra-curr-map))
+ (negative-argument arg)))
+
+;;* Misc internals
(defvar hydra-last nil
"The result of the last `hydra-set-transient-map' call.")
-;;;###autoload
-(defmacro hydra-create (body heads &optional method)
- "Create a hydra with a BODY prefix and HEADS with METHOD.
-This will result in `global-set-key' statements with the keys
-being the concatenation of BODY and each head in HEADS. HEADS is
-an list of (KEY FUNCTION &optional HINT).
-
-After one of the HEADS is called via BODY+KEY, it and the other
-HEADS can be called with only KEY (no need for BODY). This state
-is broken once any key binding that is not in HEADS is called.
-
-METHOD is a lambda takes two arguments: a KEY and a COMMAND.
-It defaults to `global-set-key'.
-When `(keymapp METHOD)`, it becomes:
-
- (lambda (key command) (define-key METHOD key command))"
- (declare (indent 1))
- `(defhydra ,(intern
- (concat
- "hydra-" (replace-regexp-in-string " " "_" body)))
- ,(cond ((hydra--callablep method)
- method)
- ((null method)
- `(global-map ,body))
- (t
- (list method body)))
- "hydra"
- ,@(eval heads)))
-
(defun hydra--callablep (x)
"Test if X is callable."
(or (functionp x)
@@ -141,8 +170,8 @@ When `(keymapp METHOD)`, it becomes:
(red 'hydra-face-red)
(t (error "Unknown color for %S" h))))
-(defun hydra--hint (docstring heads)
- "Generate a hint from DOCSTRING and HEADS.
+(defun hydra--hint (docstring heads body-color)
+ "Generate a hint from DOCSTRING and HEADS and BODY-COLOR.
It's intended for the echo area, when a Hydra is active."
(format "%s: %s."
docstring
@@ -159,13 +188,22 @@ It's intended for the echo area, when a Hydra is active."
(defun hydra-disable ()
"Disable the current Hydra."
- (if (functionp hydra-last)
- (funcall hydra-last)
- (while (and (consp (car emulation-mode-map-alists))
- (consp (caar emulation-mode-map-alists))
- (equal (cl-cdaar emulation-mode-map-alists) ',keymap))
- (setq emulation-mode-map-alists
- (cdr emulation-mode-map-alists)))))
+ (cond
+ ;; Emacs 25
+ ((functionp hydra-last)
+ (funcall hydra-last))
+
+ ;; Emacs 24.4.1
+ ((boundp 'overriding-terminal-local-map)
+ (setq overriding-terminal-local-map nil))
+
+ ;; older
+ (t
+ (while (and (consp (car emulation-mode-map-alists))
+ (consp (caar emulation-mode-map-alists))
+ (equal (cl-cdaar emulation-mode-map-alists) ',keymap))
+ (setq emulation-mode-map-alists
+ (cdr emulation-mode-map-alists))))))
(defun hydra--doc (body-key body-name heads)
"Generate a part of Hydra docstring.
@@ -183,6 +221,38 @@ HEADS is a list of heads."
heads ",\n")
(format "The body can be accessed via `%S'." body-name)))
+;;* Macros
+;;** hydra-create
+;;;###autoload
+(defmacro hydra-create (body heads &optional method)
+ "Create a hydra with a BODY prefix and HEADS with METHOD.
+This will result in `global-set-key' statements with the keys
+being the concatenation of BODY and each head in HEADS. HEADS is
+an list of (KEY FUNCTION &optional HINT).
+
+After one of the HEADS is called via BODY+KEY, it and the other
+HEADS can be called with only KEY (no need for BODY). This state
+is broken once any key binding that is not in HEADS is called.
+
+METHOD is a lambda takes two arguments: a KEY and a COMMAND.
+It defaults to `global-set-key'.
+When `(keymapp METHOD)`, it becomes:
+
+ (lambda (key command) (define-key METHOD key command))"
+ (declare (indent 1))
+ `(defhydra ,(intern
+ (concat
+ "hydra-" (replace-regexp-in-string " " "_" body)))
+ ,(cond ((hydra--callablep method)
+ method)
+ ((null method)
+ `(global-map ,body))
+ (t
+ (list method body)))
+ "hydra"
+ ,@(eval heads)))
+
+;;** defhydra
;;;###autoload
(defmacro defhydra (name body &optional docstring &rest heads)
"Create a hydra named NAME with a prefix BODY.
@@ -212,11 +282,14 @@ in turn can be either red or blue."
(setq docstring "hydra"))
(when (keywordp (car body))
(setq body (cons nil (cons nil body))))
- (let* ((keymap (make-sparse-keymap))
+ (let* ((keymap (copy-keymap hydra-base-map))
(names (mapcar
(lambda (x)
(define-key keymap (kbd (car x))
- (intern (format "%S/%s" name (cadr x)))))
+ (intern (format "%S/%s" name
+ (if (symbolp (cadr x))
+ (cadr x)
+ (concat "lambda-" (car x)))))))
heads))
(body-name (intern (format "%S/body" name)))
(body-key (unless (hydra--callablep body)
@@ -228,7 +301,7 @@ in turn can be either red or blue."
(method (if (hydra--callablep body)
body
(car body)))
- (hint (hydra--hint docstring heads))
+ (hint (hydra--hint docstring heads body-color))
(doc (hydra--doc body-key body-name heads)))
`(progn
,@(cl-mapcar
@@ -240,11 +313,11 @@ in turn can be either red or blue."
`((hydra-disable)
,@(unless (null (cadr head))
`((call-interactively #',(cadr head)))))
- `((call-interactively #',(cadr head))
- (when hydra-is-helpful
+ `((when hydra-is-helpful
(message ,hint))
(setq hydra-last
- (hydra-set-transient-map ',keymap t))))))
+ (hydra-set-transient-map (setq hydra-curr-map
',keymap) t))
+ (call-interactively #',(cadr head))))))
heads names)
,@(unless (or (null body-key)
(null method)
@@ -272,4 +345,9 @@ in turn can be either red or blue."
(hydra-set-transient-map ',keymap t))))))
(provide 'hydra)
+
+;;; Local Variables:
+;;; outline-regexp: ";;\\*+"
+;;; End:
+
;;; hydra.el ends here
- [elpa] master updated (d44f2ad -> 3c57fa9), Oleh Krehel, 2015/02/04
- [elpa] master 7222773 3/6: hydra.el (hydra-disable): adapt to Emacs 24.4.1, Oleh Krehel, 2015/02/04
- [elpa] master b60201f 4/6: Bump version, Oleh Krehel, 2015/02/04
- [elpa] master b963c70 5/6: Improve the names of functions generated from lambdas, Oleh Krehel, 2015/02/04
- [elpa] master 222ba95 2/6: hydra-examples.el: splitters take numeric argument, Oleh Krehel, 2015/02/04
- [elpa] master 0b6ef70 1/6: Add support for `universal-argument' and `digit-argument', Oleh Krehel, 2015/02/04
- [elpa] master 3c57fa9 6/6: Merge commit 'b963c70dcf211c86d4bb03bfd4a20c6807cbe679' from hydra,
Oleh Krehel <=