-
Notifications
You must be signed in to change notification settings - Fork 136
/
meow-esc.el
79 lines (68 loc) · 2.95 KB
/
meow-esc.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
;;; meow-esc.el --- make ESC works in TUI -*- lexical-binding: t; -*-
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; In the terminal, ESC can be used as META, because they send the
;; same keycode. To allow both usages simulataneously, you can
;; customize meow-esc-delay, the maximum time between ESC and the
;; keypress that should be treated as a meta combo. If the time is
;; longer than the delay, it's treated as pressing ESC and then the
;; key separately.
;;; Code:
(defvar meow-esc-delay 0.1)
(defvar meow--escape-key-seq [?\e])
;;;###autoload
(define-minor-mode meow-esc-mode
"Mode that ensures ESC works in the terminal"
:init-value nil
:global t
:group 'meow
:keymap nil
(if meow-esc-mode
(progn
(setq meow-esc-mode t)
(add-hook 'after-make-frame-functions #'meow--init-esc-if-tui)
(mapc #'meow--init-esc-if-tui (frame-list)))
(progn
(remove-hook 'after-make-frame-functions #'meow--init-esc-if-tui)
(mapc #'meow--deinit-esc-if-tui (frame-list))
(setq meow-esc-mode nil))))
(defun meow--init-esc-if-tui (frame)
(with-selected-frame frame
(unless window-system
(let ((term (frame-terminal frame)))
(when (not (terminal-parameter term 'meow-esc-map))
(let ((meow-esc-map (lookup-key input-decode-map [?\e])))
(set-terminal-parameter term 'meow-esc-map meow-esc-map)
(define-key input-decode-map meow--escape-key-seq
`(menu-item "" ,meow-esc-map :filter ,#'meow-esc))))))))
(defun meow--deinit-esc-if-tui (frame)
(with-selected-frame frame
(unless window-system
(let ((term (frame-terminal frame)))
(when (terminal-live-p term)
(let ((meow-esc-map (terminal-parameter term 'meow-esc-map)))
(when meow-esc-map
(define-key input-decode-map meow--escape-key-seq meow-esc-map)
(set-terminal-parameter term 'meow-esc-map nil))))))))
(defun meow-esc (map)
(if (and (let ((keys (this-single-command-keys)))
(and (> (length keys) 0)
(= (aref keys (1- (length keys))) ?\e)))
(sit-for meow-esc-delay))
(prog1 [escape]
(when defining-kbd-macro
(end-kbd-macro)
(setq last-kbd-macro (vconcat last-kbd-macro [escape]))
(start-kbd-macro t t)))
map))
(provide 'meow-esc)
;;; meow-esc.el ends here