sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit bf855bf3633535109899c72365de7120cd4b28aa
parent 101b4f823dfba334524ef46990d60885e9bff477
Author: FRIGN <dev@frign.de>
Date:   Tue, 20 Oct 2015 21:53:40 +0200

Update fuzzymatch patch

Reflecting recent changes in the codebase and using common practices.

Diffstat:
Atools.suckless.org/dmenu/patches/dmenu-git-20151020-fuzzymatch.diff | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dtools.suckless.org/dmenu/patches/dmenu-git-fuzzymatch.diff | 143-------------------------------------------------------------------------------
Mtools.suckless.org/dmenu/patches/fuzzymatch.md | 24+++++++++---------------
3 files changed, 144 insertions(+), 158 deletions(-)

diff --git a/tools.suckless.org/dmenu/patches/dmenu-git-20151020-fuzzymatch.diff b/tools.suckless.org/dmenu/patches/dmenu-git-20151020-fuzzymatch.diff @@ -0,0 +1,135 @@ +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; + bool 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/tools.suckless.org/dmenu/patches/dmenu-git-fuzzymatch.diff b/tools.suckless.org/dmenu/patches/dmenu-git-fuzzymatch.diff @@ -1,143 +0,0 @@ -Author: Jan Christoph Ebersbach <jceb@e-jc.de> -URL: http://tools.suckless.org/dmenu/patches/fuzzymatch -Add add fuzzy matching to dmenu - -Index: dmenu-patches/dmenu/dmenu.c -=================================================================== ---- dmenu-patches.orig/dmenu/dmenu.c -+++ dmenu-patches/dmenu/dmenu.c -@@ -23,12 +23,14 @@ struct Item { - char *text; - Item *left, *right; - Bool out; -+ int distance; - }; - - static void appenditem(Item *item, Item **list, Item **last); - static void calcoffsets(void); - static char *cistrstr(const char *s, const char *sub); - static void drawmenu(void); -+static void fuzzymatch(void); - static void grabkeyboard(void); - static void insert(const char *str, ssize_t n); - static void keypress(XKeyEvent *ev); -@@ -231,7 +233,7 @@ insert(const char *str, ssize_t n) { - if(n > 0) - memcpy(&text[cursor], str, n); - cursor += n; -- match(); -+ fuzzymatch(); - } - - void -@@ -264,7 +266,7 @@ keypress(XKeyEvent *ev) { - - case XK_k: /* delete right */ - text[cursor] = '\0'; -- match(); -+ fuzzymatch(); - break; - case XK_u: /* delete left */ - insert(NULL, 0 - cursor); -@@ -393,7 +395,7 @@ keypress(XKeyEvent *ev) { - strncpy(text, sel->text, sizeof text - 1); - text[sizeof text - 1] = '\0'; - cursor = strlen(text); -- match(); -+ fuzzymatch(); - break; - } - drawmenu(); -@@ -597,7 +599,7 @@ setup(void) { - } - promptw = (prompt && *prompt) ? textw(dc, prompt) : 0; - inputw = MIN(inputw, mw/3); -- match(); -+ fuzzymatch(); - - /* create menu window */ - swa.override_redirect = True; -Index: dmenu-patches/dmenu/fuzzymatch.c -=================================================================== ---- /dev/null -+++ dmenu-patches/dmenu/fuzzymatch.c -@@ -0,0 +1,79 @@ -+int -+compare_distance(const void *a, const void *b) { -+ Item const *da = *(Item **) a; -+ Item const *db = *(Item **) b; -+ if(!db) -+ return 1; -+ if(!da) -+ return -1; -+ return da->distance - db->distance; -+} -+ -+void -+fuzzymatch(void) { -+ /* bang - we have so much memory */ -+ Item *item; -+ Item **fuzzymatches = NULL; -+ char c; -+ int number_of_matches = 0, i, pidx, sidx, eidx; -+ int text_len = strlen(text), itext_len; -+ -+ matches = matchend = NULL; -+ -+ /* suppress compiler warning for unused match function */ -+ if(0) -+ match(); -+ -+ /* walk through all items */ -+ for(item = items; item && item->text; item++) { -+ if(text_len) { -+ itext_len = strlen(item->text); -+ pidx = 0; -+ sidx = eidx = -1; -+ /* walk through item text */ -+ for(i = 0; i < itext_len && (c = item->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 */ -+ item->distance = eidx - sidx + (itext_len - eidx + sidx) / 3; -+ appenditem(item, &matches, &matchend); -+ number_of_matches++; -+ } -+ } -+ else -+ appenditem(item, &matches, &matchend); -+ } -+ -+ if(number_of_matches) { -+ /* initialize array with matches */ -+ if(!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(Item*)))) -+ eprintf("cannot realloc %u bytes:", number_of_matches * sizeof(Item*)); -+ for(i = 0, item = matches; item && i < number_of_matches; i++, item = item->right) { -+ fuzzymatches[i] = item; -+ } -+ /* sort matches according to distance */ -+ qsort(fuzzymatches, number_of_matches, sizeof(Item*), compare_distance); -+ /* rebuild list of matches */ -+ matches = matchend = NULL; -+ for(i = 0, item = fuzzymatches[i]; i < number_of_matches && item && \ -+ item->text; i++, item = fuzzymatches[i]) { -+ appenditem(item, &matches, &matchend); -+ } -+ free(fuzzymatches); -+ } -+ curr = sel = matches; -+ calcoffsets(); -+} diff --git a/tools.suckless.org/dmenu/patches/fuzzymatch.md b/tools.suckless.org/dmenu/patches/fuzzymatch.md @@ -1,26 +1,20 @@ -Fuzzy matching support -====================== +fuzzymatch +========== Description ----------- -This patch adds support for fuzzy matching to dmenu. It allows you to type -non-consecutive portions of the string you want to match. - -Usage ------ - -* Apply patch and include `fuzzymatch.c` in `config.h`. - -`#include fuzzymatch.c` +This patch adds support for fuzzy matching to dmenu, allowing users to type +non-consecutive portions of the string to be matched. Download -------- -* [dmenu git](dmenu-git-fuzzymatch.diff) applies cleanly against 13a529ce63364544bdc851dfd5d3aa2ef8740914 -* [dmenu 4.5](dmenu-4.5-fuzzymatch.diff) +* [dmenu-4.5-fuzzymatch.diff](dmenu-4.5-fuzzymatch.diff) +* [dmenu-git-20151020-fuzzymatch.diff](dmenu-git-20151020-fuzzymatch.diff) -History +Authors ------ -Created by [Jan Christoph Ebersbach](https://github.com/jceb/dmenu-patches). +* Jan Christoph Ebersbach - jceb@e-jc.de +* Laslo Hunhold - dev@frign.de (st-git-20151020 port)