* Patch for supporting tmux
@ 2016-03-29 9:08 Philipp Stephani
0 siblings, 0 replies; only message in thread
From: Philipp Stephani @ 2016-03-29 9:08 UTC (permalink / raw
To: Emacs developers
[-- Attachment #1.1: Type: text/plain, Size: 312 bytes --]
Hi,
currently xterm.el selection access supports GNU screen, but not tmux. I've
attached a patch to refactor the detection code somewhat (so that
multiplexers are always detected) and added support for X selection access
in tmux (rather simple, requires just a different wrapping sequence for the
OSC command).
[-- Attachment #1.2: Type: text/html, Size: 362 bytes --]
[-- Attachment #2: 0001-Add-some-support-for-tmux-in-XTerm.patch --]
[-- Type: application/octet-stream, Size: 21560 bytes --]
From e5636a16f7805552cdd5a76b6ace531c258d6870 Mon Sep 17 00:00:00 2001
From: Philipp Stephani <phst@google.com>
Date: Tue, 29 Mar 2016 10:37:05 +0200
Subject: [PATCH] Add some support for tmux in XTerm
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Have xterm.el identify the terminal so that multiplexers are detected
more reliably. Allow tmux to access the X selection (requires a
different wrapper than GNU screen).
* term/xterm.el (xterm-screen-extra-capabilities): Moved from
term/screen.el; use setSelection by default.
(xterm-tmux-extra-capabilities): New customization option.
(xterm--extra-capabilities, xterm--identify)
(xterm--identification, xterm--handle-identification)
(xterm--parse-identification, xterm--wrap-selection-query): New
helper functions.
(terminal-init-xterm): Always query terminal emulator/multiplexer
version, store in new terminal parameter ‘xterm-identification.’
(gui-backend-get-selection, gui-backend-set-selection): Use helper
functions and new terminal parameter.
* term/screen.el: Delete file.
* faces.el (term-file-aliases): Treat GNU screen and tmux as alias
of XTerm.
* xterm-tests.el: Add test file.
---
lisp/faces.el | 1 +
lisp/term/screen.el | 23 ----
lisp/term/xterm.el | 254 ++++++++++++++++++++++++++++++------------
test/automated/xterm-tests.el | 97 ++++++++++++++++
4 files changed, 278 insertions(+), 97 deletions(-)
delete mode 100644 lisp/term/screen.el
create mode 100644 test/automated/xterm-tests.el
diff --git a/lisp/faces.el b/lisp/faces.el
index 612bd16..adde7e9 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -46,6 +46,7 @@ term-file-aliases
("vt320" . "vt200")
("vt400" . "vt200")
("vt420" . "vt200")
+ ("screen" . "xterm")
)
"Alist of terminal type aliases.
Entries are of the form (TYPE . ALIAS), where both elements are strings.
diff --git a/lisp/term/screen.el b/lisp/term/screen.el
deleted file mode 100644
index 7f68115..0000000
--- a/lisp/term/screen.el
+++ /dev/null
@@ -1,23 +0,0 @@
-;;; screen.el --- terminal initialization for screen and tmux -*- lexical-binding: t -*-
-;; Copyright (C) 1995, 2001-2016 Free Software Foundation, Inc.
-
-(require 'term/xterm)
-
-(defcustom xterm-screen-extra-capabilities '(modifyOtherKeys)
- "Extra capabilities supported under \"screen\".
-Some features of screen depend on the terminal emulator in which
-it runs, which can change when the screen session is moved to another tty."
- :version "25.1"
- :type xterm--extra-capabilities-type
- :group 'xterm)
-
-(defun terminal-init-screen ()
- "Terminal initialization function for screen."
- ;; Treat a screen terminal similar to an xterm, but don't use
- ;; xterm-extra-capabilities's `check' setting since that doesn't seem
- ;; to work so well (it depends too much on the surrounding terminal
- ;; emulator, which can change during the session, bug#20356).
- (let ((xterm-extra-capabilities xterm-screen-extra-capabilities))
- (tty-run-terminal-initialization (selected-frame) "xterm")))
-
-;; screen.el ends here
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
index e06423c..284855c 100644
--- a/lisp/term/xterm.el
+++ b/lisp/term/xterm.el
@@ -22,8 +22,24 @@
;;; Commentary:
+;; Integration with XTerm and terminal emulators and multiplexers
+;; compatible with XTerm. This file has some partial knowledge about
+;; the following terminal emulators and multiplexers:
+;;
+;; - XTerm
+;; - Gnome Terminal
+;; - Terminal.app
+;; - HTerm
+;; - GNU screen
+;; - tmux
+;;
+;; XTerm control sequences are documented at
+;; http://invisible-island.net/xterm/ctlseqs/ctlseqs.html.
+
;;; Code:
+(require 'subr-x)
+
(defgroup xterm nil
"XTerm support."
:version "24.1"
@@ -52,6 +68,23 @@ xterm-extra-capabilities
:type `(choice (const :tag "Check" check)
,xterm--extra-capabilities-type))
+(defcustom xterm-screen-extra-capabilities '(modifyOtherKeys setSelection)
+ "Extra capabilities supported under \"screen\".
+Some features of screen depend on the terminal emulator in which
+it runs, which can change when the screen session is moved to another tty."
+ :version "25.1"
+ :type xterm--extra-capabilities-type
+ :group 'xterm)
+
+(defcustom xterm-tmux-extra-capabilities '(modifyOtherKeys setSelection)
+ "Extra capabilities supported under \"tmux\".
+Some features of tmux depend on the terminal emulator in which it
+runs, which can change when the screen session is moved to
+another tty."
+ :version "25.1"
+ :type xterm--extra-capabilities-type
+ :group 'xterm)
+
(defcustom xterm-max-cut-length 100000
"Maximum number of bytes to cut into xterm using the OSC 52 sequence.
@@ -639,55 +672,57 @@ xterm--report-background-handler
(when recompute-faces
(tty-set-up-initial-frame-faces))))))
-(defun xterm--version-handler ()
- (let ((str "")
- chr)
- ;; The reply should be: \e [ > NUMBER1 ; NUMBER2 ; NUMBER3 c
- ;; If the timeout is completely removed for read-event, this
- ;; might hang for terminals that pretend to be xterm, but don't
- ;; respond to this escape sequence. RMS' opinion was to remove
- ;; it completely. That might be right, but let's first try to
- ;; see if by using a longer timeout we get rid of most issues.
- (while (and (setq chr (read-event nil nil 2)) (not (equal chr ?c)))
- (setq str (concat str (string chr))))
- ;; Since xterm-280, the terminal type (NUMBER1) is now 41 instead of 0.
- (when (string-match "\\([0-9]+\\);\\([0-9]+\\);0" str)
- (let ((version (string-to-number (match-string 2 str))))
- (when (and (> version 2000) (equal (match-string 1 str) "1"))
- ;; Hack attack! bug#16988: gnome-terminal reports "1;NNNN;0"
- ;; with a large NNNN but is based on a rather old xterm code.
- ;; Gnome terminal 3.6.1 reports 1;3406;0
- ;; Gnome terminal 2.32.1 reports 1;2802;0
- (setq version 200))
- (when (equal (match-string 1 str) "83")
- ;; `screen' (which returns 83;40003;0) seems to also lack support for
- ;; some of these (bug#17607, bug#20356).
- ;; Note: this code path should normally not be used any more
- ;; since term/screen.el now binds xterm-extra-capabilities
- ;; to a fixed value, rather than using the dynamic checking.
- (setq version 200))
- ;; If version is 242 or higher, assume the xterm supports
- ;; reporting the background color (TODO: maybe earlier
- ;; versions do too...)
- (when (>= version 242)
- (xterm--query "\e]11;?\e\\"
- '(("\e]11;" . xterm--report-background-handler))))
-
- ;; If version is 216 (the version when modifyOtherKeys was
- ;; introduced) or higher, initialize the
- ;; modifyOtherKeys support.
- (when (>= version 216)
- (xterm--init-modify-other-keys))
- ;; In version 203 support for accessing the X selection was
- ;; added. Hterm reports itself as version 256 and supports it
- ;; as well. gnome-terminal doesn't and is excluded by this
- ;; test.
- (when (>= version 203)
- ;; Most xterms seem to have it disabled by default, and if it's
- ;; disabled, C-y will incur a timeout, so we only use it if the user
- ;; explicitly requests it.
- ;;(xterm--init-activate-get-selection)
- (xterm--init-activate-set-selection))))))
+(defun xterm--extra-capabilities (identification)
+ "Return a list of capabilities for an XTerm-compatible terminal.
+IDENTIFICATION should be an object of type
+‘xterm--identification’."
+ ;; `screen' (which returns 83;40003;0) seems to also lack support for
+ ;; some of these (bug#17607, bug#20356).
+ ;; Note: this code path should normally not be used any more
+ ;; since term/screen.el now binds xterm-extra-capabilities
+ ;; to a fixed value, rather than using the dynamic checking.
+ ;;
+ ;; FIXME: What should actually happen is that if a multiplexer is
+ ;; encountered the underlying emulator should be detected by sending
+ ;; a wrapped “Secondary Device Attributes” query.
+ ;;
+ ;; FIXME: The following should work, but leads to an error during
+ ;; compilation:
+ ;;(cl-check-type identification xterm--identification)
+ (cl-check-type identification (satisfies xterm--identification-p))
+ (cl-ecase (xterm--identification-multiplexer identification)
+ (screen xterm-screen-extra-capabilities)
+ (tmux xterm-tmux-extra-capabilities)
+ ((nil)
+ (if (eq xterm-extra-capabilities 'check)
+ ;; Since xterm-280, the terminal type (NUMBER1) is now 41
+ ;; instead of 0.
+ (when-let ((version (xterm--identification-version identification)))
+ ;; Hack attack! bug#16988: gnome-terminal reports "1;NNNN;0"
+ ;; with a large NNNN but is based on a rather old xterm code.
+ ;; Gnome terminal 3.6.1 reports 1;3406;0
+ ;; Gnome terminal 2.32.1 reports 1;2802;0
+ (unless (and (> version 2000)
+ (eq (xterm--identification-terminal identification)
+ 'vt220))
+ (append
+ ;; If version is 242 or higher, assume the xterm
+ ;; supports reporting the background color (TODO: maybe
+ ;; earlier versions do too...)
+ (when (>= version 242) '(reportBackground))
+ ;; If version is 216 (the version when modifyOtherKeys
+ ;; was introduced) or higher, initialize the
+ ;; modifyOtherKeys support.
+ (when (>= version 216) '(modifyOtherKeys))
+ ;; In version 203 support for accessing the X selection
+ ;; was added. Hterm reports itself as version 256 and
+ ;; supports it as well. gnome-terminal doesn't and is
+ ;; excluded by this test. Most xterms seem to have
+ ;; getSelection disabled by default, and if it's
+ ;; disabled, C-y will incur a timeout, so we only use it
+ ;; if the user explicitly requests it.
+ (when (>= version 203) '(setSelection)))))
+ xterm-extra-capabilities))))
(defvar xterm-query-timeout 2
"Seconds to wait for an answer from the terminal.
@@ -766,26 +801,17 @@ terminal-init-xterm
(xterm-register-default-colors xterm-standard-colors)
(tty-set-up-initial-frame-faces)
- (if (eq xterm-extra-capabilities 'check)
- ;; Try to find out the type of terminal by sending a "Secondary
- ;; Device Attributes (DA)" query.
- (xterm--query "\e[>0c"
- ;; Some terminals (like OS X's Terminal.app) respond to
- ;; this query as if it were a "Primary Device Attributes"
- ;; query instead, so we should handle that too.
- '(("\e[?" . xterm--version-handler)
- ("\e[>" . xterm--version-handler)))
-
- (when (memq 'reportBackground xterm-extra-capabilities)
+ (let ((capabilities (xterm--extra-capabilities (xterm--identify))))
+ (when (memq 'reportBackground capabilities)
(xterm--query "\e]11;?\e\\"
'(("\e]11;" . xterm--report-background-handler))))
- (when (memq 'modifyOtherKeys xterm-extra-capabilities)
+ (when (memq 'modifyOtherKeys capabilities)
(xterm--init-modify-other-keys))
- (when (memq 'getSelection xterm-extra-capabilities)
+ (when (memq 'getSelection capabilities)
(xterm--init-activate-get-selection))
- (when (memq 'setSelection xterm-extra-capabilities)
+ (when (memq 'setSelection capabilities)
(xterm--init-activate-set-selection)))
;; Unconditionally enable bracketed paste mode: terminals that don't
@@ -794,6 +820,73 @@ terminal-init-xterm
(run-hooks 'terminal-init-xterm-hook))
+(defun xterm--identify ()
+ "Try to find out the type of terminal.
+Send a “Secondary Device Attributes (DA)” query. Store the
+result as a value of the ‘xterm--identification’ structure in the
+‘xterm-identification’ terminal parameter, and return it."
+ (xterm--query "\e[>0c"
+ ;; Some terminals (like OS X's Terminal.app) respond to
+ ;; this query as if it were a "Primary Device Attributes"
+ ;; query instead, so we should handle that too.
+ '(("\e[?" . xterm--handle-identification)
+ ("\e[>" . xterm--handle-identification)))
+ (terminal-parameter nil 'xterm-identification))
+
+(cl-defstruct xterm--identification
+ terminal multiplexer version)
+
+(defun xterm--handle-identification ()
+ "Parse the result of a “Secondary Device Attribute” query.
+Store the result as an ‘xterm--identification’ object in the
+‘xterm-identification’ terminal parameter."
+ (set-terminal-parameter
+ nil 'xterm-identification
+ (xterm--parse-identification (xterm--read-until ?c))))
+
+(defun xterm--parse-identification (string)
+ "Parse an XTerm identification STRING.
+STRING is returned by the terminal responding to a “Secondary
+Device Attribute” query. Return an ‘xterm--identification’
+object."
+ (save-match-data
+ ;; The reply should be: \e [ > NUMBER1 ; NUMBER2 ; NUMBER3 c
+ ;; If the timeout is completely removed for read-event, this
+ ;; might hang for terminals that pretend to be xterm, but don't
+ ;; respond to this escape sequence. RMS' opinion was to remove
+ ;; it completely. That might be right, but let's first try to
+ ;; see if by using a longer timeout we get rid of most issues.
+ (if (string-match
+ (rx bos (group (+ digit)) ?\; (group (+ digit)) ";0" eos)
+ string)
+ (cl-destructuring-bind
+ (terminal multiplexer)
+ (cl-ecase (string-to-number (match-string 1 string))
+ (0 '(vt100 nil))
+ (1 '(vt220 nil))
+ (2 '(vt240 nil))
+ (18 '(vt330 nil))
+ (19 '(vt340 nil))
+ (24 '(vt320 nil))
+ (41 '(vt420 nil))
+ (61 '(vt510 nil))
+ (64 '(vt520 nil))
+ (65 '(vt525 nil))
+ (83 '(nil screen))
+ (84 '(nil tmux)))
+ (make-xterm--identification
+ :terminal terminal
+ :multiplexer multiplexer
+ :version (string-to-number (match-string 2 string))))
+ (make-xterm--identification))))
+
+(defun xterm--read-until (char)
+ "Read characters from the current terminal until CHAR is encountered.
+Return the characters read (excluding CHAR) as a string."
+ (cl-loop for ch = (read-char nil nil 0.1)
+ until (or (null ch) (= ch char))
+ concat (char-to-string ch)))
+
(defun xterm--init-modify-other-keys ()
"Terminal initialization for xterm's modifyOtherKeys support."
(send-string-to-terminal "\e[>4;1m")
@@ -827,13 +920,14 @@ xterm--selection-char
((terminal-parameter nil 'xterm--get-selection) (eql t)))
(unless (eq data-type 'STRING)
(error "Unsupported data type %S" data-type))
- (let* ((screen (eq (terminal-parameter nil 'terminal-initted)
- 'terminal-init-screen))
- (query (concat "\e]52;" (xterm--selection-char type) ";")))
+ (let ((query (concat "\e]52;" (xterm--selection-char type) ";")))
(with-temp-buffer
(set-buffer-multibyte nil)
(xterm--query
- (concat (when screen "\eP") query "?\a" (when screen "\e\\"))
+ (xterm--wrap-selection-query
+ query
+ (xterm--identification-multiplexer
+ (terminal-parameter nil 'xterm-multiplexer)))
(list (cons query (lambda ()
(while (let ((char (read-char)))
(unless (eq char ?\a)
@@ -867,10 +961,10 @@ xterm--selection-char
program. When inside the screen program, this function also
chops long DCS sequences into multiple smaller ones to avoid
hitting screen's max DCS length."
- (let* ((screen (eq (terminal-parameter nil 'terminal-initted)
- 'terminal-init-screen))
+ (let* ((multiplexer (xterm--identification-multiplexer
+ (terminal-parameter nil 'xterm-identification)))
(bytes (encode-coding-string data 'utf-8-unix))
- (base-64 (if screen
+ (base-64 (if multiplexer
(replace-regexp-in-string
"\n" "\e\\\eP"
(base64-encode-string bytes)
@@ -882,10 +976,22 @@ xterm--selection-char
(warn "Selection too long to send to terminal: %d bytes" length)
(sit-for 2))
(send-string-to-terminal
- (concat
- (when screen "\eP")
- "\e]52;" (xterm--selection-char type) ";" base-64 "\a"
- (when screen "\e\\"))))))
+ (xterm--wrap-selection-query
+ (concat "\e]52;" (xterm--selection-char type) ";" base-64 "\a")
+ multiplexer)))))
+
+(defun xterm--wrap-selection-query (query multiplexer)
+ "Return a wrapped version of QUERY for the terminal MULTIPLEXER.
+QUERY should be an XTerm-compatible escape sequence to access the
+X selection. If the current terminal is in a multiplexer, return
+a wrapped version of QUERY to circumvent interpretation by the
+multiplexer."
+ (concat
+ (cl-case multiplexer
+ (screen "\eP")
+ (tmux "\ePtmux;\e"))
+ query
+ (when multiplexer "\e\\")))
(defun xterm-rgb-convert-to-16bit (prim)
"Convert an 8-bit primary color value PRIM to a corresponding 16-bit value."
diff --git a/test/automated/xterm-tests.el b/test/automated/xterm-tests.el
new file mode 100644
index 0000000..0224213
--- /dev/null
+++ b/test/automated/xterm-tests.el
@@ -0,0 +1,97 @@
+;;; xterm-tests.el --- unit tests for term/xterm.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; Author: Philipp Stephani <phst@google.com>
+;; Keywords: terminals
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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.
+
+;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Unit tests for lisp/term/xterm.el.
+
+;;; Code:
+
+(require 'term/xterm)
+(require 'seq)
+
+(defconst xterm-tests--HTerm
+ (make-xterm--identification :terminal 'vt100 :multiplexer nil :version 256))
+
+(defconst xterm-tests--Terminal.app
+ (make-xterm--identification :terminal 'vt220 :multiplexer nil :version 95))
+
+(defconst xterm-tests--XTerm
+ (make-xterm--identification :terminal 'vt420 :multiplexer nil :version 314))
+
+(defconst xterm-tests--gnome-terminal
+ (make-xterm--identification :terminal 'vt220 :multiplexer nil :version 3406))
+
+(defconst xterm-tests--screen
+ (make-xterm--identification :terminal nil :multiplexer 'screen :version 400003))
+
+(defconst xterm-tests--tmux
+ (make-xterm--identification :terminal nil :multiplexer 'tmux :version 0))
+
+(ert-deftest xterm--parse-identification--HTerm ()
+ (should (equal (xterm--parse-identification "0;256;0")
+ xterm-tests--HTerm)))
+
+(ert-deftest xterm--parse-identification--Terminal.app ()
+ (should (equal (xterm--parse-identification "1;95;0")
+ xterm-tests--Terminal.app)))
+
+(ert-deftest xterm--parse-identification--XTerm ()
+ (should (equal (xterm--parse-identification "41;314;0")
+ xterm-tests--XTerm)))
+
+(ert-deftest xterm--parse-identification--gnome-terminal ()
+ (should (equal (xterm--parse-identification "1;3406;0")
+ xterm-tests--gnome-terminal)))
+
+(ert-deftest xterm--parse-identification--screen ()
+ (should (equal (xterm--parse-identification "83;400003;0")
+ xterm-tests--screen)))
+
+(ert-deftest xterm--parse-identification--tmux ()
+ (should (equal (xterm--parse-identification "84;0;0")
+ xterm-tests--tmux)))
+
+(ert-deftest xterm--extra-capabilities--HTerm ()
+ (should (equal (xterm--extra-capabilities xterm-tests--HTerm)
+ '(reportBackground modifyOtherKeys setSelection))))
+
+(ert-deftest xterm--extra-capabilities--Terminal.app ()
+ (should-not (xterm--extra-capabilities xterm-tests--Terminal.app)))
+
+(ert-deftest xterm--extra-capabilities--XTerm ()
+ (should (equal (xterm--extra-capabilities xterm-tests--XTerm)
+ '(reportBackground modifyOtherKeys setSelection))))
+
+(ert-deftest xterm--extra-capabilities--gnome-terminal ()
+ (should-not (xterm--extra-capabilities xterm-tests--gnome-terminal)))
+
+(ert-deftest xterm--extra-capabilities--screen ()
+ (should (equal (xterm--extra-capabilities xterm-tests--screen)
+ '(modifyOtherKeys setSelection))))
+
+(ert-deftest xterm--extra-capabilities--tmux ()
+ (should (equal (xterm--extra-capabilities xterm-tests--tmux)
+ '(modifyOtherKeys setSelection))))
+
+(provide 'xterm-tests)
+;;; xterm-tests.el ends here
--
2.7.4
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2016-03-29 9:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-29 9:08 Patch for supporting tmux Philipp Stephani
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.