changeset 318:217e7bd8a0a4

Add CLI History Use the arrow keys to navigate between the last N commands, similar to most shells.
author Rowan Decker <Smasher816@gmail.com>
date Thu, 02 Apr 2015 00:19:09 -0700
parents a0ad3a172269
children 3994a5a68793
files Debug/cli/cli.c Debug/cli/cli.h
diffstat 2 files changed, 111 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/Debug/cli/cli.c	Wed Apr 01 23:38:26 2015 -0700
+++ b/Debug/cli/cli.c	Thu Apr 02 00:19:09 2015 -0700
@@ -72,6 +72,11 @@
 	// Reset the Line Buffer
 	CLILineBufferCurrent = 0;
 
+	// History starts empty
+	CLIHistoryHead = 0;
+	CLIHistoryCurrent = 0;
+	CLIHistoryTail = 0;
+
 	// Set prompt
 	prompt();
 
@@ -154,6 +159,22 @@
 			// Process the current line buffer
 			CLI_commandLookup();
 
+			// Add the command to the history
+			cli_saveHistory(CLILineBuffer);
+
+			// Keep the array circular, discarding the older entries
+			if (CLIHistoryTail < CLIHistoryHead)
+				CLIHistoryHead = (CLIHistoryHead+1)%CLIMaxHistorySize;
+			CLIHistoryTail++;
+			if (CLIHistoryTail==CLIMaxHistorySize)
+			{
+				CLIHistoryTail = 0;
+				CLIHistoryHead = 1;
+			}
+
+			CLIHistoryCurrent = CLIHistoryTail; // 'Up' starts at the last item
+			cli_saveHistory(NULL); // delete the old temp buffer
+
 			// Reset the buffer
 			CLILineBufferCurrent = 0;
 
@@ -175,9 +196,38 @@
 			//     Doesn't look like it will happen *that* often, so not handling it for now -HaaTa
 			return;
 
-		case 0x1B: // Esc
-			// Check for escape sequence
-			// TODO
+		case 0x1B: // Esc / Escape codes
+			// Check for other escape sequence
+
+			// \e[ is an escape code in vt100 compatable terminals
+			if (CLILineBufferCurrent>=prev_buf_pos+3
+				&& CLILineBuffer[prev_buf_pos]==0x1B
+				&& CLILineBuffer[prev_buf_pos+1]==0x5B)
+			{
+				// Arrow Keys: A (0x41) = Up, B (0x42) = Down, C (0x43) = Right, D (0x44) = Left
+
+				if (CLILineBuffer[prev_buf_pos+2]==0x41) // Hist prev
+				{
+					if (CLIHistoryCurrent==CLIHistoryTail)
+					{
+						// Is first time pressing arrow. Save the current buffer
+						CLILineBuffer[prev_buf_pos] = '\0';
+						cli_saveHistory(CLILineBuffer);
+					}
+
+					// Grab the previus item from the history if there is one
+					if (RING_PREV(CLIHistoryCurrent)!=RING_PREV(CLIHistoryHead))
+						CLIHistoryCurrent = RING_PREV(CLIHistoryCurrent);
+					cli_retreiveHistory(CLIHistoryCurrent);
+				}
+				if (CLILineBuffer[prev_buf_pos+2]==0x42) // Hist next
+				{
+					// Grab the next item from the history if it exists
+					if (RING_NEXT(CLIHistoryCurrent)!=RING_NEXT(CLIHistoryTail))
+						CLIHistoryCurrent = RING_NEXT(CLIHistoryCurrent);
+					cli_retreiveHistory(CLIHistoryCurrent);
+				}
+			}
 			return;
 
 		case 0x08:
@@ -348,6 +398,51 @@
 	}
 }
 
+inline int wrap(int kX, int const kLowerBound, int const kUpperBound)
+{
+	int range_size = kUpperBound - kLowerBound + 1;
+
+	if (kX < kLowerBound)
+		kX += range_size * ((kLowerBound - kX) / range_size + 1);
+
+	return kLowerBound + (kX - kLowerBound) % range_size;
+}
+
+inline void cli_saveHistory(char *buff) {
+	if (buff==NULL) {
+		//clear the item
+		CLIHistoryBuffer[CLIHistoryTail][0] = '\0';
+		return;
+	}
+
+	// Copy the line to the history
+	int i;
+	for (i=0; i<CLILineBufferCurrent; i++)
+	{
+		CLIHistoryBuffer[CLIHistoryTail][i] = CLILineBuffer[i];
+	}
+}
+
+void cli_retreiveHistory(int index) {
+	char *histMatch = CLIHistoryBuffer[index];
+
+	// Reset the buffer
+	CLILineBufferCurrent = 0;
+
+	// Reprint the prompt (automatically clears the line)
+	prompt();
+
+	// Display the command
+	dPrint( histMatch );
+
+	// There are no index counts, so just copy the whole string to the input buffe
+	CLILineBufferCurrent = 0;
+	while ( *histMatch != '\0' )
+	{
+		CLILineBuffer[CLILineBufferCurrent++] = *histMatch++;
+	}
+}
+
 
 
 // ----- CLI Command Functions -----
--- a/Debug/cli/cli.h	Wed Apr 01 23:38:26 2015 -0700
+++ b/Debug/cli/cli.h	Thu Apr 02 00:19:09 2015 -0700
@@ -36,7 +36,7 @@
 #define CLILineBufferMaxSize 100
 #define CLIMaxDictionaries   10
 #define CLIEntryTabAlign     13
-
+#define CLIMaxHistorySize    10
 
 
 // ----- Macros -----
@@ -67,6 +67,8 @@
 	const char name##CLIDict_DescEntry[] = description;
 #endif
 
+#define RING_PREV(i) wrap(i-1,0,CLIMaxHistorySize-1)
+#define RING_NEXT(i) wrap(i+1,0,CLIMaxHistorySize-1)
 
 
 // ----- Structs -----
@@ -90,6 +92,13 @@
 char*        CLIDictNames[CLIMaxDictionaries];
 uint8_t      CLIDictionariesUsed;
 
+// History
+char CLIHistoryBuffer[CLIMaxHistorySize][CLILineBufferMaxSize];
+uint8_t CLIHistoryHead;
+uint8_t CLIHistoryTail;
+int8_t CLIHistoryCurrent;
+
+// Debug
 uint8_t CLILEDState;
 uint8_t CLIHexDebugMode;
 
@@ -102,8 +111,11 @@
 void CLI_registerDictionary( const CLIDictItem *cmdDict, const char* dictName );
 void CLI_argumentIsolation( char* string, char** first, char** second );
 
+int wrap( int x, int low, int high );
 void CLI_commandLookup();
 void CLI_tabCompletion();
+void cli_saveHistory( char *buff );
+void cli_retreiveHistory( int index );
 
 // CLI Command Functions
 void cliFunc_arch    ( char* args );