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);
}
}