less icon indicating copy to clipboard operation
less copied to clipboard

How to make 'less' not take full terminal

Open fhgd opened this issue 3 years ago • 5 comments

This question arise from https://stackoverflow.com/q/27621369/5599281 with the nice answer from Will Bender https://stackoverflow.com/a/60607569/5599281 to use

git config --global core.pager "less; tput cuu 1 && tput ed"

The only drawback of this workaround is that there is some flickering of the cursor. It is possible to add another build-in option which shifts the cursor N lines above after quitting less?

fhgd avatar Oct 21 '20 14:10 fhgd

The current solution overwrite the last lines when you scrolled to the end within the less-pager. This can be avoided when you append two lines before piping the git output to less-pager with: "(cat; echo; echo) | less; tput cuu 2 && tput ed"

fhgd avatar Oct 29 '20 11:10 fhgd

It seems to me that the best solution is the one suggested by Etan Reisner in the linked thread; that is, copy the text you want before exiting less. It's clearly impossible to preserve all the text on the screen after displaying a 3-line shell prompt. For example, shifting the cursor up N lines as suggested here would overwrite the last N lines of less output. You would have to remember to keep the text you want to copy above the last N lines, but if you're doing that, why not just keep the text below the first N lines and then no change is needed? Perhaps I'm not understanding the use case clearly.

gwsw avatar Dec 31 '20 17:12 gwsw

I can't speak to whether this satisfies the author's use case but personally, I would love it --quit-if-one-screen along with --redraw-on-quit could in some way be told that the "one screen" height is 2 row shorter than what it auto-detected so that I can see the top of the output after I quit it when using my 3 line shell prompt.

Jackenmen avatar Aug 01 '22 21:08 Jackenmen

It's not clear to me what you mean. By "top of the output", do you mean you want to retain the lines that are currently at the top of the screen after you exit? In that case you would lose the 3 lines at the bottom of the screen. Is that what you're asking for? If so, why is that more useful to you than the current behavior?

gwsw avatar Aug 02 '22 00:08 gwsw

By "top of the output", do you mean you want to retain the lines that are currently at the top of the screen after you exit?

Yes.

In that case you would lose the 3 lines at the bottom of the screen. Is that what you're asking for? If so, why is that more useful to you than the current behavior?

I admit I might have not thought that through entirely... But yes, for me it would (often? I'm not sure if always) be more useful to be able to see the top of the output because typically things that I put through pager are various outputs from git - branch list, commit log, diffs - and typically the part that I was looking at right before closing (and the part I would still want to look at after closing) is going to be closer to the top. Sometimes this has to do with how the output that interest me the most is at the top (i.e. I'm usually going to be most interested in more recent commits and those are at the top).

I'm unsure whether losing the 2 lines at the bottom on quit is better though so that's entirely fair argument... If it didn't in some way handle being at the end of output, it would probably end up being a bigger annoyance than the need to scroll. It's likely that there isn't a good way to handle that.

However, I feel like I would even be fine with always compromising 2 lines of the less's screen so that everything can fit on the screen after quitting. I guess this means that what I would really want is to have a way to set top (or bottom?) "margin" then?

Jackenmen avatar Aug 02 '22 20:08 Jackenmen

This looks related to my issue. Having a multi-line shell prompt ($PS1 in bash) can cause the first few lines of output to be scrolled off the top if --quit-if-one-screen is used. Modifying the LINES environment variable has no effect since as documented TIOCGWINSZ or WIOCGETD will be used if supported. Is there a workaround? Found users with similar issues:

https://www.mail-archive.com/[email protected]/msg171339.html https://superuser.com/questions/1695369/change-less-pager-screen-size

grr avatar Dec 13 '22 09:12 grr

Again, there's no way to preserve the whole screen contents if you're using some of the lines for your prompt. If the screen is 30 lines high, less displays 29 lines of text plus a prompt line. If after exiting, you're using 2 lines for your shell PS1, there are only 28 lines available, so the 29 lines that were visible in less cannot all be displayed. You can lose the top lines (as is currently done), or you can lose the bottom lines. Or perhaps there's some other option I'm not thinking of. Can you be more specific about exactly what behavior you want?

gwsw avatar Jan 09 '23 19:01 gwsw

Or perhaps there's some other option I'm not thinking of.

I did suggest adding option for a margin above:

However, I feel like I would even be fine with always compromising 2 lines of the less's screen so that everything can fit on the screen after quitting. I guess this means that what I would really want is to have a way to set top (or bottom?) "margin" then?

Jackenmen avatar Jan 09 '23 19:01 Jackenmen

That is unfortunately a substantial change to the way less works. Currently it assumes it can add a line at the bottom of the screen and rely on the terminal to scroll the screen up when it gets the newline. Reserving blank space at the bottom of the screen would mean it would have to redraw the entire screen before each line, or manually scroll it. Reserving lines at the top would be even harder. I guess it's not impossible, but I think either way it would be tricky. I can look into this a bit more, but I guess I'm having a hard time seeing why it's useful to deliberately use less than the full screen. Currently you can just position the text the way you want it before you exit and get the same result, except you see more data while you're inside less.

gwsw avatar Jan 09 '23 19:01 gwsw

I'm having a hard time seeing why it's useful to deliberately use less than the full screen. Currently you can just position the text the way you want it before you exit and get the same result, except you see more data while you're inside less.

if you use --quit-if-one-screen you don't have the opportunity to position the text before exiting. if the user can specify an offset, or preferably set the LINES variable, the user would not need to scroll in the terminal when less auto-quits.

grr avatar Jan 09 '23 22:01 grr

Ok, in a84b46d57ffbe3329cefdb2c3422af6d1e46cd99 I have added an environment variable LESS_LINES which you can set to a value smaller than your screen size to use less than the full screen height. You can also set it to a negative number; for example LESS_LINES=-1 will make less use one fewer lines than the actual screen height.

It's a rather crude implementation, in that the screen is fully redrawn after every command, even if you're just scrolling one line. So the performance may be suboptimal, but I think it does what's being requested here.

gwsw avatar Jan 16 '23 00:01 gwsw

You can also set it to a negative number; for example LESS_LINES=-1 will make less use one fewer lines than the actual screen height.

I was about to ask if there's a way to keep less responsive to height changes and still be able to subtract the margin value from it but I see you've done the edit about negative numbers before I could even take the time to write that question :smile:

I'll start using a build from the current master tomorrow to test this feature out and see how it performs, thanks for working on this!

Jackenmen avatar Jan 16 '23 00:01 Jackenmen

So far it seems to work as expected. I can sometimes briefly notice the cursor in a place other than the prompt when I scroll at least a few lines at a time (e.g. with mouse scroll or page up/down but not with arrow keys). I imagine that's probably nothing out of the ordinary when having to fully redraw the screen after every scroll. I do find it a bit surprising that it only seems to happen when scrolling at least a few lines, but there's probably some good explanation for that as well.

Jackenmen avatar Jan 17 '23 21:01 Jackenmen

Today I've noticed an issue with less's output when using a .lesskey with these contents:

#env
LESS = -RF --redraw-on-quit --incsearch
LESS_LINES = -2

When I run less on a file that can fit on my screen (and therefore causes less to exit immediately due to the usage of -F flag), e.g. when running less .gitignore on the .gitignore file from this repository, less's output prints over the prompt's lines:

  • The terminal right before running the command: image
  • The terminal after running the command: image

I'm testing with commit d312cdf.

Jackenmen avatar Jan 23 '23 02:01 Jackenmen

Thanks, should be fixed in c4e7f5879801766033b170b8ce10cca80367be5f.

gwsw avatar Jan 23 '23 18:01 gwsw

Yep, that fixed it, thanks!

Jackenmen avatar Jan 23 '23 18:01 Jackenmen

I don't know if this is really an issue (I don't use -X and it seems like it disables termcap initialization) but I noticed that when running less -X, on startup the top N lines (where N is the margin) are from before less command was started: image

This gets fixed as soon as I hit any arrow, even the left arrow which is why I thought that maybe it is something you would want to fix: image

This can be reproduced on f0328ed by running this command (no .lesskey required):

LESS_LINES=-2 less -X less.h

The only reason I noticed this is because kitty --help uses the -X switch for some reason (probably so that all of the output you've scrolled through stays on the screen after exiting, not just the current visible screen), I don't really use it myself since, unlike --redraw-on-quit, it can't handle mouse scroll.

Jackenmen avatar Jan 29 '23 22:01 Jackenmen

Thanks, that was a side effect of my previous fix in c4e7f5879801766033b170b8ce10cca80367be5f. That fix did not work in the presence of -X. Should be fixed now in 867b988077051b72810a4783dc2ba2d8852eaecc.

gwsw avatar Feb 02 '23 23:02 gwsw

Hmm, it doesn't seem like it fixed this for me, the behavior remains identical to what I explained in the comment. less --version returns less 623, not less 623x or any other version so I'm definitely on the correct version. I can reproduce this on KDE Konsole, kitty terminal, and tty when using either bash or zsh.

Jackenmen avatar Feb 03 '23 10:02 Jackenmen

Yeah, sorry, my testing was insufficient. It should really be fixed in 1c8263695264015565d339498efddf5da944e4cf.

gwsw avatar Feb 03 '23 17:02 gwsw

Yeah, that works, thanks!

Jackenmen avatar Feb 04 '23 04:02 Jackenmen

Found one more. When switching between files (:n), there's a "...skipping..." message printed which normally gets scrolled off the screen but with LESS_LINES=-2 it doesn't since there's a margin available. This can be tested by:

  1. Running LESS_LINES=-2 less less.h .gitignore: image
  2. Typing :n: image
  3. As soon as there's a page redraw (i.e. any arrow is used), it goes back to normal: image

Jackenmen avatar Feb 05 '23 07:02 Jackenmen

I didn't expect to find another one moments after commenting here, sorry.

Reproduction steps:

  1. Resize your terminal to size: 99x29 (it probably doesn't actually matter but posting just in case, to have fuller reproduction)
  2. Run command: LESS_LINES=-2 less --help --incsearch, everything's normal: image
  3. Type /q, see the first issue with redraw (the bottom of the terminal is not reserved for margin): image
  4. Use backspace once, see more issues with redraw: image
  5. Use backspace one more time, and everything goes back to normal: image

Jackenmen avatar Feb 05 '23 07:02 Jackenmen

Ugh. I'm afraid we may find several more of these corner cases, since less was designed with the assumption that it would be using the full screen. Anyway, these last two issues should be fixed in 96431262a46a517edf2c4a601cd3aa55c052a09e.

gwsw avatar Feb 06 '23 20:02 gwsw

Just to report back, after updating to 9643126, these issues are no longer present, thanks again!

Jackenmen avatar Feb 07 '23 15:02 Jackenmen