]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve robustness xterm event processing
authorDaniel Colascione <dancol@dancol.org>
Sat, 9 Jun 2018 20:14:11 +0000 (13:14 -0700)
committerDaniel Colascione <dancol@dancol.org>
Sat, 9 Jun 2018 20:18:17 +0000 (13:18 -0700)
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.

lisp/term/xterm.el

index 06a9d443bfa39b35c403d6c865d8aa8848fc5324..a4321914c1279763e0f19fa7d96a150efdd77828 100644 (file)
@@ -95,24 +95,41 @@ Return the pasted text as a string."
        (decode-coding-region (point-min) (point) (keyboard-coding-system)
                               t)))))
 
-(defun xterm-paste ()
+(defun xterm-paste (event)
   "Handle the start of a terminal paste operation."
-  (interactive)
-  (let* ((pasted-text (xterm--pasted-text))
+  (interactive "e")
+  (unless (eq (car-safe event) 'xterm-paste)
+    (error "xterm-paste must be found to xterm-paste event"))
+  (let* ((pasted-text (nth 1 event))
          (interprogram-paste-function (lambda () pasted-text)))
     (yank)))
 
+;; Put xterm-paste itself in global-map because, after translation,
+;; it's just a normal input event.
 (define-key global-map [xterm-paste] #'xterm-paste)
 
-(defun xterm-handle-focus-in ()
-  (interactive)
-  (handle-focus-in))
-(define-key global-map [xterm-focus-in] #'xterm-handle-focus-in)
+;; By returning an empty key sequence, these two functions perform the
+;; moral equivalent of the kind of transparent event processing done
+;; by read-event's handling of special-event-map, but inside
+;; read-key-sequence (which can recognize multi-character terminal
+;; notifications) instead of read-event (which can't).
 
-(defun xterm-handle-focus-out ()
-  (interactive)
-  (handle-focus-out))
-(define-key global-map [xterm-focus-out] #'xterm-handle-focus-out)
+(defun xterm-translate-focus-in (_prompt)
+  (handle-focus-in)
+  [])
+
+(defun xterm-translate-focus-out (_prompt)
+  (handle-focus-out)
+  [])
+
+;; Similarly, we want to transparently slurp the entirety of a
+;; bracketed paste and encapsulate it into a single event.  We used to
+;; just slurp up the bracketed paste content in the event handler, but
+;; this strategy can produce unexpected results in a caller manually
+;; looping on read-key and buffering input for later processing.
+
+(defun xterm-translate-bracketed-paste (_prompt)
+  (vector (list 'xterm-paste (xterm--pasted-text))))
 
 (defvar xterm-rxvt-function-map
   (let ((map (make-sparse-keymap)))
@@ -142,12 +159,15 @@ Return the pasted text as a string."
     (define-key map "\e[13~" [f3])
     (define-key map "\e[14~" [f4])
 
-    ;; Recognize the start of a bracketed paste sequence.  The handler
-    ;; internally recognizes the end.
-    (define-key map "\e[200~" [xterm-paste])
+    ;; Recognize the start of a bracketed paste sequence.
+    ;; The translation function internally recognizes the end.
+    (define-key map "\e[200~" #'xterm-translate-bracketed-paste)
 
-    (define-key map "\e[I" [xterm-focus-in])
-    (define-key map "\e[O" [xterm-focus-out])
+    ;; These translation functions actually call the focus handlers
+    ;; internally and return an empty sequence, causing us to go on to
+    ;; read the next event.
+    (define-key map "\e[I" #'xterm-translate-focus-in)
+    (define-key map "\e[O" #'xterm-translate-focus-out)
 
     map)
   "Keymap of escape sequences, shared between xterm and rxvt support.")