dmenu-fuzzymatch-4.9.diff - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
dmenu-fuzzymatch-4.9.diff (4683B) | |
--- | |
1 From 94353eb52055927d9079f3d9e33da1c954abf386 Mon Sep 17 00:00:00 2001 | |
2 From: aleks <[email protected]> | |
3 Date: Wed, 26 Jun 2019 13:25:10 +0200 | |
4 Subject: [PATCH] Add support for fuzzy-matching | |
5 | |
6 --- | |
7 config.def.h | 1 + | |
8 config.mk | 2 +- | |
9 dmenu.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
10 3 files changed, 91 insertions(+), 1 deletion(-) | |
11 | |
12 diff --git a/config.def.h b/config.def.h | |
13 index 1edb647..51612b9 100644 | |
14 --- a/config.def.h | |
15 +++ b/config.def.h | |
16 @@ -2,6 +2,7 @@ | |
17 /* Default settings; can be overriden by command line. */ | |
18 | |
19 static int topbar = 1; /* -b option; if 0, dmenu … | |
20 +static int fuzzy = 1; /* -F option; if 0, dmenu d… | |
21 /* -fn option overrides fonts[0]; default X11 font or font set */ | |
22 static const char *fonts[] = { | |
23 "monospace:size=10" | |
24 diff --git a/config.mk b/config.mk | |
25 index 0929b4a..d14309a 100644 | |
26 --- a/config.mk | |
27 +++ b/config.mk | |
28 @@ -20,7 +20,7 @@ FREETYPEINC = /usr/include/freetype2 | |
29 | |
30 # includes and libs | |
31 INCS = -I$(X11INC) -I$(FREETYPEINC) | |
32 -LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) | |
33 +LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm | |
34 | |
35 # flags | |
36 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX… | |
37 diff --git a/dmenu.c b/dmenu.c | |
38 index 6b8f51b..96ddc98 100644 | |
39 --- a/dmenu.c | |
40 +++ b/dmenu.c | |
41 @@ -1,6 +1,7 @@ | |
42 /* See LICENSE file for copyright and license details. */ | |
43 #include <ctype.h> | |
44 #include <locale.h> | |
45 +#include <math.h> | |
46 #include <stdio.h> | |
47 #include <stdlib.h> | |
48 #include <string.h> | |
49 @@ -32,6 +33,7 @@ struct item { | |
50 char *text; | |
51 struct item *left, *right; | |
52 int out; | |
53 + double distance; | |
54 }; | |
55 | |
56 static char text[BUFSIZ] = ""; | |
57 @@ -210,9 +212,94 @@ grabkeyboard(void) | |
58 die("cannot grab keyboard"); | |
59 } | |
60 | |
61 +int | |
62 +compare_distance(const void *a, const void *b) | |
63 +{ | |
64 + struct item *da = *(struct item **) a; | |
65 + struct item *db = *(struct item **) b; | |
66 + | |
67 + if (!db) | |
68 + return 1; | |
69 + if (!da) | |
70 + return -1; | |
71 + | |
72 + return da->distance == db->distance ? 0 : da->distance < db->di… | |
73 +} | |
74 + | |
75 +void | |
76 +fuzzymatch(void) | |
77 +{ | |
78 + /* bang - we have so much memory */ | |
79 + struct item *it; | |
80 + struct item **fuzzymatches = NULL; | |
81 + char c; | |
82 + int number_of_matches = 0, i, pidx, sidx, eidx; | |
83 + int text_len = strlen(text), itext_len; | |
84 + | |
85 + matches = matchend = NULL; | |
86 + | |
87 + /* walk through all items */ | |
88 + for (it = items; it && it->text; it++) { | |
89 + if (text_len) { | |
90 + itext_len = strlen(it->text); | |
91 + pidx = 0; /* pointer */ | |
92 + sidx = eidx = -1; /* start of match, end of mat… | |
93 + /* walk through item text */ | |
94 + for (i = 0; i < itext_len && (c = it->text[i]);… | |
95 + /* fuzzy match pattern */ | |
96 + if (!fstrncmp(&text[pidx], &c, 1)) { | |
97 + if(sidx == -1) | |
98 + sidx = i; | |
99 + pidx++; | |
100 + if (pidx == text_len) { | |
101 + eidx = i; | |
102 + break; | |
103 + } | |
104 + } | |
105 + } | |
106 + /* build list of matches */ | |
107 + if (eidx != -1) { | |
108 + /* compute distance */ | |
109 + /* add penalty if match starts late (lo… | |
110 + * add penalty for long a match without… | |
111 + it->distance = log(sidx + 2) + (double)… | |
112 + /* fprintf(stderr, "distance %s %f\n", … | |
113 + appenditem(it, &matches, &matchend); | |
114 + number_of_matches++; | |
115 + } | |
116 + } else { | |
117 + appenditem(it, &matches, &matchend); | |
118 + } | |
119 + } | |
120 + | |
121 + if (number_of_matches) { | |
122 + /* initialize array with matches */ | |
123 + if (!(fuzzymatches = realloc(fuzzymatches, number_of_ma… | |
124 + die("cannot realloc %u bytes:", number_of_match… | |
125 + for (i = 0, it = matches; it && i < number_of_matches; … | |
126 + fuzzymatches[i] = it; | |
127 + } | |
128 + /* sort matches according to distance */ | |
129 + qsort(fuzzymatches, number_of_matches, sizeof(struct it… | |
130 + /* rebuild list of matches */ | |
131 + matches = matchend = NULL; | |
132 + for (i = 0, it = fuzzymatches[i]; i < number_of_matche… | |
133 + it->text; i++, it = fuzzymatches[i]) { | |
134 + appenditem(it, &matches, &matchend); | |
135 + } | |
136 + free(fuzzymatches); | |
137 + } | |
138 + curr = sel = matches; | |
139 + calcoffsets(); | |
140 +} | |
141 + | |
142 static void | |
143 match(void) | |
144 { | |
145 + if (fuzzy) { | |
146 + fuzzymatch(); | |
147 + return; | |
148 + } | |
149 static char **tokv = NULL; | |
150 static int tokn = 0; | |
151 | |
152 @@ -702,6 +789,8 @@ main(int argc, char *argv[]) | |
153 topbar = 0; | |
154 else if (!strcmp(argv[i], "-f")) /* grabs keyboard be… | |
155 fast = 1; | |
156 + else if (!strcmp(argv[i], "-F")) /* grabs keyboard be… | |
157 + fuzzy = 0; | |
158 else if (!strcmp(argv[i], "-i")) { /* case-insensitive … | |
159 fstrncmp = strncasecmp; | |
160 fstrstr = cistrstr; | |
161 -- | |
162 2.22.0 | |
163 |