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:
| M | dmenu.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;