API

The application interfaces of MicroShell are really simple. Basically, you need to use only two functions such as microshell_init and microshell_getline. For the porting to a embdded system, it needs only two blocking serial I/O interface functions for the reading and writing.

[Core] : The line input module 'microshell'

typedef void (*MICROSHELL_UART_PUTC)(char c);
typedef char (*MICROSHELL_UART_GETC)(void);
typedef void (*MICROSHELL_ACTION_HOOK)(MSCORE_ACTION action);
void microshell_init(MICROSHELL *handle, MICROSHELL_UART_PUTC uart_putc, MICROSHELL_UART_GETC uart_getc, MICROSHELL_ACTION_HOOK action_hook);
char *microshell_getline(MICROSHELL *handle, char *buf, int siz);

The shortest example

This is the completely shortest example for these core functions. You will need only two blocking functions such as UART putc and UART getc for the UART I/Os.

char buf[MSCONF_MAX_INPUT_LENGTH];
MICROSHELL ms;
microshell_init(&ms, /* uart_putc= */ utx, /* uart_getc= */ urx, /* action_hook= */ 0);

while (1) {
    /*
     * You will get the user input text string from the 'buf'.
     */
    microshell_getline(&ms, buf, sizeof(buf));
}

[Optional] : The primitive option parser 'msopt'

typedef enum {
    MSOPT_RESULT_OK = 0,
    MSOPT_RESULT_ERROR_ILLEGAL_OBJECT,
    MSOPT_RESULT_ERROR_ILLEGAL_INDEX_NUMBER,
    MSOPT_RESULT_ERROR_TOO_MUCH_ARGUMENTS,
    MSOPT_RESULT_ERROR_BUFFER_SIZE,
} MSOPT_RESULT;
MSOPT_RESULT msopt_init(MSOPT *handle, char *text);
MSOPT_RESULT msopt_get_argc(MSOPT *handle, int *argc);
MSOPT_RESULT msopt_get_argv(MSOPT *handle, int index, char *bufptr, int bufsiz);

The shortest example

MSOPT msopt;
int argc = 0;
char argv[MSCONF_MAX_INPUT_LENGTH];

msopt_init(&msopt, "system mode 1");
msopt_get_argc(&msopt, &argc);  /* You will get '3' */
msopt_get_argv(&msopt, 1, argv, sizeof(argv));  /* You will get 'mode' */ 

[Optional] : The command parser 'mscmd' based on 'msopt'

typedef int MSCMD_USER_RESULT;
typedef void * MSCMD_USER_OBJECT;
typedef MSCMD_USER_RESULT (*MSCMD_FUNC)(MSOPT *msopt, MSCMD_USER_OBJECT usrobj);
typedef struct {
    char *argv0;
    MSCMD_FUNC func;
} MSCMD_COMMAND_TABLE;

typedef struct {
    MSCMD_COMMAND_TABLE *command_table;
    int command_count;
    MSCMD_USER_OBJECT usrobj;
} MSCMD;
int mscmd_init(MSCMD *handle, MSCMD_COMMAND_TABLE *command_table, int command_count, MSCMD_USER_OBJECT usrobj);
int mscmd_execute(MSCMD *handle, char *text, MSCMD_USER_RESULT *result);

The shortest example

static MSCMD_USER_RESULT usrcmd_system(MSOPT *msopt, MSCMD_USER_OBJECT usrobj);
static MSCMD_USER_RESULT usrcmd_config(MSOPT *msopt, MSCMD_USER_OBJECT usrobj);
static MSCMD_USER_RESULT usrcmd_help(MSOPT *msopt, MSCMD_USER_OBJECT usrobj);

static MSCMD_COMMAND_TABLE table[] = {
    {   "system",   usrcmd_system   },
    {   "config",   usrcmd_config   },
    {   "help",     usrcmd_help     },
};

typedef struct {
    int dummy;
} USER_OBJECT;

void foo(void)
{
    /*
     * User defined object.
     */
    USER_OBJECT usrobj = {
        .dummy = 1,
    };

    /*
     * The initialization of the module.
     */
    MSCMD mscmd;
    mscmd_init(&mscmd, table, sizeof(table) / sizeof(table[0]), &usrobj);

    /*
     * Some input instructions here.
     * One of the good choices is using microshell_getline.
     */
        ...
        ...
        ...

    /*
     * For this example, there are 'system mode 1' text in the buf.
     * The usrcmd_system will call automatically by mscmd_execute function.
     */
    MSCMD_USER_RESULT r;
    mscmd_execute(&mscmd, buf, &r);
}