commit - 8d9debb10d556ef174679dd8ec449a1fee587a13
commit + e9f0b46746ab1311a17ca5270941e67640710ec7
blob - 31e3381fac391fcc9efb66aa8025dccd8c7344f5
blob + eb15fa7216d49f57891354c550d1defa2790f9d4
--- mymenu.c
+++ mymenu.c
# define strcasestr strstr
#endif
-#define update_completions(cs, text, lines) { \
- compl_delete_rec(cs); \
- cs = filter(text, lines); \
+#define update_completions(cs, text, lines, first_selected) { \
+ compl_delete_rec(cs); \
+ cs = filter(text, lines); \
+ if (first_selected && cs != nil) \
+ cs->selected = true; \
}
#define complete(cs, nothing_selected, p, text, textlen, status) { \
return str;
}
+// read an arbitrary amount of text until an EOF and store it in
+// lns. `items` is the capacity of lns. It may increase lns with
+// `realloc(3)` to store more line. Return the number of lines
+// read. The last item will always be a NULL pointer. It ignore the
+// "null" (empty) lines
int readlines (char ***lns, int items) {
bool finished = false;
int n = 0;
return parse_int_with_percentage(str, default_value, max);
}
-int main() {
+void usage(char *prgname) {
+ fprintf(stderr, "Usage: %s [flags]\n", prgname);
+ fprintf(stderr, "\t-a: automatic mode, the first completion is "
+ "always selected;\n");
+ fprintf(stderr, "\t-h: print this help.\n");
+}
+
+int exit_cleanup(struct rendering *r, char *ps1, char *fontname, char *text, char **lines, struct completions *cs, int status) {
+ release_keyboard(r->d);
+
+#ifdef USE_XFT
+ XftColorFree(r->d, DefaultVisual(r->d, 0), DefaultColormap(r->d, 0), &r->xft_prompt);
+ XftColorFree(r->d, DefaultVisual(r->d, 0), DefaultColormap(r->d, 0), &r->xft_completion);
+ XftColorFree(r->d, DefaultVisual(r->d, 0), DefaultColormap(r->d, 0), &r->xft_completion_highlighted);
+#endif
+
+ free(ps1);
+ free(fontname);
+ free(text);
+
+ char *l = nil;
+ char **lns = lines;
+ while ((l = *lns) != nil) {
+ free(l);
+ ++lns;
+ }
+ free(lines);
+ compl_delete(cs);
+
+ XDestroyWindow(r->d, r->w);
+ XCloseDisplay(r->d);
+
+ return status;
+}
+
+int main(int argc, char **argv) {
+ // by default the first completion isn't selected
+ bool first_selected = false;
+
+ // parse the command line options
+ int ch;
+ while ((ch = getopt(argc, argv, "ah")) != -1) {
+ switch (ch) {
+ case 'a':
+ first_selected = true;
+ break;
+ case 'h':
+ usage(*argv);
+ return 0;
+ default:
+ usage(*argv);
+ return EX_USAGE;
+ }
+ }
+
char **lines = calloc(INITIAL_ITEMS, sizeof(char*));
- int nlines = readlines(&lines, INITIAL_ITEMS);
+ readlines(&lines, INITIAL_ITEMS);
setlocale(LC_ALL, getenv("LANG"));
int x = 0;
int y = 0;
+ // the default padding
int padding = 10;
char *ps1 = strdup("$ ");
char *text = malloc(textlen * sizeof(char));
check_allocation(text);
- struct completions *cs = filter(text, lines);
- bool nothing_selected = true;
+ bool nothing_selected = first_selected;
+ /* struct completions *cs = filter(text, lines); */
+ struct completions *cs = nil;
+ update_completions(cs, text, lines, first_selected);
// start talking to xorg
Display *d = XOpenDisplay(nil);
}
if (ev->keycode == XKeysymToKeycode(d, XK_BackSpace)) {
- nothing_selected = true;
+ nothing_selected = first_selected;
popc(text, textlen);
- update_completions(cs, text, lines);
+ update_completions(cs, text, lines, first_selected);
draw(&r, text, cs);
break;
}
if (ev->keycode == XKeysymToKeycode(d, XK_Return)) {
status = OK;
+ if (first_selected) {
+ complete(cs, first_selected, false, text, textlen, status);
+ }
break;
}
if (ev->state & ControlMask) {
// check for some key bindings
if (!strcmp(str, "")) { // C-u
- nothing_selected = true;
+ nothing_selected = first_selected;
for (int i = 0; i < textlen; ++i)
text[i] = 0;
- update_completions(cs, text, lines);
+ update_completions(cs, text, lines, first_selected);
}
if (!strcmp(str, "")) { // C-h
- nothing_selected = true;
+ nothing_selected = first_selected;
popc(text, textlen);
- update_completions(cs, text, lines);
+ update_completions(cs, text, lines, first_selected);
}
if (!strcmp(str, "")) { // C-w
- nothing_selected = true;
+ nothing_selected = first_selected;
// `textlen` is the length of the allocated string, not the
// length of the ACTUAL string
text[p] = 0;
p--;
}
- update_completions(cs, text, lines);
+ update_completions(cs, text, lines, first_selected);
}
if (!strcmp(str, "\r")) { // C-m
status = OK;
+ if (first_selected) {
+ complete(cs, first_selected, false, text, textlen, status);
+ }
}
if (!strcmp(str, "")) {
complete(cs, nothing_selected, true, text, textlen, status);
status = ERR;
break;
}
- nothing_selected = true;
- update_completions(cs, text, lines);
+ nothing_selected = first_selected;
+ update_completions(cs, text, lines, first_selected);
}
}
}
}
- release_keyboard(d);
-
if (status == OK)
printf("%s\n", text);
- for (int i = 0; i < nlines; ++i) {
- free(lines[i]);
- }
-
-#ifdef USE_XFT
- XftColorFree(d, DefaultVisual(d, 0), DefaultColormap(d, 0), &r.xft_prompt);
- XftColorFree(d, DefaultVisual(d, 0), DefaultColormap(d, 0), &r.xft_completion);
- XftColorFree(d, DefaultVisual(d, 0), DefaultColormap(d, 0), &r.xft_completion_highlighted);
-#endif
-
- free(ps1);
- free(fontname);
- free(text);
- free(lines);
- compl_delete(cs);
-
- XDestroyWindow(d, w);
- XCloseDisplay(d);
-
- return status == OK ? 0 : 1;
+ return exit_cleanup(&r, ps1, fontname, text, lines, cs, status == OK ? 0 : 1);
}