123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- /*
- * Copyright (c) 2019 - 2021 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"
- #ifdef SHELLMATTA_AUTHENTICATION
- #include "shellmatta_auth.h"
- #endif
- #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;
- bool exactMatch = true;
- uint32_t printedLen = 0u;
- uint32_t sizeDiff;
- uint32_t tempCursor;
- /** -# increase the tab counter to print all matching commands next time */
- inst->tabCounter++;
- /** -# on douple tab show all matching commands */
- if (inst->tabCounter > 1u)
- {
- inst->tabCounter = 0u;
- /** -# loop through all registered commands */
- while (NULL != cmd)
- {
- #ifdef SHELLMATTA_AUTHENTICATION
- if (SHELLMATTA_OK != shellmatta_auth_is_cmd_permitted(inst, cmd))
- {
- cmd = cmd->next;
- continue;
- }
- #endif
- /** -# check if command matches the input */
- if( (strlen(cmd->cmd) >= inst->cursor)
- && (0 == strncmp(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 */
- if( (NULL != cmd->cmdAlias)
- && (strlen(cmd->cmdAlias) >= inst->cursor)
- && (0 == strncmp(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)
- {
- #ifdef SHELLMATTA_AUTHENTICATION
- if (SHELLMATTA_OK != shellmatta_auth_is_cmd_permitted(inst, cmd))
- {
- cmd = cmd->next;
- continue;
- }
- #endif
- /** -# check if command matches the input */
- if( (strlen(cmd->cmd) >= inst->cursor)
- && (0 == strncmp(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 */
- if( (NULL != cmd->cmdAlias)
- && (strlen(cmd->cmdAlias) >= inst->cursor)
- && (0 == strncmp(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, false);
- /** -# on exact match there is no need to double Tab to display all */
- if(true == exactMatch)
- {
- inst->tabCounter = 0u;
- }
- }
- }
- else
- {
- /* nothing to do here */
- }
- }
- /**
- * @}
- */
|