ksh "clear-screen" editing command

classic Classic list List threaded Threaded
43 messages Options
123
Reply | Threaded
Open this post in threaded view
|

ksh "clear-screen" editing command

Alexander Hall
This adds a "clear-screen" editing command to the emacs editing mode.
This is the same name as bash and zsh uses, and then I stopped looking.

The default binding of 'redraw' remains for ^L, for now anyway, so
you'll need to run
  $ bind ^L=clear-screen"
when testing.

$CLEARSTR can be set to an arbitrary character sequence for clearing the
screen, should ^[[H^[[J not fit the bill. For example,
  $ CLEARSTR=$(clear)
Not sure we want or need this, or what could possibly be a better name
for it.

Thoughts? OK?

/Alexander


Index: emacs.c
===================================================================
RCS file: /cvs/src/bin/ksh/emacs.c,v
retrieving revision 1.84
diff -u -p -r1.84 emacs.c
--- emacs.c 16 Jan 2018 17:17:18 -0000 1.84
+++ emacs.c 5 Jun 2018 22:03:49 -0000
@@ -146,6 +146,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 +203,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 +1006,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 +1027,15 @@ x_redraw(int limit)
  char *cp;
 
  x_adj_ok = 0;
- if (limit == -1)
+ if (limit == -2) {
+ char *clearstr = str_val(global("CLEARSTR"));
+ if (clearstr == null)
+ clearstr = "\033[H\033[J";
+ x_e_puts(clearstr);
+ }
+ else if (limit == -1)
  x_e_putc('\n');
- else
+ else if (limit >= 0)
  x_e_putc('\r');
  x_flush();
  if (xbp == xbuf) {
Index: ksh.1
===================================================================
RCS file: /cvs/src/bin/ksh/ksh.1,v
retrieving revision 1.200
diff -u -p -r1.200 ksh.1
--- ksh.1 30 May 2018 21:20:52 -0000 1.200
+++ ksh.1 5 Jun 2018 22:03:49 -0000
@@ -1345,6 +1345,8 @@ Also, the
 .Ic cd
 built-in command will display the resulting directory when a match is found
 in any search path other than the empty path.
+.It Ev CLEARSTR
+If set, overrides the default escape sequence to clear the screen.
 .It Ev COLUMNS
 Set to the number of columns on the terminal or window.
 Currently set to the
@@ -4690,6 +4692,12 @@ 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 and redraws the prompt and current input line.
+If the
+.Ev CLEARSTR
+parameter is set, it is used to clear the screen.
+Otherwise, a default escape sequence (^[[H^[2J) is used.
 .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

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Theo de Raadt-2
> +                       clearstr = "\033[H\033[J";

I abhor increasing assumptions that the terminal honours that particular
ANSI standard.

Sorry, but at that point you have to use the libraries and get the
information.

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Alexandre Ratchov-2
In reply to this post by Alexander Hall
On Wed, Jun 06, 2018 at 12:20:50AM +0200, Alexander Hall wrote:

> This adds a "clear-screen" editing command to the emacs editing mode.
> This is the same name as bash and zsh uses, and then I stopped looking.
>
> The default binding of 'redraw' remains for ^L, for now anyway, so
> you'll need to run
>   $ bind ^L=clear-screen"
> when testing.
>
> $CLEARSTR can be set to an arbitrary character sequence for clearing the
> screen, should ^[[H^[[J not fit the bill. For example,
>   $ CLEARSTR=$(clear)

I don't see the point of the environment variable, for a string
standard since 1974 or 1979, I don't remember. Or is this to make the
command do something else?

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Todd C. Miller-2
In reply to this post by Theo de Raadt-2
On Tue, 05 Jun 2018 16:29:33 -0600, "Theo de Raadt" wrote:

> > +                       clearstr = "\033[H\033[J";
>
> I abhor increasing assumptions that the terminal honours that particular
> ANSI standard.
>
> Sorry, but at that point you have to use the libraries and get the
> information.

Or just run clear(1).  That may be preferable to linking ksh with
libcurses.

 - todd

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Alexander Hall
On 06/06/18 13:50, Todd C. Miller wrote:

> On Tue, 05 Jun 2018 16:29:33 -0600, "Theo de Raadt" wrote:
>
>>> +                       clearstr = "\033[H\033[J";
>>
>> I abhor increasing assumptions that the terminal honours that particular
>> ANSI standard.
>>
>> Sorry, but at that point you have to use the libraries and get the
>> information.
>
> Or just run clear(1).  That may be preferable to linking ksh with
> libcurses.

Yeah, I wasn't keen on adding libcurses...

The diff below uses system(3) to call /usr/bin/clear, fiddling with
*env() to make sure the current TERM value is propagated. The error
handling is deliberately sparse, since I don't know what the reasonable
error actions would be.

It's quite possible there already exists a better function to call
within the ksh code already, but I was unable to figure out which if so.

Better? Worse?

/Alexander


Index: emacs.c
===================================================================
RCS file: /cvs/src/bin/ksh/emacs.c,v
retrieving revision 1.84
diff -u -p -r1.84 emacs.c
--- emacs.c 16 Jan 2018 17:17:18 -0000 1.84
+++ emacs.c 12 Jun 2018 00:19:44 -0000
@@ -146,6 +146,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 +203,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 +1006,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 +1027,24 @@ x_redraw(int limit)
  char *cp;
 
  x_adj_ok = 0;
- if (limit == -1)
+ if (limit == -2) {
+ char *oldterm = getenv("TERM");
+ char *term = str_val(global("TERM"));
+ if (term && *term) {
+ setenv("TERM", term, 1);
+ if (system("/usr/bin/clear") != 0)
+ x_e_putc('\n');
+ if (oldterm)
+ setenv("TERM", oldterm, 1);
+ else
+ unsetenv("TERM");
+ }
+ else
+ 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: ksh.1
===================================================================
RCS file: /cvs/src/bin/ksh/ksh.1,v
retrieving revision 1.200
diff -u -p -r1.200 ksh.1
--- ksh.1 30 May 2018 21:20:52 -0000 1.200
+++ ksh.1 12 Jun 2018 00:19:44 -0000
@@ -4690,6 +4690,10 @@ 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:
+Attempts to clears the screen by invoking
+.Xr clear 1
+and redraws the prompt and 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

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Todd C. Miller-2
On Tue, 12 Jun 2018 02:35:57 +0200, Alexander Hall wrote:

> The diff below uses system(3) to call /usr/bin/clear, fiddling with
> *env() to make sure the current TERM value is propagated. The error
> handling is deliberately sparse, since I don't know what the reasonable
> error actions would be.
>
> It's quite possible there already exists a better function to call
> within the ksh code already, but I was unable to figure out which if so.

Using system() within ksh seems wrong.  How about this instead?
 
 - todd

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 16 Jun 2018 12:31:59 -0000
@@ -146,6 +146,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 +203,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 +1006,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 +1027,20 @@ x_redraw(int limit)
  char *cp;
 
  x_adj_ok = 0;
- if (limit == -1)
+ if (limit == -2) {
+ char *term = str_val(global("TERM"));
+ int ret = -1;
+ if (term && *term) {
+ Source *sold = source;
+ ret = command("/usr/bin/clear", 0);
+ source = sold;
+ }
+ if (ret != 0)
+ 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 16 Jun 2018 12:29:34 -0000
@@ -4690,6 +4690,10 @@ 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:
+Attempts to clears the screen by invoking
+.Xr clear 1
+and redraws the prompt and 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

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Mark Kettenis
> From: "Todd C. Miller" <[hidden email]>
> Date: Sat, 16 Jun 2018 06:37:03 -0600
>
> On Tue, 12 Jun 2018 02:35:57 +0200, Alexander Hall wrote:
>
> > The diff below uses system(3) to call /usr/bin/clear, fiddling with
> > *env() to make sure the current TERM value is propagated. The error
> > handling is deliberately sparse, since I don't know what the reasonable
> > error actions would be.
> >
> > It's quite possible there already exists a better function to call
> > within the ksh code already, but I was unable to figure out which if so.
>
> Using system() within ksh seems wrong.  How about this instead?

To e honest, I find the whole idea of invoking an external program to
clear the screen insane.

> 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 16 Jun 2018 12:31:59 -0000
> @@ -146,6 +146,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 +203,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 +1006,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 +1027,20 @@ x_redraw(int limit)
>   char *cp;
>  
>   x_adj_ok = 0;
> - if (limit == -1)
> + if (limit == -2) {
> + char *term = str_val(global("TERM"));
> + int ret = -1;
> + if (term && *term) {
> + Source *sold = source;
> + ret = command("/usr/bin/clear", 0);
> + source = sold;
> + }
> + if (ret != 0)
> + 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 16 Jun 2018 12:29:34 -0000
> @@ -4690,6 +4690,10 @@ 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:
> +Attempts to clears the screen by invoking
> +.Xr clear 1
> +and redraws the prompt and 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
>
>

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Todd C. Miller-2
On Sat, 16 Jun 2018 14:50:40 +0200, Mark Kettenis wrote:

> To be honest, I find the whole idea of invoking an external program to
> clear the screen insane.

Do you have an alternative that doesn't require linking ksh with
curses?

 - todd

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Mark Kettenis
> From: "Todd C. Miller" <[hidden email]>
> Date: Sat, 16 Jun 2018 06:53:38 -0600
>
> On Sat, 16 Jun 2018 14:50:40 +0200, Mark Kettenis wrote:
>
> > To be honest, I find the whole idea of invoking an external program to
> > clear the screen insane.
>
> Do you have an alternative that doesn't require linking ksh with
> curses?

Simply drop the idea of implementing clear-screen?

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Tomasz Rola
In reply to this post by Mark Kettenis
On Sat, Jun 16, 2018 at 02:50:40PM +0200, Mark Kettenis wrote:
[...]
>
> To e honest, I find the whole idea of invoking an external program to
> clear the screen insane.

Not necesarilly wanting to quarrel about this, but:

1. What would you say to someone who wants to run an old sh script
which employs exactly this method?

2. What am I supposed to use instead when I want to clear the screen
from the inside of newly written sh script, while (hopefully) staying
compatible with other systems (some of them old and non-upgradeable)?

The cost of running external program that only knows one thing and
knows it well is minimal, even more so on modern platforms. Additional
benefit is having to change only this one program if such a need
arises in a future.

Just my cent or two.

--
Regards,
Tomasz Rola

--
** A C programmer asked whether computer had Buddha's nature.      **
** As the answer, master did "rm -rif" on the programmer's home    **
** directory. And then the C programmer became enlightened...      **
**                                                                 **
** Tomasz Rola          mailto:[hidden email]             **

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Mark Kettenis
> Date: Sat, 16 Jun 2018 18:15:42 +0200
> From: Tomasz Rola <[hidden email]>
>
> On Sat, Jun 16, 2018 at 02:50:40PM +0200, Mark Kettenis wrote:
> [...]
> >
> > To e honest, I find the whole idea of invoking an external program to
> > clear the screen insane.
>
> Not necesarilly wanting to quarrel about this, but:
>
> 1. What would you say to someone who wants to run an old sh script
> which employs exactly this method?
>
> 2. What am I supposed to use instead when I want to clear the screen
> from the inside of newly written sh script, while (hopefully) staying
> compatible with other systems (some of them old and non-upgradeable)?
>
> The cost of running external program that only knows one thing and
> knows it well is minimal, even more so on modern platforms. Additional
> benefit is having to change only this one program if such a need
> arises in a future.
>
> Just my cent or two.

You're missing the point here.  Calling /usr/bin/clear to clear the
screen from one of your scripts is fone.  Doing so because you press a
certain key combination while at the shell prompt isn't.

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Tomasz Rola
On Sat, Jun 16, 2018 at 07:47:07PM +0200, Mark Kettenis wrote:
> > Date: Sat, 16 Jun 2018 18:15:42 +0200
> > From: Tomasz Rola <[hidden email]>
> >
[...]
> >
> > Just my cent or two.
>
> You're missing the point here.  Calling /usr/bin/clear to clear the
> screen from one of your scripts is fone.  Doing so because you press a
> certain key combination while at the shell prompt isn't.

Ok. I stand corrected.

--
Regards,
Tomasz Rola

--
** A C programmer asked whether computer had Buddha's nature.      **
** As the answer, master did "rm -rif" on the programmer's home    **
** directory. And then the C programmer became enlightened...      **
**                                                                 **
** Tomasz Rola          mailto:[hidden email]             **

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Sebastian Benoit-3
In reply to this post by Todd C. Miller-2

fwiw you can just use

bind -m '^L'=^Uclear'^J^Y'


Todd C. Miller([hidden email]) on 2018.06.16 06:37:03 -0600:

> On Tue, 12 Jun 2018 02:35:57 +0200, Alexander Hall wrote:
>
> > The diff below uses system(3) to call /usr/bin/clear, fiddling with
> > *env() to make sure the current TERM value is propagated. The error
> > handling is deliberately sparse, since I don't know what the reasonable
> > error actions would be.
> >
> > It's quite possible there already exists a better function to call
> > within the ksh code already, but I was unable to figure out which if so.
>
> Using system() within ksh seems wrong.  How about this instead?
>  
>  - todd
>
> 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 16 Jun 2018 12:31:59 -0000
> @@ -146,6 +146,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 +203,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 +1006,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 +1027,20 @@ x_redraw(int limit)
>   char *cp;
>  
>   x_adj_ok = 0;
> - if (limit == -1)
> + if (limit == -2) {
> + char *term = str_val(global("TERM"));
> + int ret = -1;
> + if (term && *term) {
> + Source *sold = source;
> + ret = command("/usr/bin/clear", 0);
> + source = sold;
> + }
> + if (ret != 0)
> + 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 16 Jun 2018 12:29:34 -0000
> @@ -4690,6 +4690,10 @@ 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:
> +Attempts to clears the screen by invoking
> +.Xr clear 1
> +and redraws the prompt and 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
>

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Il Ka
In reply to this post by Todd C. Miller-2
> alternative that doesn't require linking ksh with
> curses?

I'm curious, is it possible to use termcap/terminfo directly here?



--
Sent from: http://openbsd-archive.7691.n7.nabble.com/openbsd-dev-tech-f151936.html

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Alexander Hall
In reply to this post by Sebastian Benoit-3
Yeah, I've made such stuff, even which preserves the actual position on the command line, but I'm not too happy about screwing up the yank buffers...

On June 16, 2018 9:16:50 PM GMT+02:00, Sebastian Benoit <[hidden email]> wrote:

>
>fwiw you can just use
>
>bind -m '^L'=^Uclear'^J^Y'
>
>
>Todd C. Miller([hidden email]) on 2018.06.16 06:37:03 -0600:
>> On Tue, 12 Jun 2018 02:35:57 +0200, Alexander Hall wrote:
>>
>> > The diff below uses system(3) to call /usr/bin/clear, fiddling with
>
>> > *env() to make sure the current TERM value is propagated. The error
>
>> > handling is deliberately sparse, since I don't know what the
>reasonable
>> > error actions would be.
>> >
>> > It's quite possible there already exists a better function to call
>> > within the ksh code already, but I was unable to figure out which
>if so.
>>
>> Using system() within ksh seems wrong.  How about this instead?
>>  
>>  - todd
>>
>> 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 16 Jun 2018 12:31:59 -0000
>> @@ -146,6 +146,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 +203,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 +1006,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 +1027,20 @@ x_redraw(int limit)
>>   char *cp;
>>  
>>   x_adj_ok = 0;
>> - if (limit == -1)
>> + if (limit == -2) {
>> + char *term = str_val(global("TERM"));
>> + int ret = -1;
>> + if (term && *term) {
>> + Source *sold = source;
>> + ret = command("/usr/bin/clear", 0);
>> + source = sold;
>> + }
>> + if (ret != 0)
>> + 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 16 Jun 2018 12:29:34 -0000
>> @@ -4690,6 +4690,10 @@ 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:
>> +Attempts to clears the screen by invoking
>> +.Xr clear 1
>> +and redraws the prompt and 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
>>

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Todd C. Miller-2
In reply to this post by Mark Kettenis
On Sat, 16 Jun 2018 14:50:40 +0200, Mark Kettenis wrote:

> To be honest, I find the whole idea of invoking an external program to
> clear the screen insane.

Linking with curses doesn't increase the size a huge amount since
we just need to query terminfo.

text    data    bss     dec     hex
529120  12584   57024   598728  922c8   /bin/ksh
595671  21904   57024   674599  a4b27   ./obj/ksh

 - 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 16 Jun 2018 22:12:24 -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,23 @@ x_redraw(int limit)
  char *cp;
 
  x_adj_ok = 0;
- if (limit == -1)
+ if (limit == -2) {
+ int ret = -1;
+#ifndef SMALL
+ char *str, *term = str_val(global("TERM"));
+ if (term && *term) {
+ setupterm(term, 1, NULL);
+ str = tigetstr("clear");
+ if (str != NULL && str != (char *)-1)
+ ret = tputs(str, 1, x_putc) == ERR;
+ }
+#endif
+ if (ret != 0)
+ 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 16 Jun 2018 12:29:34 -0000
@@ -4690,6 +4690,10 @@ 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:
+Attempts to clears the screen by invoking
+.Xr clear 1
+and redraws the prompt and 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

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Todd C. Miller-2
In reply to this post by Alexander Hall
On Sat, 16 Jun 2018 16:16:57 -0600, "Todd C. Miller" wrote:

> On Sat, 16 Jun 2018 14:50:40 +0200, Mark Kettenis wrote:
>
> > To be honest, I find the whole idea of invoking an external program to
> > clear the screen insane.
>
> Linking with curses doesn't increase the size a huge amount since
> we just need to query terminfo.
>
> text    data    bss     dec     hex
> 529120  12584   57024   598728  922c8   /bin/ksh
> 595671  21904   57024   674599  a4b27   ./obj/ksh

Slightly simpler, we can use the clear_screen macro instead of looking
it up with tigetstr().

text    data    bss     dec     hex
529120  12584   57024   598728  922c8   /bin/ksh
594844  21888   57024   673756  a47dc   ./obj/ksh

 - todd

Index: Makefile
===================================================================
RCS file: /cvs/src/bin/ksh/Makefile,v
retrieving revision 1.38
diff -u -p -u -r1.38 Makefile
--- Makefile 6 Jan 2018 16:28:58 -0000 1.38
+++ 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: edit.c
===================================================================
RCS file: /cvs/src/bin/ksh/edit.c,v
retrieving revision 1.65
diff -u -p -u -r1.65 edit.c
--- edit.c 9 Apr 2018 17:53:36 -0000 1.65
+++ 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: edit.h
===================================================================
RCS file: /cvs/src/bin/ksh/edit.h,v
retrieving revision 1.11
diff -u -p -u -r1.11 edit.h
--- edit.h 26 Jan 2016 17:39:31 -0000 1.11
+++ 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: emacs.c
===================================================================
RCS file: /cvs/src/bin/ksh/emacs.c,v
retrieving revision 1.84
diff -u -p -u -r1.84 emacs.c
--- emacs.c 16 Jan 2018 17:17:18 -0000 1.84
+++ emacs.c 17 Jun 2018 13:58:36 -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,25 @@ x_redraw(int limit)
  char *cp;
 
  x_adj_ok = 0;
- if (limit == -1)
+ if (limit == -2) {
+ int cleared = 0;
+#ifndef SMALL
+ char *term = str_val(global("TERM"));
+ if (term && *term) {
+ int errret;
+ if (setupterm(term, 1, &errret) != ERR &&
+    clear_screen != NULL && *clear_screen != '\0') {
+ 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: ksh.1
===================================================================
RCS file: /cvs/src/bin/ksh/ksh.1,v
retrieving revision 1.200
diff -u -p -u -r1.200 ksh.1
--- ksh.1 30 May 2018 21:20:52 -0000 1.200
+++ ksh.1 16 Jun 2018 12:29:34 -0000
@@ -4690,6 +4690,10 @@ 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:
+Attempts to clears the screen by invoking
+.Xr clear 1
+and redraws the prompt and 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

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Mark Kettenis
> From: "Todd C. Miller" <[hidden email]>
> Date: Sun, 17 Jun 2018 09:00:17 -0600
>
> On Sat, 16 Jun 2018 16:16:57 -0600, "Todd C. Miller" wrote:
>
> > On Sat, 16 Jun 2018 14:50:40 +0200, Mark Kettenis wrote:
> >
> > > To be honest, I find the whole idea of invoking an external program to
> > > clear the screen insane.
> >
> > Linking with curses doesn't increase the size a huge amount since
> > we just need to query terminfo.
> >
> > text    data    bss     dec     hex
> > 529120  12584   57024   598728  922c8   /bin/ksh
> > 595671  21904   57024   674599  a4b27   ./obj/ksh
>
> Slightly simpler, we can use the clear_screen macro instead of looking
> it up with tigetstr().
>
> text    data    bss     dec     hex
> 529120  12584   57024   598728  922c8   /bin/ksh
> 594844  21888   57024   673756  a47dc   ./obj/ksh

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?  Probably
best to link against libterminfo to indicate that we don't really want
full-blown curses.

The man page needs to be adjusted now that you no longer call clear(1).

Cheers,

Mark

> Index: Makefile
> ===================================================================
> RCS file: /cvs/src/bin/ksh/Makefile,v
> retrieving revision 1.38
> diff -u -p -u -r1.38 Makefile
> --- Makefile 6 Jan 2018 16:28:58 -0000 1.38
> +++ 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: edit.c
> ===================================================================
> RCS file: /cvs/src/bin/ksh/edit.c,v
> retrieving revision 1.65
> diff -u -p -u -r1.65 edit.c
> --- edit.c 9 Apr 2018 17:53:36 -0000 1.65
> +++ 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: edit.h
> ===================================================================
> RCS file: /cvs/src/bin/ksh/edit.h,v
> retrieving revision 1.11
> diff -u -p -u -r1.11 edit.h
> --- edit.h 26 Jan 2016 17:39:31 -0000 1.11
> +++ 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: emacs.c
> ===================================================================
> RCS file: /cvs/src/bin/ksh/emacs.c,v
> retrieving revision 1.84
> diff -u -p -u -r1.84 emacs.c
> --- emacs.c 16 Jan 2018 17:17:18 -0000 1.84
> +++ emacs.c 17 Jun 2018 13:58:36 -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,25 @@ x_redraw(int limit)
>   char *cp;
>  
>   x_adj_ok = 0;
> - if (limit == -1)
> + if (limit == -2) {
> + int cleared = 0;
> +#ifndef SMALL
> + char *term = str_val(global("TERM"));
> + if (term && *term) {
> + int errret;
> + if (setupterm(term, 1, &errret) != ERR &&
> +    clear_screen != NULL && *clear_screen != '\0') {
> + 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: ksh.1
> ===================================================================
> RCS file: /cvs/src/bin/ksh/ksh.1,v
> retrieving revision 1.200
> diff -u -p -u -r1.200 ksh.1
> --- ksh.1 30 May 2018 21:20:52 -0000 1.200
> +++ ksh.1 16 Jun 2018 12:29:34 -0000
> @@ -4690,6 +4690,10 @@ 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:
> +Attempts to clears the screen by invoking
> +.Xr clear 1
> +and redraws the prompt and 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
>
>

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Todd C. Miller-2
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?  Probably
> best to link against libterminfo to indicate that we don't really want
> full-blown curses.

You really need to call setupterm() any time TERM is changed, not
just when the shell is started.  We could do that but I was trying
to keep things simple for now.  There is no longer a separate
libterminfo, it is all just libcurses.  Since ksh is statically
linked we only pull in the bits we need anyway.

> The man page needs to be adjusted now that you no longer call clear(1).

I will do that if we agree this is the way forward.

 - todd

Reply | Threaded
Open this post in threaded view
|

Re: ksh "clear-screen" editing command

Todd C. Miller-2
In reply to this post by Il Ka
On Sat, 16 Jun 2018 12:41:12 -0700, Il Ka wrote:

> > alternative that doesn't require linking ksh with
> > curses?
>
> I'm curious, is it possible to use termcap/terminfo directly here?

My recent diffs use the terminfo api rather than full-blown curses
but it is all the same library.

 - todd

123