Adding "History" command

based on BDH Shell

Lab Objective

This tutorial provides a straightforward, step-by-step guide on how to create a basic CLI for the Serial Terminal. Here, you'll find a simple example of CLI creation that will introduce you to the basics of the process. This lab will also walk you through some of the fundamental concepts and techniques involved, ensuring that you understand each stage of the process.

Create New Application

Create New Application

Select Board

Select Project

Coding Explained

You can check the cmd functions in the `usrcmd.c` file.

The CLI (Command Line Interface) provides a way for users to interact with the system through text-based commands. Here is the detail of each function:

  • cmd_table_t: This is a struct that includes a command name, a description, and a function that is executed when the command is entered. The CLI (Command Line Interface) provides a way for users to interact with the system through text-based commands. Here is the detail of each function:

  • cmd_table_t: This is a struct that includes a command name, a description, and a function that is executed when the command is entered.

  • cmdlist[]: This is a list of the custom commands available in the shell. Each command corresponds to a specific function that is executed when the command is entered.

  • usrcmd_execute(): This function executes a given command by looking it up in the cmdlist and calling its corresponding function.

  • usrcmd_ntopt_callback(): This is the callback function for the command parsing library. It is invoked when a command is entered, and it executes the appropriate function based on the entered command.

  • Command Functions: Functions like usrcmd_help(), usrcmd_info(), usrcmd_clear(), etc. are the implementations of the custom commands. They are executed when the corresponding command is entered into the shell.

  • usrcmd_task(): This function is where the command line interface starts. It initializes the shell, sets the prompt, and then starts executing commands.

The new commands that we added are usrcmd_history(), usrcmd_reboot(), and usrcmd_kill().

✅ Create the commands of usrcmd_history

Please follow the steps below to add the history command:

  1. Add the following code snippet to define the usrcmd_history function and related variables at the beginning of your usrcmd.c file:

#include "ntshell.h" // Make sure you have this header included

#define MAX_HISTORY_COUNT 10 // Set the maximum number of commands to store in history
#define MAX_LINE_LENGTH 128 // Define the maximum line length for command history

static char command_history[MAX_HISTORY_COUNT][MAX_LINE_LENGTH];
static int history_count = 0;

static int usrcmd_history(int argc, char **argv)
{
    printf("Command history:\n");
    for (int i = 0; i < history_count; i++) {
        printf("%d: %s\n", i + 1, command_history[i]);
    }
    return 0;
}
  1. Modify the usrcmd_execute function to store the commands in the history. Replace the existing usrcmd_execute function with the following code snippet:

int usrcmd_execute(const char *text)
{
	// Store the command in the history
	    if (history_count < MAX_HISTORY_COUNT) {
	        strncpy(command_history[history_count], text, MAX_LINE_LENGTH);
	        command_history[history_count][MAX_LINE_LENGTH  - 1] = '\0';
	        history_count++;
	    } else {
	        // Shift the commands up in the history when the maximum count is reached
	        memmove(&command_history[0], &command_history[1], (MAX_HISTORY_COUNT - 1) * MAX_LINE_LENGTH );
	        strncpy(command_history[MAX_HISTORY_COUNT - 1], text, MAX_LINE_LENGTH );
	        command_history[MAX_HISTORY_COUNT - 1][MAX_LINE_LENGTH  - 1] = '\0';
	    }
    return ntopt_parse(text, usrcmd_ntopt_callback, 0);
}
  • First, we check if the history_count is less than the MAX_HISTORY_COUNT. If so, it means that the history buffer still has space to store new commands.

  • If there's space, we use strncpy to copy the command text into the command_history[history_count] array, with a maximum length of MAX_LINE_LENGTH. Then, we ensure that the last character in the array is set to the null terminator ('\0') to indicate the end of the string. Finally, we increment the history_count.

  • If the history_count is equal to or greater than the MAX_HISTORY_COUNT, it means that the history buffer is full. In this case, we need to make space for the new command by removing the oldest command.

  • To remove the oldest command, we use the memmove function to shift all the commands up by one position. This will overwrite the oldest command and free up space for the new command at the end of the array.

  • We then use strncpy again to copy the new command text into the last position of the command_history array, with a maximum length of * MAX_LINE_LENGTH. We also ensure that the last character in the array is set to the null terminator ('\0'**).

  • Finally, the function calls ntopt_parse to parse and execute the command.

  1. Add the history command to the cmdlist array.

Add the following line to the cmdlist array in the usrcmd.c file:

{ "history", " Show the history of executed commands", usrcmd_history },

After making these changes, you should have a working "history" command that prints the list of previously typed commands in the order they were executed. The command history stores up to MAX_HISTORY_COUNT commands. When the limit is reached, the oldest command is removed from the history to make room for new commands.

Last updated

Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University