diff options
| author | Daniel Colascione | 2018-06-09 13:14:11 -0700 |
|---|---|---|
| committer | Daniel Colascione | 2018-06-09 13:18:17 -0700 |
| commit | a66a3b7f51792aa2a91c16ed9121d7e9efea4536 (patch) | |
| tree | c79ee642c09cb0f964167d034374e28b991a85b3 | |
| parent | 66ad98685afa9ee3bc1ec2aeb116f41a2a7875b3 (diff) | |
| download | emacs-a66a3b7f51792aa2a91c16ed9121d7e9efea4536.tar.gz emacs-a66a3b7f51792aa2a91c16ed9121d7e9efea4536.zip | |
Improve robustness xterm event processing
We used to treat the start of a focus-in, focus-out, and the start of
a paste sequence as normal events bound in global-map, but this
approach produces problems when we recognize events in the middle of
actions that don't immediately dispatch to the command loop.
Now we handle these events internally inside read-key, translating the
focus events to nothing and paste-start into an xterm-paste event that
neatly encapsulates the entire paste sequence.
* lisp/term/xterm.el:
(xterm-paste): Accept an event argument; insert text from event.
(xterm-translate-focus-in,xterm-translate-focus-out)
(xterm-translate-bracketed-paste): New functions.
(xterm-handle-focus-in,xterm-handle-focus-out): Remove.
(xterm-rxvt-function-map): Bind new translation functions.
| -rw-r--r-- | lisp/term/xterm.el | 52 |
1 files changed, 36 insertions, 16 deletions
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el index 06a9d443bfa..a4321914c12 100644 --- a/lisp/term/xterm.el +++ b/lisp/term/xterm.el | |||
| @@ -95,24 +95,41 @@ Return the pasted text as a string." | |||
| 95 | (decode-coding-region (point-min) (point) (keyboard-coding-system) | 95 | (decode-coding-region (point-min) (point) (keyboard-coding-system) |
| 96 | t))))) | 96 | t))))) |
| 97 | 97 | ||
| 98 | (defun xterm-paste () | 98 | (defun xterm-paste (event) |
| 99 | "Handle the start of a terminal paste operation." | 99 | "Handle the start of a terminal paste operation." |
| 100 | (interactive) | 100 | (interactive "e") |
| 101 | (let* ((pasted-text (xterm--pasted-text)) | 101 | (unless (eq (car-safe event) 'xterm-paste) |
| 102 | (error "xterm-paste must be found to xterm-paste event")) | ||
| 103 | (let* ((pasted-text (nth 1 event)) | ||
| 102 | (interprogram-paste-function (lambda () pasted-text))) | 104 | (interprogram-paste-function (lambda () pasted-text))) |
| 103 | (yank))) | 105 | (yank))) |
| 104 | 106 | ||
| 107 | ;; Put xterm-paste itself in global-map because, after translation, | ||
| 108 | ;; it's just a normal input event. | ||
| 105 | (define-key global-map [xterm-paste] #'xterm-paste) | 109 | (define-key global-map [xterm-paste] #'xterm-paste) |
| 106 | 110 | ||
| 107 | (defun xterm-handle-focus-in () | 111 | ;; By returning an empty key sequence, these two functions perform the |
| 108 | (interactive) | 112 | ;; moral equivalent of the kind of transparent event processing done |
| 109 | (handle-focus-in)) | 113 | ;; by read-event's handling of special-event-map, but inside |
| 110 | (define-key global-map [xterm-focus-in] #'xterm-handle-focus-in) | 114 | ;; read-key-sequence (which can recognize multi-character terminal |
| 115 | ;; notifications) instead of read-event (which can't). | ||
| 111 | 116 | ||
| 112 | (defun xterm-handle-focus-out () | 117 | (defun xterm-translate-focus-in (_prompt) |
| 113 | (interactive) | 118 | (handle-focus-in) |
| 114 | (handle-focus-out)) | 119 | []) |
| 115 | (define-key global-map [xterm-focus-out] #'xterm-handle-focus-out) | 120 | |
| 121 | (defun xterm-translate-focus-out (_prompt) | ||
| 122 | (handle-focus-out) | ||
| 123 | []) | ||
| 124 | |||
| 125 | ;; Similarly, we want to transparently slurp the entirety of a | ||
| 126 | ;; bracketed paste and encapsulate it into a single event. We used to | ||
| 127 | ;; just slurp up the bracketed paste content in the event handler, but | ||
| 128 | ;; this strategy can produce unexpected results in a caller manually | ||
| 129 | ;; looping on read-key and buffering input for later processing. | ||
| 130 | |||
| 131 | (defun xterm-translate-bracketed-paste (_prompt) | ||
| 132 | (vector (list 'xterm-paste (xterm--pasted-text)))) | ||
| 116 | 133 | ||
| 117 | (defvar xterm-rxvt-function-map | 134 | (defvar xterm-rxvt-function-map |
| 118 | (let ((map (make-sparse-keymap))) | 135 | (let ((map (make-sparse-keymap))) |
| @@ -142,12 +159,15 @@ Return the pasted text as a string." | |||
| 142 | (define-key map "\e[13~" [f3]) | 159 | (define-key map "\e[13~" [f3]) |
| 143 | (define-key map "\e[14~" [f4]) | 160 | (define-key map "\e[14~" [f4]) |
| 144 | 161 | ||
| 145 | ;; Recognize the start of a bracketed paste sequence. The handler | 162 | ;; Recognize the start of a bracketed paste sequence. |
| 146 | ;; internally recognizes the end. | 163 | ;; The translation function internally recognizes the end. |
| 147 | (define-key map "\e[200~" [xterm-paste]) | 164 | (define-key map "\e[200~" #'xterm-translate-bracketed-paste) |
| 148 | 165 | ||
| 149 | (define-key map "\e[I" [xterm-focus-in]) | 166 | ;; These translation functions actually call the focus handlers |
| 150 | (define-key map "\e[O" [xterm-focus-out]) | 167 | ;; internally and return an empty sequence, causing us to go on to |
| 168 | ;; read the next event. | ||
| 169 | (define-key map "\e[I" #'xterm-translate-focus-in) | ||
| 170 | (define-key map "\e[O" #'xterm-translate-focus-out) | ||
| 151 | 171 | ||
| 152 | map) | 172 | map) |
| 153 | "Keymap of escape sequences, shared between xterm and rxvt support.") | 173 | "Keymap of escape sequences, shared between xterm and rxvt support.") |