Add token matching like dmenu - wmenu - 🔧 fork of wmenu
 (HTM) git clone git@git.drkhsh.at/wmenu.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 04dfc063795c56a5fdb3096bf8fe0b4123c3c28d
 (DIR) parent 96b3c0ef266494e6a8c0a91d1726f8dcde95d55d
 (HTM) Author: Amin Bandali <bandali@kelar.org>
       Date:   Tue, 27 Feb 2024 00:10:34 -0500
       
       Add token matching like dmenu
       
       This change ports dmenu's token matching of space-separated input to
       wmenu to match the behaviour of dmenu, with a slightly more verbose
       but hopefully more readable implementation.
       
       Diffstat:
         M main.c                              |      38 +++++++++++++++++++++++++++----
       
       1 file changed, 34 insertions(+), 4 deletions(-)
       ---
 (DIR) diff --git a/main.c b/main.c
       @@ -195,19 +195,49 @@ static void match_items(struct menu *menu) {
                struct item *lexact = NULL, *exactend = NULL;
                struct item *lprefix = NULL, *prefixend = NULL;
                struct item *lsubstr  = NULL, *substrend = NULL;
       +        char buf[sizeof menu->input], *tok;
       +        char **tokv = NULL;
       +        int i, tokc = 0;
       +        size_t tok_len;
                menu->matches = NULL;
                menu->matches_end = NULL;
                menu->sel = NULL;
        
       -        size_t len = strlen(menu->input);
       +        size_t text_len = strlen(menu->input);
       +
       +        /* tokenize text by space for matching the tokens individually */
       +        strcpy(buf, menu->input);
       +        tok = strtok(buf, " ");
       +        while (tok) {
       +                tokv = realloc(tokv, (tokc + 1) * sizeof *tokv);
       +                if (!tokv) {
       +                        fprintf(stderr, "could not realloc %zu bytes",
       +                                        (tokc + 1) * sizeof *tokv);
       +                        exit(EXIT_FAILURE);
       +                }
       +                tokv[tokc] = tok;
       +                tokc++;
       +                tok = strtok(NULL, " ");
       +        }
       +        tok_len = tokc ? strlen(tokv[0]) : 0;
        
                struct item *item;
                for (item = menu->items; item; item = item->next) {
       -                if (!menu->strncmp(menu->input, item->text, len + 1)) {
       +                for (i = 0; i < tokc; i++) {
       +                        if (!fstrstr(menu, item->text, tokv[i])) {
       +                                /* token does not match */
       +                                break;
       +                        }
       +                }
       +                if (i != tokc) {
       +                        /* not all tokens match */
       +                        continue;
       +                }
       +                if (!tokc || !menu->strncmp(menu->input, item->text, text_len + 1)) {
                                append_item(item, &lexact, &exactend);
       -                } else if (!menu->strncmp(menu->input, item->text, len)) {
       +                } else if (!menu->strncmp(tokv[0], item->text, tok_len)) {
                                append_item(item, &lprefix, &prefixend);
       -                } else if (fstrstr(menu, item->text, menu->input)) {
       +                } else {
                                append_item(item, &lsubstr, &substrend);
                        }
                }