changeset 114:c57ec00a0abc

Adding basic Tab completion.
author Jacob Alexander <haata@kiibohd.com>
date Fri, 24 Jan 2014 03:01:09 -0800
parents aaab1dfb0ca5
children d3a47c0dfb50
files Debug/cli/cli.c Debug/cli/cli.h Debug/print/print.c Debug/print/print.h
diffstat 4 files changed, 73 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/Debug/cli/cli.c	Fri Jan 24 01:58:32 2014 -0800
+++ b/Debug/cli/cli.c	Fri Jan 24 03:01:09 2014 -0800
@@ -53,8 +53,8 @@
 
 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 @@
 
 		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 @@
 		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 @@
 	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 -----
--- a/Debug/cli/cli.h	Fri Jan 24 01:58:32 2014 -0800
+++ b/Debug/cli/cli.h	Fri Jan 24 03:01:09 2014 -0800
@@ -72,6 +72,7 @@
 void argumentIsolation_cli( char* string, char** first, char** second );
 
 void commandLookup_cli();
+void tabCompletion_cli();
 
 // CLI Command Functions
 void cliFunc_arch    ( char* args );
--- a/Debug/print/print.c	Fri Jan 24 01:58:32 2014 -0800
+++ b/Debug/print/print.c	Fri Jan 24 03:01:09 2014 -0800
@@ -241,12 +241,13 @@
 }
 
 
-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;
 }
 
--- a/Debug/print/print.h	Fri Jan 24 01:58:32 2014 -0800
+++ b/Debug/print/print.h	Fri Jan 24 03:01:09 2014 -0800
@@ -109,7 +109,7 @@
 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