Hey, cc596365a (unbolify dmenu) "breaks" some of the patches provided at tools.suckless.org/dmenu/patches. Basically 's,bool,int' was all I had to do besides some offset correction. Since this is the first time I'm dealing with dmenu's source I do not guarantee anything, but it compiles fine, though. Making them apply without errors ontop of latest git was all I did, no changes in functionality or whatsoever.
Best Regards, Klemens
>From 367f55b3fc31c23fdc0d534a04e3563938a58977 Mon Sep 17 00:00:00 2001 From: Klemens Nanni <k...@posteo.org> Date: Mon, 11 Jan 2016 13:26:37 +0100 Subject: [PATCH 1/3] Typofix --- config.def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 8db1dda..dcffd38 100644 --- a/config.def.h +++ b/config.def.h @@ -6,7 +6,7 @@ static int topbar = 1; /* -b option; if 0, dmenu appears a static const char *fonts[] = { "monospace:size=10" }; -static const char *prompt = NULL; /* -p option; prompt to the elft of input field */ +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ static const char *normbgcolor = "#222222"; /* -nb option; normal background */ static const char *normfgcolor = "#bbbbbb"; /* -nf option; normal foreground */ static const char *selbgcolor = "#005577"; /* -sb option; selected background */ -- 2.6.2
diff --git a/dmenu.c b/dmenu.c index 4f22ffe..c2fc3ee 100644 --- a/dmenu.c +++ b/dmenu.c @@ -33,6 +33,7 @@ struct item { char *text; struct item *left, *right; int out; + int distance; }; static char text[BUFSIZ] = ""; @@ -254,6 +255,86 @@ match(void) calcoffsets(); } +int +compare_distance(const void *a, const void *b) +{ + struct item *da = *(struct item **) a; + struct item *db = *(struct item **) b; + + if (!db) + return 1; + if (!da) + return -1; + + return da->distance - db->distance; +} + +void +fuzzymatch(void) +{ + /* bang - we have so much memory */ + struct item *it; + struct item **fuzzymatches = NULL; + char c; + int number_of_matches = 0, i, pidx, sidx, eidx; + int text_len = strlen(text), itext_len; + + matches = matchend = NULL; + + /* walk through all items */ + for (it = items; it && it->text; it++) { + if (text_len) { + itext_len = strlen(it->text); + pidx = 0; + sidx = eidx = -1; + /* walk through item text */ + for (i = 0; i < itext_len && (c = it->text[i]); i++) { + /* fuzzy match pattern */ + if (text[pidx] == c) { + if(sidx == -1) + sidx = i; + pidx++; + if (pidx == text_len) { + eidx = i; + break; + } + } + } + /* build list of matches */ + if (eidx != -1) { + /* compute distance */ + /* factor in 30% of sidx and distance between eidx and total + * text length .. let's see how it works */ + it->distance = eidx - sidx + (itext_len - eidx + sidx) / 3; + appenditem(it, &matches, &matchend); + number_of_matches++; + } + } else { + appenditem(it, &matches, &matchend); + } + } + + if (number_of_matches) { + /* initialize array with matches */ + if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*)))) + die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item*)); + for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) { + fuzzymatches[i] = it; + } + /* sort matches according to distance */ + 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]) { + appenditem(it, &matches, &matchend); + } + free(fuzzymatches); + } + curr = sel = matches; + calcoffsets(); +} + static void insert(const char *str, ssize_t n) { @@ -264,7 +345,7 @@ insert(const char *str, ssize_t n) if (n > 0) memcpy(&text[cursor], str, n); cursor += n; - match(); + fuzzymatch(); } static size_t @@ -309,7 +390,7 @@ keypress(XKeyEvent *ev) case XK_k: /* delete right */ text[cursor] = '\0'; - match(); + fuzzymatch(); break; case XK_u: /* delete left */ insert(NULL, 0 - cursor); @@ -443,7 +524,7 @@ keypress(XKeyEvent *ev) strncpy(text, sel->text, sizeof text - 1); text[sizeof text - 1] = '\0'; cursor = strlen(text); - match(); + fuzzymatch(); break; } drawmenu(); @@ -585,7 +666,7 @@ setup(void) } promptw = (prompt && *prompt) ? TEXTW(prompt) : 0; inputw = MIN(inputw, mw/3); - match(); + fuzzymatch(); /* create menu window */ swa.override_redirect = True;
diff --git a/dmenu.c b/dmenu.c index e0c2f80..ef25442 100644 --- a/dmenu.c +++ b/dmenu.c @@ -487,6 +487,7 @@ readstdin(void) } if (items) items[i].text = NULL; + if (i == 1 && items[0].text[0] == '\0') items = realloc(items, 0); inputw = maxstr ? TEXTW(maxstr) : 0; lines = MIN(lines, i); }
diff --git a/config.def.h b/config.def.h index 8db1dda..f941d84 100644 --- a/config.def.h +++ b/config.def.h @@ -2,6 +2,8 @@ /* Default settings; can be overriden by command line. */ static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +static int instant = 0; /* -n option; if 1, dmenu ends immediately on a + distinct match */ /* -fn option overrides fonts[0]; default X11 font or font set */ static const char *fonts[] = { "monospace:size=10" diff --git a/dmenu.c b/dmenu.c index e0c2f80..340baa9 100644 --- a/dmenu.c +++ b/dmenu.c @@ -250,6 +250,11 @@ match(void) matchend = substrend; } curr = sel = matches; + if(instant && matches && matches==matchend && !lsubstr) { + puts(matches->next); + cleanup; + exit(0); + } calcoffsets(); } @@ -632,7 +637,9 @@ main(int argc, char *argv[]) else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ fstrncmp = strncasecmp; fstrstr = cistrstr; - } else if (i + 1 == argc) + } else if (!strcmp(argv[i], "-n")) /* instant match */ + instant = !instant; + else if (i + 1 == argc) usage(); /* these options take one argument */ else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */