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