diff options
author | Timothee Cour <timothee.cour2@gmail.com> | 2021-02-09 05:25:38 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-09 14:25:38 +0100 |
commit | 630f867bd71336b1227f8772205c0fd004dc9a98 (patch) | |
tree | 0b87f1a5e11bec4220a4053c9678b7839fb7205e /lib/wrappers | |
parent | 49b64e8dc717dd6db27dabd74b0fe238af5e8208 (diff) | |
download | Nim-630f867bd71336b1227f8772205c0fd004dc9a98.tar.gz |
add linenoise.readLineStatus to get status (eg: ctrl-D or ctrl-C) (#16977)
* add linenoise.readLineStatus to get status (eg: ctrl-D or ctrl-C) * changelog
Diffstat (limited to 'lib/wrappers')
-rw-r--r-- | lib/wrappers/linenoise/linenoise.c | 18 | ||||
-rw-r--r-- | lib/wrappers/linenoise/linenoise.h | 11 | ||||
-rw-r--r-- | lib/wrappers/linenoise/linenoise.nim | 41 |
3 files changed, 64 insertions, 6 deletions
diff --git a/lib/wrappers/linenoise/linenoise.c b/lib/wrappers/linenoise/linenoise.c index ae185fece..be792b96b 100644 --- a/lib/wrappers/linenoise/linenoise.c +++ b/lib/wrappers/linenoise/linenoise.c @@ -765,7 +765,7 @@ void linenoiseEditDeletePrevWord(struct linenoiseState *l) { * when ctrl+d is typed. * * The function returns the length of the current buffer. */ -static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) +static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt, linenoiseData* data) { struct linenoiseState l; @@ -827,6 +827,7 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, return (int)l.len; case CTRL_C: /* ctrl-c */ errno = EAGAIN; + data->status = linenoiseStatus_ctrl_C; return -1; case BACKSPACE: /* backspace */ case 8: /* ctrl-h */ @@ -839,6 +840,7 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, } else { history_len--; free(history[history_len]); + data->status = linenoiseStatus_ctrl_D; return -1; } break; @@ -979,7 +981,7 @@ void linenoisePrintKeyCodes(void) { /* This function calls the line editing function linenoiseEdit() using * the STDIN file descriptor set in raw mode. */ -static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { +static int linenoiseRaw(char *buf, size_t buflen, const char *prompt, linenoiseData* data) { int count; if (buflen == 0) { @@ -988,7 +990,7 @@ static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { } if (enableRawMode(STDIN_FILENO) == -1) return -1; - count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt); + count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt, data); disableRawMode(STDIN_FILENO); printf("\n"); return count; @@ -1035,7 +1037,7 @@ static char *linenoiseNoTTY(void) { * for a blacklist of stupid terminals, and later either calls the line * editing function or uses dummy fgets() so that you will be able to type * something even in the most desperate of the conditions. */ -char *linenoise(const char *prompt) { +char *linenoiseExtra(const char *prompt, linenoiseData* data) { char buf[LINENOISE_MAX_LINE]; int count; @@ -1056,12 +1058,18 @@ char *linenoise(const char *prompt) { } return strdup(buf); } else { - count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt); + count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt, data); if (count == -1) return NULL; return strdup(buf); } } +char *linenoise(const char *prompt) { + linenoiseData data; + data.status = linenoiseStatus_ctrl_unknown; + return linenoiseExtra(prompt, &data); +} + /* This is just a wrapper the user may want to call in order to make sure * the linenoise returned buffer is freed with the same allocator it was * created with. Useful when the main program is using an alternative diff --git a/lib/wrappers/linenoise/linenoise.h b/lib/wrappers/linenoise/linenoise.h index ed20232c5..aa86ccb78 100644 --- a/lib/wrappers/linenoise/linenoise.h +++ b/lib/wrappers/linenoise/linenoise.h @@ -48,6 +48,16 @@ typedef struct linenoiseCompletions { char **cvec; } linenoiseCompletions; +typedef enum linenoiseStatus { + linenoiseStatus_ctrl_unknown, + linenoiseStatus_ctrl_C, + linenoiseStatus_ctrl_D +} linenoiseStatus; + +typedef struct linenoiseData { + linenoiseStatus status; +} linenoiseData; + typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold); typedef void(linenoiseFreeHintsCallback)(void *); @@ -57,6 +67,7 @@ void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *); void linenoiseAddCompletion(linenoiseCompletions *, const char *); char *linenoise(const char *prompt); +char *linenoiseExtra(const char *prompt, linenoiseData* data); void linenoiseFree(void *ptr); int linenoiseHistoryAdd(const char *line); int linenoiseHistorySetMaxLen(int len); diff --git a/lib/wrappers/linenoise/linenoise.nim b/lib/wrappers/linenoise/linenoise.nim index a6260eb12..3bfd74586 100644 --- a/lib/wrappers/linenoise/linenoise.nim +++ b/lib/wrappers/linenoise/linenoise.nim @@ -9,7 +9,7 @@ type Completions* = object - len*: csize + len*: csize_t cvec*: cstringArray CompletionCallback* = proc (a2: cstring; a3: ptr Completions) {.cdecl.} @@ -32,3 +32,42 @@ proc printKeyCodes*() {.importc: "linenoisePrintKeyCodes".} proc free*(s: cstring) {.importc: "free", header: "<stdlib.h>".} +when defined nimExperimentalLinenoiseExtra: + # C interface + type linenoiseStatus = enum + linenoiseStatus_ctrl_unknown + linenoiseStatus_ctrl_C + linenoiseStatus_ctrl_D + + type linenoiseData* = object + status: linenoiseStatus + + proc linenoiseExtra(prompt: cstring, data: ptr linenoiseData): cstring {.importc.} + + # stable nim interface + type Status* = enum + lnCtrlUnkown + lnCtrlC + lnCtrlD + + type ReadLineResult* = object + line*: string + status*: Status + + proc readLineStatus*(prompt: string, result: var ReadLineResult) = + ## line editing API that allows returning the line entered and an indicator + ## of which control key was entered, allowing user to distinguish between + ## for example ctrl-C vs ctrl-D. + runnableExamples("-d:nimExperimentalLinenoiseExtra"): + if false: + var ret: ReadLineResult + while true: + readLineStatus("name: ", ret) # ctrl-D will exit, ctrl-C will go to next prompt + if ret.line.len > 0: echo ret.line + if ret.status == lnCtrlD: break + echo "exiting" + var data: linenoiseData + let buf = linenoiseExtra(prompt, data.addr) + result.line = $buf + free(buf) + result.status = data.status.ord.Status |