Add ask() as a way to get user input
This commit is contained in:
parent
570c4c63ca
commit
05bc754679
@ -246,6 +246,48 @@ public void say(Text_t text, bool newline)
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
|
||||
public Text_t ask(Text_t prompt, bool bold, bool force_tty)
|
||||
{
|
||||
Text_t ret = Text("");
|
||||
FILE *out = stdout;
|
||||
FILE *in = stdin;
|
||||
|
||||
if (force_tty && !isatty(STDOUT_FILENO)) {
|
||||
out = fopen("/dev/tty", "w");
|
||||
if (!out) goto cleanup;
|
||||
}
|
||||
|
||||
if (bold) fputs("\x1b[1m", out);
|
||||
Text$print(out, prompt);
|
||||
if (bold) fputs("\x1b[m", out);
|
||||
fflush(out);
|
||||
|
||||
if (force_tty && !isatty(STDIN_FILENO)) {
|
||||
in = fopen("/dev/tty", "r");
|
||||
if (!in) goto cleanup;
|
||||
}
|
||||
|
||||
char *line = NULL;
|
||||
size_t bufsize = 0;
|
||||
ssize_t length = getline(&line, &bufsize, in);
|
||||
if (length == -1) goto cleanup;
|
||||
|
||||
if (length > 0 && line[length-1] == '\n') {
|
||||
line[length-1] = '\0';
|
||||
--length;
|
||||
}
|
||||
|
||||
char *gc_input = GC_MALLOC_ATOMIC(length + 1);
|
||||
memcpy(gc_input, line, length + 1);
|
||||
|
||||
ret = Text$from_strn(gc_input, length);
|
||||
|
||||
cleanup:
|
||||
if (out && out != stdout) fclose(out);
|
||||
if (in && in != stdin) fclose(in);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool pop_flag(char **argv, int *i, const char *flag, Text_t *result)
|
||||
{
|
||||
if (argv[*i][0] != '-' || argv[*i][1] != '-') {
|
||||
|
@ -22,6 +22,7 @@ void end_test(const void *expr, const TypeInfo *type, const char *expected, cons
|
||||
start_test(__SOURCE_FILE__, start, end); \
|
||||
end_test((__typeof__(expr)[1]){expr}, typeinfo, expected, __SOURCE_FILE__, start, end); }
|
||||
void say(Text_t text, bool newline);
|
||||
Text_t ask(Text_t prompt, bool bold, bool force_tty);
|
||||
|
||||
uint64_t generic_hash(const void *obj, const TypeInfo *type);
|
||||
int32_t generic_compare(const void *x, const void *y, const TypeInfo *type);
|
||||
|
@ -30,8 +30,17 @@ env_t *new_compilation_unit(CORD *libname)
|
||||
const char *name;
|
||||
binding_t binding;
|
||||
} global_vars[] = {
|
||||
{"say", {.code="say", .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE,
|
||||
.next=new(arg_t, .name="newline", .type=Type(BoolType), .default_val=FakeAST(Bool, true))), .ret=Type(VoidType))}},
|
||||
{"say", {.code="say", .type=Type(
|
||||
FunctionType, .args=new(arg_t, .name="text", .type=TEXT_TYPE,
|
||||
.next=new(arg_t, .name="newline", .type=Type(BoolType), .default_val=FakeAST(Bool, true))),
|
||||
.ret=Type(VoidType))}},
|
||||
{"ask", {.code="ask", .type=Type(
|
||||
FunctionType, .args=new(arg_t, .name="prompt", .type=TEXT_TYPE,
|
||||
.next=new(arg_t, .name="bold", .type=Type(BoolType),
|
||||
.default_val=FakeAST(Bool, true),
|
||||
.next=new(arg_t, .name="force_tty", .type=Type(BoolType),
|
||||
.default_val=FakeAST(Bool, true)))),
|
||||
.ret=TEXT_TYPE)}},
|
||||
{"fail", {.code="fail", .type=Type(FunctionType, .args=new(arg_t, .name="message", .type=Type(CStringType)), .ret=Type(AbortType))}},
|
||||
{"USE_COLOR", {.code="USE_COLOR", .type=Type(BoolType)}},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user