On Sun, 17 Jun 2018 15:52:34 -0600, "Todd C. Miller" wrote:
> On Sun, 17 Jun 2018 17:29:31 +0200, Mark Kettenis wrote:
>
> > If folks indeed think that this is a must-have feature, this is
> > certainly a better approach. I wonder though if the setupterm() call
> > should happen earlier when interactive mode is initialized?
>
> This turns out to be simpler than expected. Now whenever TERM is
> set (including at startup) it will call setupterm().
Hopefully final diff that better handles unknown term types. Now
if you set TERM=gobbledegook the old cur_term will be invalidated
and clear-screen will not try to the escape sequence for the old
terminal.
I think this is good enough to commit.
- todd
Index: bin/ksh/Makefile
===================================================================
RCS file: /cvs/src/bin/ksh/Makefile,v
retrieving revision 1.38
diff -u -p -u -r1.38 Makefile
--- bin/ksh/Makefile 6 Jan 2018 16:28:58 -0000 1.38
+++ bin/ksh/Makefile 16 Jun 2018 22:00:32 -0000
@@ -1,6 +1,9 @@
# $OpenBSD: Makefile,v 1.38 2018/01/06 16:28:58 millert Exp $
PROG= ksh
+DPADD+= ${LIBCURSES}
+LDADD+= -lcurses
+
SRCS= alloc.c c_ksh.c c_sh.c c_test.c c_ulimit.c edit.c emacs.c eval.c \
exec.c expr.c history.c io.c jobs.c lex.c mail.c main.c \
misc.c path.c shf.c syn.c table.c trap.c tree.c tty.c var.c \
Index: bin/ksh/edit.c
===================================================================
RCS file: /cvs/src/bin/ksh/edit.c,v
retrieving revision 1.65
diff -u -p -u -r1.65 edit.c
--- bin/ksh/edit.c 9 Apr 2018 17:53:36 -0000 1.65
+++ bin/ksh/edit.c 16 Jun 2018 22:09:17 -0000
@@ -138,10 +138,10 @@ x_flush(void)
shf_flush(shl_out);
}
-void
+int
x_putc(int c)
{
- shf_putc(c, shl_out);
+ return shf_putc(c, shl_out);
}
void
Index: bin/ksh/edit.h
===================================================================
RCS file: /cvs/src/bin/ksh/edit.h,v
retrieving revision 1.11
diff -u -p -u -r1.11 edit.h
--- bin/ksh/edit.h 26 Jan 2016 17:39:31 -0000 1.11
+++ bin/ksh/edit.h 16 Jun 2018 22:09:27 -0000
@@ -37,7 +37,7 @@ extern X_chars edchars;
/* edit.c */
int x_getc(void);
void x_flush(void);
-void x_putc(int);
+int x_putc(int);
void x_puts(const char *);
bool x_mode(bool);
int promptlen(const char *, const char **);
Index: bin/ksh/emacs.c
===================================================================
RCS file: /cvs/src/bin/ksh/emacs.c,v
retrieving revision 1.84
diff -u -p -u -r1.84 emacs.c
--- bin/ksh/emacs.c 16 Jan 2018 17:17:18 -0000 1.84
+++ bin/ksh/emacs.c 18 Jun 2018 03:30:09 -0000
@@ -21,6 +21,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifndef SMALL
+# include <term.h>
+# include <curses.h>
+#endif
#include "sh.h"
#include "edit.h"
@@ -28,6 +32,7 @@
static Area aedit;
#define AEDIT &aedit /* area for kill ring and macro defns */
+#undef CTRL
#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /*
ASCII */
#define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /*
ASCII */
@@ -146,6 +151,7 @@ static int isu8cont(unsigned char);
/* proto's for keybindings */
static int x_abort(int);
static int x_beg_hist(int);
+static int x_clear_screen(int);
static int x_comp_comm(int);
static int x_comp_file(int);
static int x_complete(int);
@@ -202,6 +208,7 @@ static int x_debug_info(int);
static const struct x_ftab x_ftab[] = {
{ x_abort, "abort", 0 },
{ x_beg_hist, "beginning-of-history", 0 },
+ { x_clear_screen, "clear-screen", 0 },
{ x_comp_comm, "complete-command", 0 },
{ x_comp_file, "complete-file", 0 },
{ x_complete, "complete", 0 },
@@ -1004,12 +1011,19 @@ x_draw_line(int c)
{
x_redraw(-1);
return KSTD;
+}
+static int
+x_clear_screen(int c)
+{
+ x_redraw(-2);
+ return KSTD;
}
-/* Redraw (part of) the line. If limit is < 0, the everything is redrawn
- * on a NEW line, otherwise limit is the screen column up to which needs
- * redrawing.
+/* Redraw (part of) the line.
+ * A non-negative limit is the screen column up to which needs
+ * redrawing. A limit of -1 redraws on a new line, while a limit
+ * of -2 (attempts to) clear the screen.
*/
static void
x_redraw(int limit)
@@ -1018,9 +1032,20 @@ x_redraw(int limit)
char *cp;
x_adj_ok = 0;
- if (limit == -1)
+ if (limit == -2) {
+ int cleared = 0;
+#ifndef SMALL
+ if (cur_term != NULL && clear_screen != NULL) {
+ if (tputs(clear_screen, 1, x_putc) != ERR)
+ cleared = 1;
+ }
+#endif
+ if (!cleared)
+ x_e_putc('\n');
+ }
+ else if (limit == -1)
x_e_putc('\n');
- else
+ else if (limit >= 0)
x_e_putc('\r');
x_flush();
if (xbp == xbuf) {
Index: bin/ksh/ksh.1
===================================================================
RCS file: /cvs/src/bin/ksh/ksh.1,v
retrieving revision 1.200
diff -u -p -u -r1.200 ksh.1
--- bin/ksh/ksh.1 30 May 2018 21:20:52 -0000 1.200
+++ bin/ksh/ksh.1 17 Jun 2018 21:58:30 -0000
@@ -1717,6 +1717,10 @@ loops to store the value that is read fr
The number of seconds since the shell started or, if the parameter has been
assigned an integer value, the number of seconds since the assignment plus the
value that was assigned.
+.It Ev TERM
+The user's terminal type.
+If set, it will be used to determine the escape sequence used to
+clear the screen.
.It Ev TMOUT
If set to a positive integer in an interactive shell, it specifies the maximum
number of seconds the shell will wait for input after printing the primary
@@ -4690,6 +4694,11 @@ Moves the cursor to the beginning of the
Uppercase the first character in the next
.Ar n
words, leaving the cursor past the end of the last word.
+.It clear-screen:
+Clears the screen if the
+.Ev TERM
+parameter is set and the terminal supports clearing the screen, then
+reprints the prompt string and the current input line.
.It comment: ^[#
If the current line does not begin with a comment character, one is added at
the beginning of the line and the line is entered (as if return had been
Index: bin/ksh/table.h
===================================================================
RCS file: /cvs/src/bin/ksh/table.h,v
retrieving revision 1.14
diff -u -p -u -r1.14 table.h
--- bin/ksh/table.h 9 Apr 2018 17:53:36 -0000 1.14
+++ bin/ksh/table.h 17 Jun 2018 21:35:49 -0000
@@ -170,6 +170,7 @@ extern const struct builtin shbuiltins [
#define V_TMOUT 16
#define V_TMPDIR 17
#define V_LINENO 18
+#define V_TERM 19
/* values for set_prompt() */
#define PS1 0 /* command */
Index: bin/ksh/var.c
===================================================================
RCS file: /cvs/src/bin/ksh/var.c,v
retrieving revision 1.68
diff -u -p -u -r1.68 var.c
--- bin/ksh/var.c 13 Apr 2018 18:18:36 -0000 1.68
+++ bin/ksh/var.c 18 Jun 2018 03:32:34 -0000
@@ -11,6 +11,10 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#ifndef SMALL
+# include <term.h>
+# include <curses.h>
+#endif
#include "sh.h"
@@ -111,12 +115,13 @@ initvar(void)
{ "SECONDS", V_SECONDS },
{ "TMOUT", V_TMOUT },
{ "LINENO", V_LINENO },
+ { "TERM", V_TERM },
{ NULL, 0 }
};
int i;
struct tbl *tp;
- ktinit(&specials, APERM, 32); /* must be 2^n (currently 17 specials) */
+ ktinit(&specials, APERM, 32); /* must be 2^n (currently 19 specials) */
for (i = 0; names[i].name; i++) {
tp = ktenter(&specials, names[i].name, hash(names[i].name));
tp->flag = DEFINED|ISSET;
@@ -1056,6 +1061,18 @@ setspec(struct tbl *vp)
/* The -1 is because line numbering starts at 1. */
user_lineno = (unsigned int) intval(vp) - current_lineno - 1;
vp->flag |= SPECIAL;
+ break;
+ case V_TERM:
+#ifndef SMALL
+ {
+ int ret;
+
+ vp->flag &= ~SPECIAL;
+ if (setupterm(str_val(vp), STDOUT_FILENO, &ret) == ERR)
+ del_curterm(cur_term);
+ vp->flag |= SPECIAL;
+ }
+#endif
break;
}
}