diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2023-03-22 00:02:11 +0100 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2023-03-22 00:02:11 +0100 |
| commit | 6e1949833e5cf490cff5140b797ce25c3065ed55 (patch) | |
| tree | ff9937318e5101006070d55e20433b9faae5b2f3 | |
| parent | 7e0ace1f1e5334f13580facb53c253c94c6913f6 (diff) | |
modify match priority to a more intuitive way
| -rw-r--r-- | dmenu-wl.c | 96 |
1 files changed, 61 insertions, 35 deletions
@@ -16,6 +16,7 @@ #include "wlr-layer-shell-protocol.h" #include "drw.h" +#include "util.h" /* macro definitions */ #define MAX_LINE_LENGTH 1024 @@ -84,8 +85,8 @@ struct Options { } options = { 0 }; /* function definition */ +static void append_match(Option *item, Option **first, Option **last); static void generate_matches(); -static int match_option(char *name); static void draw_dmenu(Monitor *monitor); static void setup(); static void readstdin(); @@ -147,52 +148,76 @@ int running = 1; #include "config.h" /* function implementations */ -int -option_match(char *name) +void +append_match(Option *item, Option **first, Option **last) { - int i = 0; - - for (; *name; ++name) { - if (input_field[i] == 0) - return 1; - - if (*name != input_field[i]) { - i = 0; - } else { - ++i; - } - } - - if (input_field[i] == 0) - return 1; + if (*last) + (*last)->next_match = item; + else + *first = item; - return 0; + item->previous_match = *last; + item->next_match = 0; + *last = item; } void generate_matches() { - Option *match = options.first; - options.first_match = 0; - options.last_match = 0; + static char **tokv = NULL; + static int tokn = 0; - for (; match; match = match->next) { - if (option_match(match->name)) { - if (options.first_match == 0) { - options.first_match = match; - options.last_match = match; - } else { - options.last_match->next_match = match; - match->previous_match = options.last; - options.last_match = match; - } - } + char buf[sizeof(input_field)], *s; + int i, tokc = 0; + size_t len, textsize; + Option *item, *lprefix, *lsubstr, *prefixend, *substrend; + + + strcpy(buf, input_field); + /* separate input text into tokens to be matched individually */ + for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(0, " ")) + if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) + die("cannot realloc bytes"); + + len = tokc ? strlen(tokv[0]) : 0; + + options.first_match = lprefix = lsubstr = options.last_match = prefixend = substrend = 0; + textsize = strlen(input_field) + 1; + + for (item = options.first; item && item->name; item = item->next) { + for (i = 0; i < tokc; i++) + if (!strstr(item->name, tokv[i])) + break; + if (i != tokc) /* not all tokens match */ + continue; + /* exact matches go first, then prefixes, then substrings */ + if (!tokc || !strncmp(input_field, item->name, textsize)) + append_match(item, &options.first_match, &options.last_match); + else if (!strncmp(tokv[0], item->name, len)) + append_match(item, &lprefix, &prefixend); + else + append_match(item, &lsubstr, &substrend); + } + + if (lprefix) { + if (options.first_match) { + options.last_match->next_match = lprefix; + lprefix->previous_match = options.last_match; + } else + options.first_match = lprefix; + options.last_match = prefixend; } + if (lsubstr) { + if (options.first_match) { + options.last_match->next_match = lsubstr; + lsubstr->previous_match = options.last_match; + } else + options.first_match = lsubstr; + options.last_match = substrend; + } options.selection = options.first_match; - if (options.last_match) - options.last_match->next_match = 0; } @@ -224,6 +249,7 @@ draw_dmenu(Monitor *monitor) y += padding; } + wl_surface_attach(monitor->surface, (struct wl_buffer*)monitor->canvas->buffer, 0, 0); wl_surface_damage_buffer(monitor->surface, 0, 0, monitor->width, height); wl_surface_commit(monitor->surface); |