aboutsummaryrefslogtreecommitdiff
path: root/ask.c
diff options
context:
space:
mode:
Diffstat (limited to 'ask.c')
-rw-r--r--ask.c104
1 files changed, 74 insertions, 30 deletions
diff --git a/ask.c b/ask.c
index 409161f..7ea4de5 100644
--- a/ask.c
+++ b/ask.c
@@ -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