Subject: bug#33230: 26.1; Soft-wrap issue in term.el with term-suppress-hard-newline

From: Bruno CHARRON <[email-masked]>
Date: Sun, 4 Nov 2018 16:23:25 +0900

> It seems like this option is somewhat incompatible with shells, it's not
> clear what the right behaviour would be.  You say the problem is that
> there is no wrapping, but isn't term-suppress-hard-newline exactly
> intended to suppress this kind of wrapping?

The option is said to "mean[s] text can automatically reflow if the
window is resized" and I think the behavior of libvte with the rewrap
option implements that well. You can see in [1] the behavior with and
without the option in gnome-terminal 3.18.3. The option is extensively
documented here [3].

For emacs, the rewrapping is currently done well with
term-suppress-hard-newline for all lines except the command currently
edited. One solution, though non-trivial, may be to interpret the
cursor movements (from the shell) which fall within the "region" of
the last (emacs) line, corresponding to several (shell) lines if there
was wrapping, as movements within the last (emacs) line. Emacs moves
to a new line only if the shell movements take it away from the
current "region".

For example, with width 20, after typing x repeatedly, _ is the cursor
on the last column (emacs current col: 19)
$ xxxxxxxxxxxxxxxxx_
Here, the last emacs line corresponds to a "region" of one (shell) line.
Then typing x, the shell (bash) sends "x ^M" and thinks the display is
$ xxxxxxxxxxxxxxxxxx
_
but emacs still displays a single line, visually wrapped or truncated
according to emacs' config
$ xxxxxxxxxxxxxxxxxxx_
to get there, it first processes "x ", the cursor is now at column 21,
then it processes ^M and since the width is 20, it moves the cursor to
the beginning of the current (shell) line which is at column 21 - (21
% 20) = 20.
Here, the last emacs line corresponds to a "region" of two (shell) lines.
Then after hitting backspace, the shell sends
"^[[A^[[19C^[[K^M^J^M^[[K^[[A^[[19C" and thinks the display is
$ xxxxxxxxxxxxxxxxx_

(with an empty line)
and emacs shows
$ xxxxxxxxxxxxxxxxx_
to get there, it virtually moves up one line (but actually goes 20
columns left due to width = 20 so current col: 20 - 20 = 0) due to
^[[A, then 19 columns right (current col: 0 + 19 = 19) due to ^[[19C
then erases up to the end of the virtual line (before col (19 + 20) -
((19 + 20) % 20) = 20) due to ^[[K, then moves back to the beginning
of the virtual line (current col: 19 - (19 % 20) = 0) due to ^M, moves
down one virtual line (current col: 0 + 20 = 20) due to ^K, erases up
to the end of the virtual line (before col (20 + 20) - ((20 + 20) %
20) = 40) due to ^[[K, moves up one virtual line (current col 20 - 20
= 0) due to ^[[A, then 19 columns right (current col: 0 + 19 = 19).
Here, the last emacs line corresponds to a "region" of only one
(shell) lines, as the second (shell) line is empty (due to ^M^[[K) and
does not contain the cursor, so that if we execute and the shell sends
a newline ^J to print the output, the output will fall within a new
(emacs) line.

Definitely non-trivial but I don't have another solution in mind that
would give the expected behavior. I don't know how Visual Line works
but it seems the idea is similar so maybe it can be reused? Instead of
remapping the user's cursor movement to movements on the visual lines,
we would like to remap the shell's cursor movement to movements on the
visual lines instead of the logical lines.

Another issue I found that may need to be addressed to get a behavior
similar to gnome-terminal above is that the shell is not aware
(checking $COLUMS) of when the frame is resized, only when its window
is resized and there is another window on the side.

[1] https://imgur.com/a/7IwZfmy
[2] https://gitlab.gnome.org/GNOME/vte/blob/master/doc/rewrap.txt