Merge branch 'feature/#14-Add-shellmatta_resetShell-to-the-API' of shimatta/shellmatta into develop

close #14
This commit is contained in:
shimatta 2020-03-01 21:08:18 +01:00 committed by Gogs
commit e970b6c941
7 changed files with 269 additions and 18 deletions

21
.vscode/launch.json vendored
View File

@ -4,6 +4,27 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{
"name": "debug example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/output/example/example",
"args": ["/dev/pts/3"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "make example",
"miDebuggerPath": "/usr/bin/gdb"
},
{ {
"name": "debug unittest", "name": "debug unittest",
"type": "cppdbg", "type": "cppdbg",

View File

@ -126,6 +126,9 @@ shellmatta_retCode_t shellmatta_doInit( shellmatta_instance_t *inst,
const shellmatta_cmd_t *cmdList, const shellmatta_cmd_t *cmdList,
shellmatta_write_t writeFct); shellmatta_write_t writeFct);
shellmatta_retCode_t shellmatta_resetShell( shellmatta_handle_t handle,
bool printPrompt);
shellmatta_retCode_t shellmatta_addCmd( shellmatta_handle_t handle, shellmatta_retCode_t shellmatta_addCmd( shellmatta_handle_t handle,
shellmatta_cmd_t *cmd); shellmatta_cmd_t *cmd);

View File

@ -96,6 +96,24 @@ static shellmatta_retCode_t empty(shellmatta_handle_t handle, const char *argume
} }
shellmatta_cmd_t emptyCommand = {"empty", NULL, NULL, NULL, empty, NULL}; shellmatta_cmd_t emptyCommand = {"empty", NULL, NULL, NULL, empty, NULL};
static shellmatta_retCode_t reset(shellmatta_handle_t handle, const char *arguments, uint32_t length)
{
(void)arguments;
(void)length;
if(0 == strncmp(arguments, "prompt", length))
{
shellmatta_resetShell(handle, true);
}
else
{
shellmatta_resetShell(handle, false);
}
return SHELLMATTA_OK;
}
shellmatta_cmd_t resetCommand = {"reset", NULL, "resets the shellmatta instance", "reset [prompt]", reset, NULL};
shellmatta_retCode_t writeFct(const char* data, uint32_t length) shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{ {
@ -140,6 +158,7 @@ int main(int argc, char **argv)
shellmatta_addCmd(handle, &quitCommand); shellmatta_addCmd(handle, &quitCommand);
shellmatta_addCmd(handle, &removeCommand); shellmatta_addCmd(handle, &removeCommand);
shellmatta_addCmd(handle, &emptyCommand); shellmatta_addCmd(handle, &emptyCommand);
shellmatta_addCmd(handle, &resetCommand);
while(exitRequest == false) while(exitRequest == false)
{ {

View File

@ -111,6 +111,53 @@ shellmatta_retCode_t shellmatta_doInit(
return SHELLMATTA_OK; return SHELLMATTA_OK;
} }
/**
* @brief resets the whole shellmatta instance
* @param[in] handle shellmatta instance handle
* @param[in] printPrompt print a new command prompt
*
* This function can be used e.g. when working with connection based interfaces (e.g. sockets) to clear
* the shell from old content when a new connection is opened.
* It resets all internal states - the buffers are left as they are - they will be overwritten.
* The history buffer is deleted as well.
*/
shellmatta_retCode_t shellmatta_resetShell( shellmatta_handle_t handle, bool printPrompt)
{
shellmatta_instance_t *inst = (shellmatta_instance_t *)handle;
shellmatta_retCode_t ret = SHELLMATTA_OK;
/*! -# check if the instance is plausible */
if( (NULL != handle)
&& (SHELLMATTA_MAGIC == inst->magic))
{
inst->inputCount = 0u;
inst->lastNewlineIdx = 0u;
inst->cursor = 0u;
inst->historyStart = 0u;
inst->historyEnd = 0u;
inst->historyRead = 0u;
inst->historyReadUp = true;
inst->dirty = false;
inst->tabCounter = 0u;
inst->escapeCounter = 0u;
inst->hereStartIdx = 0u;
inst->hereDelimiterIdx = 0u;
inst->hereLength = 0u;
if(true == printPrompt)
{
/** -# print a prompt if requested */
utils_terminateInput(inst);
}
}
else
{
ret = SHELLMATTA_USE_FAULT;
}
return ret;
}
/** /**
* @brief adds a command to the command list alphabetically ordered * @brief adds a command to the command list alphabetically ordered
* @param[in] handle shellmatta instance handle * @param[in] handle shellmatta instance handle
@ -153,7 +200,8 @@ shellmatta_retCode_t shellmatta_addCmd(shellmatta_handle_t handle, shellmatta_cm
while ((false == cmdPlaced) && (SHELLMATTA_OK == ret)) while ((false == cmdPlaced) && (SHELLMATTA_OK == ret))
{ {
cmdDiff = strcmp(tempCmd->cmd, cmd->cmd); cmdDiff = strcmp(tempCmd->cmd, cmd->cmd);
if(NULL != cmd->cmdAlias) if( (NULL != cmd->cmdAlias)
&& (NULL != tempCmd->cmdAlias))
{ {
aliasDiff = strcmp(tempCmd->cmdAlias, cmd->cmdAlias); aliasDiff = strcmp(tempCmd->cmdAlias, cmd->cmdAlias);
} }
@ -275,8 +323,8 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
uint8_t cmdExecuted = 0u; uint8_t cmdExecuted = 0u;
uint32_t cmdLen; uint32_t cmdLen;
char *tempString; char *tempString;
char *argumentString = NULL; char *argumentString;
uint32_t argumentLength = 0u; uint32_t argumentLength;
uint32_t byteCounter; uint32_t byteCounter;
uint32_t idx; uint32_t idx;
@ -290,6 +338,10 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
/** -# process byte wise */ /** -# process byte wise */
for (byteCounter = 0u; byteCounter < size; byteCounter++) for (byteCounter = 0u; byteCounter < size; byteCounter++)
{ {
/*! -# set default values for the command argument - can be overwritten by heredoc */
argumentString = inst->buffer;
argumentLength = inst->inputCount;
/** -# handle escape sequences */ /** -# handle escape sequences */
if(inst->escapeCounter != 0u) if(inst->escapeCounter != 0u)
{ {
@ -315,7 +367,8 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
* } * }
* \enddot */ * \enddot */
/** -# check for heredoc */ /** -# check for heredoc - add string delimiter to stop strstr from searching too far */
inst->buffer[inst->inputCount] = '\0';
tempString = strstr(inst->buffer, "<<"); tempString = strstr(inst->buffer, "<<");
if(NULL != tempString) if(NULL != tempString)
{ {
@ -349,9 +402,6 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
} }
else else
{ {
argumentString = inst->buffer;
argumentLength = inst->inputCount;
/** -# store the current command and reset the history buffer */ /** -# store the current command and reset the history buffer */
inst->dirty = true; inst->dirty = true;
history_storeCmd(inst); history_storeCmd(inst);
@ -396,8 +446,9 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
} }
else else
{ {
/*! -# the party goes on - print the \r and add a \n to satisfy most terminals */
inst->lastNewlineIdx = inst->inputCount; inst->lastNewlineIdx = inst->inputCount;
utils_insertChars(inst, data, 1); utils_insertChars(inst, data, 1u);
} }
} }

View File

@ -47,7 +47,6 @@ shellmatta_retCode_t escape_processArrowKeys(shellmatta_instance_t *inst)
history_navigate(inst, -1); history_navigate(inst, -1);
} }
inst->historyReadUp = true; inst->historyReadUp = true;
utils_clearInput(inst);
history_restoreCmd(inst); history_restoreCmd(inst);
history_navigate(inst, -1); history_navigate(inst, -1);
@ -63,7 +62,6 @@ shellmatta_retCode_t escape_processArrowKeys(shellmatta_instance_t *inst)
} }
inst->historyReadUp = false; inst->historyReadUp = false;
history_navigate(inst, 1); history_navigate(inst, 1);
utils_clearInput(inst);
history_restoreCmd(inst); history_restoreCmd(inst);
} }
break; break;

View File

@ -201,8 +201,16 @@ void history_restoreCmd(shellmatta_instance_t *inst)
{ {
char byte; char byte;
bool ret = true; bool ret = true;
bool anythingToRestore = false;
ret = getHistoryByte(inst, &byte); ret = getHistoryByte(inst, &byte);
/*! -# delete the input if there is data in the history buffer */
if(true == ret)
{
utils_clearInput(inst);
anythingToRestore = true;
}
while((ret == true) && (byte != 0u)) while((ret == true) && (byte != 0u))
{ {
inst->buffer[inst->inputCount] = byte; inst->buffer[inst->inputCount] = byte;
@ -211,9 +219,12 @@ void history_restoreCmd(shellmatta_instance_t *inst)
ret = getHistoryByte(inst, &byte); ret = getHistoryByte(inst, &byte);
} }
if(true == anythingToRestore)
{
utils_writeEcho(inst, inst->buffer, inst->inputCount); utils_writeEcho(inst, inst->buffer, inst->inputCount);
history_navigate(inst, 1);
inst->dirty = false; inst->dirty = false;
}
history_navigate(inst, 1);
} }
/** /**

View File

@ -77,6 +77,7 @@ TEST_CASE( "shellmatta help function" ) {
char historyBuffer[1024]; char historyBuffer[1024];
char *dummyData = (char*)"?\r\n" char *dummyData = (char*)"?\r\n"
"doSomething do Function does something use me, please\r\n" "doSomething do Function does something use me, please\r\n"
"empty \r\n"
"help ? Print this help text help\r\n" "help ? Print this help text help\r\n"
"\r\nshellmatta->"; "\r\nshellmatta->";
@ -89,6 +90,7 @@ TEST_CASE( "shellmatta help function" ) {
"shellmatta->", "shellmatta->",
NULL, NULL,
writeFct); writeFct);
shellmatta_addCmd(handle, &emptyCmd);
shellmatta_addCmd(handle, &doSomethingCmd); shellmatta_addCmd(handle, &doSomethingCmd);
write_callCnt = 0u; write_callCnt = 0u;
@ -97,11 +99,9 @@ TEST_CASE( "shellmatta help function" ) {
shellmatta_processData(handle, (char*)"?\r", 2); shellmatta_processData(handle, (char*)"?\r", 2);
CHECK( write_length == 123u); CHECK( write_length == strlen(dummyData));
CHECK( strcmp(dummyData, write_data) == 0); CHECK( strcmp(dummyData, write_data) == 0);
shellmatta_addCmd(handle, &emptyCmd);
write_callCnt = 0u; write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data)); memset(write_data, 0, sizeof(write_data));
write_length = 0u; write_length = 0u;
@ -228,9 +228,157 @@ TEST_CASE( "shellmatta remove function" ) {
"help ? Print this help text help\r\n" "help ? Print this help text help\r\n"
"\r\nshellmatta->"; "\r\nshellmatta->";
printf("sdfsd sdf sdf sdf sdf sd fds\n%s", write_data);
CHECK( write_length == 72u); CHECK( write_length == 72u);
REQUIRE( strcmp(dummyData, write_data) == 0); REQUIRE( strcmp(dummyData, write_data) == 0);
}
TEST_CASE( "shellmatta reset no prompt" ) {
shellmatta_instance_t inst;
shellmatta_handle_t handle;
char buffer[1024];
char historyBuffer[1024];
char *dummyData = (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd?\r\n"
"doSomething do Function does something use me, please\r\n"
"help ? Print this help text help\r\n"
"\r\nshellmatta->";
shellmatta_doInit( &inst,
&handle,
buffer,
sizeof(buffer),
historyBuffer,
sizeof(historyBuffer),
"shellmatta->",
NULL,
writeFct);
shellmatta_addCmd(handle, &doSomethingCmd);
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd", 35);
shellmatta_resetShell(handle, false);
shellmatta_processData(handle, (char*)"?\r", 2);
CHECK( write_length == strlen(dummyData));
REQUIRE( strcmp(dummyData, write_data) == 0);
}
TEST_CASE( "shellmatta reset with prompt" ) {
shellmatta_instance_t inst;
shellmatta_handle_t handle;
char buffer[1024];
char historyBuffer[1024];
char *dummyData = (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd"
"\r\nshellmatta->?\r\n"
"doSomething do Function does something use me, please\r\n"
"help ? Print this help text help\r\n"
"\r\nshellmatta->";
shellmatta_doInit( &inst,
&handle,
buffer,
sizeof(buffer),
historyBuffer,
sizeof(historyBuffer),
"shellmatta->",
NULL,
writeFct);
shellmatta_addCmd(handle, &doSomethingCmd);
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh glkd", 35);
shellmatta_resetShell(handle, true);
shellmatta_processData(handle, (char*)"?\r", 2);
CHECK( write_length == strlen(dummyData));
REQUIRE( strcmp(dummyData, write_data) == 0);
}
TEST_CASE( "shellmatta reset no prompt history buffer" ) {
shellmatta_instance_t inst;
shellmatta_handle_t handle;
char buffer[1024];
char historyBuffer[1024];
char *dummyData = (char*)"?\r\n"
"doSomething do Function does something use me, please\r\n"
"help ? Print this help text help\r\n"
"\r\nshellmatta->";
shellmatta_doInit( &inst,
&handle,
buffer,
sizeof(buffer),
historyBuffer,
sizeof(historyBuffer),
"shellmatta->",
NULL,
writeFct);
shellmatta_addCmd(handle, &doSomethingCmd);
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
shellmatta_resetShell(handle, false);
/* process arrow key up - if reset worked this should deliver nothing */
shellmatta_processData(handle, (char*)"\033[A", 3u);
shellmatta_processData(handle, (char*)"?\r", 2);
CHECK( write_length == strlen(dummyData));
REQUIRE( strcmp(dummyData, write_data) == 0);
}
TEST_CASE( "shellmatta reset no prompt heredoc" ) {
shellmatta_instance_t inst;
shellmatta_handle_t handle;
char buffer[1024];
char historyBuffer[1024];
char *dummyData = (char*)"?\r\n"
"doSomething do Function does something use me, please\r\n"
"help ? Print this help text help\r\n"
"\r\nshellmatta->";
shellmatta_doInit( &inst,
&handle,
buffer,
sizeof(buffer),
historyBuffer,
sizeof(historyBuffer),
"shellmatta->",
NULL,
writeFct);
shellmatta_addCmd(handle, &doSomethingCmd);
shellmatta_processData(handle, (char*)"dummy cmd << EOF\r\n", 18u);
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
shellmatta_processData(handle, (char*)"dkfg hdlsfkgh ldksfjhg lkdjfsh gl\r\n", 35u);
write_callCnt = 0u;
memset(write_data, 0, sizeof(write_data));
write_length = 0u;
/* end the heredoc session by resetting the shell */
shellmatta_resetShell(handle, false);
/* now the new command should be processed */
shellmatta_processData(handle, (char*)"?\r", 2);
printf("%s", write_data);
CHECK( write_length == strlen(dummyData));
REQUIRE( strcmp(dummyData, write_data) == 0);
} }