second attempt at getting '$FOO/b*r/baz' tab-completed right,

plus the beginning of the tilde fix… do not use, this is fucking
impossible to get right, but I’d like an archival commit
This commit is contained in:
tg 2012-08-24 20:57:46 +00:00
parent 2ed6e8998c
commit 42ac0dc08e
3 changed files with 51 additions and 28 deletions

65
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.248 2012/08/24 20:05:11 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.249 2012/08/24 20:57:44 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
@ -61,8 +61,7 @@ static X_chars edchars;
#define XCF_FULLPATH BIT(2) /* command completion: store full path */ #define XCF_FULLPATH BIT(2) /* command completion: store full path */
#define XCF_COMMAND_FILE (XCF_COMMAND | XCF_FILE) #define XCF_COMMAND_FILE (XCF_COMMAND | XCF_FILE)
#define XCF_IS_COMMAND BIT(3) /* return flag: is command */ #define XCF_IS_COMMAND BIT(3) /* return flag: is command */
#define XCF_IS_SUBST BIT(4) /* return flag: is $FOO substitution */ #define XCF_IS_NOSPACE BIT(4) /* return flag: do not append a space */
#define XCF_IS_NOSPACE BIT(5) /* return flag: do not append a space */
static char editmode; static char editmode;
static int xx_cols; /* for Emacs mode */ static int xx_cols; /* for Emacs mode */
@ -378,8 +377,9 @@ x_file_glob(int *flagsp, char *toglob, char ***wordsp)
nwords = DOGLOB | DOTILDE | DOMARKDIRS; nwords = DOGLOB | DOTILDE | DOMARKDIRS;
if (*cp != EOS) { if (*cp != EOS) {
/* probably a $FOO expansion */ /* probably a $FOO expansion */
nwords = DOKEEPQUOTE; *flagsp |= XCF_IS_NOSPACE;
*flagsp |= XCF_IS_SUBST | XCF_IS_NOSPACE; /* this always results in at most one match */
nwords = DOKEEPQCHAR;
} }
expand(yylval.cp, &w, nwords); expand(yylval.cp, &w, nwords);
XPput(w, NULL); XPput(w, NULL);
@ -601,18 +601,23 @@ x_cf_glob(int *flagsp, const char *buf, int buflen, int pos, int *startp,
/* /*
* If the pathname contains a wildcard (an unquoted '*', * If the pathname contains a wildcard (an unquoted '*',
* '?', or '[') or an extglob, then it is globbed based * '?', or '[') or an extglob, then it is globbed based
* on that value (i.e., without the appended '*'). * on that value (i.e., without the appended '*'). Same
* for parameter substitutions (as in cat $HOME/.ss)
* without appending a trailing space (LP: #710539), as
* well as for ~foo (but not ~foo/).
*/ */
for (s = toglob; *s; s++) { for (s = toglob; *s; s++) {
if (*s == '\\' && s[1]) if (*s == '\\' && s[1])
s++; s++;
else if (*s == '?' || *s == '*' || *s == '[' || else if (*s == '?' || *s == '*' || *s == '[' ||
/* also skip this for variable expansion */
*s == '$' || *s == '$' ||
/* ?() *() +() @() !() but two already checked */ /* ?() *() +() @() !() but two already checked */
(s[1] == '(' /*)*/ && (s[1] == '(' /*)*/ &&
(*s == '+' || *s == '@' || *s == '!'))) { (*s == '+' || *s == '@' || *s == '!'))) {
/* just expand based on the extglob */ /*
* just expand based on the extglob
* or parameter
*/
goto dont_add_glob; goto dont_add_glob;
} }
} }
@ -807,20 +812,24 @@ glob_path(int flags, const char *pat, XPtrV *wp, const char *lpath)
static int static int
x_escape(const char *s, size_t len, int (*putbuf_func)(const char *, size_t)) x_escape(const char *s, size_t len, int (*putbuf_func)(const char *, size_t))
{ {
char ch;
size_t add = 0, wlen = len; size_t add = 0, wlen = len;
const char *ifs = str_val(local("IFS", 0)); const char *ifs = str_val(local("IFS", 0));
int rval = 0; int rval = 0;
while (wlen - add > 0) while (wlen - add > 0) {
if (vstrchr("\"#$&'()*:;<=>?[\\`{|}", s[add]) || ch = s[add];
vstrchr(ifs, s[add])) { if (vstrchr("\"#$&'()*:;<=>?[\\`{|}", ch) ||
ch == QCHAR || vstrchr(ifs, ch)) {
if (putbuf_func(s, add) != 0) { if (putbuf_func(s, add) != 0) {
rval = -1; rval = -1;
break; break;
} }
putbuf_func(s[add] == '\n' ? "'" : "\\", 1); putbuf_func(ch == '\n' ? "'" : "\\", 1);
if (ch == QCHAR)
++add;
putbuf_func(&s[add], 1); putbuf_func(&s[add], 1);
if (s[add] == '\n') if (ch == '\n')
putbuf_func("'", 1); putbuf_func("'", 1);
add++; add++;
@ -829,6 +838,7 @@ x_escape(const char *s, size_t len, int (*putbuf_func)(const char *, size_t))
add = 0; add = 0;
} else } else
++add; ++add;
}
if (wlen > 0 && rval == 0) if (wlen > 0 && rval == 0)
rval = putbuf_func(s, wlen); rval = putbuf_func(s, wlen);
@ -2748,17 +2758,33 @@ do_complete(
} }
olen = end - start; olen = end - start;
nlen = x_longest_prefix(nwords, words); nlen = x_longest_prefix(nwords, words);
if (nwords == 1 || (flags & XCF_IS_SUBST)) { if (nwords == 1) {
/* /*
* always complete the expansion of parameter and * always complete single matches;
* homedir substitution as well as single matches * any expansion of parameter substitution
* is always at most one result, too
*/ */
completed = true; completed = true;
} else { } else {
char *unescaped; char *unescaped;
/* make a copy of the original string part and... */ /* make a copy of the original string part */
strndupx(unescaped, xbuf + start, olen, ATEMP); strndupx(unescaped, xbuf + start, olen, ATEMP);
if (*unescaped == '~') {
/*
* do some tilde expansion; we know at this
* point (by means of having nwords > 1) that
* the string looke like "~foo/bar"
*/
char *cp, *dp;
cp = ucstrchr(unescaped + 1, '/');
*cp++ = 0;
if ((dp = tilde(unescaped + 1))) {
/* got a match */
}
}
/* ... convert it from backslash-escaped via QCHAR-escaped... */ /* ... convert it from backslash-escaped via QCHAR-escaped... */
x_glob_hlp_add_qchar(unescaped); x_glob_hlp_add_qchar(unescaped);
/* ... to unescaped, for comparison with the matches */ /* ... to unescaped, for comparison with the matches */
@ -2786,10 +2812,7 @@ do_complete(
xcp = xbuf + start; xcp = xbuf + start;
xep -= olen; xep -= olen;
memmove(xcp, xcp + olen, xep - xcp + 1); memmove(xcp, xcp + olen, xep - xcp + 1);
if (flags & XCF_IS_SUBST) x_escape(words[0], nlen, x_do_ins);
x_do_ins(words[0], nlen);
else
x_escape(words[0], nlen, x_do_ins);
} }
x_adjust(); x_adjust();
/* /*

9
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.126 2012/08/24 20:05:13 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.127 2012/08/24 20:57:45 tg Exp $");
/* /*
* string expansion * string expansion
@ -63,7 +63,6 @@ static char *trimsub(char *, char *, int);
static void glob(char *, XPtrV *, bool); static void glob(char *, XPtrV *, bool);
static void globit(XString *, char **, char *, XPtrV *, int); static void globit(XString *, char **, char *, XPtrV *, int);
static const char *maybe_expand_tilde(const char *, XString *, char **, int); static const char *maybe_expand_tilde(const char *, XString *, char **, int);
static char *tilde(char *);
#ifndef MKSH_NOPWNAM #ifndef MKSH_NOPWNAM
static char *homedir(char *); static char *homedir(char *);
#endif #endif
@ -1012,8 +1011,8 @@ expand(const char *cp, /* input word */
else { else {
/* undo temporary */ /* undo temporary */
quote &= ~2; quote &= ~2;
if (f & DOKEEPQUOTE) if (f & DOKEEPQCHAR)
*dp++ = '\\'; *dp++ = QCHAR;
} }
if (make_magic) { if (make_magic) {
@ -1642,7 +1641,7 @@ maybe_expand_tilde(const char *p, XString *dsp, char **dpp, int isassign)
* based on a version by Arnold Robbins * based on a version by Arnold Robbins
*/ */
static char * char *
tilde(char *cp) tilde(char *cp)
{ {
char *dp = null; char *dp = null;

5
sh.h
View File

@ -157,7 +157,7 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.581 2012/08/24 20:05:13 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.582 2012/08/24 20:57:46 tg Exp $");
#endif #endif
#define MKSH_VERSION "R40 2012/08/17" #define MKSH_VERSION "R40 2012/08/17"
@ -1343,7 +1343,7 @@ struct ioword {
#define DOTEMP BIT(8) /* dito: in word part of ${..[%#=?]..} */ #define DOTEMP BIT(8) /* dito: in word part of ${..[%#=?]..} */
#define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */ #define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */
#define DOMARKDIRS BIT(10) /* force markdirs behaviour */ #define DOMARKDIRS BIT(10) /* force markdirs behaviour */
#define DOKEEPQUOTE BIT(11) /* internal use by globbing code */ #define DOKEEPQCHAR BIT(11) /* internal use by globbing code */
/* /*
* The arguments of [[ .. ]] expressions are kept in t->args[] and flags * The arguments of [[ .. ]] expressions are kept in t->args[] and flags
@ -1635,6 +1635,7 @@ char *evalonestr(const char *cp, int);
char *debunk(char *, const char *, size_t); char *debunk(char *, const char *, size_t);
void expand(const char *, XPtrV *, int); void expand(const char *, XPtrV *, int);
int glob_str(char *, XPtrV *, bool); int glob_str(char *, XPtrV *, bool);
char *tilde(char *);
/* exec.c */ /* exec.c */
int execute(struct op * volatile, volatile int, volatile int * volatile); int execute(struct op * volatile, volatile int, volatile int * volatile);
int shcomexec(const char **); int shcomexec(const char **);