less icon indicating copy to clipboard operation
less copied to clipboard

output should start at screen top if one screen

Open PerBothner opened this issue 2 years ago • 9 comments

When displaying a single line (or more generally less than a screenfull) and not using --quit-if-one-screen there is a "random" number of blank lines before the output, which is confusing. The "randomness" may depend on both the terminal emulator used and the position in the "Normal" screen buffer before switching to the "Alternate" screen buffer. Test by doing clear followed by some number of blank lines and then:

 pwd | ./less

On xterm, the output is in the "middle" of the screen (depending on the cursor position when on invoking less). On Konsole and Gnome Terminal the output is at the bottom of the screen, which is at least less "random" but I believe top-of-screen would be more correct and less misleading.

I believe the problem is that the terminal is initialized by "\e[?1049h" which (according to ctlseqs.html) does the following:

Save cursor as in DECSC, xterm. After saving the cursor, switch to the Alternate Screen Buffer, clearing it first.

However, this sequence is not supposed to move the cursor (and on xterm does not).

The fix seems obvious and trivial: After switching to the Alternate buffer, move the cursor to the top left before doing any output.

PerBothner avatar May 19 '22 16:05 PerBothner

I see the problem you describe, but I don't think moving to top left at initialization is a viable solution. This would have adverse effects on terminals which do not switch to an alternate screen. For example, today on such a terminal, "echo hi | less" will display "hi" on the second-to-last line and leave the rest of the screen untouched. Perhaps moving to bottom left after screen init would work, but I'll need to think about the implications and do some testing.

gwsw avatar May 19 '22 17:05 gwsw

One idea, which I think should work whether or not a terminal supports an alternate screen: Assume the terminal has H lines and the output has N lines, including the final (END). When N < H first output the N lines of output, then H-L blank lines to scroll the output to the top, then adjust the cursor as desired.

PerBothner avatar May 19 '22 18:05 PerBothner

On Konsole and Gnome Terminal the output is at the bottom of the screen (…)

With less 590 in Konsole 21.12.2 with TERM set to xterm-256color the output is at the top of the screen. Each subsequent execution of the command results in the output being shown one line below the previous one.

piotr-dobrogost avatar May 19 '22 19:05 piotr-dobrogost

Outputting extra lines to force a short file to the top of the screen would be unacceptable for users who have non-alt-screen terminals. The fact that the tail of the previous screen is still visible after less starts up is a desirable feature.

gwsw avatar May 19 '22 20:05 gwsw

"Outputting extra lines to force a short file to the top of the screen would be unacceptable for users who have non-alt-screen terminals. The fact that the tail of the previous screen is still visible after less starts up is a desirable feature."

I don't think I agree. If you want the previous screen to be still visible after less starts use -F. Otherwise, having less behave differently depending on whether the terminal supports the alternate buffer would be a bug not a feature. Very few terminals that someone might run less on lack the alternate buffer, so we should not optimize for that case. One terminal that does lack the alternate buffer is Emacs's term mode - but it supports scrollback so you do have the option to see the tail of the previous screen.

(Personally, I think it makes sense to allow scrolling back from the alternate to the primary buffer. This seems to be a rare feature, but I implemented it for DomTerm.)

PerBothner avatar May 20 '22 04:05 PerBothner

The issue isn't whether the terminal supports an alt screen, it's whether the terminal init sequence in the termcap/terminfo that the user is using actually switches to the alt screen. Many people (including me) prefer to use a term setting which does not switch to the alt screen.

Using -F causes less to exit immediately after displaying a short file. That's not the desired behavior. The current behavior on a non-alt-screen terminal is that a short file displays at the bottom of the screen (as if it were catted) and less prompts for input. You then have the choice of quitting, which leaves the screen with the previous contents as well as the file displayed, or remain in less so that you can, for example, search in the displayed text. I would be very loathe to gratuitously change this behavior, and based on years of correspondence with users, many people would be very unhappy if it were to change.

gwsw avatar May 20 '22 04:05 gwsw

I'm inclined to agree that not switching to the alt screen might be nicer, especially for short files. If so, perhaps that should be made the default - without having to fiddle with TERM settings. I don't know terminfo well enough to know if it supports enabling cursor addressing without switching to the alternate buffer. However, it should be doable to go "beneath" terminfo at least for mostly-xterm-compatible terminals (which are the important ones). Perhaps see what readline or fish does.

PerBothner avatar May 20 '22 05:05 PerBothner

You can use the -X flag to disable sending the init sequence. However this is risky as using cursor addressing without sending the init is supposedly disallowed, although I don't think I've encountered a terminal where this actually causes a problem. AFAIK, terminfo does not provide a sequence to enable cursor addressing without switching to the alt screen. Looking at readline is a good idea.

gwsw avatar May 20 '22 16:05 gwsw

Using the -X flag also have some other effects that may be undesirable:

  • The screen isn't cleaned up when less exits.
  • Output is added to the scrollback buffer in a way that might be confusing/unexpected.

PerBothner avatar May 30 '22 01:05 PerBothner

As of 98782c194f16ba93088d1033702172c3c00f0a61, less moves to lower left if the terminal seems to be using an alternate screen. I'm not 100% sure the detection of when there is an alternate screen is correct but it seems to work on all systems I've tested. (It assumes an alt screen exists if termcap "ti" and "te" exist and "NR" does not exist.)

gwsw avatar Dec 10 '22 20:12 gwsw

Thanks. Seems to work fine.

PerBothner avatar Dec 29 '22 20:12 PerBothner