sites

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

commit a1a70a3418292922c8f32f0a5a0df0f85719ed36
parent 48934897865fe57309e3b475af4e47c820f62bfa
Author: Jan Christoph Ebersbach <jceb@e-jc.de>
Date:   Tue, 27 Jan 2015 19:42:34 +0100

add fuzzymatch patch

Diffstat:
Atools.suckless.org/dmenu/patches/dmenu-4.5-fuzzymatch.diff | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atools.suckless.org/dmenu/patches/dmenu-git-fuzzymatch.diff | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atools.suckless.org/dmenu/patches/fuzzymatch.md | 26++++++++++++++++++++++++++
3 files changed, 312 insertions(+), 0 deletions(-)

diff --git a/tools.suckless.org/dmenu/patches/dmenu-4.5-fuzzymatch.diff b/tools.suckless.org/dmenu/patches/dmenu-4.5-fuzzymatch.diff @@ -0,0 +1,143 @@ +Author: Jan Christoph Ebersbach <jceb@e-jc.de> +URL: no url in suckless wiki yet +Add add fuzzy matching to dmenu + +Index: dmenu-patches/dmenu/dmenu.c +=================================================================== +--- dmenu-patches.orig/dmenu/dmenu.c ++++ dmenu-patches/dmenu/dmenu.c +@@ -22,12 +22,14 @@ typedef struct Item Item; + struct Item { + char *text; + Item *left, *right; ++ 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); +@@ -230,7 +232,7 @@ insert(const char *str, ssize_t n) { + if(n > 0) + memcpy(&text[cursor], str, n); + cursor += n; +- match(); ++ fuzzymatch(); + } + + void +@@ -260,7 +262,7 @@ keypress(XKeyEvent *ev) { + + case XK_k: /* delete right */ + text[cursor] = '\0'; +- match(); ++ fuzzymatch(); + break; + case XK_u: /* delete left */ + insert(NULL, 0 - cursor); +@@ -379,7 +381,7 @@ keypress(XKeyEvent *ev) { + return; + strncpy(text, sel->text, sizeof text); + cursor = strlen(text); +- match(); ++ fuzzymatch(); + break; + } + drawmenu(); +@@ -578,7 +580,7 @@ setup(void) { + } + promptw = 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/dmenu-git-fuzzymatch.diff b/tools.suckless.org/dmenu/patches/dmenu-git-fuzzymatch.diff @@ -0,0 +1,143 @@ +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 @@ -0,0 +1,26 @@ +Fuzzy matching support +====================== + +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` + +Download +-------- + +* [dmenu git](dmenu-git-fuzzymatch.diff) applies cleanly against 13a529ce63364544bdc851dfd5d3aa2ef8740914 +* [dmenu 4.5](dmenu-4.5-fuzzymatch.diff) + +History +------ + +Created by [Jan Christoph Ebersbach](https://github.com/jceb/dmenu-patches).