diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 85ec3f2..42bb65f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,9 @@ Try and adhere to the [kernel coding style](https://www.kernel.org/doc/html/latest/process/coding-style.html) with the exception of using 4 spaces instead of 8 for indentation. -The "astyle" code formatter and the library's ```formatter.conf``` configuration file do a pretty good job of correcting indentation, removing tabs etc. +The "astyle" code formatter and the library's ```formatter.conf``` configuration file do a pretty good job of correcting indentation, removing tabs etc. ("astyle" is the formatter the Arduino IDE uses when you select "Tools...Auto format".) + +Tip: ```git diff --check``` will check your files and flag lines with trailing whitespace, and flag lines with tabs following spaces. ## Reporting Bugs diff --git a/examples/ArduinoTextInterface/MemoryUsageAVR.cpp b/examples/ArduinoTextInterface/MemoryUsageAVR.cpp index e65da83..dc37039 100644 --- a/examples/ArduinoTextInterface/MemoryUsageAVR.cpp +++ b/examples/ArduinoTextInterface/MemoryUsageAVR.cpp @@ -15,9 +15,20 @@ int MU_AVR::maxStackSize = getStackSize(); int MU_AVR::numStackComputeCalls = 0; // print 1, 2 or 3 items on a line -#define PRINT1(a) shell.println((a)); -#define PRINT2(a,b) shell.print((a)); shell.println((b)); -#define PRINT3(a,b,c) shell.print((a)); shell.print((b)); shell.println((c)); +void PRINT (const __FlashStringHelper *a, int b = -1, const __FlashStringHelper * c = NULL) +{ + shell.print(a); + if (b != -1) { + shell.print(b); + shell.print(F(" (0x")); + shell.print(b,HEX); + shell.print(F(")")); + if (c) { + shell.print(c); + } + } + shell.println(); +} /// Modified function from http://www.avr-developers.com/mm/memoryusage.html void MU_AVR::SRamDisplay(void) @@ -32,23 +43,23 @@ void MU_AVR::SRamDisplay(void) available -= data_size + bss_size + heap_size + stack_size; - PRINT3( F( "+----------------+ " ), getDataStart(), F(" (__data_start)")); - PRINT1( F( "+ data +" )); - PRINT2( F( "+ variables + size = " ), data_size); - PRINT3( F( "+----------------+ " ), (int)&__data_end, F(" (__data_end / __bss_start)")); - PRINT1( F( "+ bss +" )); - PRINT2( F( "+ variables + size = " ), bss_size); - PRINT3( F( "+----------------+ " ), (int)&__bss_end, F(" (__bss_end / __heap_start)")); - PRINT2( F( "+ heap + size = " ), heap_size); - PRINT3( F( "+----------------+ " ), (int)heap_end, F(" (__brkval if not 0, or __heap_start)")); - PRINT1( F( "+ +" )); - PRINT1( F( "+ +" )); - PRINT2( F( "+ FREE RAM + size = " ), available); - PRINT1( F( "+ +" )); - PRINT1( F( "+ +" )); - PRINT3( F( "+----------------+ " ), (int)SP, F(" (SP)")); - PRINT2( F( "+ stack + size = " ), stack_size); - PRINT3( F( "+----------------+ " ), (int)RAMEND, F(" (RAMEND / __stack)")); + PRINT( F( "+----------------+ " ), getDataStart(), F(" (__data_start)")); + PRINT( F( "+ data +" )); + PRINT( F( "+ variables + size = " ), data_size); + PRINT( F( "+----------------+ " ), (int)&__data_end, F(" (__data_end / __bss_start)")); + PRINT( F( "+ bss +" )); + PRINT( F( "+ variables + size = " ), bss_size); + PRINT( F( "+----------------+ " ), (int)&__bss_end, F(" (__bss_end / __heap_start)")); + PRINT( F( "+ heap + size = " ), heap_size); + PRINT( F( "+----------------+ " ), (int)heap_end, F(" (__brkval if not 0, or __heap_start)")); + PRINT( F( "+ +" )); + PRINT( F( "+ +" )); + PRINT( F( "+ FREE RAM + size = " ), available); + PRINT( F( "+ +" )); + PRINT( F( "+ +" )); + PRINT( F( "+----------------+ " ), (int)SP, F(" (SP)")); + PRINT( F( "+ stack + size = " ), stack_size); + PRINT( F( "+----------------+ " ), (int)RAMEND, F(" (RAMEND / __stack)")); shell.println(); shell.println(); } diff --git a/examples/ArduinoTextInterface/memoryCommands.cpp b/examples/ArduinoTextInterface/memoryCommands.cpp index 34051cd..f869cde 100644 --- a/examples/ArduinoTextInterface/memoryCommands.cpp +++ b/examples/ArduinoTextInterface/memoryCommands.cpp @@ -54,6 +54,9 @@ void prettyPrintChars(int lineNo, const char *chars, int numChars) for (int j = 0; j < numChars; j++) { // hex values unsigned char b = chars[j]; shell.print(F(" ")); + if(b < 0x10) { + shell.print(F("0")); + } shell.print(b, HEX); } shell.print(F(" ")); diff --git a/extras/tests/HelpTest/HelpTest.ino b/extras/tests/HelpTest/HelpTest.ino index 35db55f..f78ce04 100644 --- a/extras/tests/HelpTest/HelpTest.ino +++ b/extras/tests/HelpTest/HelpTest.ino @@ -44,7 +44,7 @@ class HelpTest: public aunit::TestOnce { } }; -int echo(int, char **) +int echo(int, char **) { return 0; } @@ -53,7 +53,7 @@ int echo(int, char **) #define rangeCommandNameAndDocs F("range ") -int rangeCommand(int, char **) +int rangeCommand(int, char **) { // simulates setting range (lower, upper) return 0; @@ -62,21 +62,66 @@ int rangeCommand(int, char **) ////////////////////////////////////////////////////////////////////////////// // The goal of this test is to validate that the help messages // return as expected. -testF(HelpTest, helpTest) +testF(HelpTest, helpTest) { const char* testCommand = "help\r"; terminal.pressKeys(testCommand); assertTrue(shell.executeIfInput()); // The begining part of the response is the echo of the user's input. - assertEqual(terminal.getline(), - ("help" NEW_LINE - HELP_PREAMBLE NEW_LINE - TWO_SPACE "echo" NEW_LINE - TWO_SPACE "help" NEW_LINE + assertEqual(terminal.getline(), + ("help" NEW_LINE + HELP_PREAMBLE NEW_LINE + TWO_SPACE "echo" NEW_LINE + TWO_SPACE "help" NEW_LINE TWO_SPACE "range " COMMAND_PROMPT)); } +////////////////////////////////////////////////////////////////////////////// +// The goal of this test is to check a bug (#28) that was introduced when using +// a command that starts off with another. +testF(HelpTest, helpTest2) +{ + // Notice that this command text is a superset of the "range" command + terminal.pressKeys("ranger 1 2\r"); + assertTrue(shell.executeIfInput()); + + // The begining part of the response is the echo of the user's input. + assertEqual(terminal.getline(), + ("ranger 1 2" NEW_LINE + "\"ranger\": -1: command not found" + COMMAND_PROMPT)); + + // Notice that this command text is a subset of the "range" command + terminal.pressKeys("rang 1 2\r"); + assertTrue(shell.executeIfInput()); + + // The begining part of the response is the echo of the user's input. + assertEqual(terminal.getline(), + ("rang 1 2" NEW_LINE + "\"rang\": -1: command not found" + COMMAND_PROMPT)); + + // Now check the normal command + terminal.pressKeys("range 1 2\r"); + assertTrue(shell.executeIfInput()); + + // The begining part of the response is the echo of the user's input. + assertEqual(terminal.getline(), + ("range 1 2" + COMMAND_PROMPT)); + + // Now check the normal command, except show that the comparison is + // case-insensitive (per original implementation) + terminal.pressKeys("Range 1 2\r"); + assertTrue(shell.executeIfInput()); + + // The begining part of the response is the echo of the user's input. + assertEqual(terminal.getline(), + ("Range 1 2" + COMMAND_PROMPT)); +} + ////////////////////////////////////////////////////////////////////////////// // ... so which sketch is this? int showID(int /*argc*/ = 0, char ** /*argv*/ = NULL) diff --git a/library.properties b/library.properties index 4659107..db29bfb 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SimpleSerialShell -version=0.9.1 +version=0.9.2 author=Phil Jansen maintainer=Phil Jansen diff --git a/releaseNotes.md b/releaseNotes.md index 82b0547..64423ad 100644 --- a/releaseNotes.md +++ b/releaseNotes.md @@ -1,5 +1,9 @@ Release notes +### v0.9.2 +* #28 bug - use full command name (no partial matches) +* added example memory dump commands + ### v0.9.1 * Ensure shell is a Singleton diff --git a/src/SimpleSerialShell.cpp b/src/SimpleSerialShell.cpp index 535f46a..c14b4f3 100644 --- a/src/SimpleSerialShell.cpp +++ b/src/SimpleSerialShell.cpp @@ -9,12 +9,12 @@ * */ -// The static instance of the singleton +// The static instance of the singleton SimpleSerialShell SimpleSerialShell::theShell; -// A reference to the singleton shell in the global namespace. There is an -// extern definition of this in SimpleSherialShell.h, so all users of the -// class will have visibilty to this reference. +// A reference to the singleton shell in the global namespace. There is an +// extern definition of this in SimpleSherialShell.h, so all users of the +// class will have visibilty to this reference. SimpleSerialShell& shell = SimpleSerialShell::theShell; // @@ -42,27 +42,26 @@ class SimpleSerialShell::Command { }; int compareName(const char * aName) const - { - // Look for the command delimiter and make sure we don't + { + // Look for the command delimiter and make sure we don't // consider anything beyond it in the comparison. There // may be more documentation in the string. // // Note for future consideration: The temporary String here could - // be eliminated here by leveraging strlen_P, pgm_read_byte, and - // strncasecmp_P. That will take a bit of research since + // be eliminated here by leveraging strlen_P, pgm_read_byte, and + // strncasecmp_P. That will take a bit of research since // the header file may have a different name on ESP2886/ESP32. String work(nameAndDocs); - int compareLength = SIMPLE_SERIAL_SHELL_BUFSIZE; int delim = work.indexOf(' '); - if (delim >=0) { - compareLength = delim; + if (delim >= 0) { + work.remove(delim); } - return strncasecmp(work.c_str(), aName, compareLength); + return strncasecmp(work.c_str(), aName, SIMPLE_SERIAL_SHELL_BUFSIZE); }; /** * @brief Writes the documentation associated with this command. - * + * * @param str Stream to write into. */ void renderDocumentation(Stream& str) const @@ -341,7 +340,7 @@ void SimpleSerialShell::flush() shellConnection->flush(); } -void SimpleSerialShell::setTokenizer(TokenizerFunction f) +void SimpleSerialShell::setTokenizer(TokenizerFunction f) { tokenizer = f; }