diff --git a/.gitignore b/.gitignore index 9c4744c..fc05e5a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ microrl_test tags *.swp +*.vscode diff --git a/README b/README.md similarity index 78% rename from README rename to README.md index 4bf02dc..20f08d7 100644 --- a/README +++ b/README.md @@ -30,20 +30,25 @@ Microrl library is designed to help implement command line interface in small an ** completion - via completion callback + ** echo + - use "microrl_set_echo" function to turn on or turn off echo. + - could be used to print * insted of real characters. +![Window of terminal with microrl library](https://s8.hostingkartinok.com/uploads/images/2017/12/62be1f601c0d64fcf142597c1610147d.png) 3. SRC STRUCTURE -src/ - library source - microrl.c - microrl routines - microrl.h - lib interface and data type - config.h - customisation config-file -examples/ - library usage examples - avr_misc/ - avr specific routines for avr example - unix_misc/ - unix specific routines for desktop example - example.c - common part of example, for build demonstrating example for various platform - example_misc.h - interface to platform specific routines for example build (avr, unix) - Makefile - unix example build (gcc) - Makefile.avr - avr example build (avr-gcc) +src/ - library source + microrl.c - microrl routines + microrl.h - lib interface and data type + config.h - customisation config-file +examples/ - library usage examples + avr_misc/ - avr specific routines for avr example + unix_misc/ - unix specific routines for desktop example + esp8266_example/ - example for esp8266 (platformio) - echo feature + example.c - common part of example, for build demonstrating example for various platform + example_misc.h - interface to platform specific routines for example build (avr, unix) + Makefile - unix example build (gcc) + Makefile.avr - avr example build (avr-gcc) 4. INSTALL diff --git a/examples/esp8266_example/lib/esp8266_misc/esp8266_misc.cpp b/examples/esp8266_example/lib/esp8266_misc/esp8266_misc.cpp new file mode 100644 index 0000000..9879237 --- /dev/null +++ b/examples/esp8266_example/lib/esp8266_misc/esp8266_misc.cpp @@ -0,0 +1,83 @@ +#include "esp8266_misc.h" + +/* +ESP8266 platform specific implementation routines. +*/ +#define _ESP8266_DEMO_VER "1.0" + +#define _LOGIN "admin" +#define _PASSWORD "1234" + + +// definition commands word +#define _CMD_HELP "help" +#define _CMD_CLEAR "clear" +#define _CMD_LOGIN "login" + +//***************************************************************************** +void print (const char* str) +{ + Serial.print(str); +} + +//***************************************************************************** +void print_help (void) +{ + print ("clean - clear screen\n\r"); + print ("login YOUR_LOGIN - admin in this example\n\r"); + print ("if login is correct, you will be asked to enter password.\n\r"); +} + +//***************************************************************************** +// execute callback for microrl library +// do what you want here, but don't write to argv!!! read only!! +int execute (int argc, const char * const * argv) +{ + static int pass_word = 0; + int i = 0; + // just iterate through argv word and compare it with your commands + while (i < argc) { + if (strcmp (argv[i], _CMD_HELP) == 0) { + print ("microrl v"); + print (MICRORL_LIB_VER); + print ("\r\nESP8266 DEMO v"); + print (_ESP8266_DEMO_VER); + print("\n\r"); + print_help (); // print help + } else if (strcmp (argv[i], _CMD_CLEAR) == 0) { + print ("\033[2J"); // ESC seq for clear entire screen + print ("\033[H"); // ESC seq for move cursor at left-top corner + } else if (strcmp (argv[i], _CMD_LOGIN) == 0) { + if (++i < argc) { + if (strcmp (argv[i], _LOGIN) == 0) { + print("Enter your password:\r\n"); + microrl_set_echo (prl, ONCE); + pass_word = 1; + return 1; + } else { + print("Wrong login name. try again.\r\n"); + return 1; + } + } else { + print("Enter your login after command login.\r\n"); + return 1; + } + } else if (pass_word == 1) { + if (strcmp(argv[i], _PASSWORD) == 0) { + print("Grate You Log In!!!\r\n"); + pass_word = 0; + return 1; + } else { + print("Wrong password, try log in again.\r\n"); + pass_word = 0; + return 1; + } + } else { + print ("Command: '"); + print ((char*)argv[i]); + print ("' Not found.\n\r"); + } + i++; + } + return 0; +} \ No newline at end of file diff --git a/examples/esp8266_example/lib/esp8266_misc/esp8266_misc.h b/examples/esp8266_example/lib/esp8266_misc/esp8266_misc.h new file mode 100644 index 0000000..6eaf79d --- /dev/null +++ b/examples/esp8266_example/lib/esp8266_misc/esp8266_misc.h @@ -0,0 +1,25 @@ +#ifndef _MICRORL_MISC_H_ +#define _MICRORL_MISC_H_ +#include +#include "config.h" +#include +#include +extern "C" { + #include "microrl.h" +} + +extern microrl_t * prl; + +// print to stream callback +void print (const char * str); + +// execute callback +int execute (int argc, const char * const * argv); + +// completion callback +char ** complet (int argc, const char * const * argv); + +// ctrl+c callback +void sigint (void); + +#endif /* _MICRORL_MISC_H_ */ diff --git a/examples/esp8266_example/lib/readme.txt b/examples/esp8266_example/lib/readme.txt new file mode 100644 index 0000000..dbadc3d --- /dev/null +++ b/examples/esp8266_example/lib/readme.txt @@ -0,0 +1,36 @@ + +This directory is intended for the project specific (private) libraries. +PlatformIO will compile them to static libraries and link to executable file. + +The source code of each library should be placed in separate directory, like +"lib/private_lib/[here are source files]". + +For example, see how can be organized `Foo` and `Bar` libraries: + +|--lib +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| |--Foo +| | |- Foo.c +| | |- Foo.h +| |- readme.txt --> THIS FILE +|- platformio.ini +|--src + |- main.c + +Then in `src/main.c` you should use: + +#include +#include + +// rest H/C/CPP code + +PlatformIO will find your libraries automatically, configure preprocessor's +include paths and build them. + +More information about PlatformIO Library Dependency Finder +- http://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/esp8266_example/platformio.ini b/examples/esp8266_example/platformio.ini new file mode 100644 index 0000000..d197df6 --- /dev/null +++ b/examples/esp8266_example/platformio.ini @@ -0,0 +1,16 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html +[platformio] +lib_extra_dirs = lib, ../.. + +[env:esp12e] +platform = espressif8266 +board = esp12e +framework = arduino \ No newline at end of file diff --git a/examples/esp8266_example/src/main.cpp b/examples/esp8266_example/src/main.cpp new file mode 100644 index 0000000..858515f --- /dev/null +++ b/examples/esp8266_example/src/main.cpp @@ -0,0 +1,33 @@ +#include +extern "C" { + #include "microrl.h" +} +#include "esp8266_misc.h" + + extern void microrl_init (microrl_t * pThis, void (*print)(const char*)); + +// create microrl object and pointer on it + microrl_t rl; + microrl_t * prl = &rl; + +void setup() { + // // call init with ptr to microrl instance and print callback + microrl_init (prl, print); + // // set callback for execute + microrl_set_execute_callback (prl, execute); + Serial.begin(115200); + +} + +void loop() { + int temp; + + while(1) { + + if (Serial.available() > 0) { + temp = Serial.read(); + microrl_insert_char (prl, temp); + } + + } +} \ No newline at end of file diff --git a/src/microrl.c b/src/microrl.c index 5bf1962..223db48 100644 --- a/src/microrl.c +++ b/src/microrl.c @@ -1,7 +1,6 @@ /* Author: Samoylov Eugene aka Helius (ghelius@gmail.com) BUGS and TODO: --- add echo_off feature -- rewrite history for use more than 256 byte buffer */ @@ -300,19 +299,23 @@ static void terminal_reset_cursor (microrl_t * pThis) // print cmdline to screen, replace '\0' to wihitespace static void terminal_print_line (microrl_t * pThis, int pos, int cursor) { - pThis->print ("\033[K"); // delete all from cursor to end - - char nch [] = {0,0}; - int i; - for (i = pos; i < pThis->cmdlen; i++) { - nch [0] = pThis->cmdline [i]; - if (nch[0] == '\0') - nch[0] = ' '; - pThis->print (nch); + if (!ECHO_IS_OFF()) { + pThis->print ("\033[K"); // delete all from cursor to end + + char nch [] = {0,0}; + int i; + for (i = pos; i < pThis->cmdlen; i++) { + nch [0] = pThis->cmdline [i]; + if (nch[0] == '\0') + nch[0] = ' '; + if ((i >= pThis->start_password) & (ECHO_IS_ONCE())) + nch[0] = '*'; + pThis->print (nch); + } + + terminal_reset_cursor (pThis); + terminal_move_cursor (pThis, cursor); } - - terminal_reset_cursor (pThis); - terminal_move_cursor (pThis, cursor); } //***************************************************************************** @@ -337,6 +340,8 @@ void microrl_init (microrl_t * pThis, void (*print) (const char *)) #ifdef _ENABLE_INIT_PROMPT print_prompt (pThis); #endif + pThis->echo = ON; + pThis->start_password = -1; // } //***************************************************************************** @@ -432,6 +437,8 @@ static int microrl_insert_text (microrl_t * pThis, char * text, int len) { int i; if (pThis->cmdlen + len < _COMMAND_LINE_LEN) { + if (ECHO_IS_ONCE() & (pThis->start_password == -1)) + pThis->start_password = pThis->cmdlen; memmove (pThis->cmdline + pThis->cursor + len, pThis->cmdline + pThis->cursor, pThis->cmdlen - pThis->cursor); @@ -537,6 +544,11 @@ void new_line_handler(microrl_t * pThis){ char const * tkn_arr [_COMMAND_TOKEN_NMB]; int status; + if (ECHO_IS_ONCE()){ + microrl_set_echo(pThis, ON); + pThis->start_password = -1; + } + terminal_newline (pThis); #ifdef _USE_HISTORY if (pThis->cmdlen > 0) @@ -693,3 +705,8 @@ void microrl_insert_char (microrl_t * pThis, int ch) } #endif } + +//***************************************************************************** +void microrl_set_echo (microrl_t * pThis, echo_t echo) { + pThis->echo = echo; +} \ No newline at end of file diff --git a/src/microrl.h b/src/microrl.h index 3831afe..88c6a63 100644 --- a/src/microrl.h +++ b/src/microrl.h @@ -63,6 +63,17 @@ typedef struct { } ring_history_t; #endif +typedef enum echo_ { + ONCE, + ON, + OFF +} echo_t; + +#define ECHO_IS_ON() ((pThis->echo) == (ON)) +#define ECHO_IS_OFF() ((pThis->echo) == (OFF)) +#define ECHO_IS_ONCE() ((pThis->echo) == (ONCE)) + + // microrl struct, contain internal library data typedef struct { #ifdef _USE_ESC_SEQ @@ -85,14 +96,18 @@ typedef struct { #ifdef _USE_CTLR_C void (*sigint) (void); #endif + echo_t echo; + int start_password; // position when start printing * } microrl_t; // init internal data, calls once at start up void microrl_init (microrl_t * pThis, void (*print)(const char*)); -// set echo mode (true/false), using for disabling echo for password input +// set echo mode (ON/OFF/ONCE), using for disabling echo for password input +// using ONCE for disabling echo for password input, // echo mode will enabled after user press Enter. -void microrl_set_echo (int); +// use ON and OFF for turning echo off and on manualy. +void microrl_set_echo (microrl_t * pThis, echo_t echo); // set pointer to callback complition func, that called when user press 'Tab' // callback func description: