Add auto-margin enable/disable to term
* test/lisp/term-tests.el (term-line-wrap-no-auto-margins): add test * lisp/term.el (term-auto-margins): new variable (term-mode): documentation (term-termcap-format): mention auto-margins flag (term-emulate-terminal): support it (term-reset-terminal): reset it (term-handle-ansi-escape): notice it * etc/e/eterm-color.ti: add auto margin capability * etc/e/README: fix build documentation * etc/NEWS: mention auto-margins
This commit is contained in:
parent
83e2e5e24b
commit
13b1436d97
7 changed files with 115 additions and 38 deletions
13
etc/NEWS
13
etc/NEWS
|
@ -488,6 +488,19 @@ content.
|
|||
When non-nil, buffer sizes are shown in human readable format. The
|
||||
default is nil, which retains the old format.
|
||||
|
||||
** Term
|
||||
|
||||
*** The terminal emulator now supports auto-margins control.
|
||||
Term mode now handles DECAWM escape sequences that control whether text
|
||||
automatically wraps at the right margin:
|
||||
- \e[?7h enables auto-margins (default)
|
||||
- \e[?7l disables auto-margins
|
||||
|
||||
When auto-margins is disabled, characters that would go beyond the right margin
|
||||
are discarded, which matches the behavior of physical terminals and other
|
||||
terminal emulators. Control sequences and escape sequences are still processed
|
||||
correctly regardless of margin position.
|
||||
|
||||
** Smerge
|
||||
|
||||
*** New command 'smerge-extend' extends a conflict over surrounding lines.
|
||||
|
|
|
@ -7,6 +7,9 @@ version. If it is necessary, use:
|
|||
|
||||
tic -o ../ ./eterm-color.ti
|
||||
|
||||
(Sometimes tic puts output in etc/65 instead of etc/e. Move it to etc/e
|
||||
yourself if it does that.)
|
||||
|
||||
The compiled files are used by lisp/term.el, so if they are moved,
|
||||
term.el needs to be changed. terminfo requires them to be stored in
|
||||
an 'e' subdirectory (the first character of the file name).
|
||||
|
|
Binary file not shown.
|
@ -4,8 +4,8 @@ eterm-color|Emacs term.el terminal emulator term-protocol-version 0.96,
|
|||
# copyright, constituting the only possible expression of the algorithm
|
||||
# in this format.
|
||||
#
|
||||
# When updating this file, etc/e/eterm-color should be regenerated by
|
||||
# running "make e/eterm-color" in the etc directory.
|
||||
# When updating this file, etc/e/eterm-color should be regenerated by
|
||||
# following the instructions in etc/e/README.
|
||||
# Any change to this file should be done at the same time with a
|
||||
# corresponding change to the TERMCAP environment variable in term.el.
|
||||
# Comments in term.el specify where each of these capabilities is implemented.
|
||||
|
@ -80,6 +80,8 @@ eterm-color|Emacs term.el terminal emulator term-protocol-version 0.96,
|
|||
u7=\E[6n,
|
||||
smcup=\E[47h,
|
||||
rmcup=\E[47l,
|
||||
smam=\E[?7h,
|
||||
rmam=\E[?7l,
|
||||
# rs2 may need to be added
|
||||
|
||||
eterm-direct|Emacs term.el with direct-color indexing term-protocol-version 0.96,
|
||||
|
|
Binary file not shown.
107
lisp/term.el
107
lisp/term.el
|
@ -349,6 +349,10 @@ contains saved `term-home-marker' from original sub-buffer.")
|
|||
"Current vertical row (relative to home-marker) or nil if unknown.")
|
||||
(defvar term-insert-mode nil)
|
||||
(defvar term-vertical-motion)
|
||||
(defvar term-auto-margins t
|
||||
"When non-nil, terminal will automatically wrap lines at the right margin.
|
||||
This can be toggled by the application using DECAWM escape sequences.")
|
||||
|
||||
(defvar term-do-line-wrapping nil
|
||||
"Last character was a graphic in the last column.
|
||||
If next char is graphic, first move one column right
|
||||
|
@ -1148,6 +1152,7 @@ Entry to this mode runs the hooks on `term-mode-hook'."
|
|||
(setq-local term-last-input-start (make-marker))
|
||||
(setq-local term-last-input-end (make-marker))
|
||||
(setq-local term-last-input-match "")
|
||||
(setq-local term-auto-margins t)
|
||||
|
||||
;; Always display the onscreen keyboard.
|
||||
(setq-local touch-screen-display-keyboard t)
|
||||
|
@ -1682,7 +1687,7 @@ Using \"emacs\" loses, because bash disables editing if $TERM == emacs.")
|
|||
:mk=\\E[8m:cb=\\E[1K:op=\\E[39;49m:Co#256:pa#32767\
|
||||
:AB=\\E[48;5;%%dm:AF=\\E[38;5;%%dm:cr=^M\
|
||||
:bl=^G:do=^J:le=^H:ta=^I:se=\\E[27m:ue=\\E[24m\
|
||||
:kb=^?:kD=^[[3~:sc=\\E7:rc=\\E8:r1=\\Ec:"
|
||||
:kb=^?:kD=^[[3~:sc=\\E7:rc=\\E8:r1=\\Ec:RA=\\E[?7l:SA=\\E[?7h:"
|
||||
;; : -undefine ic
|
||||
;; don't define :te=\\E[2J\\E[?47l\\E8:ti=\\E7\\E[?47h\
|
||||
"Termcap capabilities supported.")
|
||||
|
@ -3128,19 +3133,24 @@ See `term-prompt-regexp'."
|
|||
(unless term-suppress-hard-newline
|
||||
(while (> (+ (length decoded-substring) old-column)
|
||||
term-width)
|
||||
(insert (substring decoded-substring 0
|
||||
(- term-width old-column)))
|
||||
;; Since we've enough text to fill the whole line,
|
||||
;; delete previous text regardless of
|
||||
;; `term-insert-mode's value.
|
||||
(delete-region (point) (line-end-position))
|
||||
(term-down 1 t)
|
||||
(term-move-columns (- (term-current-column)))
|
||||
(add-text-properties (1- (point)) (point)
|
||||
'(term-line-wrap t rear-nonsticky t))
|
||||
(setq decoded-substring
|
||||
(substring decoded-substring (- term-width old-column)))
|
||||
(setq old-column 0)))
|
||||
(let* ((here-length (- term-width old-column))
|
||||
(to-insert (substring decoded-substring 0 here-length)))
|
||||
(setf decoded-substring (substring decoded-substring here-length))
|
||||
(insert to-insert)
|
||||
(setf term-current-column nil)
|
||||
;; Since we've enough text to fill the whole line,
|
||||
;; delete previous text regardless of
|
||||
;; `term-insert-mode's value.
|
||||
(delete-region (point) (line-end-position))
|
||||
(if term-auto-margins
|
||||
(progn
|
||||
(term-move-to-column 0)
|
||||
(term-down 1 t)
|
||||
(add-text-properties (1- (point)) (point)
|
||||
'(term-line-wrap t rear-nonsticky t))
|
||||
(setq old-column 0))
|
||||
(term-move-columns -1)
|
||||
(setf old-column (term-current-column))))))
|
||||
(insert decoded-substring)
|
||||
(setq term-current-column (current-column)
|
||||
columns (- term-current-column old-column))
|
||||
|
@ -3162,14 +3172,18 @@ See `term-prompt-regexp'."
|
|||
|
||||
(put-text-property old-point (point)
|
||||
'font-lock-face term-current-face))
|
||||
;; If the last char was written in last column,
|
||||
;; If the last char was written in last column and auto-margins is enabled,
|
||||
;; back up one column, but remember we did so.
|
||||
;; Thus we emulate xterm/vt100-style line-wrapping.
|
||||
;; If auto-margins is disabled, the cursor stays at the last column
|
||||
;; and further output is discarded until a cursor movement occurs.
|
||||
(when (eq (term-current-column) term-width)
|
||||
(term-move-columns -1)
|
||||
;; We check after ctrl sequence handling if point
|
||||
;; was moved (and leave line-wrapping state if so).
|
||||
(setq term-do-line-wrapping (point)))
|
||||
;; Only set line-wrapping if auto-margins is enabled
|
||||
(when term-auto-margins
|
||||
;; We check after ctrl sequence handling if point
|
||||
;; was moved (and leave line-wrapping state if so).
|
||||
(setq term-do-line-wrapping (point))))
|
||||
(setq term-current-column nil)
|
||||
(setq i funny))
|
||||
(pcase-exhaustive (and (<= ctl-end str-length) (aref str i))
|
||||
|
@ -3205,15 +3219,19 @@ See `term-prompt-regexp'."
|
|||
;; We only handle control sequences with a single
|
||||
;; "Final" byte (see [ECMA-48] section 5.4).
|
||||
(when (eq ctl-params-end (1- ctl-end))
|
||||
(term-handle-ansi-escape
|
||||
proc
|
||||
(mapcar ;; We don't distinguish empty params
|
||||
;; from 0 (according to [ECMA-48] we
|
||||
;; should, but all commands we support
|
||||
;; default to 0 values anyway).
|
||||
#'string-to-number
|
||||
(split-string ctl-params ";"))
|
||||
(aref str (1- ctl-end)))))
|
||||
(let* ((private (string-prefix-p "?" ctl-params))
|
||||
(ctl-params
|
||||
(if private (substring ctl-params 1) ctl-params)))
|
||||
(term-handle-ansi-escape
|
||||
proc
|
||||
(mapcar ;; We don't distinguish empty params
|
||||
;; from 0 (according to [ECMA-48] we
|
||||
;; should, but all commands we support
|
||||
;; default to 0 values anyway).
|
||||
#'string-to-number
|
||||
(split-string ctl-params ";"))
|
||||
(aref str (1- ctl-end))
|
||||
private))))
|
||||
(?D ;; Scroll forward (apparently not documented in
|
||||
;; [ECMA-48], [ctlseqs] mentions it as C1
|
||||
;; character "Index" though).
|
||||
|
@ -3426,7 +3444,8 @@ option is enabled. See `term-set-goto-process-mark'."
|
|||
(setq term-current-row 0)
|
||||
(setq term-current-column 1)
|
||||
(term--reset-scroll-region)
|
||||
(setq term-insert-mode nil))
|
||||
(setq term-insert-mode nil)
|
||||
(setq term-auto-margins t))
|
||||
|
||||
(defun term--color-as-hex (for-foreground)
|
||||
"Return the current ANSI color as a hexadecimal color string.
|
||||
|
@ -3569,8 +3588,11 @@ color is unset in the terminal state."
|
|||
;; Handle a character assuming (eq terminal-state 2) -
|
||||
;; i.e. we have previously seen Escape followed by ?[.
|
||||
|
||||
(defun term-handle-ansi-escape (proc params char)
|
||||
(defun term-handle-ansi-escape (proc params char &optional private)
|
||||
(cond
|
||||
((and private (not (memq char '(?h ?l))))
|
||||
;; Recognize private capabilities only for mode entry and exit
|
||||
nil)
|
||||
((or (eq char ?H) ;; cursor motion (terminfo: cup,home)
|
||||
;; (eq char ?f) ;; xterm seems to handle this sequence too, not
|
||||
;; needed for now
|
||||
|
@ -3633,17 +3655,30 @@ color is unset in the terminal state."
|
|||
((eq char ?@)
|
||||
(term-insert-spaces (max 1 (car params))))
|
||||
;; \E[?h - DEC Private Mode Set
|
||||
|
||||
;; N.B. we previously had a bug in which we'd decode \e[?<NR>h or
|
||||
;; \e[?<NR>l as a command with zero in the params field and so
|
||||
;; didn't recognize DEC private escape sequences. However, the
|
||||
;; termcap and terminfo files had the non-? (question mark means DEC
|
||||
;; private) versions, so things kind of worked anyway. To preserve
|
||||
;; compatibility, we recognize both private- and non-private
|
||||
;; messages for capabilities we added before we fixed the bug but
|
||||
;; require the private flag for capabilities we added after.
|
||||
((eq char ?h)
|
||||
(cond ((eq (car params) 4) ;; (terminfo: smir)
|
||||
(setq term-insert-mode t))
|
||||
((eq (car params) 47) ;; (terminfo: smcup)
|
||||
(term-switch-to-alternate-sub-buffer t))))
|
||||
(cond ((eq (car params) 4) ;; (terminfo: smir)
|
||||
(setq term-insert-mode t))
|
||||
((and private (eq (car params) 7)) ;; (terminfo: smam)
|
||||
(setq term-auto-margins t))
|
||||
((eq (car params) 47) ;; (terminfo: smcup)
|
||||
(term-switch-to-alternate-sub-buffer t))))
|
||||
;; \E[?l - DEC Private Mode Reset
|
||||
((eq char ?l)
|
||||
(cond ((eq (car params) 4) ;; (terminfo: rmir)
|
||||
(setq term-insert-mode nil))
|
||||
(cond ((eq (car params) 4) ;; (terminfo: rmir)
|
||||
(setq term-insert-mode nil))
|
||||
((and private (eq (car params) 7)) ;; (terminfo: rmam)
|
||||
(setq term-auto-margins nil))
|
||||
((eq (car params) 47) ;; (terminfo: rmcup)
|
||||
(term-switch-to-alternate-sub-buffer nil))))
|
||||
(term-switch-to-alternate-sub-buffer nil))))
|
||||
|
||||
;; Modified to allow ansi coloring -mm
|
||||
;; \E[m - Set/reset modes, set bg/fg
|
||||
|
|
|
@ -129,6 +129,30 @@ first line\r_next line\r\n"))
|
|||
(term-test-screen-from-input 40 12 (let ((str (make-string 30 ?a)))
|
||||
(list str str))))))
|
||||
|
||||
(ert-deftest term-line-wrap-no-auto-margins ()
|
||||
(skip-when (memq system-type '(windows-nt ms-dos)))
|
||||
(let* ((width 40)
|
||||
(line (cl-loop for i upfrom 0 to 60
|
||||
collect (+ ?a (% i 26)) into chars
|
||||
finally return (apply #'string chars)))
|
||||
(expected (concat (substring line 0 (1- width))
|
||||
(substring line (1- (length line)))))
|
||||
(rmam "\e[?7l"))
|
||||
(should
|
||||
(equal (term-test-screen-from-input width 12 (concat rmam line))
|
||||
expected))
|
||||
;; Again, but split input into chunks.
|
||||
(should (equal
|
||||
(term-test-screen-from-input
|
||||
width 12
|
||||
(cl-loop
|
||||
with step = 3
|
||||
with n = (length line)
|
||||
for i upfrom 0 below n by step
|
||||
collect (substring line i (min n (+ i step))) into parts
|
||||
finally return (cons rmam parts)))
|
||||
expected))))
|
||||
|
||||
(ert-deftest term-colors ()
|
||||
(skip-when (memq system-type '(windows-nt ms-dos)))
|
||||
(pcase-dolist (`(,str ,expected) ansi-test-strings)
|
||||
|
|
Loading…
Add table
Reference in a new issue