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 :*/  | 
