From f55ec0de1ab0b96dc4fb64e36815c334e5c03462 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Fri, 24 Jan 2014 03:01:09 -0800 Subject: [PATCH] Adding basic Tab completion. --- Debug/cli/cli.c | 71 ++++++++++++++++++++++++++++++++++++++++++--- Debug/cli/cli.h | 1 + Debug/print/print.c | 7 +++-- Debug/print/print.h | 2 +- 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/Debug/cli/cli.c b/Debug/cli/cli.c index f4415af..e44d613 100644 --- a/Debug/cli/cli.c +++ b/Debug/cli/cli.c @@ -53,8 +53,8 @@ CLIDictItem basicCLIDict[] = { inline void prompt() { - print("\033[2K"); // Erases the current line - print("\033[1;34m:\033[0m "); + print("\033[2K\r"); // Erases the current line and resets cursor to beginning of line + print("\033[1;34m:\033[0m "); // Blue bold prompt } // Initialize the CLI @@ -155,7 +155,12 @@ void process_cli() case 0x09: // Tab // Tab completion for the current command - // TODO + tabCompletion_cli(); + + CLILineBufferCurrent--; // Remove the Tab + + // XXX There is a potential bug here when resetting the buffer (losing valid keypresses) + // Doesn't look like it will happen *that* often, so not handling it for now -HaaTa return; case 0x1B: // Esc @@ -242,7 +247,7 @@ void commandLookup_cli() for ( uint8_t cmd = 0; CLIDict[dict][cmd].name != 0; cmd++ ) { // Compare the first argument and each command entry - if ( eqStr( cmdPtr, CLIDict[dict][cmd].name ) ) + if ( eqStr( cmdPtr, CLIDict[dict][cmd].name ) == -1 ) { // Run the specified command function pointer // argPtr is already pointing at the first character of the arguments @@ -273,6 +278,64 @@ inline void registerDictionary_cli( CLIDictItem *cmdDict, char* dictName ) CLIDict[CLIDictionariesUsed++] = cmdDict; } +inline void tabCompletion_cli() +{ + // Ignore command if buffer is 0 length + if ( CLILineBufferCurrent == 0 ) + return; + + // Set the last+1 character of the buffer to NULL for string processing + CLILineBuffer[CLILineBufferCurrent] = '\0'; + + // Retrieve pointers to command and beginning of arguments + // Places a NULL at the first space after the command + char* cmdPtr; + char* argPtr; + argumentIsolation_cli( CLILineBuffer, &cmdPtr, &argPtr ); + + // Tab match pointer + char* tabMatch = 0; + uint8_t matches = 0; + + // Scan array of dictionaries for a valid command match + for ( uint8_t dict = 0; dict < CLIDictionariesUsed; dict++ ) + { + // Parse each cmd until a null command entry is found, or an argument match + for ( uint8_t cmd = 0; CLIDict[dict][cmd].name != 0; cmd++ ) + { + // Compare the first argument piece to each command entry to see if it is "like" + // NOTE: To save on processing, we only care about the commands and ignore the arguments + // If there are arguments, and a valid tab match is found, buffer is cleared (args lost) + // Also ignores full matches + if ( eqStr( cmdPtr, CLIDict[dict][cmd].name ) == 0 ) + { + // TODO Make list of commands if multiple matches + matches++; + tabMatch = CLIDict[dict][cmd].name; + } + } + } + + // Only tab complete if there was 1 match + if ( matches == 1 ) + { + // Reset the buffer + CLILineBufferCurrent = 0; + + // Reprint the prompt (automatically clears the line) + prompt(); + + // Display the command + dPrint( tabMatch ); + + // There are no index counts, so just copy the whole string to the input buffer + while ( *tabMatch != '\0' ) + { + CLILineBuffer[CLILineBufferCurrent++] = *tabMatch++; + } + } +} + // ----- CLI Command Functions ----- diff --git a/Debug/cli/cli.h b/Debug/cli/cli.h index 0a20803..e7529b1 100644 --- a/Debug/cli/cli.h +++ b/Debug/cli/cli.h @@ -72,6 +72,7 @@ void registerDictionary_cli( CLIDictItem *cmdDict, char* dictName ); void argumentIsolation_cli( char* string, char** first, char** second ); void commandLookup_cli(); +void tabCompletion_cli(); // CLI Command Functions void cliFunc_arch ( char* args ); diff --git a/Debug/print/print.c b/Debug/print/print.c index 27ecf4b..147bd97 100644 --- a/Debug/print/print.c +++ b/Debug/print/print.c @@ -241,12 +241,13 @@ uint16_t lenStr( char* in ) } -uint8_t eqStr( char* str1, char* str2 ) +int16_t eqStr( char* str1, char* str2 ) { // Scan each string for NULLs and whether they are the same while( *str1 != '\0' && *str1++ == *str2++ ); - // If the strings are still identical (i.e. both NULL), then return 1, otherwise 0 - return *--str1 == *--str2 ? 1 : 0; + // If the strings are still identical (i.e. both NULL), then return -1, otherwise current *str1 + // If *str1 is 0, then str1 ended (and str1 is "like" str2), otherwise strings are different + return *--str1 == *--str2 ? -1 : *++str1; } diff --git a/Debug/print/print.h b/Debug/print/print.h index 924d101..c4d9092 100644 --- a/Debug/print/print.h +++ b/Debug/print/print.h @@ -109,7 +109,7 @@ void int16ToStr ( uint16_t in, char* out ); void hexToStr_op( uint16_t in, char* out, uint8_t op ); void revsStr ( char* in ); uint16_t lenStr ( char* in ); -uint8_t eqStr ( char* str1, char* str2 ); // Returns 1 if identical, 0 otherwise +int16_t eqStr ( char* str1, char* str2 ); // Returns -1 if identical, last character of str1 comparison (0 if str1 is like str2) #endif