summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2001-06-11 11:46:23 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2001-06-11 11:46:23 +0000
commit9cc9cc946643961eb5e8ef63be165dcfd0d2ae6a (patch)
tree4366868db63d201847099edde3ffc91e4e20a5a0
parent4d59e2ce45b9f6f6d11b44c0546e217dfa6b2373 (diff)
downloadzsh-9cc9cc946643961eb5e8ef63be165dcfd0d2ae6a.tar.gz
zsh-9cc9cc946643961eb5e8ef63be165dcfd0d2ae6a.zip
(14841)
-rw-r--r--ChangeLog6
-rw-r--r--Completion/Base/Utility/_values2
-rw-r--r--Src/Zle/computil.c282
3 files changed, 191 insertions, 99 deletions
diff --git a/ChangeLog b/ChangeLog
index a22de8d47..07a933a8f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2001-06-11 Sven Wischnowsky <wischnow@zsh.org>
+
+ * 14841: Completion/Base/Utility/_values, Src/Zle/computil.c:
+ new word parsing for compvalues; this should now handle empty
+ separators correctly, as far as it is possible
+
2001-06-11 Peter Stephenson <pws@csr.com>
* 14840: Doc/Zsh/options.yo: document search behaviour with
diff --git a/Completion/Base/Utility/_values b/Completion/Base/Utility/_values
index d065961a6..9a6913dad 100644
--- a/Completion/Base/Utility/_values
+++ b/Completion/Base/Utility/_values
@@ -27,7 +27,7 @@ if compvalues -i "$@"; then
compvalues -V noargs args opts
- if [[ "$PREFIX" = *${argsep}${~test} ]]; then
+ if [[ -n "$argsep" && "$PREFIX" = *${argsep}${~test} ]]; then
local name
name="${PREFIX%%${argsep}*}"
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index 0f6b70e01..e9453808c 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -2103,10 +2103,7 @@ parse_cvdef(char *nam, char **args)
while (args[0][0] == '-' && (args[0][1] == 's' || args[0][1] == 'S') &&
!args[0][2]) {
- if (!args[1][0] || (args[1][0] && args[1][1])) {
- zwarnnam(nam, "invalid separator: %s", args[1], 0);
- return NULL;
- }
+
if (args[0][1] == 's') {
hassep = 1;
sep = args[1][0];
@@ -2314,20 +2311,122 @@ struct cvstate {
static struct cvstate cv_laststate;
static int cv_parsed = 0, cv_alloced = 0;
+/* Get the next value in the string. Return it's definition and update the
+ * sp pointer to point to the end of the value (plus argument, if any).
+ * If there is no next value, the string pointer is set to null. In any
+ * case ap will point to the beginning of the argument or will be a null
+ * pointer if there is no argument.
+ */
+
+static Cvval
+cv_next(Cvdef d, char **sp, char **ap)
+{
+ Cvval r = NULL;
+ char *s = *sp;
+
+ if (!*s) {
+ *sp = *ap = NULL;
+
+ return NULL;
+ }
+ if ((d->hassep && !d->sep) || !d->argsep) {
+ char sav, ec, *v = s, *os;
+
+ ec = ((d->hassep && d->sep) ? d->sep : d->argsep);
+
+ do {
+ sav = *++s;
+ *s = '\0';
+ if ((r = cv_get_val(d, v))) {
+ *s = sav;
+
+ break;
+ }
+ *s = sav;
+ } while (*s && *s != ec);
+
+ os = s;
+
+ if (d->hassep && d->sep) {
+ if ((s = strchr(s, d->sep)))
+ *sp = s + 1;
+ else
+ *sp = NULL;
+ } else
+ *sp = s;
+ if (d->argsep && *os == d->argsep) {
+ *ap = os + 1;
+ *sp = NULL;
+ } else if (r && r->type != CVV_NOARG)
+ *ap = os;
+ else
+ *ap = NULL;
+
+ return r;
+
+ } else if (d->hassep) {
+ char *ns = strchr(s, d->sep), *as, *sap, sav;
+ int skip = 0;
+
+ if (d->argsep && (as = strchr(s, d->argsep)) && (!ns || as <= ns)) {
+ *ap = as + 1;
+ ns = strchr(as + 1, d->sep);
+ skip = 1;
+ sap = as;
+ } else {
+ *ap = NULL;
+ sap = ns;
+ }
+ if (sap) {
+ sav = *sap;
+ *sap = '\0';
+ }
+ if ((!(r = cv_get_val(d, s)) || r->type == CVV_NOARG) && skip)
+ ns = as;
+
+ if (sap)
+ *sap = sav;
+
+ *sp = ((!ns || (ns == as && r && r->type != CVV_NOARG)) ? NULL : ns + 1);
+
+ return r;
+ } else {
+ char *as = strchr(s, d->argsep), *sap, sav;
+
+ *sp = NULL;
+
+ if (as) {
+ *ap = as + 1;
+ sap = as;
+ sav = *as;
+ *sap = '\0';
+ } else
+ *ap = sap = NULL;
+
+ r = cv_get_val(d, s);
+
+ if (sap)
+ *sap = sav;
+
+ return r;
+ }
+}
+
/* Parse the current word. */
static void
cv_parse_word(Cvdef d)
{
- Cvval ptr;
+ Cvval val;
struct cvstate state;
- char *str, *eq;
+ char *str, *arg = NULL, *pign = compprefix;
+ int nosfx = 0;
if (cv_alloced)
freelinklist(cv_laststate.vals, freestr);
- for (ptr = d->vals; ptr; ptr = ptr->next)
- ptr->active = 1;
+ for (val = d->vals; val; val = val->next)
+ val->active = 1;
state.d = d;
state.def = NULL;
@@ -2336,103 +2435,90 @@ cv_parse_word(Cvdef d)
cv_alloced = 1;
- if (d->hassep) {
- if (d->sep) {
- char *end;
- int heq;
-
- for (str = compprefix, end = strchr(str, d->sep); end;) {
- *end = '\0';
-
- if ((heq = !!(eq = strchr(str, d->argsep))))
- *eq++ = '\0';
- else
- eq = "";
-
- if ((ptr = cv_get_val(d, str))) {
- zaddlinknode(state.vals, ztrdup(str));
- zaddlinknode(state.vals, ztrdup(eq));
-
- cv_inactive(d, ptr->xor);
- }
- if (heq)
- eq[-1] = d->argsep;
-
- *end = d->sep;
- str = end + 1;
- end = strchr(str, d->sep);
- }
- ignore_prefix(str - compprefix);
-
- if ((str = strchr(compsuffix, d->sep))) {
- char *beg = str;
-
- for (str++; str; str = end) {
- if ((end = strchr(str, d->sep)))
- *end = '\0';
-
- if ((heq = !!(eq = strchr(str, d->argsep))))
- *eq++ = '\0';
- else
- eq = "";
-
- if ((ptr = cv_get_val(d, str))) {
- zaddlinknode(state.vals, ztrdup(str));
- zaddlinknode(state.vals, ztrdup(eq));
+ for (str = compprefix; str && *str; ) {
+ if ((val = cv_next(d, &str, &arg))) {
+ zaddlinknode(state.vals, ztrdup(val->name));
+ if (arg) {
+ if (str) {
+ char sav = str[-1];
+
+ str[-1] = '\0';
+ zaddlinknode(state.vals, ztrdup(arg));
+ str[-1] = sav;
+ } else {
+ zaddlinknode(state.vals, tricat(arg, compsuffix, ""));
+ nosfx = 1;
+ }
+ } else
+ zaddlinknode(state.vals, ztrdup(""));
+
+ cv_inactive(d, val->xor);
+
+ if (str)
+ pign = str;
+ else
+ val->active = 1;
+ }
+ }
+ state.val = val;
+ if (val && arg && !str)
+ state.def = val->arg;
- cv_inactive(d, ptr->xor);
- }
- if (heq)
- eq[-1] = d->argsep;
- if (end)
- *end++ = d->sep;
- }
- ignore_suffix(strlen(beg));
- }
- } else {
- char tmp[2];
+ if (!nosfx && d->hassep) {
+ int ign = 0;
+ char *more = NULL;
- tmp[1] = '\0';
+ ignore_prefix(pign - compprefix);
- for (str = compprefix; *str; str++) {
- tmp[0] = *str;
- if ((ptr = cv_get_val(d, tmp))) {
- zaddlinknode(state.vals, ztrdup(tmp));
- zaddlinknode(state.vals, ztrdup(""));
+ if (!d->sep && (!val || val->type == CVV_NOARG)) {
+ ign = strlen(compsuffix);
+ more = compsuffix;
+ } else {
+ if (d->sep) {
+ char *ns = strchr(compsuffix, d->sep), *as;
- cv_inactive(d, ptr->xor);
- }
- }
- for (str = compsuffix; *str; str++) {
- tmp[0] = *str;
- if ((ptr = cv_get_val(d, tmp))) {
- zaddlinknode(state.vals, ztrdup(tmp));
- zaddlinknode(state.vals, ztrdup(""));
+ if (d->argsep && (as = strchr(compsuffix, d->argsep)) &&
+ (!ns || as <= ns)) {
+ ign = strlen(as);
+ } else
+ ign = (ns ? strlen(ns) : 0);
- cv_inactive(d, ptr->xor);
- }
- }
- ignore_prefix(strlen(compprefix));
- ignore_suffix(strlen(compsuffix));
- }
- }
- str = tricat(compprefix, compsuffix, "");
- zsfree(compprefix);
- zsfree(compsuffix);
- compprefix = str;
- compsuffix = ztrdup("");
+ more = (ns ? ns + 1 : NULL);
+ } else if (d->argsep) {
+ char *as;
- if ((eq = strchr(str, d->argsep))) {
- *eq++ = '\0';
+ if ((as = strchr(compsuffix, d->argsep)))
+ ign = strlen(as);
+ }
+ }
+ if (ign)
+ ignore_suffix(ign);
+
+ while (more && *more) {
+ if ((val = cv_next(d, &str, &arg))) {
+ zaddlinknode(state.vals, ztrdup(val->name));
+ if (arg) {
+ if (str) {
+ char sav = str[-1];
+
+ str[-1] = '\0';
+ zaddlinknode(state.vals, ztrdup(arg));
+ str[-1] = sav;
+ } else {
+ zaddlinknode(state.vals, tricat(arg, compsuffix, ""));
+ nosfx = 1;
+ }
+ } else
+ zaddlinknode(state.vals, ztrdup(""));
+
+ cv_inactive(d, val->xor);
+ }
+ }
+ } else if (arg)
+ ignore_prefix(arg - compprefix);
+ else
+ ignore_prefix(pign - compprefix);
- if ((ptr = cv_get_val(d, str)) && ptr->type != CVV_NOARG) {
- eq[-1] = d->argsep;
- ignore_prefix(eq - str);
- state.def = ptr->arg;
- state.val = ptr;
- } else
- eq[-1] = d->argsep;
- }
memcpy(&cv_laststate, &state, sizeof(state));
}