aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJared Finder2025-12-29 12:35:24 -0800
committerSean Whitton2026-01-10 12:49:43 +0000
commit4e779d20f1840fef380f5688ceb2cd80658bde0b (patch)
tree79ad054524a73dced6d382a99d0a6a476f7ad1f9
parent88d3101fdd10f5e922aae9d99fcfd103a33747db (diff)
downloademacs-4e779d20f1840fef380f5688ceb2cd80658bde0b.tar.gz
emacs-4e779d20f1840fef380f5688ceb2cd80658bde0b.zip
Update cursor display using Xterm escape sequences
* lisp/term/xterm.el (xterm-update-cursor): New user option. (xterm--init): Use it. (xterm--post-command-hook): New function for all xterm functionality installed in 'post-command-hook'. (xterm--init-frame-title): Install it. (xterm--init-update-cursor, xterm--set-cursor-type) (xterm--update-cursor-type, xterm--update-cursor-color): New functions. (xterm--cursor-type-to-int): New constant. * doc/emacs/display.texi (Cursor Display): * etc/NEWS: Document the new feature.
-rw-r--r--doc/emacs/display.texi53
-rw-r--r--etc/NEWS9
-rw-r--r--lisp/term/xterm.el111
3 files changed, 152 insertions, 21 deletions
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index 05a25323543..d475fc3cfde 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -2048,20 +2048,41 @@ variable @code{visible-cursor} is @code{nil} when Emacs starts or
2048resumes, it uses the normal cursor. 2048resumes, it uses the normal cursor.
2049 2049
2050@vindex cursor-type 2050@vindex cursor-type
2051 On a graphical display, many more properties of the text cursor can 2051 On a graphical display and many Xterm-compatible text terminals, the
2052be altered. To customize its color, change the @code{:background} 2052color and shape of the text cursor can be altered. To customize its
2053attribute of the face named @code{cursor} (@pxref{Face 2053color, change the @code{:background} attribute of the face named
2054Customization}). (The other attributes of this face have no effect; 2054@code{cursor} (@pxref{Face Customization}). (The other attributes of
2055the text shown under the cursor is drawn using the frame's background 2055this face have no effect; the text shown under the cursor is drawn using
2056color.) To change its shape, customize the buffer-local variable 2056the frame's background color.) To change its shape, customize the
2057@code{cursor-type}; possible values are @code{box} (the default), 2057buffer-local variable @code{cursor-type}; possible values are @code{box}
2058@code{(box . @var{size})} (box cursor becoming a hollow box under 2058(the default), @code{(box . @var{size})} (box cursor becoming a hollow
2059masked images larger than @var{size} pixels in either dimension), 2059box under masked images larger than @var{size} pixels in either
2060@code{hollow} (a hollow box), @code{bar} (a vertical bar), @code{(bar 2060dimension), @code{hollow} (a hollow box), @code{bar} (a vertical bar),
2061. @var{n})} (a vertical bar @var{n} pixels wide), @code{hbar} (a 2061@code{(bar . @var{n})} (a vertical bar @var{n} pixels wide), @code{hbar}
2062horizontal bar), @code{(hbar . @var{n})} (a horizontal bar @var{n} 2062(a horizontal bar), @code{(hbar . @var{n})} (a horizontal bar @var{n}
2063pixels tall), or @code{nil} (no cursor at all). 2063pixels tall), or @code{nil} (no cursor at all).
2064 2064
2065@vindex xterm-update-cursor
2066 On Xterm-compatible text terminals cursor customiztaion is controlled
2067by the user option @code{xterm-update-cursor}. Valid values are:
2068@code{t} to update the cursor's color and shape, @code{type} to update
2069the cursor's shape only, @code{color} to update the cursor's color only,
2070and @code{nil} to not update the cursor's appearance. Xterm-compatible
2071text terminals can not display a hollow box and instead use a filled
2072box. Similarly, Xterm-compatible text terminals ignore the pixel sizes
2073for @code{bar} and @code{hbar}.
2074
2075@findex hl-line-mode
2076@findex global-hl-line-mode
2077@cindex highlight current line
2078 To make the cursor even more visible, you can use HL Line mode, a
2079minor mode that highlights the line containing point. Use @kbd{M-x
2080hl-line-mode} to enable or disable it in the current buffer. @kbd{M-x
2081global-hl-line-mode} enables or disables the same mode globally.
2082
2083 The remaining controls only work on graphical displays where Emacs can
2084fully control the way the cursor appears.
2085
2065@findex blink-cursor-mode 2086@findex blink-cursor-mode
2066@cindex cursor, blinking 2087@cindex cursor, blinking
2067@cindex blinking cursor 2088@cindex blinking cursor
@@ -2105,14 +2126,6 @@ non-blinking hollow box. (For a bar cursor, it instead appears as a
2105thinner bar.) To turn off cursors in non-selected windows, change the 2126thinner bar.) To turn off cursors in non-selected windows, change the
2106variable @code{cursor-in-non-selected-windows} to @code{nil}. 2127variable @code{cursor-in-non-selected-windows} to @code{nil}.
2107 2128
2108@findex hl-line-mode
2109@findex global-hl-line-mode
2110@cindex highlight current line
2111 To make the cursor even more visible, you can use HL Line mode, a
2112minor mode that highlights the line containing point. Use @kbd{M-x
2113hl-line-mode} to enable or disable it in the current buffer. @kbd{M-x
2114global-hl-line-mode} enables or disables the same mode globally.
2115
2116@node Line Truncation 2129@node Line Truncation
2117@section Line Truncation 2130@section Line Truncation
2118 2131
diff --git a/etc/NEWS b/etc/NEWS
index 68cb6c642fb..27aff3b7a1e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -772,6 +772,15 @@ Emacs previously discarded arguments to emacsclient of zero length, such
772as in 'emacsclient --eval "(length (pop server-eval-args-left))" ""'. 772as in 'emacsclient --eval "(length (pop server-eval-args-left))" ""'.
773These are no longer discarded. 773These are no longer discarded.
774 774
775+++
776** New user option 'xterm-update-cursor' to update cursor display on TTYs.
777When enabled, Emacs sends Xterm escape sequences on Xterm-compatible
778terminals to update the cursor's appearacse. Emacs can update the
779cursor's shape and color. For example, if you use a purple bar cursor
780on graphical displays then when this option is enabled Emacs will use a
781purple bar cursor on compatible terminals as well. See the Info node
782"(emacs) Cursor Display" for more information.
783
775 784
776* Editing Changes in Emacs 31.1 785* Editing Changes in Emacs 31.1
777 786
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
index dd179c4e3eb..47e82decb03 100644
--- a/lisp/term/xterm.el
+++ b/lisp/term/xterm.el
@@ -80,6 +80,20 @@ capabilities, and only when that terminal understands bracketed paste."
80 :version "28.1" 80 :version "28.1"
81 :type 'boolean) 81 :type 'boolean)
82 82
83(defcustom xterm-update-cursor nil
84 "If non-nil, try to update the cursor's appearance on XTerm terminals.
85
86If set to t all supported attributes of the cursor are updated.
87If set to `type' only the cursor type is updated. This uses the CSI
88DECSCUSR escape sequence.
89If set to `color' only the cursor color is updated. This uses the OSC
9012 escape sequence."
91 :version "31.1"
92 :type '(radio (const :tag "Do not update" nil)
93 (const :tag "Update" t)
94 (const :tag "Update type only" type)
95 (const :tag "Update color only" color)))
96
83(defconst xterm-paste-ending-sequence "\e[201~" 97(defconst xterm-paste-ending-sequence "\e[201~"
84 "Characters sent by the terminal to end a bracketed paste.") 98 "Characters sent by the terminal to end a bracketed paste.")
85 99
@@ -988,6 +1002,8 @@ We run the first FUNCTION whose STRING matches the input events."
988 1002
989 (when xterm-set-window-title 1003 (when xterm-set-window-title
990 (xterm--init-frame-title)) 1004 (xterm--init-frame-title))
1005 (when xterm-update-cursor
1006 (xterm--init-update-cursor))
991 1007
992 (let ((bg-color (terminal-parameter nil 'xterm--background-color)) 1008 (let ((bg-color (terminal-parameter nil 'xterm--background-color))
993 (fg-color (terminal-parameter nil 'xterm--foreground-color))) 1009 (fg-color (terminal-parameter nil 'xterm--foreground-color)))
@@ -1025,6 +1041,17 @@ We run the first FUNCTION whose STRING matches the input events."
1025 ;; We likewise unconditionally enable support for focus tracking. 1041 ;; We likewise unconditionally enable support for focus tracking.
1026 (xterm--init-focus-tracking)) 1042 (xterm--init-focus-tracking))
1027 1043
1044(defun xterm--post-command-hook ()
1045 "Hook for xterm features that need to be frequently updated."
1046
1047 (unless (display-graphic-p)
1048 (when xterm-set-window-title
1049 (xterm-set-window-title))
1050 (when (memq xterm-update-cursor '(t type))
1051 (xterm--update-cursor-type))
1052 (when (memq xterm-update-cursor '(t color))
1053 (xterm--update-cursor-color))))
1054
1028(defun terminal-init-xterm () 1055(defun terminal-init-xterm ()
1029 "Terminal initialization function for xterm." 1056 "Terminal initialization function for xterm."
1030 (unwind-protect 1057 (unwind-protect
@@ -1067,7 +1094,7 @@ We run the first FUNCTION whose STRING matches the input events."
1067 (xterm-set-window-title) 1094 (xterm-set-window-title)
1068 (add-hook 'after-make-frame-functions 'xterm-set-window-title-flag) 1095 (add-hook 'after-make-frame-functions 'xterm-set-window-title-flag)
1069 (add-hook 'window-configuration-change-hook 'xterm-unset-window-title-flag) 1096 (add-hook 'window-configuration-change-hook 'xterm-unset-window-title-flag)
1070 (add-hook 'post-command-hook 'xterm-set-window-title) 1097 (add-hook 'post-command-hook 'xterm--post-command-hook)
1071 (add-hook 'minibuffer-exit-hook 'xterm-set-window-title)) 1098 (add-hook 'minibuffer-exit-hook 'xterm-set-window-title))
1072 1099
1073(defvar xterm-window-title-flag nil 1100(defvar xterm-window-title-flag nil
@@ -1300,6 +1327,88 @@ versions of xterm."
1300 (b (caddr fg-color))) 1327 (b (caddr fg-color)))
1301 (set-face-foreground 'default (format "#%04x%04x%04x" r g b) frame))))) 1328 (set-face-foreground 'default (format "#%04x%04x%04x" r g b) frame)))))
1302 1329
1330(defun xterm--init-update-cursor ()
1331 "Register hooks to run `xterm--update-cursor-type' appropriately."
1332
1333 (when (memq xterm-update-cursor '(color t))
1334 (xterm--query
1335 "\e]12;?\e\\"
1336 '(("\e]12;" . (lambda ()
1337 (let ((str (xterm--read-string ?\e ?\\)))
1338 ;; The response is specifically formated to set the
1339 ;; color
1340 (push
1341 (concat "\e]12;" str "\e\\")
1342 (terminal-parameter nil 'tty-mode-reset-strings)))))))
1343 ;; No need to set tty-mode-set-strings because
1344 ;; xterm--post-command-hook handles restoring the cursor color.
1345
1346 (xterm--update-cursor-color))
1347
1348 (when (memq xterm-update-cursor '(type t))
1349 (xterm--update-cursor-type))
1350
1351 (add-hook 'post-command-hook 'xterm--post-command-hook))
1352
1353(defconst xterm--cursor-type-to-int
1354 '(nil 0
1355 box 1
1356 hollow 1
1357 bar 5
1358 hbar 3)
1359 "Mapping of cursor type symbols to control sequence integers.
1360
1361Cursor type symbols are the same as for `cursor-type'.")
1362
1363(defun xterm--set-cursor-type (terminal type)
1364 (let ((type-int (or (plist-get xterm--cursor-type-to-int type) 1))
1365 (old (terminal-parameter terminal 'xterm--cursor-style)))
1366
1367 (when old
1368 (set-terminal-parameter
1369 terminal
1370 'tty-mode-set-strings
1371 (delete (format "\e[%d q" old)
1372 (terminal-parameter terminal 'tty-mode-set-strings))))
1373 (let ((set-string (format "\e[%d q" type-int)))
1374 (push set-string (terminal-parameter terminal 'tty-mode-set-strings))
1375 (send-string-to-terminal set-string terminal))
1376 (unless old
1377 ;; Assume that the default cursor is appropriate when exiting Emacs.
1378 (push "\e[0 q" (terminal-parameter terminal 'tty-mode-reset-strings)))
1379
1380 (set-terminal-parameter terminal 'xterm--cursor-type type-int)))
1381
1382(defun xterm--update-cursor-type ()
1383 "Update the cursor type for Xterm-compatible terminals.
1384This updates the selected frame's terminal based on `cursor-type'."
1385 (let ((buffer-cursor cursor-type)
1386 (window-cursor (window-cursor-type))
1387 (frame-cursor (frame-parameter nil 'cursor-type))
1388 type)
1389 ;; All of them can be conses, in which case the type symbol is the car.
1390 (when (consp buffer-cursor) (setf buffer-cursor (car buffer-cursor)))
1391 (when (consp window-cursor) (setf window-cursor (car window-cursor)))
1392 (when (consp frame-cursor) (setf frame-cursor (car frame-cursor)))
1393
1394 (cond
1395 ((not (eq window-cursor t))
1396 (setf type window-cursor))
1397 ((not (eq buffer-cursor t))
1398 (setf type buffer-cursor))
1399 (t
1400 (setf type frame-cursor)))
1401 (xterm--set-cursor-type nil type)))
1402
1403(defun xterm--update-cursor-color ()
1404 "Update the cursor color for Xterm-compatible terminals.
1405This updates the selected frame's terminal based on the face `cursor'."
1406 (let* ((color (color-values (face-background 'cursor)))
1407 (r (nth 0 color))
1408 (g (nth 1 color))
1409 (b (nth 2 color)))
1410 (send-string-to-terminal (format "\e]12;rgb:%04x/%04x/%04x\e\\" r g b))))
1411
1303(provide 'xterm) ;Backward compatibility. 1412(provide 'xterm) ;Backward compatibility.
1304(provide 'term/xterm) 1413(provide 'term/xterm)
1305;;; xterm.el ends here 1414;;; xterm.el ends here