2019-06-24 23:31:26 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2019 Stefan Strobel <stefan.strobel@shimatta.net>
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file shellmatta_autocomplete.c
|
|
|
|
* @brief autocomplete function of shellmatta
|
|
|
|
* @author Stefan Strobel <stefan.strobel@shimatta.net>
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @addtogroup shellmatta_autocomplete
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "shellmatta.h"
|
|
|
|
#include "shellmatta_autocomplete.h"
|
|
|
|
#include "shellmatta_utils.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief searches the registered commands for matching ones and prints
|
|
|
|
* the common part of all matching commands on the output
|
|
|
|
* if called twice all matching commands are printed
|
|
|
|
* @param[in] inst pointer to a shellmatta instance
|
|
|
|
*/
|
|
|
|
void autocomplete_run(shellmatta_instance_t *inst)
|
|
|
|
{
|
|
|
|
shellmatta_cmd_t *cmd = inst->cmdList;
|
|
|
|
char *tempCmd = NULL;
|
|
|
|
uint32_t minLen = 0u;
|
|
|
|
uint32_t sizeDiff = 0u;
|
|
|
|
bool exactMatch = true;
|
|
|
|
uint32_t printedLen = 0u;
|
|
|
|
uint32_t tempCursor = 0u;
|
|
|
|
|
|
|
|
/** -# increase the tab counter to print all matching commands next time */
|
|
|
|
inst->tabCounter++;
|
|
|
|
|
|
|
|
/** -# on douple tab show all matching commands */
|
|
|
|
if (1u < inst->tabCounter)
|
|
|
|
{
|
|
|
|
inst->tabCounter = 0u;
|
|
|
|
|
|
|
|
/** -# loop through all registered commands */
|
|
|
|
while (NULL != cmd)
|
|
|
|
{
|
|
|
|
/** -# check if command matches the input */
|
|
|
|
if( (strlen(cmd->cmd) >= inst->cursor)
|
|
|
|
&& (0u == memcmp(cmd->cmd, inst->buffer, inst->cursor)))
|
|
|
|
{
|
|
|
|
/** -# add newline on first find */
|
|
|
|
if(0u == printedLen)
|
|
|
|
{
|
|
|
|
inst->write("\r\n", 2u);
|
|
|
|
}
|
|
|
|
inst->write(cmd->cmd, strlen(cmd->cmd));
|
|
|
|
printedLen += strlen(cmd->cmd);
|
|
|
|
inst->write(" ", 4u);
|
|
|
|
printedLen += 4u;
|
|
|
|
}
|
|
|
|
/** -# check if command alias matches the input */
|
2020-03-01 18:45:30 +01:00
|
|
|
if( (NULL != cmd->cmdAlias)
|
|
|
|
&& (strlen(cmd->cmdAlias) >= inst->cursor)
|
2019-06-24 23:31:26 +02:00
|
|
|
&& (0u == memcmp(cmd->cmdAlias, inst->buffer, inst->cursor)))
|
|
|
|
{
|
|
|
|
/** -# add newline on first find */
|
|
|
|
if(0u == printedLen)
|
|
|
|
{
|
|
|
|
inst->write("\r\n", 2u);
|
|
|
|
}
|
|
|
|
inst->write(cmd->cmdAlias, strlen(cmd->cmdAlias));
|
|
|
|
printedLen += strlen(cmd->cmdAlias);
|
|
|
|
inst->write(" ", 4u);
|
|
|
|
printedLen += 4u;
|
|
|
|
}
|
|
|
|
cmd = cmd->next;
|
|
|
|
}
|
|
|
|
/** -# print input again if a commands was found */
|
|
|
|
if(printedLen > 0u)
|
|
|
|
{
|
|
|
|
utils_writeEcho(inst, "\r\n", 2u);
|
|
|
|
utils_writeEcho(inst, inst->prompt, strlen(inst->prompt));
|
|
|
|
utils_writeEcho(inst, inst->buffer, inst->inputCount);
|
|
|
|
tempCursor = inst->cursor;
|
|
|
|
inst->cursor = inst->inputCount;
|
|
|
|
utils_rewindCursor(inst, inst->inputCount - tempCursor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/** -# on single tab autocomplete as far as possible */
|
|
|
|
else if(0u != inst->cursor)
|
|
|
|
{
|
|
|
|
/** -# loop through all registered commands */
|
|
|
|
while (NULL != cmd)
|
|
|
|
{
|
|
|
|
/** -# check if command matches the input */
|
|
|
|
if( (strlen(cmd->cmd) >= inst->cursor)
|
|
|
|
&& (0u == memcmp(cmd->cmd, inst->buffer, inst->cursor)))
|
|
|
|
{
|
|
|
|
/** -# store first match */
|
|
|
|
if(NULL == tempCmd)
|
|
|
|
{
|
|
|
|
tempCmd = cmd->cmd;
|
|
|
|
minLen = strlen(cmd->cmd);
|
|
|
|
}
|
|
|
|
/** -# find common part of the matching commands */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
exactMatch = false;
|
|
|
|
minLen = SHELLMATTA_MIN(strlen(cmd->cmd), minLen);
|
|
|
|
for(uint32_t i = 0u; i < minLen; i++)
|
|
|
|
{
|
|
|
|
if(cmd->cmd[i] != tempCmd[i])
|
|
|
|
{
|
|
|
|
minLen = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** -# check if command Alias matches the input */
|
2020-03-01 18:45:30 +01:00
|
|
|
if( (NULL != cmd->cmdAlias)
|
|
|
|
&& (strlen(cmd->cmdAlias) >= inst->cursor)
|
2019-06-24 23:31:26 +02:00
|
|
|
&& (0u == memcmp(cmd->cmdAlias, inst->buffer, inst->cursor)))
|
|
|
|
{
|
|
|
|
/** -# store first match */
|
|
|
|
if(NULL == tempCmd)
|
|
|
|
{
|
|
|
|
tempCmd = cmd->cmdAlias;
|
|
|
|
minLen = strlen(cmd->cmdAlias);
|
|
|
|
}
|
|
|
|
/** -# find common part of the matches */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
exactMatch = false;
|
|
|
|
minLen = SHELLMATTA_MIN(strlen(cmd->cmdAlias), minLen);
|
|
|
|
for(uint32_t i = 0u; i < minLen; i++)
|
|
|
|
{
|
|
|
|
if(cmd->cmdAlias[i] != tempCmd[i])
|
|
|
|
{
|
|
|
|
minLen = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cmd = cmd->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** -# autocomplete found command */
|
|
|
|
if(NULL != tempCmd)
|
|
|
|
{
|
|
|
|
/** -# calculate the size of the command to be inserted */
|
|
|
|
sizeDiff = minLen - inst->cursor;
|
|
|
|
|
|
|
|
/** -# copy the found part into the buffer and display it */
|
|
|
|
utils_insertChars(inst, &(tempCmd[inst->cursor]), sizeDiff);
|
|
|
|
|
|
|
|
/** -# on exact match there is no need to double Tab to display all */
|
|
|
|
if(true == exactMatch)
|
|
|
|
{
|
|
|
|
inst->tabCounter = 0u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* nothing to do here */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|