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")) {
menupaddingh = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-pri")) {
parse_hpitems(argv[++i]);
hpitems = tokenize(argv[++i], ",", &hplength);
} else if (!strcmp(argv[i], "-ig")) {
imagegaps = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-la")) {

View file

@ -1,22 +1,35 @@
char **
tokenize(char *source, const char *delim, int *llen)
{
int listlength = 0, list_size = 0;
char **list = NULL, *token;
token = strtok(source, delim);
while (token) {
if (listlength + 1 >= list_size) {
if (!(list = realloc(list, (list_size += 8) * sizeof(*list))))
die("Unable to realloc %zu bytes\n", list_size * sizeof(*list));
}
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
str_compar(const void *s0_in, const void *s1_in)
arrayhas(char **list, int length, char *item)
{
const char *s0 = *(const char **)s0_in;
const char *s1 = *(const char **)s1_in;
return fstrncmp == strncasecmp ? strcasecmp(s0, s1) : strcmp(s0, s1);
}
int i;
void
parse_hpitems(char *src)
{
int n = 0;
char *t;
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;
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 void parse_hpitems(char *src);
static char **tokenize(char *source, const char *delim, int *llen);
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 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 char **hpitems = NULL; /* High priority items */
/* Line options */
static int lineheight = 5; /* Line height (0: Calculate automatically) */

View file

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