summaryrefslogtreecommitdiff
path: root/dmenu-wl.c
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2023-03-22 00:02:11 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2023-03-22 00:02:11 +0100
commit6e1949833e5cf490cff5140b797ce25c3065ed55 (patch)
treeff9937318e5101006070d55e20433b9faae5b2f3 /dmenu-wl.c
parent7e0ace1f1e5334f13580facb53c253c94c6913f6 (diff)
modify match priority to a more intuitive way
Diffstat (limited to 'dmenu-wl.c')
-rw-r--r--dmenu-wl.c96
1 files changed, 61 insertions, 35 deletions
diff --git a/dmenu-wl.c b/dmenu-wl.c
index 252182c..a3d30ae 100644
--- a/dmenu-wl.c
+++ b/dmenu-wl.c
@@ -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);