Add ask() as a way to get user input

This commit is contained in:
Bruce Hill 2024-09-04 14:55:00 -04:00
parent 570c4c63ca
commit 05bc754679
3 changed files with 54 additions and 2 deletions

View File

@ -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] != '-') {

View File

@ -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);

View File

@ -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)}},
};