Fix some aspects of globbing - in emacs mode at least.

echo ~<ESC><ESC> and $HOME<ESC><ESC> as well as ~/b<ESC><ESC> all
now expand correctly.
This commit is contained in:
sjg 2002-01-25 23:40:51 +00:00
parent bab1dc1428
commit 84412e9292
2 changed files with 75 additions and 9 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: edit.c,v 1.6 1999/11/02 22:06:45 jdolecek Exp $ */
/* $NetBSD: edit.c,v 1.7 2002/01/25 23:40:51 sjg Exp $ */
/*
* Command line editing - common code
@ -840,6 +840,40 @@ x_cf_glob(flags, buf, buflen, pos, startp, endp, wordsp, is_commandp)
return nwords;
}
static char *
find_match(const char *s, int have)
{
int want = 0;
int nest = 1;
int c;
switch (have) {
case '(': want = ')'; break;
case '{': want = '}'; break;
case '[': want = ']'; break;
case '\'':
case '"': want = have; break;
}
if (want == 0 || s == NULL)
return NULL;
while (nest > 0 && (c = *s)) {
if (c == '\\') {
s++;
s++;
continue;
}
if (c == want)
nest--;
else if (c == have)
nest++;
if (nest > 0)
s++;
}
return (nest == 0) ? (char *) s : NULL;
}
/* Given a string, copy it and possibly add a '*' to the end. The
* new string is returned.
*/
@ -859,19 +893,33 @@ add_glob(str, slen)
toglob[slen] = '\0';
/*
* If the pathname contains a wildcard (an unquoted '*',
* '?', or '[') or parameter expansion ('$'), or a ~username
* with no trailing slash, then it is globbed based on that
* value (i.e., without the appended '*').
* If the pathname contains a wildcard (an unquoted '*', '?',
* or '[') or parameter expansion ('$') with nothing following
* it, or a ~username with no trailing slash, then it is
* globbed based on that value (i.e., without the appended
* '*').
*/
for (s = toglob; *s; s++) {
if (*s == '\\' && s[1])
s++;
else if (*s == '*' || *s == '[' || *s == '?' || *s == '$'
else if (*s == '*' || *s == '[' || *s == '?'
|| (s[1] == '(' /*)*/ && strchr("*+?@!", *s)))
break;
else if (ISDIRSEP(*s))
saw_slash = TRUE;
else if (*s == '$') {
if (*++s == '{') {
char *cp;
if ((cp = find_match(&s[1], '{')))
s = ++cp;
}
if (*s)
s += strcspn(s,
".,/?-<>[]{}()'\";:\\|=+*&^%$#@!`~");
if (!*s)
return toglob;
}
}
if (!*s && (*toglob != '~' || saw_slash)) {
toglob[slen] = '*';

View File

@ -1,4 +1,4 @@
/* $NetBSD: emacs.c,v 1.10 1999/11/09 00:01:49 jdolecek Exp $ */
/* $NetBSD: emacs.c,v 1.11 2002/01/25 23:40:51 sjg Exp $ */
/*
* Emacs-like command line editing and history
@ -1768,6 +1768,17 @@ x_expand(c)
return KSTD;
}
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)
@ -1854,8 +1865,15 @@ do_complete(flags, type)
* space to the end...
*/
if (nwords == 1
&& !ISDIRSEP(words[0][nlen - 1]))
x_ins(space);
&& !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);
}
} else
x_e_putc(BEL);
}