• 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: 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 $
@ -31,7 +31,7 @@
# http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD
expected-stdout:
@(#)MIRBSD KSH R47 2013/07/25
@(#)MIRBSD KSH R47 2013/07/26
description:
Check version of shell.
stdin:
@ -40,7 +40,7 @@ name: KSH_VERSION
category: shell:legacy-no
---
expected-stdout:
@(#)LEGACY KSH R47 2013/07/25
@(#)LEGACY KSH R47 2013/07/26
description:
Check version of legacy shell.
stdin:

157
edit.c
View File

@ -28,7 +28,7 @@
#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
@ -919,7 +919,6 @@ static bool x_adj_ok;
*/
static int x_adj_done; /* is incremented by x_adjust() */
static int x_col;
static int x_displen;
static int x_arg; /* general purpose arg */
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? */
#endif
#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 char *wbuf[2]; /* window buffers */
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 holdlen; /* length of holdbuf */
#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 void x_delete(size_t, bool);
static size_t x_bword(void);
static size_t x_fword(bool);
static void x_goto(char *);
static char *x_bs0(char *, char *);
static void x_bs3(char **);
static int x_size_str(char *);
static int x_size2(char *, char **);
@ -1170,20 +1169,14 @@ x_e_getmbc(char *sbuf)
static void
x_init_prompt(void)
{
x_col = promptlen(prompt);
x_adj_ok = true;
prompt_redraw = true;
if (x_col >= xx_cols)
x_col %= xx_cols;
x_displen = xx_cols - 2 - x_col;
x_adj_done = 0;
pprompt(prompt, 0);
if (x_displen < 1) {
x_col = 0;
x_displen = xx_cols - 2;
prompt_trunc = pprompt(prompt, 0);
pwidth = prompt_trunc % x_cols;
prompt_trunc -= pwidth;
if ((mksh_uari_t)pwidth > ((mksh_uari_t)x_cols - 3 - MIN_EDIT_SPACE)) {
/* force newline after prompt */
prompt_trunc = -1;
pwidth = 0;
x_e_putc2('\n');
prompt_redraw = false;
}
}
@ -1202,8 +1195,10 @@ x_emacs(char *buf, size_t len)
x_histp = histptr + 1;
x_last_command = XFUNC_error;
xx_cols = x_cols;
x_init_prompt();
x_displen = (xx_cols = x_cols) - 2 - (x_col = pwidth);
x_adj_done = 0;
x_adj_ok = true;
x_histncp = NULL;
if (x_nextcmd >= 0) {
@ -1561,11 +1556,7 @@ x_fword(bool move)
static void
x_goto(char *cp)
{
if (cp >= xep)
cp = xep;
else if (UTFMODE)
while ((cp > xbuf) && ((*cp & 0xC0) == 0x80))
--cp;
cp = cp >= xep ? xep : x_bs0(cp, xbuf);
if (cp < xbp || cp >= utf_skipcols(xbp, x_displen)) {
/* we are heading off screen */
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
x_bs3(char **p)
{
int i;
(*p)--;
if (UTFMODE)
while (((unsigned char)**p & 0xC0) == 0x80)
(*p)--;
*p = x_bs0((*p) - 1, NULL);
i = x_size2(*p, NULL);
while (i--)
x_e_putc2('\b');
@ -2080,7 +2077,7 @@ x_cls(int c MKSH_A_UNUSED)
static void
x_redraw(int limit)
{
int i, j, x_trunc = 0;
int i, j;
char *cp;
x_adj_ok = false;
@ -2090,19 +2087,11 @@ x_redraw(int limit)
x_e_putc2('\r');
x_flush();
if (xbp == xbuf) {
x_col = promptlen(prompt);
if (x_col >= xx_cols)
x_trunc = (x_col / xx_cols) * xx_cols;
if (prompt_redraw)
pprompt(prompt, x_trunc);
if (prompt_trunc != -1)
pprompt(prompt, prompt_trunc);
x_col = pwidth;
}
if (x_col >= xx_cols)
x_col %= xx_cols;
x_displen = xx_cols - 2 - x_col;
if (x_displen < 1) {
x_col = 0;
x_displen = xx_cols - 2;
}
xlp_valid = false;
x_zots(xbp);
if (xbp != xbuf || xep > xlp)
@ -2816,16 +2805,42 @@ do_complete(
static 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++;
/*
* 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)
xbp = xbuf;
if (UTFMODE)
while ((xbp > xbuf) && ((*xbp & 0xC0) == 0x80))
--xbp;
if ((col_left = xx_cols * 2 / 3) < MIN_EDIT_SPACE) {
/*
* cowardly refuse to do anything
* if the available space is too small;
* 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;
x_redraw(xx_cols);
x_flush();
@ -3517,18 +3532,8 @@ x_vi(char *buf, size_t len)
es->cursor = undo->cursor = 0;
es->winleft = undo->winleft = 0;
cur_col = promptlen(prompt);
prompt_trunc = (cur_col / x_cols) * x_cols;
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;
x_init_prompt();
x_col = pwidth;
if (!wbuf_len || wbuf_len != x_cols - 3) {
wbuf_len = x_cols - 3;
@ -5057,9 +5062,9 @@ redraw_line(bool newl)
x_putc('\r');
x_putc('\n');
}
if (prompt_redraw)
if (prompt_trunc != -1)
pprompt(prompt, prompt_trunc);
cur_col = pwidth;
x_col = pwidth;
morec = ' ';
}
@ -5177,10 +5182,10 @@ display(char *wb1, char *wb2, int leftside)
twb2 = wb2;
while (cnt--) {
if (*twb1 != *twb2) {
if (cur_col != col)
if (x_col != col)
ed_mov_opt(col, wb1);
x_putc(*twb1);
cur_col++;
x_col++;
}
twb1++;
twb2++;
@ -5201,34 +5206,34 @@ display(char *wb1, char *wb2, int leftside)
if (mc != morec) {
ed_mov_opt(pwidth + winwidth + 1, wb1);
x_putc(mc);
cur_col++;
x_col++;
morec = mc;
}
if (cur_col != ncol)
if (x_col != ncol)
ed_mov_opt(ncol, wb1);
}
static void
ed_mov_opt(int col, char *wb)
{
if (col < cur_col) {
if (col + 1 < cur_col - col) {
if (col < x_col) {
if (col + 1 < x_col - col) {
x_putc('\r');
if (prompt_redraw)
if (prompt_trunc != -1)
pprompt(prompt, prompt_trunc);
cur_col = pwidth;
while (cur_col++ < col)
x_col = pwidth;
while (x_col++ < col)
x_putcf(*wb++);
} else {
while (cur_col-- > col)
while (x_col-- > col)
x_putc('\b');
}
} else {
wb = &wb[cur_col - pwidth];
while (cur_col++ < col)
wb = &wb[x_col - pwidth];
while (x_col++ < col)
x_putcf(*wb++);
}
cur_col = col;
x_col = col;
}

30
lex.c
View File

@ -23,7 +23,7 @@
#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
@ -102,8 +102,6 @@ static void gethere(bool);
static Lex_state *push_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 ignore_backslash_newline;
@ -1520,8 +1518,8 @@ set_prompt(int to, Source *s)
}
}
static int
dopprompt(const char *cp, int ntruncate, bool doprint)
int
pprompt(const char *cp, int ntruncate)
{
int columns = 0, lines = 0;
bool indelimit = false;
@ -1554,35 +1552,21 @@ dopprompt(const char *cp, int ntruncate, bool doprint)
else if (UTFMODE && ((unsigned char)*cp > 0x7F)) {
const char *cp2;
columns += utf_widthadj(cp, &cp2);
if (doprint && (indelimit ||
(ntruncate < (x_cols * lines + columns))))
if (indelimit ||
(ntruncate < (x_cols * lines + columns)))
shf_write(cp, cp2 - cp, shl_out);
cp = cp2 - /* loop increment */ 1;
continue;
} else
columns++;
if (doprint && (*cp != delimiter) &&
if ((*cp != delimiter) &&
(indelimit || (ntruncate < (x_cols * lines + columns))))
shf_putc(*cp, shl_out);
}
if (doprint)
shf_flush(shl_out);
shf_flush(shl_out);
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
* including the :[-+?=#%] or close-brace).

11
sh.h
View File

@ -164,9 +164,9 @@
#endif
#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
#define MKSH_VERSION "R47 2013/07/25"
#define MKSH_VERSION "R47 2013/07/26"
/* arithmetic types: C implementation */
#if !HAVE_CAN_INTTYPES
@ -444,8 +444,6 @@ extern int wcwidth(__WCHAR_TYPE__);
#define MAGIC (7) /* prefix for *?[!{,} during expand */
#define ISMAGIC(c) ((unsigned char)(c) == MAGIC)
#define LINE 4096 /* input line size */
EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */
#ifdef MKSH_LEGACY_MODE
@ -992,6 +990,8 @@ EXTERN uint32_t builtin_flag;
/* current working directory */
EXTERN char *current_wd;
/* input line size */
#define LINE 4096
/*
* Minimum required space to work with on a line - if the prompt leaves
* 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);
Source *pushs(int, Area *);
void set_prompt(int, Source *);
void pprompt(const char *, int);
int promptlen(const char *);
int pprompt(const char *, int);
/* main.c */
int include(const char *, int, const char **, bool);
int command(const char *, int);