The diff is clearly a layer violation, trying to interpret and dance
for an event which happens after less terminates.

What comes next, someone wanting ANSI control characters to be parsed
and evaluated to avoid screen damage?

Richard Ulmer <maillists.rul...@mailbox.org> wrote:

> Hi,
> when using a $PS1, which has more than one line, `less --no-init` cuts
> of some lines at the top, when it quits. This is especially annyoing
> when using `git diff` and `git show`. For example,
> `echo "foo\nbar" | less --no-init --quit-if-one-screen` with a two-line
> $PS1 leads to terminal content like this:
> 
> .-------------------.
> | bar               |
> | ~                 |
> | ~                 |
> | PS1 line 1        |
> | PS1 line 2$       |
> `-------------------'
> 
> I think, that using an environment variable like $PS1_LINES to inform
> less about a multiline $PS1, would be a solution for the problem. This
> is what I came up with:
> 
> Index: usr.bin/less/funcs.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/less/funcs.h,v
> retrieving revision 1.25
> diff -u -p -u -r1.25 funcs.h
> --- usr.bin/less/funcs.h      2 Sep 2019 14:07:45 -0000       1.25
> +++ usr.bin/less/funcs.h      19 Jan 2020 11:23:56 -0000
> @@ -30,6 +30,7 @@ void ring_bell(void);
>  void do_clear(void);
>  void clear_eol(void);
>  void clear_bot(void);
> +void clear_above_bot(int);
>  void at_enter(int);
>  void at_exit(void);
>  void at_switch(int);
> Index: usr.bin/less/main.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/less/main.c,v
> retrieving revision 1.37
> diff -u -p -u -r1.37 main.c
> --- usr.bin/less/main.c       28 Jun 2019 05:44:09 -0000      1.37
> +++ usr.bin/less/main.c       19 Jan 2020 11:23:56 -0000
> @@ -47,6 +47,7 @@ extern char *tags;
>  extern char  *tagoption;
>  extern int   jump_sline;
>  extern int   less_is_more;
> +extern int   ps1_lines;
>  extern int   missing_cap;
>  extern int   know_dumb;
>  extern int   quit_if_one_screen;
> @@ -102,6 +103,9 @@ main(int argc, char *argv[])
>               }
>       }
>  
> +     if ((s = lgetenv("PS1_LINES")) != NULL)
> +             ps1_lines = atoi(s);
> +
>       /*
>        * Process command line arguments and LESS environment arguments.
>        * Command line arguments override environment arguments.
> @@ -383,8 +387,10 @@ quit(int status)
>       edit(NULL);
>       if (!secure)
>               save_cmdhist();
> -     if (any_display && is_tty)
> +     if (any_display && is_tty) {
>               clear_bot();
> +             clear_above_bot(ps1_lines - 1);
> +     }
>       deinit();
>       flush(1);
>       raw_mode(0);
> Index: usr.bin/less/opttbl.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/less/opttbl.c,v
> retrieving revision 1.19
> diff -u -p -u -r1.19 opttbl.c
> --- usr.bin/less/opttbl.c     17 Sep 2016 15:06:41 -0000      1.19
> +++ usr.bin/less/opttbl.c     19 Jan 2020 11:23:56 -0000
> @@ -53,6 +53,7 @@ int opt_use_backslash;      /* Use backslash 
>  int hilite_search;   /* Highlight matched search patterns? */
>  
>  int less_is_more = 0;        /* Make compatible with POSIX more */
> +int ps1_lines = 1;   /* Height of the primary prompt */
>  
>  /*
>   * Long option names.
> Index: usr.bin/less/screen.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/less/screen.c,v
> retrieving revision 1.25
> diff -u -p -u -r1.25 screen.c
> --- usr.bin/less/screen.c     3 Sep 2019 23:08:42 -0000       1.25
> +++ usr.bin/less/screen.c     19 Jan 2020 11:23:56 -0000
> @@ -34,6 +34,7 @@ static char
>       *sc_lower_left,         /* Cursor to last line, first column */
>       *sc_return,             /* Cursor to beginning of current line */
>       *sc_move,               /* General cursor positioning */
> +     *sc_up,                 /* Cursor up one line */
>       *sc_clear,              /* Clear screen */
>       *sc_eol_clear,          /* Clear to end of line */
>       *sc_eos_clear,          /* Clear to end of screen */
> @@ -87,6 +88,7 @@ extern int tty;
>  extern int top_scroll;
>  extern int oldbot;
>  extern int hilite_search;
> +extern int ps1_lines;
>  
>  /*
>   * Change terminal to "raw mode", or restore to "normal" mode.
> @@ -414,6 +416,10 @@ get_term(void)
>       }
>       sc_lower_left = cheaper(t1, t2, "\r");
>  
> +     sc_up = cursor_up;
> +     if (ps1_lines > 1 && sc_up == NULL)
> +             missing_cap = 1;
> +
>       /*
>        * Get carriage return string.
>        */
> @@ -699,6 +705,20 @@ clear_bot(void)
>               at_exit();
>               clear_eol_bot();
>               at_enter(saved_attrmode);
> +     }
> +}
> +
> +/*
> + * Clear n lines above the bottom line of the display.
> + * The cursor must be set to the beginning of the bottom line before.
> + */
> +void
> +clear_above_bot(int n)
> +{
> +     int i;
> +     for (i = 0; i < n; i++) {
> +             tputs(sc_up, 1, putchr);
> +             tputs(sc_eol_clear, 1, putchr);
>       }
>  }
>  
> 

Reply via email to