aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2016-05-19 12:50:48 +0200
committerMarc André Tanner <mat@brain-dump.org>2016-05-19 18:51:30 +0200
commitb28f3de3520282c35e41813a0177887dcd736c6c (patch)
tree19176e121ed11774b691caad225440d35d8afa66
parent04ce53f3f90ddbe77eff6c65ce77f2d789455dd5 (diff)
downloadvis-b28f3de3520282c35e41813a0177887dcd736c6c.tar.gz
vis-b28f3de3520282c35e41813a0177887dcd736c6c.tar.xz
vis-menu: import token based match function from dmenu
-rw-r--r--vis-menu.c73
1 files changed, 43 insertions, 30 deletions
diff --git a/vis-menu.c b/vis-menu.c
index 41ec76a..2b9bad7 100644
--- a/vis-menu.c
+++ b/vis-menu.c
@@ -68,7 +68,7 @@ static void drawtext(const char*, size_t, Color);
static void drawmenu(void);
static char *fstrstr(const char*, const char*);
static void insert(const char*, ssize_t);
-static void match(int);
+static void match();
static size_t nextrune(int);
static void readstdin(void);
static int run(void);
@@ -222,43 +222,56 @@ insert(const char *str, ssize_t n) {
if(n > 0)
memcpy(&text[cursor], str, n);
cursor += n;
- match(n > 0 && text[cursor] == '\0');
+ match();
}
-void
-match(int sub) {
- size_t len = strlen(text);
- Item *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend;
- Item *item, *lnext;
-
- lexact = lprefix = lsubstr = exactend = prefixend = substrend = NULL;
- for(item = sub ? matches : items; item && item->text; item = lnext) {
- lnext = sub ? item->right : item + 1;
- if(!fstrncmp(text, item->text, len + 1))
- appenditem(item, &lexact, &exactend);
- else if(!fstrncmp(text, item->text, len))
+static void
+match(void)
+{
+ static char **tokv = NULL;
+ static int tokn = 0;
+
+ char buf[sizeof text], *s;
+ int i, tokc = 0;
+ size_t len, textsize;
+ Item *item, *lprefix, *lsubstr, *prefixend, *substrend;
+
+ strcpy(buf, text);
+ /* separate input text into tokens to be matched individually */
+ for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " "))
+ if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv)))
+ die("Can't realloc.");
+ len = tokc ? strlen(tokv[0]) : 0;
+
+ matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL;
+ textsize = strlen(text);
+ for (item = items; item && item->text; item++) {
+ for (i = 0; i < tokc; i++)
+ if (!fstrstr(item->text, tokv[i]))
+ break;
+ if (i != tokc) /* not all tokens match */
+ continue;
+ /* exact matches go first, then prefixes, then substrings */
+ if (!tokc || !fstrncmp(text, item->text, textsize))
+ appenditem(item, &matches, &matchend);
+ else if (!fstrncmp(tokv[0], item->text, len))
appenditem(item, &lprefix, &prefixend);
- else if(fstrstr(item->text, text))
+ else
appenditem(item, &lsubstr, &substrend);
}
- matches = lexact;
- matchend = exactend;
-
- if(lprefix) {
- if(matchend) {
+ if (lprefix) {
+ if (matches) {
matchend->right = lprefix;
lprefix->left = matchend;
- }
- else
+ } else
matches = lprefix;
matchend = prefixend;
}
- if(lsubstr) {
- if(matchend) {
+ if (lsubstr) {
+ if (matches) {
matchend->right = lsubstr;
lsubstr->left = matchend;
- }
- else
+ } else
matches = lsubstr;
matchend = substrend;
}
@@ -405,7 +418,7 @@ run(void) {
case CONTROL('J'):
if(sel) strncpy(text, sel->text, sizeof text); /* Complete the input first, when hitting return */
cursor = strlen(text);
- match(TRUE);
+ match();
drawmenu();
/* fallthrough */
case CONTROL(']'):
@@ -475,11 +488,11 @@ run(void) {
break;
strncpy(text, sel->text, sizeof text);
cursor = strlen(text);
- match(TRUE);
+ match();
break;
case CONTROL('K'):
text[cursor] = '\0';
- match(FALSE);
+ match();
break;
case CONTROL('U'):
insert(NULL, 0 - cursor);
@@ -543,7 +556,7 @@ setup(void) {
lines=MIN(MAX(lines, 0), mh);
promptw=(prompt?textw(prompt):0);
inputw=MIN(inputw, mw/3);
- match(FALSE);
+ match();
if(barpos!=0) resetline();
drawmenu();
}