aboutsummaryrefslogtreecommitdiff
path: root/evil-core.el
diff options
context:
space:
mode:
Diffstat (limited to 'evil-core.el')
-rw-r--r--evil-core.el85
1 files changed, 54 insertions, 31 deletions
diff --git a/evil-core.el b/evil-core.el
index 506b422..0419212 100644
--- a/evil-core.el
+++ b/evil-core.el
@@ -105,6 +105,8 @@
;;; Code:
+(declare-function evil-emacs-state-p "evil-states")
+
(define-minor-mode evil-local-mode
"Minor mode for setting up Evil in a single buffer."
:init-value nil
@@ -180,10 +182,12 @@ To enable Evil globally, do (evil-mode 1)."
;; changed back by `evil-local-mode'
(setq-default major-mode 'turn-on-evil-mode)
(ad-enable-regexp "^evil")
- (ad-activate-regexp "^evil"))
+ (ad-activate-regexp "^evil")
+ (with-no-warnings (evil-esc-mode 1)))
(setq-default major-mode 'fundamental-mode)
(ad-disable-regexp "^evil")
- (ad-update-regexp "^evil")))
+ (ad-update-regexp "^evil")
+ (with-no-warnings (evil-esc-mode -1))))
(put 'evil-mode 'function-documentation
"Toggle Evil in all buffers.
@@ -531,27 +535,54 @@ may be specified before the body code:
,@body))
',keymap)))
-;; Intercept the ESC event when running in the terminal. This allows
-;; keys that use "ESC" as a prefix key, such as "M-x". If "ESC" is
-;; immediately followed by another key, or another key is pressed
-;; within `evil-esc-delay', the prefixed key sequence is sent.
-;; Otherwise only [escape] is sent.
-(evil-define-keymap evil-esc-map
- "Keymap for intercepting ESC."
- :intercept t)
-
-(defun evil-turn-on-esc-mode ()
- "Enable interception of ESC."
- (unless (eq this-command #'evil-esc)
- (evil-esc-mode 1)
- (remove-hook 'pre-command-hook #'evil-turn-on-esc-mode t)))
-(put 'evil-turn-on-esc-mode 'permanent-local-hook t)
-
-;; `evil-esc' is bound to (kbd "ESC"), while other commands
-;; are bound to [escape]. That way `evil-esc' is used only when
-;; (kbd "ESC") and [escape] are the same event -- i.e., when
-;; running Emacs in the terminal.
-(define-key evil-esc-map (kbd "ESC") 'evil-esc)
+;; The ESC -> escape translation code has been provided by Stefan
+;; Monnier in the discussion of GNU Emacs bug #13793.
+(defun evil-esc-mode (&optional arg)
+ "Toggle interception of \\e (escape).
+Enable with positive ARG and disable with negative ARG.
+
+When enabled, `evil-esc-mode' modifies the entry of \\e in
+`input-decode-map'. If such an event arrives, it is translated to
+a plain 'escape event if no further event occurs within
+`evil-esc-delay' seconds. Otherwise no translation happens and
+the ESC prefix map (i.e. the map originally bound to \\e in
+`input-decode-map`) is returned."
+ (cond
+ ((or (null arg) (eq arg 0))
+ (evil-esc-mode (if evil-esc-mode -1 +1)))
+
+ ((> arg 0)
+ (unless evil-esc-mode
+ (setq evil-esc-map (lookup-key input-decode-map [?\e]))
+ (define-key input-decode-map [?\e]
+ `(menu-item "" ,evil-esc-map :filter ,#'evil-esc))
+ (setq evil-esc-mode t)))
+ ((< arg 0)
+ (when evil-esc-mode
+ (define-key input-decode-map [?\e] evil-esc-map)))))
+
+(defun evil-esc (map)
+ "Translate \\e to 'escape if no further event arrives.
+This function is used to translate a \\e event either to 'escape
+or to the standard ESC prefix translation map. If \\e arrives,
+this function waits for `evil-esc-delay' seconds for another
+event. If no other event arrives, the event is translated to
+'escape, otherwise it is translated to the standard ESC prefix
+map stored in `input-decode-map'. If `evil-inhibit-esc' is
+non-nil or if evil is in emacs state, the event is always
+translated to the ESC prefix.
+
+The translation to 'escape happens only if the current command
+has indeed been triggered by \\e. In other words, this will only
+happen when the keymap is accessed from `read-key-sequence'. In
+particular, if it is access from `define-key' the returned
+mapping will always be the ESC prefix map."
+ (if (and (not evil-inhibit-esc)
+ evil-local-mode
+ (not (evil-emacs-state-p))
+ (equal (this-single-command-keys) [?\e])
+ (sit-for evil-esc-delay))
+ [escape] map))
(defun evil-state-p (sym)
"Whether SYM is the name of a state."
@@ -713,7 +744,6 @@ See also `evil-mode-for-keymap'."
(when (setq map (evil-intercept-keymap-p map state))
(push (cons (evil-mode-for-keymap map t) map) result)))
(setq result (nreverse result))
- (add-to-list 'result `(evil-esc-mode . ,evil-esc-map))
result))
(defun evil-set-auxiliary-keymap (map state &optional aux)
@@ -928,7 +958,6 @@ the local keymap will be `evil-test-state-local-map', and so on.
(exit-hook (intern (format "%s-exit-hook" toggle)))
(modes (intern (format "%s-modes" toggle)))
(predicate (intern (format "%s-p" toggle)))
- (intercept-esc t)
arg cursor-value enable entry-hook-value exit-hook-value
input-method key message-value suppress-keymap tag-value)
;; collect keywords
@@ -954,8 +983,6 @@ the local keymap will be `evil-test-state-local-map', and so on.
(setq enable arg))
((eq key :input-method)
(setq input-method arg))
- ((eq key :intercept-esc)
- (setq intercept-esc arg))
((eq key :suppress-keymap)
(setq suppress-keymap arg))))
@@ -1029,7 +1056,6 @@ If ARG is nil, don't display a message in the echo area.%s" name doc)
(let ((evil-state ',state))
(run-hooks ',exit-hook)
(setq evil-state nil)
- (evil-esc-mode -1)
(evil-normalize-keymaps)
,@body))
(t
@@ -1044,9 +1070,6 @@ If ARG is nil, don't display a message in the echo area.%s" name doc)
',state evil-previous-state)
(let ((evil-state ',state))
(evil-normalize-keymaps)
- (if ,intercept-esc
- (evil-esc-mode 1)
- (evil-esc-mode -1))
(if ',input-method
(activate-input-method evil-input-method)
(deactivate-input-method))