diff options
Diffstat (limited to 'client/common')
-rw-r--r-- | client/common/common.c | 274 | ||||
-rw-r--r-- | client/common/common.h | 28 |
2 files changed, 302 insertions, 0 deletions
diff --git a/client/common/common.c b/client/common/common.c new file mode 100644 index 0000000..e34a34f --- /dev/null +++ b/client/common/common.c @@ -0,0 +1,274 @@ +#define _DEFAULT_SOURCE +#include "common.h" +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> +#include <getopt.h> +#include <assert.h> + +static void +disco_trap(int sig) +{ + (void)sig; + printf("\e[?25h\n"); + fflush(stdout); + exit(EXIT_FAILURE); +} + +static void +disco(void) +{ + struct sigaction action; + memset(&action, 0, sizeof(struct sigaction)); + action.sa_handler = disco_trap; + sigaction(SIGABRT, &action, NULL); + sigaction(SIGSEGV, &action, NULL); + sigaction(SIGTRAP, &action, NULL); + sigaction(SIGINT, &action, NULL); + + uint32_t cc, c = 80; + printf("\e[?25l"); + while (1) { + for (uint32_t i = 1; i < c - 1; ++i) { + printf("\r %*s%s %s %s ", (i > c / 2 ? c - i : i), " ", ((i % 2) ? "<o/" : "\\o>"), ((i % 4) ? "DISCO" : " "), ((i %2) ? "\\o>" : "<o/")); + for (cc = 0; cc < (i < c / 2 ? c / 2 - i : i - c / 2); ++cc) printf(((i % 2) ? "^" : "'")); + printf("%s %s \r %s %s", ((i % 2) ? "*" : "•"), ((i % 3) ? "\\o" : "<o"), ((i % 3) ? "o/" : "o>"), ((i % 2) ? "*" : "•")); + for (cc = 2; cc < (i > c / 2 ? c - i : i); ++cc) printf(((i % 2) ? "^" : "'")); + fflush(stdout); + usleep(140 * 1000); + } + } + printf("\e[?25h"); + exit(EXIT_SUCCESS); +} + +static void +version(const char *name) +{ + assert(name); + char *base = strrchr(name, '/'); + printf("%s v%s\n", (base ? base + 1 : name), bm_version()); + exit(EXIT_SUCCESS); +} + +static void +usage(FILE *out, const char *name) +{ + assert(out && name); + + char *base = strrchr(name, '/'); + fprintf(out, "usage: %s [options]\n", (base ? base + 1 : name)); + fputs("Options\n" + " -h, --help display this help and exit.\n" + " -v, --version display version.\n" + " -i, --ignorecase match items case insensitively.\n" + " -w, --wrap wraps cursor selection.\n" + " -l, --list list items vertically with the given number of lines.\n" + " -p, --prompt defines the prompt text to be displayed.\n" + " -I, --index select item at index automatically.\n" + " --backend options: curses, wayland\n" + " --prioritory options: terminal, gui\n\n" + + "Backend specific options\n" + " c = ncurses, w == wayland\n" + " (...) At end of help indicates the backend support for option.\n\n" + + " -b, --bottom appears at the bottom of the screen. ()\n" + " -f, --grab grabs the keyboard before reading stdin. ()\n" + " -m, --monitor index of monitor where menu will appear. ()\n" + " --fn defines the font to be used. (w)\n" + " --bg defines the background color. (w)\n" + " --tb defines the title background color. (w)\n" + " --tf defines the title foreground color. (w)\n" + " --fb defines the filter background color. (w)\n" + " --ff defines the filter foreground color. (w)\n" + " --nb defines the normal background color. (w)\n" + " --nf defines the normal foreground color. (w)\n" + " --hb defines the highlighted background color. (w)\n" + " --hf defines the highlighted foreground color. (w)\n" + " --sb defines the selected background color. (w)\n" + " --sf defines the selected foreground color. (w)\n", out); + + exit((out == stderr ? EXIT_FAILURE : EXIT_SUCCESS)); +} + +void +parse_args(struct client *client, int *argc, char **argv[]) +{ + assert(client && argc && argv); + + static const struct option opts[] = { + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + + { "ignorecase", no_argument, 0, 'i' }, + { "wrap", no_argument, 0, 'w' }, + { "list", required_argument, 0, 'l' }, + { "prompt", required_argument, 0, 'p' }, + { "index", required_argument, 0, 'I' }, + { "backend", required_argument, 0, 0x100 }, + { "prioritory", required_argument, 0, 0x101 }, + + { "bottom", no_argument, 0, 'b' }, + { "grab", no_argument, 0, 'f' }, + { "monitor", required_argument, 0, 'm' }, + { "fn", required_argument, 0, 0x102 }, + { "bg", required_argument, 0, 0x103 }, + { "tb", required_argument, 0, 0x104 }, + { "tf", required_argument, 0, 0x105 }, + { "fb", required_argument, 0, 0x106 }, + { "ff", required_argument, 0, 0x107 }, + { "nb", required_argument, 0, 0x108 }, + { "nf", required_argument, 0, 0x109 }, + { "hb", required_argument, 0, 0x110 }, + { "hf", required_argument, 0, 0x111 }, + { "sb", required_argument, 0, 0x112 }, + { "sf", required_argument, 0, 0x113 }, + + { "disco", no_argument, 0, 0x114 }, + { 0, 0, 0, 0 } + }; + + /* TODO: getopt does not support -sf, -sb etc.. + * Either break the interface and make them --sf, --sb (like they are now), + * or parse them before running getopt.. */ + + for (;;) { + int32_t opt = getopt_long(*argc, *argv, "hviwl:I:p:I:bfm:", opts, NULL); + if (opt < 0) + break; + + switch (opt) { + case 'h': + usage(stdout, *argv[0]); + break; + case 'v': + version(*argv[0]); + break; + + case 'i': + client->filter_mode = BM_FILTER_MODE_DMENU_CASE_INSENSITIVE; + break; + case 'w': + client->wrap = 1; + break; + case 'l': + client->lines = strtol(optarg, NULL, 10); + break; + case 'p': + client->title = optarg; + break; + case 'I': + client->selected = strtol(optarg, NULL, 10); + break; + + case 0x100: + client->renderer = optarg; + break; + + case 0x101: + if (!strcmp(optarg, "terminal")) + client->prioritory = BM_PRIO_TERMINAL; + else if (!strcmp(optarg, "gui")) + client->prioritory = BM_PRIO_GUI; + break; + + case 'b': + client->bottom = 1; + break; + case 'f': + client->grab = 1; + break; + case 'm': + client->monitor = strtol(optarg, NULL, 10); + break; + + case 0x102: + if (sscanf(optarg, "%ms:%u", &client->font, &client->font_size) < 2) + sscanf(optarg, "%ms", &client->font); + break; + case 0x103: + client->colors[BM_COLOR_BG] = optarg; + break; + case 0x104: + client->colors[BM_COLOR_TITLE_BG] = optarg; + break; + case 0x105: + client->colors[BM_COLOR_TITLE_FG] = optarg; + break; + case 0x106: + client->colors[BM_COLOR_FILTER_BG] = optarg; + break; + case 0x107: + client->colors[BM_COLOR_FILTER_FG] = optarg; + break; + case 0x108: + client->colors[BM_COLOR_ITEM_BG] = optarg; + break; + case 0x109: + client->colors[BM_COLOR_ITEM_FG] = optarg; + break; + case 0x110: + client->colors[BM_COLOR_HIGHLIGHTED_BG] = optarg; + break; + case 0x111: + client->colors[BM_COLOR_HIGHLIGHTED_FG] = optarg; + break; + case 0x112: + client->colors[BM_COLOR_SELECTED_BG] = optarg; + break; + case 0x113: + client->colors[BM_COLOR_SELECTED_FG] = optarg; + break; + + case 0x114: + disco(); + break; + + case ':': + case '?': + fputs("\n", stderr); + usage(stderr, *argv[0]); + break; + } + } + + *argc -= optind; + *argv += optind; +} + +struct bm_menu* +menu_with_options(struct client *client) +{ + struct bm_menu *menu; + if (!(menu = bm_menu_new(client->renderer, client->prioritory))) + return NULL; + + bm_menu_set_font(menu, client->font, client->font_size); + bm_menu_set_title(menu, client->title); + bm_menu_set_filter_mode(menu, client->filter_mode); + bm_menu_set_lines(menu, client->lines); + bm_menu_set_wrap(menu, client->wrap); + + for (uint32_t i = 0; i < BM_COLOR_LAST; ++i) + bm_menu_set_color(menu, i, client->colors[i]); + + return menu; +} + +enum bm_run_result +run_menu(struct bm_menu *menu) +{ + uint32_t unicode; + enum bm_key key; + enum bm_run_result status = BM_RUN_RESULT_RUNNING; + do { + bm_menu_render(menu); + key = bm_menu_poll_key(menu, &unicode); + } while ((status = bm_menu_run_with_key(menu, key, unicode)) == BM_RUN_RESULT_RUNNING); + return status; +} + +/* vim: set ts=8 sw=4 tw=0 :*/ diff --git a/client/common/common.h b/client/common/common.h new file mode 100644 index 0000000..b87b974 --- /dev/null +++ b/client/common/common.h @@ -0,0 +1,28 @@ +#ifndef _BM_COMMON_H_ +#define _BM_COMMON_H_ + +#include <bemenu.h> + +struct client { + enum bm_prioritory prioritory; + enum bm_filter_mode filter_mode; + int32_t wrap; + uint32_t lines; + const char *colors[BM_COLOR_LAST]; + const char *title; + const char *renderer; + char *font; + uint32_t font_size; + int32_t selected; + int32_t bottom; + int32_t grab; + int32_t monitor; +}; + +void parse_args(struct client *client, int *argc, char **argv[]); +struct bm_menu* menu_with_options(struct client *client); +enum bm_run_result run_menu(struct bm_menu *menu); + +#endif /* _BM_COMMON_H_ */ + +/* vim: set ts=8 sw=4 tw=0 :*/ |