added basic heredoc function
Some things are broken: navigation in multiline inputs history buffer for multiline inputs some things not been noticed yet
This commit is contained in:
parent
fc8a34dd1c
commit
280e512746
@ -91,6 +91,7 @@ typedef struct
|
|||||||
char *buffer; /**< input buffer */
|
char *buffer; /**< input buffer */
|
||||||
uint32_t bufferSize; /**< size of the input buffer */
|
uint32_t bufferSize; /**< size of the input buffer */
|
||||||
uint32_t inputCount; /**< offset of the current write operation */
|
uint32_t inputCount; /**< offset of the current write operation */
|
||||||
|
uint32_t lastNewlineIdx; /**< index of the lest newline */
|
||||||
uint32_t cursor; /**< offset where the cursor is at */
|
uint32_t cursor; /**< offset where the cursor is at */
|
||||||
char *historyBuffer; /**< buffer to store the last commands */
|
char *historyBuffer; /**< buffer to store the last commands */
|
||||||
uint32_t historyBufferSize; /**< size of the history buffer */
|
uint32_t historyBufferSize; /**< size of the history buffer */
|
||||||
@ -100,7 +101,9 @@ typedef struct
|
|||||||
bool historyReadUp; /**< flag to show the last history dir */
|
bool historyReadUp; /**< flag to show the last history dir */
|
||||||
uint32_t tabCounter; /**< counts the tabulator key presses */
|
uint32_t tabCounter; /**< counts the tabulator key presses */
|
||||||
uint32_t escapeCounter; /**< counts the characters of an escape seq */
|
uint32_t escapeCounter; /**< counts the characters of an escape seq */
|
||||||
char escapeChars[4]; /**< buffer to save the escape characters */
|
char escapeChars[4u]; /**< buffer to save the escape characters */
|
||||||
|
char hereDelimiter[16u]; /**< heredoc delimiter */
|
||||||
|
uint32_t hereLength; /**< length of the heredoc delimiter */
|
||||||
bool echoEnabled; /**< if true the input is printed */
|
bool echoEnabled; /**< if true the input is printed */
|
||||||
bool dirty; /**< dirty flag to show changes */
|
bool dirty; /**< dirty flag to show changes */
|
||||||
const char *prompt; /**< prompt is printed after every command */
|
const char *prompt; /**< prompt is printed after every command */
|
||||||
|
@ -22,8 +22,7 @@ static bool exitRequest = false;
|
|||||||
int f;
|
int f;
|
||||||
shellmatta_handle_t handle;
|
shellmatta_handle_t handle;
|
||||||
|
|
||||||
void
|
void set_blocking (int fd, int should_block)
|
||||||
set_blocking (int fd, int should_block)
|
|
||||||
{
|
{
|
||||||
struct termios tty;
|
struct termios tty;
|
||||||
memset (&tty, 0, sizeof tty);
|
memset (&tty, 0, sizeof tty);
|
||||||
@ -80,7 +79,7 @@ int main(void)
|
|||||||
static char historyBuffer[4096];
|
static char historyBuffer[4096];
|
||||||
static shellmatta_instance_t instance;
|
static shellmatta_instance_t instance;
|
||||||
|
|
||||||
f = open("/dev/pts/3", O_RDWR | O_SYNC);
|
f = open("/dev/pts/1", O_RDWR | O_SYNC);
|
||||||
|
|
||||||
if (f < 0)
|
if (f < 0)
|
||||||
{
|
{
|
||||||
|
154
src/shellmatta.c
154
src/shellmatta.c
@ -74,6 +74,7 @@ shellmatta_retCode_t shellmatta_doInit(
|
|||||||
inst->buffer = buffer;
|
inst->buffer = buffer;
|
||||||
inst->bufferSize = bufferSize;
|
inst->bufferSize = bufferSize;
|
||||||
inst->inputCount = 0u;
|
inst->inputCount = 0u;
|
||||||
|
inst->lastNewlineIdx = 0u;
|
||||||
inst->cursor = 0u;
|
inst->cursor = 0u;
|
||||||
inst->historyBuffer = historyBuffer;
|
inst->historyBuffer = historyBuffer;
|
||||||
inst->historyBufferSize = historyBufferSize;
|
inst->historyBufferSize = historyBufferSize;
|
||||||
@ -87,6 +88,7 @@ shellmatta_retCode_t shellmatta_doInit(
|
|||||||
inst->dirty = false;
|
inst->dirty = false;
|
||||||
inst->tabCounter = 0u;
|
inst->tabCounter = 0u;
|
||||||
inst->escapeCounter = 0u;
|
inst->escapeCounter = 0u;
|
||||||
|
inst->hereLength = 0u;
|
||||||
inst->mode = SHELLMATTA_MODE_INSERT;
|
inst->mode = SHELLMATTA_MODE_INSERT;
|
||||||
inst->cmdList = &helpCmd;
|
inst->cmdList = &helpCmd;
|
||||||
inst->cmdListIsConst = false;
|
inst->cmdListIsConst = false;
|
||||||
@ -194,6 +196,7 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
|
|||||||
shellmatta_cmd_t *cmd;
|
shellmatta_cmd_t *cmd;
|
||||||
uint8_t cmdExecuted = 0u;
|
uint8_t cmdExecuted = 0u;
|
||||||
uint32_t cmdLen;
|
uint32_t cmdLen;
|
||||||
|
char *tempString;
|
||||||
shellmatta_retCode_t ret = SHELLMATTA_OK;
|
shellmatta_retCode_t ret = SHELLMATTA_OK;
|
||||||
shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
|
shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
|
||||||
|
|
||||||
@ -218,56 +221,131 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
|
|||||||
/** -# handle return as start of processing the command */
|
/** -# handle return as start of processing the command */
|
||||||
else if ('\r' == *data)
|
else if ('\r' == *data)
|
||||||
{
|
{
|
||||||
cmd = inst->cmdList;
|
if(0u == inst->hereLength)
|
||||||
inst->buffer[inst->inputCount] = 0u;
|
|
||||||
|
|
||||||
/** -# store the current command and reset the history buffer */
|
|
||||||
inst->dirty = true;
|
|
||||||
history_storeCmd(inst);
|
|
||||||
history_reset(inst);
|
|
||||||
|
|
||||||
/** -# determine the cmd len (chars until first space or \0 is found */
|
|
||||||
cmdLen = 0u;
|
|
||||||
while( (cmdLen < inst->inputCount)
|
|
||||||
&& (' ' != inst->buffer[cmdLen])
|
|
||||||
&& ('\0' != inst->buffer[cmdLen]))
|
|
||||||
{
|
{
|
||||||
cmdLen ++;
|
/**
|
||||||
}
|
* \dot
|
||||||
|
* digraph heredocParser {
|
||||||
|
* start -> wait [ label="<< in first line - store delimiter" ];
|
||||||
|
* wait -> wait [ label="delimiter not detected" ];
|
||||||
|
* wait -> end [ label="delimiter found - remove all heredoc stuff and send the input to the command" ];
|
||||||
|
* }
|
||||||
|
* \enddot */
|
||||||
|
|
||||||
/** -# search for a matching command */
|
/** -# check for heredoc */
|
||||||
while (NULL != cmd)
|
tempString = strstr(inst->buffer, "<<");
|
||||||
{
|
if(NULL != tempString)
|
||||||
/** -# compare command string and length */
|
|
||||||
if ( ((0 == strncmp( inst->buffer,
|
|
||||||
cmd->cmd,
|
|
||||||
cmdLen))
|
|
||||||
&& (cmdLen == strlen(cmd->cmd)))
|
|
||||||
|| ((0 == strncmp( inst->buffer,
|
|
||||||
cmd->cmdAlias,
|
|
||||||
cmdLen))
|
|
||||||
&& (cmdLen == strlen(cmd->cmdAlias))))
|
|
||||||
{
|
{
|
||||||
inst->write("\r\n", 2u);
|
/*' -# check if length of heredoc delimiter is valid */
|
||||||
|
if(inst->inputCount > ((uint32_t)(tempString - inst->buffer) + 2u))
|
||||||
|
{
|
||||||
|
inst->hereLength = inst->inputCount - ((uint32_t)(tempString - inst->buffer) + 2u);
|
||||||
|
|
||||||
cmdExecuted = 1u;
|
if(sizeof(inst->hereDelimiter) < inst->hereLength)
|
||||||
cmd->cmdFct(inst, inst->buffer, inst->inputCount);
|
{
|
||||||
cmd = NULL;
|
inst->write("\r\nHeredoc delimiter too long\r\n", 30u);
|
||||||
|
inst->inputCount = 0u;
|
||||||
|
inst->hereLength = 0u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/** -# store delimiter and remove it from the input buffer */
|
||||||
|
strncpy(inst->hereDelimiter, &(tempString[2u]), inst->hereLength);
|
||||||
|
|
||||||
|
inst->inputCount -= (inst->hereLength + 2u);
|
||||||
|
inst->cursor = inst->inputCount;
|
||||||
|
inst->dirty = true;
|
||||||
|
utils_insertChars(inst, data, 1);
|
||||||
|
inst->lastNewlineIdx = inst->inputCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inst->hereLength = 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tempString = &inst->buffer[inst->lastNewlineIdx];
|
||||||
|
cmdLen = inst->inputCount - inst->lastNewlineIdx;
|
||||||
|
|
||||||
|
/** -# skip newline characters before comparison */
|
||||||
|
while(('\n' == *tempString) || ('\r' == *tempString))
|
||||||
|
{
|
||||||
|
tempString ++;
|
||||||
|
cmdLen --;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (inst->hereLength == cmdLen)
|
||||||
|
&& (0 == strncmp( inst->hereDelimiter,
|
||||||
|
tempString,
|
||||||
|
inst->hereLength)))
|
||||||
|
{
|
||||||
|
inst->inputCount = inst->lastNewlineIdx;
|
||||||
|
inst->hereLength = 0u;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cmd = cmd->next;
|
inst->lastNewlineIdx = inst->inputCount;
|
||||||
|
utils_insertChars(inst, data, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cmdExecuted == 0u) && (inst->inputCount > 0))
|
if(0u == inst->hereLength)
|
||||||
{
|
{
|
||||||
inst->buffer[inst->inputCount] = '\0';
|
cmd = inst->cmdList;
|
||||||
inst->write("\r\nCommand: ", 11u);
|
inst->buffer[inst->inputCount] = 0u;
|
||||||
inst->write(inst->buffer, inst->inputCount);
|
|
||||||
inst->write(" not found", 10u);
|
/** -# store the current command and reset the history buffer */
|
||||||
|
inst->dirty = true;
|
||||||
|
history_storeCmd(inst);
|
||||||
|
history_reset(inst);
|
||||||
|
|
||||||
|
/** -# determine the cmd len (chars until first space or \0 is found */
|
||||||
|
cmdLen = 0u;
|
||||||
|
while( (cmdLen < inst->inputCount)
|
||||||
|
&& (' ' != inst->buffer[cmdLen])
|
||||||
|
&& ('\0' != inst->buffer[cmdLen]))
|
||||||
|
{
|
||||||
|
cmdLen ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -# search for a matching command */
|
||||||
|
while (NULL != cmd)
|
||||||
|
{
|
||||||
|
/** -# compare command string and length */
|
||||||
|
if ( ((0 == strncmp( inst->buffer,
|
||||||
|
cmd->cmd,
|
||||||
|
cmdLen))
|
||||||
|
&& (cmdLen == strlen(cmd->cmd)))
|
||||||
|
|| ((0 == strncmp( inst->buffer,
|
||||||
|
cmd->cmdAlias,
|
||||||
|
cmdLen))
|
||||||
|
&& (cmdLen == strlen(cmd->cmdAlias))))
|
||||||
|
{
|
||||||
|
inst->write("\r\n", 2u);
|
||||||
|
|
||||||
|
cmdExecuted = 1u;
|
||||||
|
cmd->cmdFct(inst, inst->buffer, inst->inputCount);
|
||||||
|
cmd = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd = cmd->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cmdExecuted == 0u) && (inst->inputCount > 0))
|
||||||
|
{
|
||||||
|
inst->buffer[inst->inputCount] = '\0';
|
||||||
|
inst->write("\r\nCommand: ", 11u);
|
||||||
|
inst->write(inst->buffer, inst->inputCount);
|
||||||
|
inst->write(" not found", 10u);
|
||||||
|
}
|
||||||
|
utils_terminateInput(inst);
|
||||||
}
|
}
|
||||||
utils_terminateInput(inst);
|
|
||||||
}
|
}
|
||||||
/** -# check for tabulator key - auto complete */
|
/** -# check for tabulator key - auto complete */
|
||||||
else if('\t' == *data)
|
else if('\t' == *data)
|
||||||
|
@ -335,8 +335,10 @@ shellmatta_cmd_t helpCmd = {"help", "h", "Print this help text", "help", helpCmd
|
|||||||
*/
|
*/
|
||||||
void utils_terminateInput(shellmatta_instance_t *inst)
|
void utils_terminateInput(shellmatta_instance_t *inst)
|
||||||
{
|
{
|
||||||
inst->inputCount = 0u;
|
inst->inputCount = 0u;
|
||||||
inst->cursor = 0u;
|
inst->lastNewlineIdx = 0u;
|
||||||
|
inst->hereLength = 0u;
|
||||||
|
inst->cursor = 0u;
|
||||||
inst->write("\r\n", 2u);
|
inst->write("\r\n", 2u);
|
||||||
inst->write(inst->prompt, strlen(inst->prompt));
|
inst->write(inst->prompt, strlen(inst->prompt));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user