forked from test34/can_wizard
some linenoise refactoring
This commit is contained in:
parent
c76a9669d8
commit
98b406b571
3 changed files with 57 additions and 83 deletions
|
@ -53,7 +53,7 @@ void list_insert(List** head, void* data) {
|
||||||
*head = node;
|
*head = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int list_sizeof(List* head) {
|
unsigned int list_sizeof(const List* head) {
|
||||||
if (head == NULL) {
|
if (head == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ void* list_pop(List** head);
|
||||||
void list_insert(List** head, void* data);
|
void list_insert(List** head, void* data);
|
||||||
|
|
||||||
// Get the size of the list.
|
// Get the size of the list.
|
||||||
unsigned int list_sizeof(List* head);
|
unsigned int list_sizeof(const List* head);
|
||||||
|
|
||||||
// Get the data of the node at the given ordinal number in the list.
|
// Get the data of the node at the given ordinal number in the list.
|
||||||
List* list_get(List* head, unsigned int index);
|
List* list_get(List* head, unsigned int index);
|
||||||
|
|
|
@ -104,19 +104,15 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// ReSharper disable CppDefaultCaseNotHandledInSwitchStatement
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdio_ext.h>
|
#include <stdio_ext.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include "linenoise.h"
|
#include "linenoise.h"
|
||||||
|
|
||||||
#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
|
#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
|
||||||
|
@ -128,7 +124,7 @@
|
||||||
static linenoiseCompletionCallback *completionCallback = NULL;
|
static linenoiseCompletionCallback *completionCallback = NULL;
|
||||||
static linenoiseHintsCallback *hintsCallback = NULL;
|
static linenoiseHintsCallback *hintsCallback = NULL;
|
||||||
static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
|
static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
|
||||||
static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseCompletions *lc, int flags);
|
static void refreshLineWithCompletion(struct linenoiseState *ls, const linenoiseCompletions *lc, int flags);
|
||||||
static void refreshLineWithFlags(struct linenoiseState *l, int flags);
|
static void refreshLineWithFlags(struct linenoiseState *l, int flags);
|
||||||
|
|
||||||
static int maskmode = 0; /* Show "***" instead of input. For passwords. */
|
static int maskmode = 0; /* Show "***" instead of input. For passwords. */
|
||||||
|
@ -265,9 +261,6 @@ static int getCursorPosition(void) {
|
||||||
/* Try to get the number of columns in the current terminal, or assume 80
|
/* Try to get the number of columns in the current terminal, or assume 80
|
||||||
* if it fails. */
|
* if it fails. */
|
||||||
static int getColumns(void) {
|
static int getColumns(void) {
|
||||||
int start = 0;
|
|
||||||
int cols = 0;
|
|
||||||
int written = 0;
|
|
||||||
char seq[LINENOISE_COMMAND_MAX_LEN] = { 0 };
|
char seq[LINENOISE_COMMAND_MAX_LEN] = { 0 };
|
||||||
const int fd = fileno(stdout);
|
const int fd = fileno(stdout);
|
||||||
|
|
||||||
|
@ -280,7 +273,7 @@ static int getColumns(void) {
|
||||||
const char set_cursor_pos[] = "\x1b[%dD";
|
const char set_cursor_pos[] = "\x1b[%dD";
|
||||||
|
|
||||||
/* Get the initial position so we can restore it later. */
|
/* Get the initial position so we can restore it later. */
|
||||||
start = getCursorPosition();
|
const int start = getCursorPosition();
|
||||||
if (start == -1) {
|
if (start == -1) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
@ -294,7 +287,7 @@ static int getColumns(void) {
|
||||||
|
|
||||||
/* After sending this command, we can get the new position of the cursor,
|
/* After sending this command, we can get the new position of the cursor,
|
||||||
* we'd get the size, in columns, of the opened TTY. */
|
* we'd get the size, in columns, of the opened TTY. */
|
||||||
cols = getCursorPosition();
|
const int cols = getCursorPosition();
|
||||||
if (cols == -1) {
|
if (cols == -1) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
@ -302,7 +295,7 @@ static int getColumns(void) {
|
||||||
/* Restore the position of the cursor back. */
|
/* Restore the position of the cursor back. */
|
||||||
if (cols > start) {
|
if (cols > start) {
|
||||||
/* Generate the move cursor command. */
|
/* Generate the move cursor command. */
|
||||||
written = snprintf(seq, LINENOISE_COMMAND_MAX_LEN, set_cursor_pos, cols-start);
|
const int written = snprintf(seq, LINENOISE_COMMAND_MAX_LEN, set_cursor_pos, cols - start);
|
||||||
|
|
||||||
/* If `written` is equal or bigger than LINENOISE_COMMAND_MAX_LEN, it
|
/* If `written` is equal or bigger than LINENOISE_COMMAND_MAX_LEN, it
|
||||||
* means that the output has been truncated because the size provided
|
* means that the output has been truncated because the size provided
|
||||||
|
@ -337,12 +330,10 @@ static void linenoiseBeep(void) {
|
||||||
/* ============================== Completion ================================ */
|
/* ============================== Completion ================================ */
|
||||||
|
|
||||||
/* Free a list of completion option populated by linenoiseAddCompletion(). */
|
/* Free a list of completion option populated by linenoiseAddCompletion(). */
|
||||||
static void freeCompletions(linenoiseCompletions *lc) {
|
static void freeCompletions(const linenoiseCompletions *lc) {
|
||||||
size_t i;
|
for (size_t i = 0; i < lc->len; i++)
|
||||||
for (i = 0; i < lc->len; i++)
|
// ReSharper disable once CppDFANullDereference
|
||||||
free(lc->cvec[i]);
|
free(lc->cvec[i]);
|
||||||
if (lc->cvec != NULL)
|
|
||||||
free(lc->cvec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called by completeLine() and linenoiseShow() to render the current
|
/* Called by completeLine() and linenoiseShow() to render the current
|
||||||
|
@ -351,7 +342,7 @@ static void freeCompletions(linenoiseCompletions *lc) {
|
||||||
* function will use the callback to obtain it.
|
* function will use the callback to obtain it.
|
||||||
*
|
*
|
||||||
* Flags are the same as refreshLine*(), that is REFRESH_* macros. */
|
* Flags are the same as refreshLine*(), that is REFRESH_* macros. */
|
||||||
static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseCompletions *lc, int flags) {
|
static void refreshLineWithCompletion(struct linenoiseState *ls, const linenoiseCompletions *lc, int flags) {
|
||||||
/* Obtain the table of completions if the caller didn't provide one. */
|
/* Obtain the table of completions if the caller didn't provide one. */
|
||||||
linenoiseCompletions ctable = { 0, NULL };
|
linenoiseCompletions ctable = { 0, NULL };
|
||||||
if (lc == NULL) {
|
if (lc == NULL) {
|
||||||
|
@ -361,7 +352,7 @@ static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseComple
|
||||||
|
|
||||||
/* Show the edited line with completion if possible, or just refresh. */
|
/* Show the edited line with completion if possible, or just refresh. */
|
||||||
if (ls->completion_idx < lc->len) {
|
if (ls->completion_idx < lc->len) {
|
||||||
struct linenoiseState saved = *ls;
|
const struct linenoiseState saved = *ls;
|
||||||
ls->len = ls->pos = strlen(lc->cvec[ls->completion_idx]);
|
ls->len = ls->pos = strlen(lc->cvec[ls->completion_idx]);
|
||||||
ls->buf = lc->cvec[ls->completion_idx];
|
ls->buf = lc->cvec[ls->completion_idx];
|
||||||
refreshLineWithFlags(ls,flags);
|
refreshLineWithFlags(ls,flags);
|
||||||
|
@ -392,7 +383,6 @@ static void refreshLineWithCompletion(struct linenoiseState *ls, linenoiseComple
|
||||||
* from stdin. */
|
* from stdin. */
|
||||||
static int completeLine(struct linenoiseState *ls, int keypressed) {
|
static int completeLine(struct linenoiseState *ls, int keypressed) {
|
||||||
linenoiseCompletions lc = { 0, NULL };
|
linenoiseCompletions lc = { 0, NULL };
|
||||||
int nwritten;
|
|
||||||
char c = keypressed;
|
char c = keypressed;
|
||||||
|
|
||||||
completionCallback(ls->buf,&lc);
|
completionCallback(ls->buf,&lc);
|
||||||
|
@ -421,8 +411,7 @@ static int completeLine(struct linenoiseState *ls, int keypressed) {
|
||||||
default:
|
default:
|
||||||
/* Update buffer and return */
|
/* Update buffer and return */
|
||||||
if (ls->completion_idx < lc.len) {
|
if (ls->completion_idx < lc.len) {
|
||||||
nwritten = snprintf(ls->buf,ls->buflen,"%s",
|
const int nwritten = snprintf(ls->buf, ls->buflen, "%s", lc.cvec[ls->completion_idx]);
|
||||||
lc.cvec[ls->completion_idx]);
|
|
||||||
ls->len = ls->pos = nwritten;
|
ls->len = ls->pos = nwritten;
|
||||||
}
|
}
|
||||||
ls->in_completion = 0;
|
ls->in_completion = 0;
|
||||||
|
@ -463,13 +452,12 @@ void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) {
|
||||||
* user typed <tab>. See the example.c source code for a very easy to
|
* user typed <tab>. See the example.c source code for a very easy to
|
||||||
* understand example. */
|
* understand example. */
|
||||||
void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
|
void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) {
|
||||||
size_t len = strlen(str);
|
const size_t len = strlen(str);
|
||||||
char *copy, **cvec;
|
|
||||||
|
|
||||||
copy = malloc(len+1);
|
char* copy = malloc(len + 1);
|
||||||
if (copy == NULL) return;
|
if (copy == NULL) return;
|
||||||
memcpy(copy,str,len+1);
|
memcpy(copy,str,len+1);
|
||||||
cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));
|
char** cvec = realloc(lc->cvec, sizeof(char*) * (lc->len + 1));
|
||||||
if (cvec == NULL) {
|
if (cvec == NULL) {
|
||||||
free(copy);
|
free(copy);
|
||||||
return;
|
return;
|
||||||
|
@ -503,20 +491,20 @@ static void abAppend(struct abuf *ab, const char *s, int len) {
|
||||||
ab->len += len;
|
ab->len += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void abFree(struct abuf *ab) {
|
static void abFree(const struct abuf *ab) {
|
||||||
free(ab->b);
|
free(ab->b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
|
/* Helper of refreshSingleLine() and refreshMultiLine() to show hints
|
||||||
* to the right of the prompt. */
|
* to the right of the prompt. */
|
||||||
void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
|
void refreshShowHints(struct abuf *ab, const struct linenoiseState *l, int plen) {
|
||||||
char seq[64];
|
|
||||||
if (hintsCallback && plen+l->len < l->cols) {
|
if (hintsCallback && plen+l->len < l->cols) {
|
||||||
int color = -1, bold = 0;
|
int color = -1, bold = 0;
|
||||||
char *hint = hintsCallback(l->buf,&color,&bold);
|
char *hint = hintsCallback(l->buf,&color,&bold);
|
||||||
if (hint) {
|
if (hint) {
|
||||||
|
char seq[64];
|
||||||
int hintlen = strlen(hint);
|
int hintlen = strlen(hint);
|
||||||
int hintmaxlen = l->cols-(plen+l->len);
|
const int hintmaxlen = l->cols-(plen+l->len);
|
||||||
if (hintlen > hintmaxlen) hintlen = hintmaxlen;
|
if (hintlen > hintmaxlen) hintlen = hintmaxlen;
|
||||||
if (bold == 1 && color == -1) color = 37;
|
if (bold == 1 && color == -1) color = 37;
|
||||||
if (color != -1 || bold != 0)
|
if (color != -1 || bold != 0)
|
||||||
|
@ -540,10 +528,10 @@ void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
|
||||||
*
|
*
|
||||||
* Flags is REFRESH_* macros. The function can just remove the old
|
* Flags is REFRESH_* macros. The function can just remove the old
|
||||||
* prompt, just write it, or both. */
|
* prompt, just write it, or both. */
|
||||||
static void refreshSingleLine(struct linenoiseState *l, int flags) {
|
static void refreshSingleLine(const struct linenoiseState *l, int flags) {
|
||||||
char seq[64];
|
char seq[64];
|
||||||
size_t plen = l->plen;
|
const size_t plen = l->plen;
|
||||||
char *buf = l->buf;
|
const char *buf = l->buf;
|
||||||
size_t len = l->len;
|
size_t len = l->len;
|
||||||
size_t pos = l->pos;
|
size_t pos = l->pos;
|
||||||
struct abuf ab;
|
struct abuf ab;
|
||||||
|
@ -597,13 +585,10 @@ static void refreshSingleLine(struct linenoiseState *l, int flags) {
|
||||||
* prompt, just write it, or both. */
|
* prompt, just write it, or both. */
|
||||||
static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
||||||
char seq[64];
|
char seq[64];
|
||||||
int plen = l->plen;
|
const int plen = l->plen;
|
||||||
int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */
|
int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */
|
||||||
int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */
|
const int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */
|
||||||
int rpos2; /* rpos after refresh. */
|
const int old_rows = l->oldrows;
|
||||||
int col; /* colum position, zero-based. */
|
|
||||||
int old_rows = l->oldrows;
|
|
||||||
int j;
|
|
||||||
struct abuf ab;
|
struct abuf ab;
|
||||||
|
|
||||||
l->oldrows = rows;
|
l->oldrows = rows;
|
||||||
|
@ -619,7 +604,7 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now for every row clear it, go up. */
|
/* Now for every row clear it, go up. */
|
||||||
for (j = 0; j < old_rows-1; j++) {
|
for (int j = 0; j < old_rows-1; j++) {
|
||||||
snprintf(seq,64,"\r\x1b[0K\x1b[1A");
|
snprintf(seq,64,"\r\x1b[0K\x1b[1A");
|
||||||
abAppend(&ab,seq,strlen(seq));
|
abAppend(&ab,seq,strlen(seq));
|
||||||
}
|
}
|
||||||
|
@ -635,8 +620,7 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
||||||
/* Write the prompt and the current buffer content */
|
/* Write the prompt and the current buffer content */
|
||||||
abAppend(&ab,l->prompt,strlen(l->prompt));
|
abAppend(&ab,l->prompt,strlen(l->prompt));
|
||||||
if (maskmode == 1) {
|
if (maskmode == 1) {
|
||||||
unsigned int i;
|
for (unsigned int i = 0; i < l->len; i++) abAppend(&ab,"*",1);
|
||||||
for (i = 0; i < l->len; i++) abAppend(&ab,"*",1);
|
|
||||||
} else {
|
} else {
|
||||||
abAppend(&ab,l->buf,l->len);
|
abAppend(&ab,l->buf,l->len);
|
||||||
}
|
}
|
||||||
|
@ -658,7 +642,7 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move cursor to right position. */
|
/* Move cursor to right position. */
|
||||||
rpos2 = (plen+l->pos+l->cols)/l->cols; /* Current cursor relative row */
|
const int rpos2 = (plen + l->pos + l->cols) / l->cols; /* Current cursor relative row */
|
||||||
|
|
||||||
/* Go up till we reach the expected positon. */
|
/* Go up till we reach the expected positon. */
|
||||||
if (rows-rpos2 > 0) {
|
if (rows-rpos2 > 0) {
|
||||||
|
@ -667,7 +651,7 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set column. */
|
/* Set column. */
|
||||||
col = (plen+(int)l->pos) % (int)l->cols;
|
const int col = (plen + (int) l->pos) % (int) l->cols;
|
||||||
if (col)
|
if (col)
|
||||||
snprintf(seq,64,"\r\x1b[%dC", col);
|
snprintf(seq,64,"\r\x1b[%dC", col);
|
||||||
else
|
else
|
||||||
|
@ -726,7 +710,7 @@ int linenoiseEditInsert(struct linenoiseState *l, char c) {
|
||||||
if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {
|
if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {
|
||||||
/* Avoid a full update of the line in the
|
/* Avoid a full update of the line in the
|
||||||
* trivial case. */
|
* trivial case. */
|
||||||
char d = (maskmode==1) ? '*' : c;
|
const char d = (maskmode==1) ? '*' : c;
|
||||||
if (fwrite(&d,1,1,stdout) == -1) return -1;
|
if (fwrite(&d,1,1,stdout) == -1) return -1;
|
||||||
flushWrite();
|
flushWrite();
|
||||||
} else {
|
} else {
|
||||||
|
@ -745,7 +729,7 @@ int linenoiseEditInsert(struct linenoiseState *l, char c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int linenoiseInsertPastedChar(struct linenoiseState *l, char c) {
|
int linenoiseInsertPastedChar(struct linenoiseState *l, char c) {
|
||||||
int fd = fileno(stdout);
|
const int fd = fileno(stdout);
|
||||||
if (l->len < l->buflen && l->len == l->pos) {
|
if (l->len < l->buflen && l->len == l->pos) {
|
||||||
l->buf[l->pos] = c;
|
l->buf[l->pos] = c;
|
||||||
l->pos++;
|
l->pos++;
|
||||||
|
@ -842,14 +826,13 @@ void linenoiseEditBackspace(struct linenoiseState *l) {
|
||||||
/* Delete the previosu word, maintaining the cursor at the start of the
|
/* Delete the previosu word, maintaining the cursor at the start of the
|
||||||
* current word. */
|
* current word. */
|
||||||
void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
|
void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
|
||||||
size_t old_pos = l->pos;
|
const size_t old_pos = l->pos;
|
||||||
size_t diff;
|
|
||||||
|
|
||||||
while (l->pos > 0 && l->buf[l->pos-1] == ' ')
|
while (l->pos > 0 && l->buf[l->pos-1] == ' ')
|
||||||
l->pos--;
|
l->pos--;
|
||||||
while (l->pos > 0 && l->buf[l->pos - 1] != ' ')
|
while (l->pos > 0 && l->buf[l->pos - 1] != ' ')
|
||||||
l->pos--;
|
l->pos--;
|
||||||
diff = old_pos - l->pos;
|
const size_t diff = old_pos - l->pos;
|
||||||
memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);
|
memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1);
|
||||||
l->len -= diff;
|
l->len -= diff;
|
||||||
refreshLine(l);
|
refreshLine(l);
|
||||||
|
@ -863,7 +846,7 @@ static char *linenoiseDumb(struct linenoiseState *l) {
|
||||||
// flushWrite();
|
// flushWrite();
|
||||||
l->len = 0; //needed?
|
l->len = 0; //needed?
|
||||||
while (l->len < l->buflen) {
|
while (l->len < l->buflen) {
|
||||||
int c = fgetc(stdin);
|
const int c = fgetc(stdin);
|
||||||
xSemaphoreTake(stdout_taken_sem, portMAX_DELAY);
|
xSemaphoreTake(stdout_taken_sem, portMAX_DELAY);
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
xSemaphoreGive(stdout_taken_sem);
|
xSemaphoreGive(stdout_taken_sem);
|
||||||
|
@ -987,10 +970,7 @@ char *linenoiseEditMore = "If you see this, you are misusing the API: when linen
|
||||||
*/
|
*/
|
||||||
char *linenoiseEditFeed(struct linenoiseState *l) {
|
char *linenoiseEditFeed(struct linenoiseState *l) {
|
||||||
if (dumbmode) return linenoiseDumb(l);
|
if (dumbmode) return linenoiseDumb(l);
|
||||||
uint32_t t1 = 0;
|
|
||||||
uint32_t t2;
|
|
||||||
char c;
|
char c;
|
||||||
int nread;
|
|
||||||
char seq[3];
|
char seq[3];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1002,10 +982,10 @@ char *linenoiseEditFeed(struct linenoiseState *l) {
|
||||||
* NOTE: pressing a key down without releasing it will also spend
|
* NOTE: pressing a key down without releasing it will also spend
|
||||||
* about 40ms (or even more)
|
* about 40ms (or even more)
|
||||||
*/
|
*/
|
||||||
t1 = getMillis();
|
const uint32_t t1 = getMillis();
|
||||||
nread = fread(&c, 1, 1, stdin);
|
const int nread = fread(&c, 1, 1, stdin);
|
||||||
if (nread <= 0) return linenoiseEditMore;
|
if (nread <= 0) return linenoiseEditMore;
|
||||||
t2 = getMillis();
|
const uint32_t t2 = getMillis();
|
||||||
xSemaphoreTake(stdout_taken_sem, portMAX_DELAY);
|
xSemaphoreTake(stdout_taken_sem, portMAX_DELAY);
|
||||||
// FIXME: line printed twice after pasting something that takes more than 1 line
|
// FIXME: line printed twice after pasting something that takes more than 1 line
|
||||||
if ( (t2 - t1) < LINENOISE_PASTE_KEY_DELAY && c != ENTER) {
|
if ( (t2 - t1) < LINENOISE_PASTE_KEY_DELAY && c != ENTER) {
|
||||||
|
@ -1073,7 +1053,7 @@ char *linenoiseEditFeed(struct linenoiseState *l) {
|
||||||
break;
|
break;
|
||||||
case CTRL_T: /* ctrl-t, swaps current character with previous. */
|
case CTRL_T: /* ctrl-t, swaps current character with previous. */
|
||||||
if (l->pos > 0 && l->pos < l->len) {
|
if (l->pos > 0 && l->pos < l->len) {
|
||||||
int aux = l->buf[l->pos-1];
|
const int aux = l->buf[l->pos-1];
|
||||||
l->buf[l->pos-1] = l->buf[l->pos];
|
l->buf[l->pos-1] = l->buf[l->pos];
|
||||||
l->buf[l->pos] = aux;
|
l->buf[l->pos] = aux;
|
||||||
if (l->pos != l->len-1) l->pos++;
|
if (l->pos != l->len-1) l->pos++;
|
||||||
|
@ -1208,6 +1188,7 @@ static char *linenoiseBlockingEdit(struct linenoiseState *l)
|
||||||
char *res;
|
char *res;
|
||||||
l->buflen = max_cmdline_length;
|
l->buflen = max_cmdline_length;
|
||||||
linenoiseEditStart(l);
|
linenoiseEditStart(l);
|
||||||
|
// ReSharper disable once CppPossiblyErroneousEmptyStatements
|
||||||
while ((res = linenoiseEditFeed(l)) == linenoiseEditMore);
|
while ((res = linenoiseEditFeed(l)) == linenoiseEditMore);
|
||||||
linenoiseEditStop(l);
|
linenoiseEditStop(l);
|
||||||
return res;
|
return res;
|
||||||
|
@ -1216,7 +1197,7 @@ static char *linenoiseBlockingEdit(struct linenoiseState *l)
|
||||||
int linenoiseProbe() {
|
int linenoiseProbe() {
|
||||||
xSemaphoreTake(stdout_taken_sem, portMAX_DELAY);
|
xSemaphoreTake(stdout_taken_sem, portMAX_DELAY);
|
||||||
/* Switch to non-blocking mode */
|
/* Switch to non-blocking mode */
|
||||||
int stdin_fileno = fileno(stdin);
|
const int stdin_fileno = fileno(stdin);
|
||||||
int flags = fcntl(stdin_fileno, F_GETFL);
|
int flags = fcntl(stdin_fileno, F_GETFL);
|
||||||
flags |= O_NONBLOCK;
|
flags |= O_NONBLOCK;
|
||||||
int res = fcntl(stdin_fileno, F_SETFL, flags);
|
int res = fcntl(stdin_fileno, F_SETFL, flags);
|
||||||
|
@ -1230,13 +1211,14 @@ int linenoiseProbe() {
|
||||||
|
|
||||||
/* Try to read response */
|
/* Try to read response */
|
||||||
int timeout_ms = 500;
|
int timeout_ms = 500;
|
||||||
const int retry_ms = 10;
|
|
||||||
size_t read_bytes = 0;
|
size_t read_bytes = 0;
|
||||||
while (timeout_ms > 0 && read_bytes < 4) { // response is ESC[0n or ESC[3n
|
while (timeout_ms > 0 && read_bytes < 4) {
|
||||||
|
const int retry_ms = 10;
|
||||||
|
// response is ESC[0n or ESC[3n
|
||||||
usleep(retry_ms * 1000);
|
usleep(retry_ms * 1000);
|
||||||
timeout_ms -= retry_ms;
|
timeout_ms -= retry_ms;
|
||||||
char c;
|
char c;
|
||||||
int cb = read(stdin_fileno, &c, 1);
|
const int cb = read(stdin_fileno, &c, 1);
|
||||||
if (cb < 0) {
|
if (cb < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1262,14 +1244,12 @@ int linenoiseProbe() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The high level function that is the main API of the linenoise library. */
|
/* The high level function that is the main API of the linenoise library. */
|
||||||
// passing ls_to_pass is optional, you can just provide NULL
|
|
||||||
char *linenoise(const char *prompt, struct linenoiseState **ls_to_pass) {
|
char *linenoise(const char *prompt, struct linenoiseState **ls_to_pass) {
|
||||||
struct linenoiseState l;
|
struct linenoiseState *l = *ls_to_pass;
|
||||||
if (ls_to_pass != NULL) *ls_to_pass = &l;
|
|
||||||
char *buf = calloc(1, max_cmdline_length);
|
char *buf = calloc(1, max_cmdline_length);
|
||||||
l.prompt = prompt;
|
l->prompt = prompt;
|
||||||
l.buf = buf;
|
l->buf = buf;
|
||||||
char *retval = linenoiseBlockingEdit(&l);
|
char *retval = linenoiseBlockingEdit(l);
|
||||||
free(buf);
|
free(buf);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1303,7 +1283,6 @@ void linenoiseHistoryFree() {
|
||||||
*
|
*
|
||||||
* Using a circular buffer is smarter, but a bit more complex to handle. */
|
* Using a circular buffer is smarter, but a bit more complex to handle. */
|
||||||
int linenoiseHistoryAdd(const char *line) {
|
int linenoiseHistoryAdd(const char *line) {
|
||||||
char *linecopy;
|
|
||||||
|
|
||||||
if (history_max_len == 0) return 0;
|
if (history_max_len == 0) return 0;
|
||||||
|
|
||||||
|
@ -1319,7 +1298,7 @@ int linenoiseHistoryAdd(const char *line) {
|
||||||
|
|
||||||
/* Add an heap allocated copy of the line in the history.
|
/* Add an heap allocated copy of the line in the history.
|
||||||
* If we reached the max length, remove the older line. */
|
* If we reached the max length, remove the older line. */
|
||||||
linecopy = strdup(line);
|
char* linecopy = strdup(line);
|
||||||
if (!linecopy) return 0;
|
if (!linecopy) return 0;
|
||||||
if (history_len == history_max_len) {
|
if (history_len == history_max_len) {
|
||||||
free(history[0]);
|
free(history[0]);
|
||||||
|
@ -1336,20 +1315,18 @@ int linenoiseHistoryAdd(const char *line) {
|
||||||
* just the latest 'len' elements if the new history length value is smaller
|
* just the latest 'len' elements if the new history length value is smaller
|
||||||
* than the amount of items already inside the history. */
|
* than the amount of items already inside the history. */
|
||||||
int linenoiseHistorySetMaxLen(int len) {
|
int linenoiseHistorySetMaxLen(int len) {
|
||||||
char **new;
|
|
||||||
|
|
||||||
if (len < 1) return 0;
|
if (len < 1) return 0;
|
||||||
if (history) {
|
if (history) {
|
||||||
int tocopy = history_len;
|
int tocopy = history_len;
|
||||||
|
|
||||||
new = malloc(sizeof(char*)*len);
|
char** new = malloc(sizeof(char*) * len);
|
||||||
if (new == NULL) return 0;
|
if (new == NULL) return 0;
|
||||||
|
|
||||||
/* If we can't copy everything, free the elements we'll not use. */
|
/* If we can't copy everything, free the elements we'll not use. */
|
||||||
if (len < tocopy) {
|
if (len < tocopy) {
|
||||||
int j;
|
|
||||||
|
|
||||||
for (j = 0; j < tocopy-len; j++) free(history[j]);
|
for (int j = 0; j < tocopy-len; j++) free(history[j]);
|
||||||
tocopy = len;
|
tocopy = len;
|
||||||
}
|
}
|
||||||
memset(new,0,sizeof(char*)*len);
|
memset(new,0,sizeof(char*)*len);
|
||||||
|
@ -1366,12 +1343,10 @@ int linenoiseHistorySetMaxLen(int len) {
|
||||||
/* Save the history in the specified file. On success 0 is returned
|
/* Save the history in the specified file. On success 0 is returned
|
||||||
* otherwise -1 is returned. */
|
* otherwise -1 is returned. */
|
||||||
int linenoiseHistorySave(const char *filename) {
|
int linenoiseHistorySave(const char *filename) {
|
||||||
FILE *fp;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
fp = fopen(filename,"w");
|
FILE* fp = fopen(filename, "w");
|
||||||
if (fp == NULL) return -1;
|
if (fp == NULL) return -1;
|
||||||
for (j = 0; j < history_len; j++)
|
for (int j = 0; j < history_len; j++)
|
||||||
fprintf(fp,"%s\n",history[j]);
|
fprintf(fp,"%s\n",history[j]);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1393,8 +1368,7 @@ int linenoiseHistoryLoad(const char *filename) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
while (fgets(buf, max_cmdline_length, fp) != NULL) {
|
while (fgets(buf, max_cmdline_length, fp) != NULL) {
|
||||||
char *p;
|
char* p = strchr(buf, '\r');
|
||||||
p = strchr(buf,'\r');
|
|
||||||
if (!p) p = strchr(buf,'\n');
|
if (!p) p = strchr(buf,'\n');
|
||||||
if (p) *p = '\0';
|
if (p) *p = '\0';
|
||||||
linenoiseHistoryAdd(buf);
|
linenoiseHistoryAdd(buf);
|
||||||
|
|
Loading…
Reference in a new issue