dmenu-json-4.9-r2.diff (6200B)
1 diff --git a/config.mk b/config.mk 2 index 0929b4a..4627988 100644 3 --- a/config.mk 4 +++ b/config.mk 5 @@ -18,13 +18,19 @@ FREETYPEINC = /usr/include/freetype2 6 # OpenBSD (uncomment) 7 #FREETYPEINC = $(X11INC)/freetype2 8 9 +# jansson 10 +JANSSONINC = `pkg-config --cflags jansson` 11 +JANSSONLIBS = `pkg-config --libs jansson` 12 +# uncomment on RHEL for strcasecmp 13 +#EXTRAFLAGS=-D_GNU_SOURCE 14 + 15 # includes and libs 16 -INCS = -I$(X11INC) -I$(FREETYPEINC) 17 -LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) 18 +INCS = -I$(X11INC) -I$(FREETYPEINC) $(JANSSONINC) 19 +LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) $(JANSSONLIBS) 20 21 # flags 22 -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) 23 -CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) 24 +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) $(EXTRAFLAGS) 25 +CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) 26 LDFLAGS = $(LIBS) 27 28 # compiler and linker 29 diff --git a/dmenu.c b/dmenu.c 30 index 65f25ce..58c1e23 100644 31 --- a/dmenu.c 32 +++ b/dmenu.c 33 @@ -15,6 +15,7 @@ 34 #include <X11/extensions/Xinerama.h> 35 #endif 36 #include <X11/Xft/Xft.h> 37 +#include <jansson.h> 38 39 #include "drw.h" 40 #include "util.h" 41 @@ -32,6 +33,7 @@ struct item { 42 char *text; 43 struct item *left, *right; 44 int out; 45 + json_t *json; 46 }; 47 48 static char text[BUFSIZ] = ""; 49 @@ -40,6 +42,8 @@ static int bh, mw, mh; 50 static int inputw = 0, promptw; 51 static int lrpad; /* sum of left and right padding */ 52 static size_t cursor; 53 +static size_t items_sz = 0; 54 +static size_t items_ln = 0; 55 static struct item *items = NULL; 56 static struct item *matches, *matchend; 57 static struct item *prev, *curr, *next, *sel; 58 @@ -58,6 +62,18 @@ static Clr *scheme[SchemeLast]; 59 static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; 60 static char *(*fstrstr)(const char *, const char *) = strstr; 61 62 +static void listjson(json_t *obj); 63 +static json_t *json = NULL; 64 + 65 +static struct item * 66 +itemnew(void) 67 +{ 68 + if (items_ln + 1 >= (items_sz / sizeof *items)) 69 + if (!(items = realloc(items, (items_sz += BUFSIZ)))) 70 + die("cannot realloc %u bytes:", items_sz); 71 + return &items[items_ln++]; 72 +} 73 + 74 static void 75 appenditem(struct item *item, struct item **list, struct item **last) 76 { 77 @@ -221,6 +237,8 @@ match(void) 78 size_t len, textsize; 79 struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; 80 81 + if (json) 82 + fstrstr = strcasestr; 83 strcpy(buf, text); 84 /* separate input text into tokens to be matched individually */ 85 for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) 86 @@ -464,7 +482,19 @@ insert: 87 break; 88 case XK_Return: 89 case XK_KP_Enter: 90 - puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); 91 + if (sel && sel->json) { 92 + if (json_is_object(sel->json)) { 93 + listjson(sel->json); 94 + text[0] = '\0'; 95 + match(); 96 + drawmenu(); 97 + break; 98 + } else { 99 + puts(json_string_value(sel->json)); 100 + } 101 + } else { 102 + puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); 103 + } 104 if (!(ev->state & ControlMask)) { 105 cleanup(); 106 exit(0); 107 @@ -519,32 +549,71 @@ paste(void) 108 } 109 110 static void 111 +readjson(const char *path) 112 +{ 113 + json_error_t jerr; 114 + 115 + if (!(json = json_load_file(path, 0, &jerr))) 116 + die("%s @ line: %i - %s", jerr.text, jerr.line, path); 117 +} 118 + 119 +static void 120 +listjson(json_t *obj) 121 +{ 122 + void *iter; 123 + unsigned imax = 0; 124 + unsigned tmpmax = 0; 125 + struct item *item; 126 + 127 + items_ln = 0; 128 + iter = json_object_iter(obj); 129 + while (iter) { 130 + item = itemnew(); 131 + item->text = (char*) json_object_iter_key(iter); 132 + item->json = json_object_iter_value(iter); 133 + item->out = 0; 134 + drw_font_getexts(drw->fonts, item->text, strlen(item->text), 135 + &tmpmax, NULL); 136 + if (tmpmax > inputw) { 137 + inputw = tmpmax; 138 + imax = items_ln - 1; 139 + } 140 + iter = json_object_iter_next(obj, iter); 141 + } 142 + if (items) 143 + items[items_ln].text = NULL; 144 + inputw = items ? TEXTW(items[imax].text) : 0; 145 + lines = MIN(lines, items_ln - 1); 146 +} 147 + 148 +static void 149 readstdin(void) 150 { 151 char buf[sizeof text], *p; 152 - size_t i, imax = 0, size = 0; 153 + size_t i; 154 + unsigned int imax = 0; 155 unsigned int tmpmax = 0; 156 + struct item *item; 157 158 /* read each line from stdin and add it to the item list */ 159 for (i = 0; fgets(buf, sizeof buf, stdin); i++) { 160 - if (i + 1 >= size / sizeof *items) 161 - if (!(items = realloc(items, (size += BUFSIZ)))) 162 - die("cannot realloc %u bytes:", size); 163 + item = itemnew(); 164 if ((p = strchr(buf, '\n'))) 165 *p = '\0'; 166 - if (!(items[i].text = strdup(buf))) 167 + if (!(item->text = strdup(buf))) 168 die("cannot strdup %u bytes:", strlen(buf) + 1); 169 - items[i].out = 0; 170 + item->json = NULL; 171 + item->out = 0; 172 drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); 173 if (tmpmax > inputw) { 174 inputw = tmpmax; 175 - imax = i; 176 + imax = items_ln - 1; 177 } 178 } 179 if (items) 180 - items[i].text = NULL; 181 + items[items_ln].text = NULL; 182 inputw = items ? TEXTW(items[imax].text) : 0; 183 - lines = MIN(lines, i); 184 + lines = MIN(lines, items_ln); 185 } 186 187 static void 188 @@ -689,8 +758,9 @@ setup(void) 189 static void 190 usage(void) 191 { 192 - fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" 193 - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); 194 + fputs("usage: dmenu [-bfiv] [-j json-file] [-l lines] [-p prompt]\n" 195 + " [-fn font] [-m monitor] [-nb color] [-nf color]\n" 196 + " [-sb color] [-sf color] [-w windowid]\n", stderr); 197 exit(1); 198 } 199 200 @@ -715,6 +785,8 @@ main(int argc, char *argv[]) 201 } else if (i + 1 == argc) 202 usage(); 203 /* these options take one argument */ 204 + else if (!strcmp(argv[i], "-j")) 205 + readjson(argv[++i]); 206 else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */ 207 lines = atoi(argv[++i]); 208 else if (!strcmp(argv[i], "-m")) 209 @@ -759,9 +831,15 @@ main(int argc, char *argv[]) 210 211 if (fast && !isatty(0)) { 212 grabkeyboard(); 213 - readstdin(); 214 + if (json) 215 + listjson(json); 216 + else 217 + readstdin(); 218 } else { 219 - readstdin(); 220 + if (json) 221 + listjson(json); 222 + else 223 + readstdin(); 224 grabkeyboard(); 225 } 226 setup();