fix fuzzy sorting

This commit is contained in:
speedie 2023-03-09 11:56:44 +01:00
parent 9b806fa9c0
commit 89f5a54918
5 changed files with 57 additions and 34 deletions

View file

@ -142,7 +142,7 @@ readargs(int argc, char *argv[])
} else if (!strcmp(argv[i], "-hp")) { } else if (!strcmp(argv[i], "-hp")) {
menupaddingh = atoi(argv[++i]); menupaddingh = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-pri")) { } else if (!strcmp(argv[i], "-pri")) {
parse_hpitems(argv[++i]); hpitems = tokenize(argv[++i], ",", &hplength);
} else if (!strcmp(argv[i], "-ig")) { } else if (!strcmp(argv[i], "-ig")) {
imagegaps = atoi(argv[++i]); imagegaps = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-la")) { } else if (!strcmp(argv[i], "-la")) {

View file

@ -1,22 +1,35 @@
int char **
str_compar(const void *s0_in, const void *s1_in) tokenize(char *source, const char *delim, int *llen)
{ {
const char *s0 = *(const char **)s0_in; int listlength = 0, list_size = 0;
const char *s1 = *(const char **)s1_in; char **list = NULL, *token;
return fstrncmp == strncasecmp ? strcasecmp(s0, s1) : strcmp(s0, s1);
}
void token = strtok(source, delim);
parse_hpitems(char *src) while (token) {
{ if (listlength + 1 >= list_size) {
int n = 0; if (!(list = realloc(list, (list_size += 8) * sizeof(*list))))
char *t; die("Unable to realloc %zu bytes\n", list_size * sizeof(*list));
for (t = strtok(src, ","); t; t = strtok(NULL, ",")) {
if (hplength + 1 >= n) {
if (!(hpitems = realloc(hpitems, (n += 8) * sizeof *hpitems)))
die("Unable to realloc %zu bytes\n", n * sizeof *hpitems);
} }
hpitems[hplength++] = t; if (!(list[listlength] = strdup(token)))
die("Unable to strdup %zu bytes\n", strlen(token) + 1);
token = strtok(NULL, delim);
listlength++;
} }
*llen = listlength;
return list;
}
int
arrayhas(char **list, int length, char *item)
{
int i;
for (i = 0; i < length; i++) {
size_t len1 = strlen(list[i]);
size_t len2 = strlen(item);
if (!fstrncmp(list[i], item, len1 > len2 ? len2 : len1))
return 1;
}
return 0;
} }

View file

@ -1,2 +1,2 @@
static int str_compar(const void *s0_in, const void *s1_in); static char **tokenize(char *source, const char *delim, int *llen);
static void parse_hpitems(char *src); static int arrayhas(char **list, int length, char *item);

View file

@ -48,7 +48,6 @@ static int casesensitive = 0; /* Case-sensitive by default? (0/1)
static int preselected = 0; /* Which line should spmenu preselect? */ static int preselected = 0; /* Which line should spmenu preselect? */
static int accuratewidth = 1; /* Enable accurate width. May have a performance hit if you are matching a lot of items at once */ static int accuratewidth = 1; /* Enable accurate width. May have a performance hit if you are matching a lot of items at once */
static int fuzzy = 1; /* Whether or not to enable fuzzy matching by default */ static int fuzzy = 1; /* Whether or not to enable fuzzy matching by default */
static char **hpitems = NULL; /* High priority items */
/* Line options */ /* Line options */
static int lineheight = 5; /* Line height (0: Calculate automatically) */ static int lineheight = 5; /* Line height (0: Calculate automatically) */

View file

@ -135,6 +135,7 @@ typedef struct {
static char numbers[NUMBERSBUFSIZE] = ""; static char numbers[NUMBERSBUFSIZE] = "";
static int hplength = 0; static int hplength = 0;
static char **hpitems = NULL;
static char *embed; static char *embed;
static int numlockmask = 0; static int numlockmask = 0;
static int bh, mw, mh; static int bh, mw, mh;
@ -320,8 +321,13 @@ cleanup(void)
#endif #endif
XUngrabKey(dpy, AnyKey, AnyModifier, root); XUngrabKey(dpy, AnyKey, AnyModifier, root);
for (i = 0; i < SchemeLast; i++) for (i = 0; i < SchemeLast; i++)
free(scheme[i]); free(scheme[i]);
for (i = 0; i < hplength; ++i)
free(hpitems[i]);
drw_free(drw); drw_free(drw);
XSync(dpy, False); XSync(dpy, False);
XCloseDisplay(dpy); XCloseDisplay(dpy);
@ -410,6 +416,8 @@ fuzzymatch(void)
/* bang - we have so much memory */ /* bang - we have so much memory */
struct item *it; struct item *it;
struct item **fuzzymatches = NULL; struct item **fuzzymatches = NULL;
struct item *lhpprefix, *hpprefixend;
lhpprefix = hpprefixend = NULL;
char c; char c;
int number_of_matches = 0, i, pidx, sidx, eidx; int number_of_matches = 0, i, pidx, sidx, eidx;
int text_len = strlen(text), itext_len; int text_len = strlen(text), itext_len;
@ -458,16 +466,26 @@ fuzzymatch(void)
fuzzymatches[i] = it; fuzzymatches[i] = it;
} }
/* sort matches according to distance */ /* sort matches according to distance */
qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance); if (sortmatches) qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance);
/* rebuild list of matches */ /* rebuild list of matches */
matches = matchend = NULL; matches = matchend = NULL;
for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \ for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \
it->text; i++, it = fuzzymatches[i]) { it->text; i++, it = fuzzymatches[i]) {
appenditem(it, &matches, &matchend);
if (sortmatches && it->hp)
appenditem(it, &lhpprefix, &hpprefixend);
appenditem(it, &matches, &matchend);
} }
free(fuzzymatches); free(fuzzymatches);
} }
if (lhpprefix) {
hpprefixend->right = matches;
matches = lhpprefix;
}
curr = sel = matches; curr = sel = matches;
for (i = 0; i < preselected; i++) { for (i = 0; i < preselected; i++) {
@ -515,10 +533,10 @@ match(void)
appenditem(item, &matches, &matchend); appenditem(item, &matches, &matchend);
else { else {
/* exact matches go first, then prefixes with high priority, then prefixes, then substrings */ /* exact matches go first, then prefixes with high priority, then prefixes, then substrings */
if (!tokc || !fstrncmp(text, item->text, textsize)) if (item->hp && !fstrncmp(tokv[0], item->text, len))
appenditem(item, &matches, &matchend);
else if (item->hp && !fstrncmp(tokv[0], item->text, len))
appenditem(item, &lhpprefix, &hpprefixend); appenditem(item, &lhpprefix, &hpprefixend);
else if (!tokc || !fstrncmp(text, item->text, textsize))
appenditem(item, &matches, &matchend);
else if (!fstrncmp(tokv[0], item->text, len)) else if (!fstrncmp(tokv[0], item->text, len))
appenditem(item, &lprefix, &prefixend); appenditem(item, &lprefix, &prefixend);
else else
@ -749,9 +767,6 @@ readstdin(void)
return; return;
} }
if (hpitems && hplength > 0)
qsort(hpitems, hplength, sizeof *hpitems, str_compar);
/* read each line from stdin and add it to the item list */ /* read each line from stdin and add it to the item list */
for (i = 0; fgets(buf, sizeof buf, stdin); i++) { for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
if (i + 1 >= itemsiz) { if (i + 1 >= itemsiz) {
@ -763,11 +778,7 @@ readstdin(void)
*p = '\0'; *p = '\0';
if (!(items[i].text = strdup(buf))) if (!(items[i].text = strdup(buf)))
die("cannot strdup %u bytes:", strlen(buf) + 1); die("cannot strdup %u bytes:", strlen(buf) + 1);
p = hpitems == NULL ? NULL : bsearch( items[i].hp = arrayhas(hpitems, hplength, items[i].text);
&items[i].text, hpitems, hplength, sizeof *hpitems,
str_compar
);
items[i].hp = p != NULL;
drw_font_getexts(drw->font, buf, strlen(buf), &tmpmax, NULL, True); drw_font_getexts(drw->font, buf, strlen(buf), &tmpmax, NULL, True);
if (tmpmax > inputw) { if (tmpmax > inputw) {
inputw = tmpmax; inputw = tmpmax;