diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2019-06-06 17:46:59 -0700 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2019-06-06 17:46:59 -0700 |
| commit | 88ed75a56bfebbaa9c5c023ebe2e03664106edbc (patch) | |
| tree | 254866877a59b2578b8561107de2b0122d9f4fdd /ask.c | |
| parent | 5f84d6988193a81d52e54696503d624a4e43780e (diff) | |
Added --yes and --no options, and renamed --initial to --query for
compatibility with fzf and fzy
Diffstat (limited to 'ask.c')
| -rw-r--r-- | ask.c | 104 |
1 files changed, 74 insertions, 30 deletions
@@ -1,12 +1,15 @@ /* ask - a simple command line asker * Copyright 2019 Bruce Hill * Released under the MIT License (see LICENSE for details) - * Usage: ask [-q|--quickpick] [-p|--password] [-v|--version] [-h|--help] [--initial=initial] [prompt [options...]] + * Usage: ask [-Q|--quickpick] [-y|--yes] [-n|--no] [-p|--password] + * [-v|--version] [-h|--help] [-q |--query=initial] [[--prompt=]prompt [options...]] * --password: password mode * --quickpick: quickpick mode (exit when only one option remains) * --version: print version and exit * --help: print usage and exit - * --initial: initial value to pre-populate user input + * --query: initial value to pre-populate user input + * --prompt: use the given prompt (displayed in bold) + * --yes: append "[Y/n]" to the prompt, use quickpick mode, */ #include <poll.h> #include <stdio.h> @@ -19,6 +22,7 @@ #include "bterm.h" +#define ASK_VERSION "0.2" #define LOWERCASE(c) ('A' <= (c) && (c) <= 'Z' ? ((c) + 'a' - 'A') : (c)) #define EQ(a, b) (case_sensitive ? (a) == (b) : LOWERCASE(a) == LOWERCASE(b)) #define PASSWORD "-\\|/" @@ -125,7 +129,6 @@ static int draw_line(FILE *out, const char *line, const char *patt, int cursor) */ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *initial, int nopts, char **opts) { - if (!prompt) prompt = "> "; fprintf(out, "\033[K\033[0;1m%s\033[0m", prompt); size_t cap = initial ? strlen(initial) + 100 : 100; char *buf = memcheck(calloc(cap, 1)); @@ -184,7 +187,6 @@ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *init switch (key) { case -1: case -2: case -3: goto skip_redraw; case '\r': - // TODO: support backslash-enter goto finished; case KEY_CTRL_C: case KEY_ESC: free(buf); @@ -295,28 +297,21 @@ static char *get_input(FILE *in, FILE *out, const char *prompt, const char *init int main(int argc, char *argv[]) { - FILE *tty_in = fopen("/dev/tty", "r"); - FILE *tty_out = fopen("/dev/tty", "w"); - struct termios orig_termios, bb_termios; - tcgetattr(fileno(tty_out), &orig_termios); - cfmakeraw(&bb_termios); - if (tcsetattr(fileno(tty_out), TCSAFLUSH, &bb_termios) == -1) - return 1; - - char *prompt = NULL, *initial = NULL; - char **lines = NULL; + int yes = 0, no = 0; + char *prompt = NULL, *query = NULL; + char **opts = NULL; size_t linescap = 0, linecap = 0; - int nlines = 0; + int nopts = 0; char *line = NULL; struct pollfd pfd = {STDIN_FILENO, POLLIN, 0}; if (poll(&pfd, 1, 50) > 0) { while ((getline(&line, &linecap, stdin)) >= 0) { - if ((size_t)nlines >= linescap) - lines = memcheck(realloc(lines, (linescap += 100)*sizeof(char*))); + if ((size_t)nopts >= linescap) + opts = memcheck(realloc(opts, (linescap += 100)*sizeof(char*))); if (!line[0]) continue; if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0'; - lines[nlines++] = memcheck(strdup(line)); + opts[nopts++] = memcheck(strdup(line)); } } int a = 1; @@ -324,26 +319,41 @@ int main(int argc, char *argv[]) if (argv[a][0] == '-' && argv[a][1] != '-') { for (char *p = &argv[a][1]; *p; p++) { switch (*p) { - case 'p': password = 1; break; + case 'P': password = 1; break; case 'q': quickpick = 1; break; case 'h': goto help_flag; case 'v': goto version_flag; + case 'y': yes = 1; quickpick = 1; break; + case 'n': no = 1; quickpick = 1; break; } } - } else if (strncmp(argv[a], "--initial=", strlen("--initial=")) == 0) { - initial = &argv[a][strlen("--initial=")]; + } else if (strcmp(argv[a], "-p") == 0) { + prompt = argv[++a]; + } else if (strcmp(argv[a], "-q") == 0) { + query = argv[++a]; + } else if (strncmp(argv[a], "--prompt=", strlen("--prompt=")) == 0) { + prompt = &argv[a][strlen("--prompt=")]; + } else if (strncmp(argv[a], "--query=", strlen("--query=")) == 0) { + query = &argv[a][strlen("--query=")]; } else if (strcmp(argv[a], "--password") == 0) { password = 1; } else if (strcmp(argv[a], "--quickpick") == 0) { quickpick = 1; + } else if (strcmp(argv[a], "--yes") == 0) { + yes = 1; + quickpick = 1; + } else if (strcmp(argv[a], "--no") == 0) { + no = 1; + quickpick = 1; } else if (strcmp(argv[a], "--help") == 0) { help_flag: printf("ask - A simple command line input tool.\n" - "Usage: ask [-q|--quickpick] [-p|--password] [-v|--version] [-h|--help] [--initial=initial] [prompt [options...]]\n"); + "Usage: ask [-Q|--quickpick] [-P|--password] [-v|--version] [-h|--help] " + "[-y|--yes] [-n|--no] [-q |--query=query] [[-p |--prompt=]prompt [options...]]\n"); return 0; } else if (strcmp(argv[a], "--version") == 0) { version_flag: - printf("ask v0.1\n"); + printf("ask %s\n", ASK_VERSION); return 0; } else break; ++a; @@ -351,12 +361,43 @@ int main(int argc, char *argv[]) if (!prompt && a < argc) prompt = argv[a++]; while (a < argc) { - if ((size_t)nlines >= linescap) - lines = memcheck(realloc(lines, (linescap += 100)*sizeof(char*))); - lines[nlines++] = argv[a++]; + if ((size_t)nopts >= linescap) + opts = memcheck(realloc(opts, (linescap += 100)*sizeof(char*))); + opts[nopts++] = argv[a++]; } - char *output = get_input(tty_in, tty_out, prompt, initial, nlines, lines); + if (yes || no) { + if ((size_t)nopts + 4 >= linescap) + opts = memcheck(realloc(opts, (linescap += 4)*sizeof(char*))); + opts[nopts++] = "y"; + opts[nopts++] = "n"; + opts[nopts++] = "Y"; + opts[nopts++] = "N"; + } + + if (yes) { + char *p2 = memcheck(calloc((prompt ? strlen(prompt) : 0)+5+1, sizeof(char))); + if (prompt) strcpy(p2, prompt); + strcat(p2, "[Y/n]"); + prompt = p2; + } else if (no) { + char *p2 = memcheck(calloc((prompt ? strlen(prompt) : 0)+5+1, sizeof(char))); + if (prompt) strcpy(p2, prompt); + strcat(p2, "[y/N]"); + prompt = p2; + } + + if (!prompt) prompt = "> "; + + FILE *tty_in = fopen("/dev/tty", "r"); + FILE *tty_out = fopen("/dev/tty", "w"); + struct termios orig_termios, bb_termios; + tcgetattr(fileno(tty_out), &orig_termios); + cfmakeraw(&bb_termios); + if (tcsetattr(fileno(tty_out), TCSAFLUSH, &bb_termios) == -1) + return 1; + + char *output = get_input(tty_in, tty_out, prompt, query, nopts, opts); fflush(tty_out); tcsetattr(fileno(tty_out), TCSAFLUSH, &orig_termios); @@ -365,13 +406,16 @@ int main(int argc, char *argv[]) fclose(tty_in); tty_in = NULL; + // This doesn't free memory, but it doesn't need to because + // the program is exiting if (!output) return 1; fputs(output, stdout); - free(output); + if (yes) + return strcmp(output, "n") == 0 && strcmp(output, "N") == 0; + if (no) + return strcmp(output, "y") != 0 && strcmp(output, "Y") != 0; - // This doesn't free the memory in lines, but it doesn't need to because - // the program is exiting return 0; } // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1 |
