dmenu

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit c489e532d3df154f61921c2d559cbec1aefff870
parent 57852d9e44da3396c662f64befda55cc10ddd222
Author: AndrewLockVI <andrew@laack.co>
Date:   Sun, 23 Feb 2025 14:03:15 -0600

Removed fuzzy finding patch. It sometimes broke search results.

Diffstat:
Mdmenu.c | 123++++++++++++++++++++++++++++++++-----------------------------------------------
1 file changed, 49 insertions(+), 74 deletions(-)

diff --git a/dmenu.c b/dmenu.c @@ -31,7 +31,6 @@ struct item { char *text; struct item *left, *right; int out; - int distance; }; static char text[BUFSIZ] = ""; @@ -79,20 +78,6 @@ appenditem(struct item *item, struct item **list, struct item **last) } -static int -compare_distance(const void *a, const void *b) -{ - struct item const *da = *(struct item **) a; - struct item const *db = *(struct item **) b; - - if (!db) - return 1; - if (!da) - return -1; - return da->distance - db->distance; -} - - static void calcoffsets(void) { @@ -111,66 +96,56 @@ calcoffsets(void) break; } + static void -fuzzymatch(void) +match(void) { - struct item *item; - struct item **fuzzymatches = NULL; - char c; - int number_of_matches = 0, i, pidx, sidx, eidx; - int text_len = strlen(text), itext_len; - - matches = matchend = NULL; - - /* walk through all items */ + static char **tokv = NULL; + static int tokn = 0; + + char buf[sizeof text], *s; + int i, tokc = 0; + size_t len, textsize; + struct 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("cannot realloc %zu bytes:", tokn * sizeof *tokv); + len = tokc ? strlen(tokv[0]) : 0; + + matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; + textsize = strlen(text) + 1; for (item = items; item && item->text; item++) { - if (text_len) { - itext_len = strlen(item->text); - pidx = 0; - sidx = eidx = -1; - /* walk through item text */ - for (i = 0; i < itext_len && (c = item->text[i]); i++) { - /* fuzzy match pattern */ - if (text[pidx] == c) { - if (sidx == -1) - sidx = i; - pidx++; - if (pidx == text_len) { - eidx = i; - break; - } - } - } - /* build list of matches */ - if (eidx != -1) { - /* compute distance */ - /* factor in 30% of sidx and distance between eidx and total - * text length .. let's see how it works */ - item->distance = eidx - sidx + (itext_len - eidx + sidx) / 3; - appenditem(item, &matches, &matchend); - number_of_matches++; - } - } - else + 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 + appenditem(item, &lsubstr, &substrend); } - - if (number_of_matches) { - /* initialize array with matches */ - if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*)))) - die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item *)); - for (i = 0, item = matches; item && i < number_of_matches; i++, item = item->right) - fuzzymatches[i] = item; - - /* sort matches according to distance */ - qsort(fuzzymatches, number_of_matches, sizeof(struct item *), compare_distance); - /* rebuild list of matches */ - matches = matchend = NULL; - for (i = 0, item = fuzzymatches[0]; i < number_of_matches && item && \ - item->text; item = fuzzymatches[i], i++) - appenditem(item, &matches, &matchend); - - free(fuzzymatches); + if (lprefix) { + if (matches) { + matchend->right = lprefix; + lprefix->left = matchend; + } else + matches = lprefix; + matchend = prefixend; + } + if (lsubstr) { + if (matches) { + matchend->right = lsubstr; + lsubstr->left = matchend; + } else + matches = lsubstr; + matchend = substrend; } curr = sel = matches; calcoffsets(); @@ -318,7 +293,7 @@ insert(const char *str, ssize_t n) if (n > 0) memcpy(&text[cursor], str, n); cursor += n; - fuzzymatch(); + match(); } static size_t @@ -387,7 +362,7 @@ keypress(XKeyEvent *ev) case XK_k: /* delete right */ text[cursor] = '\0'; - fuzzymatch(); + match(); break; case XK_u: /* delete left */ insert(NULL, 0 - cursor); @@ -547,7 +522,7 @@ insert: cursor = strnlen(sel->text, sizeof text - 1); memcpy(text, sel->text, cursor); text[cursor] = '\0'; - fuzzymatch(); + match(); break; } @@ -706,7 +681,7 @@ setup(void) } promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; inputw = mw / 3; /* input width: ~33% of monitor width */ - fuzzymatch(); + match(); /* create menu window */ swa.override_redirect = True;