• Completely overhaul prompt length calculation and

prompt display routines; make Emacs and Vi share
  code, permitting reducing of duplication and code
  removal as well as more consistent behaviour; put
  some common code into shared helper functions, too
• New x_adjust() logic (Emacs mode): when determining
  what portion of a line to render use a much more
  sophisticated algorithm and try to fill up ⅔ of the
  total screen width (with line and prompt both) also
  as wished from Steffen Daode Nurpmeso
This commit is contained in:
tg
2013-07-26 20:33:39 +00:00
parent 472bc350b5
commit 247e20c524
4 changed files with 96 additions and 108 deletions

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.624 2013/07/25 18:07:44 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.625 2013/07/26 20:33:35 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@ -31,7 +31,7 @@
# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD # http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R47 2013/07/25 @(#)MIRBSD KSH R47 2013/07/26
description: description:
Check version of shell. Check version of shell.
stdin: stdin:
@ -40,7 +40,7 @@ name: KSH_VERSION
category: shell:legacy-no category: shell:legacy-no
--- ---
expected-stdout: expected-stdout:
@(#)LEGACY KSH R47 2013/07/25 @(#)LEGACY KSH R47 2013/07/26
description: description:
Check version of legacy shell. Check version of legacy shell.
stdin: stdin:

157
edit.c
View File

@ -28,7 +28,7 @@
#ifndef MKSH_NO_CMDLINE_EDITING #ifndef MKSH_NO_CMDLINE_EDITING
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.267 2013/06/03 22:27:42 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.268 2013/07/26 20:33:37 tg Exp $");
/* /*
* in later versions we might use libtermcap for this, but since external * in later versions we might use libtermcap for this, but since external
@ -919,7 +919,6 @@ static bool x_adj_ok;
*/ */
static int x_adj_done; /* is incremented by x_adjust() */ static int x_adj_done; /* is incremented by x_adjust() */
static int x_col;
static int x_displen; static int x_displen;
static int x_arg; /* general purpose arg */ static int x_arg; /* general purpose arg */
static bool x_arg_defaulted; /* x_arg not explicitly set; defaulted to 1 */ static bool x_arg_defaulted; /* x_arg not explicitly set; defaulted to 1 */
@ -944,9 +943,6 @@ static int x_curprefix;
static char *macroptr; /* bind key macro active? */ static char *macroptr; /* bind key macro active? */
#endif #endif
#if !MKSH_S_NOVI #if !MKSH_S_NOVI
static int cur_col; /* current column on line */
static int pwidth; /* width of prompt */
static int prompt_trunc; /* how much of prompt to truncate */
static int winwidth; /* width of window */ static int winwidth; /* width of window */
static char *wbuf[2]; /* window buffers */ static char *wbuf[2]; /* window buffers */
static int wbuf_len; /* length of window buffers (x_cols - 3) */ static int wbuf_len; /* length of window buffers (x_cols - 3) */
@ -955,13 +951,16 @@ static char morec; /* more character at right of window */
static int lastref; /* argument to last refresh() */ static int lastref; /* argument to last refresh() */
static int holdlen; /* length of holdbuf */ static int holdlen; /* length of holdbuf */
#endif #endif
static bool prompt_redraw; /* false if newline forced after prompt */ static int pwidth; /* width of prompt */
static int prompt_trunc; /* how much of prompt to truncate or -1 */
static int x_col; /* current column on line */
static int x_ins(const char *); static int x_ins(const char *);
static void x_delete(size_t, bool); static void x_delete(size_t, bool);
static size_t x_bword(void); static size_t x_bword(void);
static size_t x_fword(bool); static size_t x_fword(bool);
static void x_goto(char *); static void x_goto(char *);
static char *x_bs0(char *, char *);
static void x_bs3(char **); static void x_bs3(char **);
static int x_size_str(char *); static int x_size_str(char *);
static int x_size2(char *, char **); static int x_size2(char *, char **);
@ -1170,20 +1169,14 @@ x_e_getmbc(char *sbuf)
static void static void
x_init_prompt(void) x_init_prompt(void)
{ {
x_col = promptlen(prompt); prompt_trunc = pprompt(prompt, 0);
x_adj_ok = true; pwidth = prompt_trunc % x_cols;
prompt_redraw = true; prompt_trunc -= pwidth;
if (x_col >= xx_cols) if ((mksh_uari_t)pwidth > ((mksh_uari_t)x_cols - 3 - MIN_EDIT_SPACE)) {
x_col %= xx_cols; /* force newline after prompt */
x_displen = xx_cols - 2 - x_col; prompt_trunc = -1;
x_adj_done = 0; pwidth = 0;
pprompt(prompt, 0);
if (x_displen < 1) {
x_col = 0;
x_displen = xx_cols - 2;
x_e_putc2('\n'); x_e_putc2('\n');
prompt_redraw = false;
} }
} }
@ -1202,8 +1195,10 @@ x_emacs(char *buf, size_t len)
x_histp = histptr + 1; x_histp = histptr + 1;
x_last_command = XFUNC_error; x_last_command = XFUNC_error;
xx_cols = x_cols;
x_init_prompt(); x_init_prompt();
x_displen = (xx_cols = x_cols) - 2 - (x_col = pwidth);
x_adj_done = 0;
x_adj_ok = true;
x_histncp = NULL; x_histncp = NULL;
if (x_nextcmd >= 0) { if (x_nextcmd >= 0) {
@ -1561,11 +1556,7 @@ x_fword(bool move)
static void static void
x_goto(char *cp) x_goto(char *cp)
{ {
if (cp >= xep) cp = cp >= xep ? xep : x_bs0(cp, xbuf);
cp = xep;
else if (UTFMODE)
while ((cp > xbuf) && ((*cp & 0xC0) == 0x80))
--cp;
if (cp < xbp || cp >= utf_skipcols(xbp, x_displen)) { if (cp < xbp || cp >= utf_skipcols(xbp, x_displen)) {
/* we are heading off screen */ /* we are heading off screen */
xcp = cp; xcp = cp;
@ -1581,16 +1572,22 @@ x_goto(char *cp)
} }
} }
static char *
x_bs0(char *cp, char *lower_bound)
{
if (UTFMODE)
while ((!lower_bound || (cp > lower_bound)) &&
((*(unsigned char *)cp & 0xC0) == 0x80))
--cp;
return (cp);
}
static void static void
x_bs3(char **p) x_bs3(char **p)
{ {
int i; int i;
(*p)--; *p = x_bs0((*p) - 1, NULL);
if (UTFMODE)
while (((unsigned char)**p & 0xC0) == 0x80)
(*p)--;
i = x_size2(*p, NULL); i = x_size2(*p, NULL);
while (i--) while (i--)
x_e_putc2('\b'); x_e_putc2('\b');
@ -2080,7 +2077,7 @@ x_cls(int c MKSH_A_UNUSED)
static void static void
x_redraw(int limit) x_redraw(int limit)
{ {
int i, j, x_trunc = 0; int i, j;
char *cp; char *cp;
x_adj_ok = false; x_adj_ok = false;
@ -2090,19 +2087,11 @@ x_redraw(int limit)
x_e_putc2('\r'); x_e_putc2('\r');
x_flush(); x_flush();
if (xbp == xbuf) { if (xbp == xbuf) {
x_col = promptlen(prompt); if (prompt_trunc != -1)
if (x_col >= xx_cols) pprompt(prompt, prompt_trunc);
x_trunc = (x_col / xx_cols) * xx_cols; x_col = pwidth;
if (prompt_redraw)
pprompt(prompt, x_trunc);
} }
if (x_col >= xx_cols)
x_col %= xx_cols;
x_displen = xx_cols - 2 - x_col; x_displen = xx_cols - 2 - x_col;
if (x_displen < 1) {
x_col = 0;
x_displen = xx_cols - 2;
}
xlp_valid = false; xlp_valid = false;
x_zots(xbp); x_zots(xbp);
if (xbp != xbuf || xep > xlp) if (xbp != xbuf || xep > xlp)
@ -2816,16 +2805,42 @@ do_complete(
static void static void
x_adjust(void) x_adjust(void)
{ {
/* flag the fact that we were called. */ int col_left, n;
/* flag the fact that we were called */
x_adj_done++; x_adj_done++;
/* /*
* we had a problem if the prompt length > xx_cols / 2 * calculate the amount of columns we need to "go back"
* from xcp to set xbp to (but never < xbuf) to 2/3 of
* the display width; take care of pwidth though
*/ */
if ((xbp = xcp - (x_displen / 2)) < xbuf) if ((col_left = xx_cols * 2 / 3) < MIN_EDIT_SPACE) {
xbp = xbuf; /*
if (UTFMODE) * cowardly refuse to do anything
while ((xbp > xbuf) && ((*xbp & 0xC0) == 0x80)) * if the available space is too small;
--xbp; * fall back to dumb pdksh code
*/
if ((xbp = xcp - (x_displen / 2)) < xbuf)
xbp = xbuf;
/* elide UTF-8 fixup as penalty */
goto x_adjust_out;
}
/* fix up xbp to character begin first */
xbp = x_bs0(xcp, xbuf);
/* walk backwards */
while (xbp > xbuf && col_left > 0) {
xbp = x_bs0(xbp - 1, xbuf);
col_left -= (n = x_size2(xbp, NULL));
}
/* check if we hit the prompt */
if (xbp == xbuf && xcp != xbuf && col_left > 0 && col_left < pwidth) {
/* so we did; force scrolling occurs */
xbp += utf_ptradj(xbp);
}
x_adjust_out:
xlp_valid = false; xlp_valid = false;
x_redraw(xx_cols); x_redraw(xx_cols);
x_flush(); x_flush();
@ -3517,18 +3532,8 @@ x_vi(char *buf, size_t len)
es->cursor = undo->cursor = 0; es->cursor = undo->cursor = 0;
es->winleft = undo->winleft = 0; es->winleft = undo->winleft = 0;
cur_col = promptlen(prompt); x_init_prompt();
prompt_trunc = (cur_col / x_cols) * x_cols; x_col = pwidth;
cur_col -= prompt_trunc;
pprompt(prompt, 0);
if ((mksh_uari_t)cur_col > (mksh_uari_t)x_cols - 3 - MIN_EDIT_SPACE) {
prompt_redraw = false;
cur_col = 0;
x_putc('\n');
} else
prompt_redraw = true;
pwidth = cur_col;
if (!wbuf_len || wbuf_len != x_cols - 3) { if (!wbuf_len || wbuf_len != x_cols - 3) {
wbuf_len = x_cols - 3; wbuf_len = x_cols - 3;
@ -5057,9 +5062,9 @@ redraw_line(bool newl)
x_putc('\r'); x_putc('\r');
x_putc('\n'); x_putc('\n');
} }
if (prompt_redraw) if (prompt_trunc != -1)
pprompt(prompt, prompt_trunc); pprompt(prompt, prompt_trunc);
cur_col = pwidth; x_col = pwidth;
morec = ' '; morec = ' ';
} }
@ -5177,10 +5182,10 @@ display(char *wb1, char *wb2, int leftside)
twb2 = wb2; twb2 = wb2;
while (cnt--) { while (cnt--) {
if (*twb1 != *twb2) { if (*twb1 != *twb2) {
if (cur_col != col) if (x_col != col)
ed_mov_opt(col, wb1); ed_mov_opt(col, wb1);
x_putc(*twb1); x_putc(*twb1);
cur_col++; x_col++;
} }
twb1++; twb1++;
twb2++; twb2++;
@ -5201,34 +5206,34 @@ display(char *wb1, char *wb2, int leftside)
if (mc != morec) { if (mc != morec) {
ed_mov_opt(pwidth + winwidth + 1, wb1); ed_mov_opt(pwidth + winwidth + 1, wb1);
x_putc(mc); x_putc(mc);
cur_col++; x_col++;
morec = mc; morec = mc;
} }
if (cur_col != ncol) if (x_col != ncol)
ed_mov_opt(ncol, wb1); ed_mov_opt(ncol, wb1);
} }
static void static void
ed_mov_opt(int col, char *wb) ed_mov_opt(int col, char *wb)
{ {
if (col < cur_col) { if (col < x_col) {
if (col + 1 < cur_col - col) { if (col + 1 < x_col - col) {
x_putc('\r'); x_putc('\r');
if (prompt_redraw) if (prompt_trunc != -1)
pprompt(prompt, prompt_trunc); pprompt(prompt, prompt_trunc);
cur_col = pwidth; x_col = pwidth;
while (cur_col++ < col) while (x_col++ < col)
x_putcf(*wb++); x_putcf(*wb++);
} else { } else {
while (cur_col-- > col) while (x_col-- > col)
x_putc('\b'); x_putc('\b');
} }
} else { } else {
wb = &wb[cur_col - pwidth]; wb = &wb[x_col - pwidth];
while (cur_col++ < col) while (x_col++ < col)
x_putcf(*wb++); x_putcf(*wb++);
} }
cur_col = col; x_col = col;
} }

30
lex.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.186 2013/06/01 00:15:57 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/lex.c,v 1.187 2013/07/26 20:33:38 tg Exp $");
/* /*
* states while lexing word * states while lexing word
@ -102,8 +102,6 @@ static void gethere(bool);
static Lex_state *push_state_i(State_info *, Lex_state *); static Lex_state *push_state_i(State_info *, Lex_state *);
static Lex_state *pop_state_i(State_info *, Lex_state *); static Lex_state *pop_state_i(State_info *, Lex_state *);
static int dopprompt(const char *, int, bool);
static int backslash_skip; static int backslash_skip;
static int ignore_backslash_newline; static int ignore_backslash_newline;
@ -1520,8 +1518,8 @@ set_prompt(int to, Source *s)
} }
} }
static int int
dopprompt(const char *cp, int ntruncate, bool doprint) pprompt(const char *cp, int ntruncate)
{ {
int columns = 0, lines = 0; int columns = 0, lines = 0;
bool indelimit = false; bool indelimit = false;
@ -1554,35 +1552,21 @@ dopprompt(const char *cp, int ntruncate, bool doprint)
else if (UTFMODE && ((unsigned char)*cp > 0x7F)) { else if (UTFMODE && ((unsigned char)*cp > 0x7F)) {
const char *cp2; const char *cp2;
columns += utf_widthadj(cp, &cp2); columns += utf_widthadj(cp, &cp2);
if (doprint && (indelimit || if (indelimit ||
(ntruncate < (x_cols * lines + columns)))) (ntruncate < (x_cols * lines + columns)))
shf_write(cp, cp2 - cp, shl_out); shf_write(cp, cp2 - cp, shl_out);
cp = cp2 - /* loop increment */ 1; cp = cp2 - /* loop increment */ 1;
continue; continue;
} else } else
columns++; columns++;
if (doprint && (*cp != delimiter) && if ((*cp != delimiter) &&
(indelimit || (ntruncate < (x_cols * lines + columns)))) (indelimit || (ntruncate < (x_cols * lines + columns))))
shf_putc(*cp, shl_out); shf_putc(*cp, shl_out);
} }
if (doprint) shf_flush(shl_out);
shf_flush(shl_out);
return (x_cols * lines + columns); return (x_cols * lines + columns);
} }
void
pprompt(const char *cp, int ntruncate)
{
dopprompt(cp, ntruncate, true);
}
int
promptlen(const char *cp)
{
return (dopprompt(cp, 0, false));
}
/* /*
* Read the variable part of a ${...} expression (i.e. up to but not * Read the variable part of a ${...} expression (i.e. up to but not
* including the :[-+?=#%] or close-brace). * including the :[-+?=#%] or close-brace).

11
sh.h
View File

@ -164,9 +164,9 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.662 2013/07/25 18:07:47 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.663 2013/07/26 20:33:39 tg Exp $");
#endif #endif
#define MKSH_VERSION "R47 2013/07/25" #define MKSH_VERSION "R47 2013/07/26"
/* arithmetic types: C implementation */ /* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES #if !HAVE_CAN_INTTYPES
@ -444,8 +444,6 @@ extern int wcwidth(__WCHAR_TYPE__);
#define MAGIC (7) /* prefix for *?[!{,} during expand */ #define MAGIC (7) /* prefix for *?[!{,} during expand */
#define ISMAGIC(c) ((unsigned char)(c) == MAGIC) #define ISMAGIC(c) ((unsigned char)(c) == MAGIC)
#define LINE 4096 /* input line size */
EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */ EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */
#ifdef MKSH_LEGACY_MODE #ifdef MKSH_LEGACY_MODE
@ -992,6 +990,8 @@ EXTERN uint32_t builtin_flag;
/* current working directory */ /* current working directory */
EXTERN char *current_wd; EXTERN char *current_wd;
/* input line size */
#define LINE 4096
/* /*
* Minimum required space to work with on a line - if the prompt leaves * Minimum required space to work with on a line - if the prompt leaves
* less space than this on a line, the prompt is truncated. * less space than this on a line, the prompt is truncated.
@ -1837,8 +1837,7 @@ void yyerror(const char *, ...)
MKSH_A_FORMAT(__printf__, 1, 2); MKSH_A_FORMAT(__printf__, 1, 2);
Source *pushs(int, Area *); Source *pushs(int, Area *);
void set_prompt(int, Source *); void set_prompt(int, Source *);
void pprompt(const char *, int); int pprompt(const char *, int);
int promptlen(const char *);
/* main.c */ /* main.c */
int include(const char *, int, const char **, bool); int include(const char *, int, const char **, bool);
int command(const char *, int); int command(const char *, int);