GNOME Bugzilla – Bug 763390
Multi-line fish prompt mangled on window resize
Last modified: 2021-06-10 15:12:03 UTC
Created attachment 323537 [details] Illustration of multi-line fish prompt behavior on window resize Attachment should clarify the issue, as I find this a little difficult to describe. I performed the following test with the latest version of vte (git master, commit 659d64b) via the testvte program: * start testvte * run shell of choice, which has been configured to use a multi-line prompt * resize the window such that it is smaller horizontally than before With fish, this results in the prompt being shifted by one row and the first line of the prompt being copied (occupying the row that was shifted). With zsh and an essentially identical prompt, this does not occur. If I clear the screen (ctrl+l) before performing the resize, the issue doesn't occur. I use a tiling window manager [1], and creating multiple terminals causes them to resize horizontally automatically, amplifying this effect each time they're resized -- that is, it's no longer just a shift of the prompt by a row, but more "noise" from the prompt is added at seemingly random places. I have been unable to replicate this behavior with other terminal emulators not based on vte, such as rxvt-unicode and st. [1]: I can replicate these results with GNOME Terminal under GNOME Shell as well.
I think this boils down to an interference between how the terminal rewraps the contents on resize and how afterwards your shell redisplays the prompt. st doesn't rewrap on resize, rxvt only rewraps after a screenful of data has been output and probably uses a different algorithm than vte. One of your options is to disable this feature in vte/gnome-terminal. It would be nice to see your exact prompt definition, as well as a script(1) log of what's happening. Although, I find it very unlikely and unreasonable that we'd modify vte's rewrap algorithm to please fish. IMO it should happen the other way around.
Created attachment 323662 [details] script(1) logs -- first without resizing, then with resizing
script(1) log has been added. I concatenated two sessions: one where I just started script/ran fish/exited, and one where I resized before exiting. My current fish_prompt function can be seen here: https://github.com/ixjlyons/dotfiles/blob/577b80f2079a317d62b66316612526746a8348f6/fish/functions/fish_prompt.fish
Okay, so it contains the trick to denote if the previous command's output wasn't terminated by a newline. It's a standard trick to print a symbol (e.g. "⏎" in your case), followed by width-1 spaces, then a carriage return, and then a space-backspace or something similar. If the previous command's output ends properly in a newline then it's (almost) a no-op. If the previous command's output, however, ends in the middle of a line, then it causes "⏎" to get displayed and then overflow to the next line where the prompt will be presented. The problem is, however, that this construct causes the line to be filled up by spaces, which is rewrapped when the terminal is resized. For the "normal" case (when the output ends with a newline character) the following will probably help: After those tons of spaces, your prompt outputs a "\r \r" (carriage return, space, carriage return). Change this to "\r\e[K" (carriage return, escape, [, K). This escape sequence clears to the end of the line, replacing the explicit spaces by empty (unused) cells. The "output didn't end in a newline" case will still not be perfect though. Ideally there should be an escape sequence that aids printing conditionally, only if the cursor is not in the first column. It would require coordination across most popular emulators, and it's unclear to me how it should work. So I think it's unlikely to get implemented any time soon.
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/vte/-/issues/2294.