change complete-list to first complete and then print a list,

also complete after '=' (dd), and ':' (ssh) and ` (backtick)
improvements from camield@openbsd.org.  approved by perry and thorpej.
This commit is contained in:
provos 2002-09-25 02:41:11 +00:00
parent de1af2db11
commit f9b44bb190
6 changed files with 92 additions and 113 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: c_ksh.c,v 1.6 2001/06/11 01:50:48 wiz Exp $ */
/* $NetBSD: c_ksh.c,v 1.7 2002/09/25 02:41:11 provos Exp $ */
/*
* built-in Korn commands: c_*
@ -1264,7 +1264,7 @@ c_kill(wp)
print_columns(shl_stdout, SIGNALS - 1,
kill_fmt_entry, (void *) &ki,
ki.num_width + ki.name_width + mess_width + 3);
ki.num_width + ki.name_width + mess_width + 3, 1);
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: edit.c,v 1.7 2002/01/25 23:40:51 sjg Exp $ */
/* $NetBSD: edit.c,v 1.8 2002/09/25 02:41:11 provos Exp $ */
/*
* Command line editing - common code
@ -501,7 +501,7 @@ x_print_expansions(nwords, words, is_command)
XPtrV l;
/* Check if all matches are in the same directory (in this
* case, we want to omitt the directory name)
* case, we want to omit the directory name)
*/
if (!is_command
&& (prefix_len = x_longest_prefix(nwords, words)) > 0)
@ -534,7 +534,7 @@ x_print_expansions(nwords, words, is_command)
*/
x_putc('\r');
x_putc('\n');
pr_menu(use_copy ? (char **) XPptrv(l) : words);
pr_list(use_copy ? (char **) XPptrv(l) : words);
if (use_copy)
XPfree(l); /* not x_free_words() */
@ -740,7 +740,8 @@ x_command_glob(flags, str, slen, wordsp)
return nwords;
}
#define IS_WORDC(c) !(ctype(c, C_LEX1) || (c) == '\'' || (c) == '"')
#define IS_WORDC(c) !( ctype(c, C_LEX1) || (c) == '\'' || (c) == '"' \
|| (c) == '`' || (c) == '=' || (c) == ':' )
static int
x_locate_word(buf, buflen, pos, startp, is_commandp)
@ -780,7 +781,7 @@ x_locate_word(buf, buflen, pos, startp, is_commandp)
/* Figure out if this is a command */
for (p = start - 1; p >= 0 && isspace((unsigned char)buf[p]); p--)
;
iscmd = p < 0 || strchr(";|&()", buf[p]);
iscmd = p < 0 || strchr(";|&()`", buf[p]);
if (iscmd) {
/* If command has a /, path, etc. is not searched;
* only current directory is searched, which is just
@ -1030,6 +1031,7 @@ glob_path(flags, pat, wp, path)
{
const char *sp, *p;
char *xp;
int staterr;
int pathlen;
int patlen;
int oldsize, newsize, i, j;
@ -1064,13 +1066,15 @@ glob_path(flags, pat, wp, path)
memcpy(xp, pat, patlen);
oldsize = XPsize(*wp);
glob_str(Xstring(xs, xp), wp, 0);
glob_str(Xstring(xs, xp), wp, 1); /* mark dirs */
newsize = XPsize(*wp);
/* Check that each match is executable... */
words = (char **) XPptrv(*wp);
for (i = j = oldsize; i < newsize; i++) {
if (search_access(words[i], X_OK, (int *) 0) >= 0) {
staterr = 0;
if ((search_access(words[i], X_OK, &staterr) >= 0)
|| (staterr == EISDIR)) {
words[j] = words[i];
if (!(flags & XCF_FULLPATH))
memmove(words[j], words[j] + pathlen,

View File

@ -1,4 +1,4 @@
/* $NetBSD: emacs.c,v 1.11 2002/01/25 23:40:51 sjg Exp $ */
/* $NetBSD: emacs.c,v 1.12 2002/09/25 02:41:11 provos Exp $ */
/*
* Emacs-like command line editing and history
@ -1769,16 +1769,6 @@ x_expand(c)
}
static int
is_dir(const char *path)
{
struct stat st;
if (stat(path, &st) == 0)
return S_ISDIR(st.st_mode);
return 0;
}
/* type == 0 for list, 1 for complete and 2 for complete-list */
static void
do_complete(flags, type)
@ -1786,99 +1776,50 @@ do_complete(flags, type)
Comp_type type;
{
char **words;
int nwords = 0;
int start, end;
int nwords;
int start, end, nlen, olen;
int is_command;
int do_glob = 1;
Comp_type t = type;
char *comp_word = (char *) 0;
int completed = 0;
if (type == CT_COMPLIST) {
do_glob = 0;
/* decide what we will do */
nwords = x_cf_glob(flags,
xbuf, xep - xbuf, xcp - xbuf,
&start, &end, &words, &is_command);
if (nwords > 0) {
if (nwords > 1) {
int len = x_longest_prefix(nwords, words);
t = CT_LIST;
/* Do completion if prefix matches original
* prefix (ie, no globbing chars), otherwise
* don't bother
*/
if (strncmp(words[0], xbuf + start, end - start)
== 0)
comp_word = str_nsave(words[0], len,
ATEMP);
else
type = CT_LIST;
/* Redo globing to show full paths if this
* is a command.
*/
if (is_command) {
do_glob = 1;
x_free_words(nwords, words);
}
} else
type = t = CT_COMPLETE;
}
}
if (do_glob)
nwords = x_cf_glob(flags | (t == CT_LIST ? XCF_FULLPATH : 0),
xbuf, xep - xbuf, xcp - xbuf,
nwords = x_cf_glob(flags, xbuf, xep - xbuf, xcp - xbuf,
&start, &end, &words, &is_command);
/* no match */
if (nwords == 0) {
x_e_putc(BEL);
return;
}
switch (type) {
case CT_LIST:
if (type == CT_LIST) {
x_print_expansions(nwords, words, is_command);
x_redraw(0);
break;
case CT_COMPLIST:
/* Only get here if nwords > 1 && comp_word is set */
{
int olen = end - start;
int nlen = strlen(comp_word);
x_print_expansions(nwords, words, is_command);
xcp = xbuf + end;
x_escape(comp_word + olen, nlen - olen, x_emacs_putbuf);
x_redraw(0);
x_free_words(nwords, words);
}
break;
case CT_COMPLETE:
{
int nlen = x_longest_prefix(nwords, words);
if (nlen > 0) {
olen = end - start;
nlen = x_longest_prefix(nwords, words);
/* complete single match, or multi-match without globbing chars */
if ((nlen > olen) &&
((nwords == 1) || (strncmp(words[0], xbuf + start, olen) == 0))) {
x_goto(xbuf + start);
x_delete(end - start, FALSE);
x_delete(olen, FALSE);
x_escape(words[0], nlen, x_emacs_putbuf);
x_adjust();
/* If single match is not a directory, add a
* space to the end...
*/
if (nwords == 1
&& !ISDIRSEP(words[0][nlen - 1])) {
/*
* we may be here because we
* just expanded $HOME in
* which case adding '/' is
* correct.
*/
x_ins(is_dir(words[0]) ? slash : space);
completed = 1;
}
} else
x_e_putc(BEL);
if ((nwords == 1) && (!ISDIRSEP(words[0][nlen - 1]))) {
x_ins(space);
completed = 1;
}
break;
if (type == CT_COMPLIST && !completed) {
x_print_expansions(nwords, words, is_command);
completed = 1;
}
if (completed)
x_redraw(0);
x_free_words(nwords, words);
}
/* NAME:

View File

@ -1,4 +1,4 @@
/* $NetBSD: exec.c,v 1.6 2001/09/29 15:05:47 wiz Exp $ */
/* $NetBSD: exec.c,v 1.7 2002/09/25 02:41:11 provos Exp $ */
/*
* execute command tree
@ -1598,7 +1598,39 @@ pr_menu(ap)
smi.arg_width = nwidth;
smi.num_width = dwidth;
print_columns(shl_out, n, select_fmt_entry, (void *) &smi,
dwidth + nwidth + 2);
dwidth + nwidth + 2, 1);
return n;
}
/* XXX: horrible kludge to fit within the framework */
static char *plain_fmt_entry ARGS((void *arg, int i, char *buf, int buflen));
static char *
plain_fmt_entry(arg, i, buf, buflen)
void *arg;
int i;
char *buf;
int buflen;
{
shf_snprintf(buf, buflen, "%s", ((char *const *)arg)[i]);
return buf;
}
int
pr_list(ap)
char *const *ap;
{
char *const *pp;
int nwidth;
int i, n;
for (n = 0, nwidth = 0, pp = ap; *pp; n++, pp++) {
i = strlen(*pp);
nwidth = (i > nwidth) ? i : nwidth;
}
print_columns(shl_out, n, plain_fmt_entry, (void *) ap, nwidth + 1, 0);
return n;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: misc.c,v 1.5 2001/02/04 19:26:04 christos Exp $ */
/* $NetBSD: misc.c,v 1.6 2002/09/25 02:41:11 provos Exp $ */
/*
* Miscellaneous functions
@ -243,7 +243,7 @@ printoptions(verbose)
oi.opt_width = len;
}
print_columns(shl_stdout, n, options_fmt_entry, &oi,
oi.opt_width + 5);
oi.opt_width + 5, 1);
} else {
/* short version ala ksh93 */
shprintf("set");
@ -1090,12 +1090,13 @@ print_value_quoted(s)
* element
*/
void
print_columns(shf, n, func, arg, max_width)
print_columns(shf, n, func, arg, max_width, prefcol)
struct shf *shf;
int n;
char *(*func) ARGS((void *, int, char *, int));
void *arg;
int max_width;
int prefcol;
{
char *str = (char *) alloc(max_width + 1, ATEMP);
int i;
@ -1111,7 +1112,7 @@ print_columns(shf, n, func, arg, max_width)
if (!cols)
cols = 1;
rows = (n + cols - 1) / cols;
if (n && cols > rows) {
if (prefcol && n && cols > rows) {
int tmp = rows;
rows = cols;

View File

@ -1,9 +1,9 @@
/* $NetBSD: proto.h,v 1.4 1999/10/20 15:10:00 hubertf Exp $ */
/* $NetBSD: proto.h,v 1.5 2002/09/25 02:41:11 provos Exp $ */
/*
* prototypes for PD-KSH
* originally generated using "cproto.c 3.5 92/04/11 19:28:01 cthuang "
* $Id: proto.h,v 1.4 1999/10/20 15:10:00 hubertf Exp $
* $Id: proto.h,v 1.5 2002/09/25 02:41:11 provos Exp $
*/
/* alloc.c */
@ -78,6 +78,7 @@ char * search ARGS((const char *name, const char *path, int mode,
int *errnop));
int search_access ARGS((const char *path, int mode, int *errnop));
int pr_menu ARGS((char *const *ap));
int pr_list ARGS((char *const *ap));
/* expr.c */
int evaluate ARGS((const char *expr, long *rval, int error_ok));
int v_evaluate ARGS((struct tbl *vp, const char *expr, volatile int error_ok));
@ -199,7 +200,7 @@ int ksh_getopt ARGS((char **argv, Getopt *go, const char *options));
void print_value_quoted ARGS((const char *s));
void print_columns ARGS((struct shf *shf, int n,
char *(*func)(void *, int, char *, int),
void *arg, int max_width));
void *arg, int max_width, int prefcol));
int strip_nuls ARGS((char *buf, int nbytes));
char *str_zcpy ARGS((char *dst, const char *src, int dsize));
int blocking_read ARGS((int fd, char *buf, int nbytes));