8

When I run less on some file, the prompt goes away, and I get the contents of the file on screen. Then when I press q, it goes back to the prompt. I think less does this by saving the current terminal buffer, opening a new buffer, outputting the file into the new one, then when closed, discarding the new buffer, and restoring the old, but I don't know what this process is called or how it does this.

I looked in man less but didn't find anything. I tried googling it, but couldn't find anything useful, except that the screen command can do the same thing with shell sessions.

Ultimately, I'm asking because I want git diff to use a new buffer instead of printing inline. I've already set GIT_PAGER=less and git --paginate diff, but they didn't change anything. And I have a workaround, but it's a bit long: git diff --color=always | less -R

Update: After some research, it looks like tput smcup and tput rmcup are high-level commands to do the same thing, probably using the termcap package.

wjandrea
  • 14,109
  • 4
  • 48
  • 98
  • 1
    Keyword: “termcap initialization and deinitialization strings”, see `less`'s `-X` option which disables this behaviour. Btw `man less` helps: “Less uses termcap (or terminfo on some systems), so it can run on a variety of terminals.” – dessert Dec 07 '17 at 21:19
  • 1
    Related: https://unix.stackexchange.com/questions/119/colors-in-man-pages, https://unix.stackexchange.com/questions/108699/documentation-on-less-termcap-variables and https://wiki.archlinux.org/index.php/Color_output_in_console#man – dessert Dec 07 '17 at 21:29
  • Related: [How does terminal programs add scrolling to the screen?](https://stackoverflow.com/q/22537797/4518341) – wjandrea Dec 07 '17 at 21:36
  • What are your `less` settings? (Look at the `LESS` variable in particular.) On my system, `git` pages by default, using `less`; but if you have `-X`, `-E` or `-F` in your `less` configuration it could give the impression that it’s not initialising the terminal at all. – Stephen Kitt Dec 07 '17 at 22:06
  • @StephenKitt `$LESS` is unset. To clarify, `git` uses `less` on my system, but doesn't initialize a new terminal. I've tried setting git's pager as `less -+X` in the gitconfig and `$GIT_PAGER`, but neither worked. – wjandrea Dec 07 '17 at 22:26
  • What’s your `TERM` set to? – Stephen Kitt Dec 07 '17 at 22:28
  • @StephenKitt xterm – wjandrea Dec 07 '17 at 22:29
  • Disregard my comment about the pager. I don't think I set it correctly (didn't export the var, forgot to save the gitconfig). – wjandrea Dec 08 '17 at 19:02

1 Answers1

5

All of less’s screen management functions are in its screen.c module. At startup, unless it’s in “no init” (-X or --no-init) mode, it outputs its sc_init string, which is termcap’s ti string (“terminal initialisation”, which gets the terminal ready for full-screen, cursor-controlling operation). At exit, it outputs its sc_deinit string, which is termcap’s te string.

The behaviour you’re seeing is the default behaviour with git, if less isn’t configured (i.e. the LESS variable is unset); when that’s the case, git runs less with the FRX options, which cause less to respectively quit if the content fits on a single screen, display colours, and skip initialising the terminal.

To get the behaviour you’re after, set LESS to -R, or set the core.pager git setting to something like less -+X (see man git-config for details).

Stephen Kitt
  • 1,432
  • 13
  • 17
  • 1
    Setting `LESS=-R` worked, but setting `core.pager` as `less -R` didn't. However setting `core.pager` as `less -+X` did. – wjandrea Dec 07 '17 at 22:52
  • 1
    You’re welcome! `less -+X` is the recommended setting in `man git-config`, which is why I mentioned the latter, but I’ve added it explicitly to the answer. – Stephen Kitt Dec 08 '17 at 08:17