summaryrefslogtreecommitdiff
path: root/Src/Zle/complete.c
diff options
context:
space:
mode:
authorAxel Beckert <abe@deuxchevaux.org>2020-02-14 01:58:20 +0100
committerAxel Beckert <abe@deuxchevaux.org>2020-02-14 01:58:20 +0100
commitbfc5d42735c1660263904ec5254cccf539a0a458 (patch)
tree9bbb81b4a53941427e6f9e65ae55027d9108df8c /Src/Zle/complete.c
parent74561cc51b8867e43cb2937ab2edfb36e2a829bf (diff)
parent643de931640e01aa246723d2038328ef33737965 (diff)
downloadzsh-bfc5d42735c1660263904ec5254cccf539a0a458.tar.gz
zsh-bfc5d42735c1660263904ec5254cccf539a0a458.zip
Merge tag 'zsh-5.7.1-test-3' into debian
Test release: 5.7.1-test-3
Diffstat (limited to 'Src/Zle/complete.c')
-rw-r--r--Src/Zle/complete.c63
1 files changed, 56 insertions, 7 deletions
diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c
index 1dc2b01c2..7beb6d847 100644
--- a/Src/Zle/complete.c
+++ b/Src/Zle/complete.c
@@ -84,7 +84,7 @@ char *compiprefix,
Param *comprpms;
/*
- * An array of Param structures for elemens of $compstate; see
+ * An array of Param structures for elements of $compstate; see
* 'compkparams' below.
*
* See CP_KEYPARAMS.
@@ -558,12 +558,53 @@ parse_class(Cpattern p, char *iptr)
return iptr;
}
+static struct { char *name; int abbrev; int oflag; } orderopts[] = {
+ { "nosort", 2, CAF_NOSORT },
+ { "match", 3, CAF_MATSORT },
+ { "numeric", 3, CAF_NUMSORT },
+ { "reverse", 3, CAF_REVSORT }
+};
+
+/* Parse the option to compadd -o, if flags is non-NULL set it
+ * returns -1 if the argument isn't a valid ordering, 0 otherwise */
+
+/**/
+static int
+parse_ordering(const char *arg, int *flags)
+{
+ int o, fl = 0;
+ const char *next, *opt = arg;
+ do {
+ int found = 0;
+ next = strchr(opt, ',');
+ if (!next)
+ next = opt + strlen(opt);
+
+ for (o = sizeof(orderopts)/sizeof(*orderopts) - 1; o >= 0 &&
+ !found; --o)
+ {
+ if ((found = next - opt >= orderopts[o].abbrev &&
+ !strncmp(orderopts[o].name, opt, next - opt)))
+ fl |= orderopts[o].oflag;
+ }
+ if (!found) {
+ if (flags) /* default to "match" */
+ *flags = CAF_MATSORT;
+ return -1;
+ }
+ } while (*next && ((opt = next + 1)));
+ if (flags)
+ *flags |= fl;
+ return 0;
+}
+
/**/
static int
bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
{
struct cadata dat;
char *mstr = NULL; /* argument of -M options, accumulated */
+ char *oarg = NULL; /* argument of -o option */
int added; /* return value */
Cmatcher match = NULL;
@@ -572,7 +613,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
return 1;
}
dat.ipre = dat.isuf = dat.ppre = dat.psuf = dat.prpre = dat.mesg =
- dat.pre = dat.suf = dat.group = dat.rems = dat.remf = dat.disp =
+ dat.pre = dat.suf = dat.group = dat.rems = dat.remf = dat.disp =
dat.ign = dat.exp = dat.apar = dat.opar = dat.dpar = NULL;
dat.match = NULL;
dat.flags = 0;
@@ -587,6 +628,7 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
}
for (p = *argv + 1; *p; p++) {
char *m = NULL; /* argument of -M option (this one only) */
+ int order = 0; /* if -o found (argument to which is optional) */
char **sp = NULL; /* the argument to an option should be copied
to *sp. */
const char *e; /* error message */
@@ -710,7 +752,11 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
dat.flags |= CMF_DISPLINE;
break;
case 'o':
- dat.flags |= CMF_MORDER;
+ /* we honour just the first -o option but need to skip
+ * over a valid argument to subsequent -o options */
+ order = oarg ? -1 : 1;
+ sp = &oarg;
+ /* no error string because argument is optional */
break;
case 'E':
if (p[1]) {
@@ -741,15 +787,18 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
if (sp) {
if (p[1]) {
/* Pasted argument: -Xfoo. */
- if (!*sp)
+ if (!*sp) /* take first option only */
*sp = p + 1;
- p += strlen(p+1);
+ if (!order || !parse_ordering(oarg, order == 1 ? &dat.aflags : NULL))
+ p += strlen(p+1);
} else if (argv[1]) {
/* Argument in a separate word: -X foo. */
argv++;
if (!*sp)
*sp = *argv;
- } else {
+ if (order && parse_ordering(oarg, order == 1 ? &dat.aflags : NULL))
+ --argv;
+ } else if (!order) {
/* Missing argument: argv[N] == "-X", argv[N+1] == NULL. */
zwarnnam(name, e, *p);
zsfree(mstr);
@@ -962,7 +1011,7 @@ do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod)
}
} else
#endif
- if ((int)strlen(test == CVT_PRENUM ? compprefix : compsuffix) >= na)
+ if ((int)strlen(test == CVT_PRENUM ? compprefix : compsuffix) < na)
return 0;
if (test == CVT_PRENUM)
ignore_prefix(na);