From 2a4871ebabfbd26bc585703018ea2267474b4301 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 27 Feb 2020 16:53:22 +0800 Subject: [PATCH] Rewrote the calculation of prompt length, ignoring length of ANSI escape codes --- example.c | 3 ++- linenoise.c | 25 ++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/example.c b/example.c index 3a544d3c..169dbaeb 100644 --- a/example.c +++ b/example.c @@ -55,7 +55,8 @@ int main(int argc, char **argv) { * * The typed string is returned as a malloc() allocated string by * linenoise, so the user needs to free() it. */ - while((line = linenoise("hello> ")) != NULL) { + const char *prompt = "\033[01;33mhello\033[0m>> "; + while((line = linenoise(prompt)) != NULL) { /* Do something with the string. */ if (line[0] != '\0' && line[0] != '/') { printf("echo: '%s'\n", line); diff --git a/linenoise.c b/linenoise.c index 10ffd71c..a6b1d81e 100644 --- a/linenoise.c +++ b/linenoise.c @@ -175,6 +175,7 @@ enum KEY_ACTION{ static void linenoiseAtExit(void); int linenoiseHistoryAdd(const char *line); static void refreshLine(struct linenoiseState *l); +size_t pstrlen(const char *s); /* Debugging macro. */ #if 0 @@ -503,7 +504,7 @@ void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) { * cursor position, and number of columns of the terminal. */ static void refreshSingleLine(struct linenoiseState *l) { char seq[64]; - size_t plen = strlen(l->prompt); + size_t plen = pstrlen(l->prompt); int fd = l->ofd; char *buf = l->buf; size_t len = l->len; @@ -778,7 +779,8 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, l.buf = buf; l.buflen = buflen; l.prompt = prompt; - l.plen = strlen(prompt); + // l.plen = strlen(prompt); + l.plen = pstrlen(prompt); l.oldpos = l.pos = 0; l.len = 0; l.cols = getColumns(stdin_fd, stdout_fd); @@ -793,7 +795,7 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, * initially is just an empty string. */ linenoiseHistoryAdd(""); - if (write(l.ofd,prompt,l.plen) == -1) return -1; + if (write(l.ofd,prompt,strlen(prompt)) == -1) return -1; while(1) { char c; int nread; @@ -1199,3 +1201,20 @@ int linenoiseHistoryLoad(const char *filename) { fclose(fp); return 0; } + +/* Calculatethe length of the prompt string as is seen from a terminal, + * that is to ignore the length of possible ANSI escape codes. + * Therefore possible mispositions of the cursor can be avoided. + */ +size_t pstrlen(const char *s) { + size_t len = 0, i = 0; + while (s[i] != '\0') { + if (s[i] == '\033') { + i = strpbrk(s + i, "m") - s + 1; + continue; + } + len++; + i++; + } + return len; +} \ No newline at end of file