diff --git a/CLI/CLI.c b/CLI/CLI.c index 53fda27..70a0386 100644 --- a/CLI/CLI.c +++ b/CLI/CLI.c @@ -5,11 +5,24 @@ #include #include +// #include + #include "../FIFOBuff/FIFOBuffChar.h" +#ifdef HISTORY +#include "../History/history.h" +#endif CLI_charOutFn CLI_charOut; CMDList_t* CMDList; FIFOBuffChar_t* FIFO; +#ifdef HISTORY +enum { + CLI_State_Default, + CLI_State_Esc, + CLI_State_ANSIVT100 +} CLI_State = CLI_State_Default; +History_t* History; +#endif void CLI_charOut_save(char ch) { @@ -36,6 +49,9 @@ bool CLI_init(CLI_charOutFn lineOut, CMDList_t* cmdList) CMDList = cmdList; FIFO = FIFOBuffChar_create(); +#ifdef HISTORY + History = History_init(); +#endif if (CLI_charOut != NULL) { @@ -51,6 +67,9 @@ bool CLI_deinit() CMDList = NULL; FIFOBuffChar_delete(FIFO); +#ifdef HISTORY + History_deinit(History); +#endif return true; } @@ -70,14 +89,46 @@ char* fifoToString(FIFOBuffChar_t* fifo) return out; } +#ifdef HISTORY +void CLI_PrintHistory() +{ + char** historyList; + int ret = History_getFullHistory(History, &historyList); + if (ret >= 0) + { + for (int i=0; *(historyList + i) != NULL; i++) + { + printf("%03i: %s\n", i, *(historyList + i)); + } + } + else + { + printf("ERROR: get history returnd: %i\n", ret); + } + free(historyList); +} +#endif + int tryExecute(FIFOBuffChar_t* fifo) { int ret = 0; + CMD_t* cmd = NULL; char* line = fifoToString(fifo); - CMD_t* cmd = CMDList_get(CMDList, line); + if (*line == '\0') + { // empty line + ret = 1; + CLI_stringOut((char*)"> "); + } + else + { + cmd = CMDList_get(CMDList, line); + } if (cmd != NULL) { +#ifdef HISTORY + History_put(History, line); +#endif int ret = (*(cmd->fn))(line); if (ret != INT_MIN) @@ -86,7 +137,7 @@ int tryExecute(FIFOBuffChar_t* fifo) } ret = 0; } - else + else if (ret == 0) { if (CLI_charOut != NULL) { @@ -95,8 +146,14 @@ int tryExecute(FIFOBuffChar_t* fifo) CLI_stringOut(&err[0]); } ret = -1; + +#ifdef HISTORY + free(line); +#endif } +#ifndef HISTORY free(line); +#endif return ret; } @@ -104,59 +161,114 @@ int tryExecute(FIFOBuffChar_t* fifo) bool CLI_charIn(char c) { bool ok = true; + char str[100]; char C = c; if ((C >= 'a') && (C <= 'z')) { C &= (~0x20); // convert to uppercase } - if ( //TODO: update list of accepted characters - ((C >= 'A') && (C <= 'Z')) - || ((c >= '0') && (c <= '9')) - || (c == ' ') - || (c == '-') - || (c == '_') - ) +#ifdef HISTORY + switch (CLI_State) { - FIFOBuffChar_put(FIFO, C); // save char in buffer - CLI_charOut_save(c); - } - else - { - char str[100]; - switch (c) - { - case '\n': - case '\r': - if (CLI_charOut != NULL) - { // echo to terminal - char ch[2] = {c, 0}; - (*CLI_charOut)(&ch[0]); - } - FIFOBuffChar_t* fifo = FIFO; - FIFO = FIFOBuffChar_create(); - ok = (tryExecute(fifo) == 0); - FIFOBuffChar_delete(fifo); - break; - - case 127: // backspace - if (FIFOBuffChar_pop(FIFO)) - { // pop something of the buffer - CLI_stringOut((char*)"\x1b[D \x1b[D"); // "" - } - break; + case CLI_State_Default: +#endif + if ( //TODO: update list of accepted characters + ((C >= 'A') && (C <= 'Z')) + || ((c >= '0') && (c <= '9')) + || (c == ' ') + || (c == '-') + || (c == '_') + ) + { + FIFOBuffChar_put(FIFO, C); // save char in buffer + CLI_charOut_save(c); + } + else + { + switch (c) + { + case '\n': + case '\r': + if (CLI_charOut != NULL) + { // echo to terminal + char ch[2] = {c, 0}; + (*CLI_charOut)(&ch[0]); + } + FIFOBuffChar_t* fifo = FIFO; + FIFO = FIFOBuffChar_create(); + ok = (tryExecute(fifo) == 0); + FIFOBuffChar_delete(fifo); + break; + + case 127: // backspace + if (FIFOBuffChar_pop(FIFO)) + { // pop something of the buffer + CLI_stringOut((char*)"\x1b[D \x1b[D"); // "" + } + break; - case 27: // escape (start for arrow keys) - sprintf(&str[0], "\ninvlid char: ESC - (%i)\n", c); - CLI_stringOut(&str[0]); - break; + case 27: // escape (start for arrow keys) +#ifdef HISTORY + CLI_State = CLI_State_Esc; + break; +#else + sprintf(&str[0], "\ninvlid char: ESC - (%i)\n", c); + CLI_stringOut(&str[0]); + break; +#endif - default: - sprintf(&str[0], "\ninvlid char: '%c' - (%i)\n", c, c); - CLI_stringOut(&str[0]); - break; - } + default: + sprintf(&str[0], "\ninvlid char: '%c' - (%i)\n", c, c); + CLI_stringOut(&str[0]); + break; + } + } +#ifdef HISTORY + break; + + case CLI_State_Esc: + if (c == '[') + { + CLI_State = CLI_State_ANSIVT100; + } + else + { + CLI_State = CLI_State_Default; + } + break; + + case CLI_State_ANSIVT100: + switch (c) + { + case 'A': // arrow up + // history previus + CLI_stringOut((char*)"(key arrow up)"); + CLI_State = CLI_State_Default; + break; + case 'B': // arrow down + CLI_stringOut((char*)"(key arrow down)"); + // history next + CLI_State = CLI_State_Default; + break; + case 'C': // arrow right + CLI_stringOut((char*)"(key arrow right)"); + CLI_State = CLI_State_Default; + break; + case 'D': // arrow left + CLI_stringOut((char*)"(key arrow left)"); + CLI_State = CLI_State_Default; + break; + default: + if ((C >= 'A') && (C <= 'Z')) + { + CLI_State = CLI_State_Default; + } + } + break; + } +#endif return ok; } diff --git a/CLI/CLI.h b/CLI/CLI.h index 32af73a..e09b5e9 100644 --- a/CLI/CLI.h +++ b/CLI/CLI.h @@ -11,6 +11,10 @@ typedef int (*CLI_charOutFn)(const char* line); bool CLI_init(CLI_charOutFn lineOut, CMDList_t* cmdList); bool CLI_deinit(); +#ifdef HISTORY +extern void CLI_PrintHistory(); +#endif + // to recive a single caracter bool CLI_charIn(char c); diff --git a/CMakeLists.txt b/CMakeLists.txt index ee81a76..ec5cf73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,9 +6,13 @@ add_library(FIFOBuffChar FIFOBuff/FIFOBuffChar.c) add_library(CMDList CMDList/CMDList.c) add_library(CMDListPrint CMDList/printList.c) +# History +add_library(history History/History.c) + # CLI add_library(CLI CLI/CLI.c) target_link_libraries(CLI CMDList FIFOBuffChar) -# History -add_library(history History/History.c) +add_library(CLI_History CLI/CLI.c) +target_link_libraries(CLI_History CMDList FIFOBuffChar history) +target_compile_definitions(CLI_History PRIVATE HISTORY) diff --git a/History/History.c b/History/History.c index dfc771d..4c9bcfa 100644 --- a/History/History.c +++ b/History/History.c @@ -139,6 +139,34 @@ int History_getNext(History_t* history, char** line) return 0; } +int History_getFullHistory(History_t* history, char*** list) +{ + int retCode = 0; + *list = malloc(sizeof(char**) * (History_getSize(history) + 1)); + History_element_t* el = history->FirstEl_p; + + for (int i = 0; (i < History_getSize(history)-1) && (retCode >= 0); i++) + { + *((*list) + i) = el->line; + if (el->nextEl_p == NULL) + { + retCode = -1; + } + else + { + el = (History_element_t*)el->nextEl_p; + } + } + + if (retCode >= 0) + { + // indicate end of list + *((*list) + History_getSize(history)) = NULL; + } + + return retCode; +} + unsigned int History_getSize(History_t *history) { return history->size; diff --git a/History/history.h b/History/history.h index 7a7ce3a..d6c7b60 100644 --- a/History/history.h +++ b/History/history.h @@ -31,6 +31,8 @@ extern int History_put(History_t *history, char* line); extern int History_getPrev(History_t* history, char** line); extern int History_getNext(History_t* history, char** line); +extern int History_getFullHistory(History_t* history, char*** list); + extern unsigned int History_getSize(History_t *history); #endif \ No newline at end of file