diff options
author | Camiel Dobbelaar <camield@cvs.openbsd.org> | 2001-02-19 09:49:55 +0000 |
---|---|---|
committer | Camiel Dobbelaar <camield@cvs.openbsd.org> | 2001-02-19 09:49:55 +0000 |
commit | 147724caa4166bbf864e69d7c6009148b51da7db (patch) | |
tree | b2581b725dcb21de1157fade3ca9cb9f23fd0d71 /bin/ksh | |
parent | df3bcfa4b92155daf478bb54bc1b87efa61f5b18 (diff) |
bash-like 'double-tab' completion
- bind TAB (^I) to complete-list by default
- complete-list now lists 'ls style' not 'menu style'
- complete-list first completes; if that does not work, it lists
- fix a memleak in emacs.c, do_complete
- completion now works after '=' (dd), and ':' (ssh) and ` (backtick)
- a command can now start with a subdir from the current dir
Diffstat (limited to 'bin/ksh')
-rw-r--r-- | bin/ksh/c_ksh.c | 4 | ||||
-rw-r--r-- | bin/ksh/edit.c | 20 | ||||
-rw-r--r-- | bin/ksh/emacs.c | 115 | ||||
-rw-r--r-- | bin/ksh/exec.c | 36 | ||||
-rw-r--r-- | bin/ksh/misc.c | 9 | ||||
-rw-r--r-- | bin/ksh/proto.h | 5 |
6 files changed, 94 insertions, 95 deletions
diff --git a/bin/ksh/c_ksh.c b/bin/ksh/c_ksh.c index 974d24611c2..0b6c600193a 100644 --- a/bin/ksh/c_ksh.c +++ b/bin/ksh/c_ksh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_ksh.c,v 1.13 2000/11/21 22:41:03 millert Exp $ */ +/* $OpenBSD: c_ksh.c,v 1.14 2001/02/19 09:49:50 camield 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; } diff --git a/bin/ksh/edit.c b/bin/ksh/edit.c index 6b383785f8b..8754d863721 100644 --- a/bin/ksh/edit.c +++ b/bin/ksh/edit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: edit.c,v 1.11 1999/11/14 22:04:02 d Exp $ */ +/* $OpenBSD: edit.c,v 1.12 2001/02/19 09:49:51 camield Exp $ */ /* * Command line editing - common code @@ -500,7 +500,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) @@ -533,7 +533,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() */ @@ -739,7 +739,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) @@ -779,7 +780,8 @@ x_locate_word(buf, buflen, pos, startp, is_commandp) /* Figure out if this is a command */ for (p = start - 1; p >= 0 && isspace(buf[p]); p--) ; - iscmd = p < 0 || strchr(";|&()", buf[p]); + iscmd = p < 0 || strchr(";|&()`", buf[p]); +#if 0 if (iscmd) { /* If command has a /, path, etc. is not searched; * only current directory is searched, which is just @@ -790,6 +792,7 @@ x_locate_word(buf, buflen, pos, startp, is_commandp) break; iscmd = p == end; } +#endif *is_commandp = iscmd; } @@ -981,6 +984,7 @@ glob_path(flags, pat, wp, path) { const char *sp, *p; char *xp; + int staterr; int pathlen; int patlen; int oldsize, newsize, i, j; @@ -1015,13 +1019,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, diff --git a/bin/ksh/emacs.c b/bin/ksh/emacs.c index 2ef3ce5732e..5864be51940 100644 --- a/bin/ksh/emacs.c +++ b/bin/ksh/emacs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: emacs.c,v 1.13 2000/01/24 03:12:12 millert Exp $ */ +/* $OpenBSD: emacs.c,v 1.14 2001/02/19 09:49:52 camield Exp $ */ /* * Emacs-like command line editing and history @@ -273,7 +273,7 @@ static struct x_defbindings const x_defbindings[] = { { XFUNC_transpose, 0, CTRL('T') }, #endif { XFUNC_complete, 1, CTRL('[') }, - { XFUNC_complete, 0, CTRL('I') }, + { XFUNC_comp_list, 0, CTRL('I') }, { XFUNC_comp_list, 1, '=' }, { XFUNC_enumerate, 1, '?' }, { XFUNC_expand, 1, '*' }, @@ -1776,92 +1776,51 @@ 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; - - 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, - &start, &end, &words, &is_command); + int completed = 0; + + 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_free_words(nwords, words); + return; + } - x_print_expansions(nwords, words, is_command); - xcp = xbuf + end; - x_do_ins(comp_word + olen, nlen - olen); - x_redraw(0); - } - break; + 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(olen, FALSE); + x_escape(words[0], nlen, x_emacs_putbuf); + x_adjust(); + completed = 1; + } + if ((nwords == 1) && (!ISDIRSEP(words[0][nlen - 1]))) { + x_ins(space); + completed = 1; + } - case CT_COMPLETE: - { - int nlen = x_longest_prefix(nwords, words); - - if (nlen > 0) { - x_goto(xbuf + start); - x_delete(end - start, 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])) - x_ins(space); - } else - x_e_putc(BEL); - } - 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: diff --git a/bin/ksh/exec.c b/bin/ksh/exec.c index 68443e8c521..ca696aa54bc 100644 --- a/bin/ksh/exec.c +++ b/bin/ksh/exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec.c,v 1.21 1999/07/15 20:35:33 millert Exp $ */ +/* $OpenBSD: exec.c,v 1.22 2001/02/19 09:49:52 camield Exp $ */ /* * execute command tree @@ -1595,7 +1595,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; } diff --git a/bin/ksh/misc.c b/bin/ksh/misc.c index 8ead4710d18..7de3ac2c98c 100644 --- a/bin/ksh/misc.c +++ b/bin/ksh/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.11 2000/06/28 20:36:37 mickey Exp $ */ +/* $OpenBSD: misc.c,v 1.12 2001/02/19 09:49:53 camield Exp $ */ /* * Miscellaneous functions @@ -244,7 +244,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; diff --git a/bin/ksh/proto.h b/bin/ksh/proto.h index 627a6f674ba..7a7c9a80dcb 100644 --- a/bin/ksh/proto.h +++ b/bin/ksh/proto.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proto.h,v 1.8 1999/07/14 13:37:24 millert Exp $ */ +/* $OpenBSD: proto.h,v 1.9 2001/02/19 09:49:54 camield Exp $ */ /* * prototypes for PD-KSH @@ -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)); @@ -200,7 +201,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)); |