summaryrefslogtreecommitdiff
path: root/Src/Zle/computil.c
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2000-06-19 09:32:30 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2000-06-19 09:32:30 +0000
commit2769b198812abf82cc3b074852714959213f266a (patch)
tree9e04e9f98e6974108c8e8e6511f29df62ff56bcb /Src/Zle/computil.c
parent207758992aed766b96e511bf067b6505c9e783cd (diff)
downloadzsh-2769b198812abf82cc3b074852714959213f266a.tar.gz
zsh-2769b198812abf82cc3b074852714959213f266a.zip
improve filename completion; use accept-exact for in-path completion; new fake style (11971)
Diffstat (limited to 'Src/Zle/computil.c')
-rw-r--r--Src/Zle/computil.c203
1 files changed, 183 insertions, 20 deletions
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index 51a1f61aa..3955ed69d 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -3058,17 +3058,37 @@ bin_compfmt(char *nam, char **args, char *ops, int func)
#define PATH_MAX2 (PATH_MAX * 2)
static LinkList
-cfp_test_exact(LinkList names, char *skipped)
+cfp_test_exact(LinkList names, char **accept, char *skipped)
{
char buf[PATH_MAX2 + 1], *suf, *p;
int l, sl, found = 0;
struct stat st;
LinkNode node;
- LinkList ret = newlinklist();
+ LinkList ret = newlinklist(), alist = NULL;
- if (!(compprefix && *compprefix) && !(compsuffix && *compsuffix))
+ if ((!(compprefix && *compprefix) && !(compsuffix && *compsuffix)) ||
+ (!accept || !*accept ||
+ ((!strcmp(*accept, "false") || !strcmp(*accept, "no") ||
+ !strcmp(*accept, "off") || !strcmp(*accept, "0")) && !accept[1])))
return NULL;
+ if (accept[1] ||
+ (strcmp(*accept, "true") && strcmp(*accept, "yes") &&
+ strcmp(*accept, "on") && strcmp(*accept, "1"))) {
+ Patprog prog;
+
+ alist = newlinklist();
+
+ for (; (p = *accept); accept++) {
+ if (*p == '*' && !p[1]) {
+ alist = NULL;
+ break;
+ }
+ tokenize(p = dupstring(p));
+ if ((prog = patcompile(p, 0, NULL)))
+ addlinknode(alist, prog);
+ }
+ }
sl = strlen(skipped) + (compprefix ? strlen(compprefix) : 0) +
(compsuffix ? strlen(compsuffix) : 0);
@@ -3078,11 +3098,22 @@ cfp_test_exact(LinkList names, char *skipped)
suf = dyncat(skipped, rembslash(dyncat(compprefix, compsuffix)));
for (node = firstnode(names); node; incnode(node)) {
- if ((l = strlen(p = (char *) getdata(node))) && l + sl < PATH_MAX2) {
+ l = strlen(p = (char *) getdata(node));
+ if (l + sl < PATH_MAX2) {
strcpy(buf, p);
strcpy(buf + l, suf);
- if (!ztat(buf, &st, 0) && S_ISDIR(st.st_mode)) {
+ if (!ztat(buf, &st, 0)) {
+ if (alist) {
+ LinkNode anode;
+
+ for (anode = firstnode(alist); anode; incnode(anode))
+ if (pattry((Patprog) getdata(anode), buf))
+ break;
+
+ if (!anode)
+ continue;
+ }
found = 1;
addlinknode(ret, dupstring(buf));
}
@@ -3334,12 +3365,14 @@ cfp_bld_pats(int dirs, LinkList names, char *skipped, char **pats)
}
static LinkList
-cfp_add_sdirs(LinkList final, LinkList orig, char *skipped, char *sdirs)
+cfp_add_sdirs(LinkList final, LinkList orig, char *skipped,
+ char *sdirs, char **fake)
{
int add = 0;
- if (*sdirs) {
- if (!strcmp(sdirs, "yes"))
+ if (*sdirs && (isset(GLOBDOTS) || (compprefix && *compprefix == '.'))) {
+ if (!strcmp(sdirs, "yes") || !strcmp(sdirs, "true") ||
+ !strcmp(sdirs, "on") || !strcmp(sdirs, "1"))
add = 2;
else if (!strcmp(sdirs, ".."))
add = 1;
@@ -3350,10 +3383,62 @@ cfp_add_sdirs(LinkList final, LinkList orig, char *skipped, char *sdirs)
char *s2 = (add == 2 ? dyncat(skipped, ".") : NULL), *m;
for (node = firstnode(orig); node; incnode(node)) {
- if (*(m = (char *) getdata(node))) {
- addlinknode(final, dyncat((char *) getdata(node), s1));
+ if ((m = (char *) getdata(node))) {
+ addlinknode(final, dyncat(m, s1));
if (s2)
- addlinknode(final, dyncat((char *) getdata(node), s2));
+ addlinknode(final, dyncat(m, s2));
+ }
+ }
+ }
+ if (fake && *fake) {
+ LinkNode node;
+ char *m, *f, *p, *t, *a, c;
+ int sl = strlen(skipped) + 1;
+ struct stat st1, st2;
+
+ for (; (f = *fake); fake++) {
+ f = dupstring(f);
+ for (p = t = f; *p; p++) {
+ if (*p == ':')
+ break;
+ else if (*p == '\\' && p[1])
+ p++;
+ *t++ = *p;
+ }
+ if (*p) {
+ *t = *p++ = '\0';
+ if (!*p)
+ continue;
+
+ for (node = firstnode(orig); node; incnode(node)) {
+ if ((m = (char *) getdata(node)) &&
+ (!strcmp(f, m) ||
+ (!stat(f, &st1) && !stat((*m ? m : "."), &st2) &&
+ st1.st_dev == st2.st_dev &&
+ st1.st_ino == st2.st_ino))) {
+ while (*p) {
+ while (*p && inblank(*p))
+ p++;
+ if (!*p)
+ break;
+ for (f = t = p; *p; p++) {
+ if (inblank(*p))
+ break;
+ else if (*p == '\\' && p[1])
+ p++;
+ *t++ = *p;
+ }
+ c = *t;
+ *t = '\0';
+ a = (char *) zhalloc(strlen(m) + sl + strlen(f));
+ strcpy(a, m);
+ strcat(a, skipped);
+ strcat(a, f);
+ addlinknode(final, a);
+ *t = c;
+ }
+ }
+ }
}
}
}
@@ -3361,14 +3446,14 @@ cfp_add_sdirs(LinkList final, LinkList orig, char *skipped, char *sdirs)
}
static LinkList
-cf_pats(int dirs, int noopt, LinkList names, char *skipped, char *matcher,
- char *sdirs, char **pats)
+cf_pats(int dirs, int noopt, LinkList names, char **accept, char *skipped,
+ char *matcher, char *sdirs, char **fake, char **pats)
{
LinkList ret;
char *dpats[2];
- if (dirs && (ret = cfp_test_exact(names, skipped)))
- return cfp_add_sdirs(ret, names, skipped, sdirs);
+ if ((ret = cfp_test_exact(names, accept, skipped)))
+ return cfp_add_sdirs(ret, names, skipped, sdirs, fake);
if (dirs) {
dpats[0] = "*(-/)";
@@ -3379,7 +3464,7 @@ cf_pats(int dirs, int noopt, LinkList names, char *skipped, char *matcher,
cfp_opt_pats(pats, matcher);
return cfp_add_sdirs(cfp_bld_pats(dirs, names, skipped, pats),
- names, skipped, sdirs);
+ names, skipped, sdirs, fake);
}
static void
@@ -3421,6 +3506,61 @@ cf_ignore(char **names, LinkList ign, char *style, char *path)
}
}
+static LinkList
+cf_remove_other(char **names, char *pre, int *amb)
+{
+ char *p;
+
+ if ((p = strchr(pre, '/'))) {
+ char **n;
+
+ *p = '\0';
+ pre = dyncat(pre, "/");
+ *p = '/';
+
+ for (n = names; *n; n++)
+ if (strpfx(pre, *n))
+ break;
+
+ if (*n) {
+ LinkList ret = newlinklist();
+
+ for (; *names; names++)
+ if (strpfx(pre, *names))
+ addlinknode(ret, dupstring(*names));
+
+ *amb = 0;
+
+ return ret;
+ } else {
+ if (!(p = *names++))
+ *amb = 0;
+ else {
+ char *q;
+
+ if ((q = strchr((p = dupstring(p)), '/')))
+ *q = '\0';
+
+ for (; *names; names++)
+ if (!strpfx(p, *names)) {
+ *amb = 1;
+ return NULL;
+ }
+ }
+ }
+ } else {
+ if (!(p = *names++))
+ *amb = 0;
+ else
+ for (; *names; names++)
+ if (strcmp(p, *names)) {
+ *amb = 1;
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
static int
bin_compfiles(char *nam, char **args, char *ops, int func)
{
@@ -3438,8 +3578,8 @@ bin_compfiles(char *nam, char **args, char *ops, int func)
char **tmp;
LinkList l;
- if (!args[1] || !args[2] || !args[3] || !args[4] ||
- (args[0][1] == 'p' && !args[5])) {
+ if (!args[1] || !args[2] || !args[3] || !args[4] || !args[5] ||
+ !args[6] || (args[0][1] == 'p' && !args[7])) {
zwarnnam(nam, "too few arguments", NULL, 0);
return 1;
}
@@ -3450,8 +3590,9 @@ bin_compfiles(char *nam, char **args, char *ops, int func)
for (l = newlinklist(); *tmp; tmp++)
addlinknode(l, *tmp);
set_list_array(args[1], cf_pats((args[0][1] == 'P'), !!args[0][2],
- l, args[2], args[3], args[4],
- args + 5));
+ l, getaparam(args[2]), args[3],
+ args[4], args[5],
+ getaparam(args[6]), args + 7));
return 0;
}
case 'i':
@@ -3483,6 +3624,28 @@ bin_compfiles(char *nam, char **args, char *ops, int func)
set_list_array(args[2], l);
return 0;
}
+ case 'r':
+ {
+ char **tmp;
+ LinkList l;
+ int ret = 0;
+
+ if (!args[1] || !args[2]) {
+ zwarnnam(nam, "too few arguments", NULL, 0);
+ return 1;
+ }
+ if (args[3]) {
+ zwarnnam(nam, "too many arguments", NULL, 0);
+ return 1;
+ }
+ if (!(tmp = getaparam(args[1]))) {
+ zwarnnam(nam, "unknown parameter: %s", args[1], 0);
+ return 0;
+ }
+ if ((l = cf_remove_other(tmp, args[2], &ret)))
+ set_list_array(args[1], l);
+ return ret;
+ }
}
zwarnnam(nam, "invalid option: %s", *args, 0);
return 1;