forked from test34/can_wizard
Some changes from esp-idf
This commit is contained in:
parent
f05da6c6ca
commit
d74c0675f5
2 changed files with 123 additions and 12 deletions
|
@ -107,17 +107,21 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdio_ext.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "linenoise.h"
|
#include "linenoise.h"
|
||||||
|
|
||||||
#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
|
#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
|
||||||
#define LINENOISE_MAX_LINE 4096
|
#define LINENOISE_MAX_LINE 4096
|
||||||
|
#define LINENOISE_COMMAND_MAX_LEN 32
|
||||||
|
|
||||||
static linenoiseCompletionCallback *completionCallback = NULL;
|
static linenoiseCompletionCallback *completionCallback = NULL;
|
||||||
static linenoiseHintsCallback *hintsCallback = NULL;
|
static linenoiseHintsCallback *hintsCallback = NULL;
|
||||||
|
@ -127,6 +131,7 @@ 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. */
|
||||||
static int mlmode = 0; /* Multi line mode. Default is single line. */
|
static int mlmode = 0; /* Multi line mode. Default is single line. */
|
||||||
|
static int dumbmode = 0; /* Dumb mode where line editing is disabled. Off by default */
|
||||||
static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
|
static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
|
||||||
static int history_len = 0;
|
static int history_len = 0;
|
||||||
static char **history = NULL;
|
static char **history = NULL;
|
||||||
|
@ -180,6 +185,23 @@ void linenoiseSetMultiLine(int ml) {
|
||||||
mlmode = ml;
|
mlmode = ml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set if terminal does not recognize escape sequences */
|
||||||
|
void linenoiseSetDumbMode(int set) {
|
||||||
|
dumbmode = set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns whether the current mode is dumbmode or not. */
|
||||||
|
bool linenoiseIsDumbMode(void) {
|
||||||
|
return dumbmode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flushWrite(void) {
|
||||||
|
if (__fbufsize(stdout) > 0) {
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
fsync(fileno(stdout));
|
||||||
|
}
|
||||||
|
|
||||||
/* Use the ESC [6n escape sequence to query the horizontal cursor position
|
/* Use the ESC [6n escape sequence to query the horizontal cursor position
|
||||||
* and return it. On error -1 is returned, on success the position of the
|
* and return it. On error -1 is returned, on success the position of the
|
||||||
* cursor. */
|
* cursor. */
|
||||||
|
@ -190,6 +212,7 @@ static int getCursorPosition() {
|
||||||
|
|
||||||
/* Report cursor location */
|
/* Report cursor location */
|
||||||
fprintf(stdout, "\x1b[6n");
|
fprintf(stdout, "\x1b[6n");
|
||||||
|
flushWrite();
|
||||||
/* Read the response: ESC [ rows ; cols R */
|
/* Read the response: ESC [ rows ; cols R */
|
||||||
while (i < sizeof(buf)-1) {
|
while (i < sizeof(buf)-1) {
|
||||||
if (fread(buf+i, 1, 1, stdin) != 1) break;
|
if (fread(buf+i, 1, 1, stdin) != 1) break;
|
||||||
|
@ -214,6 +237,7 @@ static int getColumns() {
|
||||||
|
|
||||||
/* Go to right margin and get position. */
|
/* Go to right margin and get position. */
|
||||||
if (fwrite("\x1b[999C", 1, 6, stdout) != 6) goto failed;
|
if (fwrite("\x1b[999C", 1, 6, stdout) != 6) goto failed;
|
||||||
|
flushWrite();
|
||||||
cols = getCursorPosition();
|
cols = getCursorPosition();
|
||||||
if (cols == -1) goto failed;
|
if (cols == -1) goto failed;
|
||||||
|
|
||||||
|
@ -224,6 +248,7 @@ static int getColumns() {
|
||||||
if (fwrite(seq, 1, strlen(seq), stdout) == -1) {
|
if (fwrite(seq, 1, strlen(seq), stdout) == -1) {
|
||||||
/* Can't recover... */
|
/* Can't recover... */
|
||||||
}
|
}
|
||||||
|
flushWrite();
|
||||||
}
|
}
|
||||||
return cols;
|
return cols;
|
||||||
|
|
||||||
|
@ -234,12 +259,14 @@ failed:
|
||||||
/* Clear the screen. Used to handle ctrl+l */
|
/* Clear the screen. Used to handle ctrl+l */
|
||||||
void linenoiseClearScreen(void) {
|
void linenoiseClearScreen(void) {
|
||||||
fprintf(stdout,"\x1b[H\x1b[2J");
|
fprintf(stdout,"\x1b[H\x1b[2J");
|
||||||
|
flushWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Beep, used for completion when there is nothing to complete or when all
|
/* Beep, used for completion when there is nothing to complete or when all
|
||||||
* the choices were already shown. */
|
* the choices were already shown. */
|
||||||
static void linenoiseBeep(void) {
|
static void linenoiseBeep(void) {
|
||||||
fprintf(stdout, "\x7");
|
fprintf(stdout, "\x7");
|
||||||
|
flushWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================== Completion ================================ */
|
/* ============================== Completion ================================ */
|
||||||
|
@ -492,6 +519,7 @@ static void refreshSingleLine(struct linenoiseState *l, int flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwrite(ab.b, ab.len, 1, stdout) == -1) {} /* Can't recover from write error. */
|
if (fwrite(ab.b, ab.len, 1, stdout) == -1) {} /* Can't recover from write error. */
|
||||||
|
flushWrite();
|
||||||
abFree(&ab);
|
abFree(&ab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,6 +613,7 @@ static void refreshMultiLine(struct linenoiseState *l, int flags) {
|
||||||
l->oldpos = l->pos;
|
l->oldpos = l->pos;
|
||||||
|
|
||||||
if (fwrite(ab.b, ab.len, 1, stdout) == -1) {} /* Can't recover from write error. */
|
if (fwrite(ab.b, ab.len, 1, stdout) == -1) {} /* Can't recover from write error. */
|
||||||
|
flushWrite();
|
||||||
abFree(&ab);
|
abFree(&ab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,6 +663,7 @@ int linenoiseEditInsert(struct linenoiseState *l, char c) {
|
||||||
* trivial case. */
|
* trivial case. */
|
||||||
char d = (maskmode==1) ? '*' : c;
|
char d = (maskmode==1) ? '*' : c;
|
||||||
if (fwrite(&d,1,1,stdout) == -1) return -1;
|
if (fwrite(&d,1,1,stdout) == -1) return -1;
|
||||||
|
flushWrite();
|
||||||
} else {
|
} else {
|
||||||
refreshLine(l);
|
refreshLine(l);
|
||||||
}
|
}
|
||||||
|
@ -745,6 +775,38 @@ void linenoiseEditDeletePrevWord(struct linenoiseState *l) {
|
||||||
refreshLine(l);
|
refreshLine(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: try to make a non-blocking dumb mode
|
||||||
|
static char *linenoiseDumb(struct linenoiseState *l) {
|
||||||
|
/* dumb terminal, fall back to fgets */
|
||||||
|
fputs(l->prompt, stdout);
|
||||||
|
flushWrite();
|
||||||
|
l->len = 0; //needed?
|
||||||
|
while (l->len < l->buflen) {
|
||||||
|
int c = fgetc(stdin);
|
||||||
|
if (c == '\n') {
|
||||||
|
break;
|
||||||
|
} else if (c >= 0x1c && c <= 0x1f){
|
||||||
|
continue; /* consume arrow keys */
|
||||||
|
} else if (c == BACKSPACE || c == 0x8) {
|
||||||
|
if (l->len > 0) {
|
||||||
|
l->buf[l->len - 1] = 0;
|
||||||
|
l->len --;
|
||||||
|
}
|
||||||
|
fputs("\x08 ", stdout); /* Windows CMD: erase symbol under cursor */
|
||||||
|
flushWrite();
|
||||||
|
} else {
|
||||||
|
l->buf[l->len] = c;
|
||||||
|
l->len++;
|
||||||
|
}
|
||||||
|
fputc(c, stdout); /* echo */
|
||||||
|
flushWrite();
|
||||||
|
}
|
||||||
|
fputc('\n', stdout);
|
||||||
|
flushWrite();
|
||||||
|
if (l->len == 0) return linenoiseEditMore;
|
||||||
|
return strdup(l->buf);
|
||||||
|
}
|
||||||
|
|
||||||
/* This function is part of the multiplexed API of Linenoise, that is used
|
/* This function is part of the multiplexed API of Linenoise, that is used
|
||||||
* in order to implement the blocking variant of the API but can also be
|
* in order to implement the blocking variant of the API but can also be
|
||||||
* called by the user directly in an event driven program. It will:
|
* called by the user directly in an event driven program. It will:
|
||||||
|
@ -789,13 +851,18 @@ int linenoiseEditStart(struct linenoiseState *l, char *buf, size_t buflen, const
|
||||||
|
|
||||||
/* The latest history entry is always our current buffer, that
|
/* The latest history entry is always our current buffer, that
|
||||||
* initially is just an empty string. */
|
* initially is just an empty string. */
|
||||||
linenoiseHistoryAdd("");
|
if (!dumbmode) {
|
||||||
|
linenoiseHistoryAdd("");
|
||||||
int pos1 = getCursorPosition();
|
int pos1 = getCursorPosition();
|
||||||
if (fwrite(prompt,l->plen,1,stdout) == -1) return -1;
|
if (fwrite(prompt,l->plen,1,stdout) == -1) return -1;
|
||||||
int pos2 = getCursorPosition();
|
flushWrite();
|
||||||
if (pos1 >= 0 && pos2 >= 0) {
|
int pos2 = getCursorPosition();
|
||||||
l->plen = pos2 - pos1;
|
if (pos1 >= 0 && pos2 >= 0) {
|
||||||
|
l->plen = pos2 - pos1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (fwrite(prompt,l->plen,1,stdout) == -1) return -1;
|
||||||
|
flushWrite();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -821,6 +888,7 @@ char *linenoiseEditMore = "If you see this, you are misusing the API: when linen
|
||||||
* Some other errno: I/O error.
|
* Some other errno: I/O error.
|
||||||
*/
|
*/
|
||||||
char *linenoiseEditFeed(struct linenoiseState *l) {
|
char *linenoiseEditFeed(struct linenoiseState *l) {
|
||||||
|
if (dumbmode) return linenoiseDumb(l);
|
||||||
char c;
|
char c;
|
||||||
int nread;
|
int nread;
|
||||||
char seq[3];
|
char seq[3];
|
||||||
|
@ -974,6 +1042,7 @@ char *linenoiseEditFeed(struct linenoiseState *l) {
|
||||||
linenoiseEditDeletePrevWord(l);
|
linenoiseEditDeletePrevWord(l);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
flushWrite();
|
||||||
return linenoiseEditMore;
|
return linenoiseEditMore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -983,9 +1052,12 @@ char *linenoiseEditFeed(struct linenoiseState *l) {
|
||||||
* returns something different than NULL. At this point the user input
|
* returns something different than NULL. At this point the user input
|
||||||
* is in the buffer, and we can restore the terminal in normal mode. */
|
* is in the buffer, and we can restore the terminal in normal mode. */
|
||||||
void linenoiseEditStop(struct linenoiseState *l) {
|
void linenoiseEditStop(struct linenoiseState *l) {
|
||||||
printf("\n");
|
fputc('\n', stdout);
|
||||||
|
flushWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This just implements a blocking loop for the multiplexed API.
|
/* This just implements a blocking loop for the multiplexed API.
|
||||||
* In many applications that are not event-drivern, we can just call
|
* In many applications that are not event-drivern, we can just call
|
||||||
* the blocking linenoise API, wait for the user to complete the editing
|
* the blocking linenoise API, wait for the user to complete the editing
|
||||||
|
@ -998,18 +1070,55 @@ static char *linenoiseBlockingEdit(char *buf, size_t buflen, const char *prompt)
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
linenoiseEditStart(&l,buf,buflen,prompt);
|
|
||||||
char *res;
|
char *res;
|
||||||
|
linenoiseEditStart(&l,buf,buflen,prompt);
|
||||||
while((res = linenoiseEditFeed(&l)) == linenoiseEditMore);
|
while((res = linenoiseEditFeed(&l)) == linenoiseEditMore);
|
||||||
linenoiseEditStop(&l);
|
linenoiseEditStop(&l);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int linenoiseProbe() {
|
||||||
|
/* Switch to non-blocking mode */
|
||||||
|
int stdin_fileno = fileno(stdin);
|
||||||
|
int flags = fcntl(stdin_fileno, F_GETFL);
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
int res = fcntl(stdin_fileno, F_SETFL, flags);
|
||||||
|
if (res != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Device status request */
|
||||||
|
fprintf(stdout, "\x1b[5n");
|
||||||
|
flushWrite();
|
||||||
|
|
||||||
|
/* Try to read response */
|
||||||
|
int timeout_ms = 200;
|
||||||
|
const int retry_ms = 10;
|
||||||
|
size_t read_bytes = 0;
|
||||||
|
while (timeout_ms > 0 && read_bytes < 4) { // response is ESC[0n or ESC[3n
|
||||||
|
usleep(retry_ms * 1000);
|
||||||
|
timeout_ms -= retry_ms;
|
||||||
|
char c;
|
||||||
|
int cb = read(stdin_fileno, &c, 1);
|
||||||
|
if (cb < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
read_bytes += cb;
|
||||||
|
}
|
||||||
|
/* Restore old mode */
|
||||||
|
flags &= ~O_NONBLOCK;
|
||||||
|
res = fcntl(stdin_fileno, F_SETFL, flags);
|
||||||
|
if (res != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (read_bytes < 4) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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. */
|
||||||
char *linenoise(const char *prompt) {
|
char *linenoise(const char *prompt) {
|
||||||
char buf[LINENOISE_MAX_LINE];
|
char buf[LINENOISE_MAX_LINE];
|
||||||
|
|
||||||
char *retval = linenoiseBlockingEdit(buf,LINENOISE_MAX_LINE,prompt);
|
char *retval = linenoiseBlockingEdit(buf,LINENOISE_MAX_LINE,prompt);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stddef.h> /* For size_t. */
|
#include <stddef.h> /* For size_t. */
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
extern char *linenoiseEditMore;
|
extern char *linenoiseEditMore;
|
||||||
|
|
||||||
|
@ -105,7 +106,8 @@ void linenoiseHistoryFree();
|
||||||
/* Other utilities. */
|
/* Other utilities. */
|
||||||
void linenoiseClearScreen(void);
|
void linenoiseClearScreen(void);
|
||||||
void linenoiseSetMultiLine(int ml);
|
void linenoiseSetMultiLine(int ml);
|
||||||
void linenoisePrintKeyCodes(void);
|
void linenoiseSetDumbMode(int set);
|
||||||
|
bool linenoiseIsDumbMode(void);
|
||||||
void linenoiseMaskModeEnable(void);
|
void linenoiseMaskModeEnable(void);
|
||||||
void linenoiseMaskModeDisable(void);
|
void linenoiseMaskModeDisable(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue