literm is a small terminal for the mbed This library allows mbed users to easily create a terminal for their mbed and simplify developpment. Users can simply add their own commands by using the LITERM_CMD macro. Each command is described by a name a description and a fallback which can get literm context and commands arguments. Please refers to the documentation, examples and don't hesitate to submit bugs, advices or request.

literm.cpp

Committer:
garfunkheul
Date:
2013-10-08
Revision:
0:ae9f1dd56e92

File content as of revision 0:ae9f1dd56e92:

#include "literm.h"
#include "mbed.h"

void literm::redraw(const char *line)
{
    out->printf("\x1B[1K");     /* Clear line */
    out->printf("\x1B[140D");   /* Move cursor to Left */
    out->printf("%s%s", prompt, line);
}

int do_help(literm *term, char *args)
{
    struct literm_cmd *pcmd = term->get_cmds();
    Serial *out = term->get_out();

    while (pcmd->prev != NULL) {
        out->printf("\r\n%s - %s", pcmd->name, pcmd->desc);
        pcmd = pcmd->prev;
    }

    return 0;
}

literm::literm(Serial *_out)
{
    out = _out;
    
    /* Register default config */
    sprintf(prompt, "mbed > ");
    sprintf(welcome, "\r\n\r\nHello from literm library");
    
    /* Register Help command which is the first one */
    sprintf(help_cmd.name, "help");
    help_cmd.prev = NULL;    
    help_cmd.func = do_help;
    cmd_list = &help_cmd;
}

void literm::loop()
{
    int hist_begin = -1; /* -1 = empty hist */
    int hist_end = 0;
    int hist_cur;
    int hist_full = 0;
    char hist[HIST_SIZE][MAX_CMDLINE_SIZE];
    
    char cmdline[MAX_CMDLINE_SIZE];
    int max_cmdline, i;
    struct literm_cmd *pcmd;

    out->printf(welcome);

    while (1) {
begin:
        pcmd = cmd_list;
        max_cmdline = 0;
        hist_cur = -1; /* -1 = no hist used */

        out->printf("\r\n%s",prompt);
        do {
            if (out->readable()) {
                cmdline[max_cmdline] = out->getc();
                
                if (cmdline[max_cmdline] == 3)
                    goto begin;
                if (cmdline[max_cmdline] == 4)
                    goto exit;
                if (cmdline[max_cmdline] == 8 || cmdline[max_cmdline] == 127) {
                    if (max_cmdline > 0) {
                        max_cmdline--;
                        cmdline[max_cmdline] = '\0';
                        redraw(cmdline);
                    }
                } else if (cmdline[max_cmdline] == 27) {
                    out->getc(); /* trash useless value */
                    char tmp = out->getc();
                    if (tmp == 65) { /* up */
                        if (hist_cur != hist_end && hist_begin != -1) {
                            if (hist_cur == -1)
                                hist_cur = hist_begin;
                            else
                                hist_cur--;
                            if (hist_cur < 0)
                                hist_cur = HIST_SIZE - 1;
                            redraw(hist[hist_cur]);
                        }                    
                    } else if (tmp == 66) { /* down */
                        if (hist_cur != hist_begin) {
                            hist_cur++;
                            if(hist_cur >= HIST_SIZE)
                                hist_cur = 0;
                            redraw(hist[hist_cur]);
                        }
                    }
                } else
                    out->putc(cmdline[max_cmdline++]);
            }
        } while (cmdline[max_cmdline - 1] != 13);
      
        /* use a command from history */
        if (hist_cur != -1) {
            strncpy(cmdline, hist[hist_cur], MAX_CMDLINE_SIZE - 1);
            max_cmdline = strlen(cmdline);
            if (hist_cur == hist_begin)
                goto proceed;
        
        /* use a new command */    
        } else {
            /* deal with empty lines */
            if (max_cmdline < 2 && hist_cur == -1)
                goto begin;
      
            cmdline[max_cmdline - 1] = '\0';  
        }      
          
        /* Update History */
        hist_begin++;
        if (hist_begin >= HIST_SIZE) {
            hist_begin = 0;
            hist_full = 1;
        }
        if (hist_full)
            hist_end++;
        if (hist_end >= HIST_SIZE)
            hist_end = 0;
        strncpy(hist[hist_begin], cmdline, MAX_CMDLINE_SIZE - 1);
                
proceed:
        for (i = 0; i < max_cmdline; ++i) {
            if (cmdline[i] == ' ') {
                cmdline[i] = '\0';
                break;
            }
            if (cmdline[i] == '\0') {
                cmdline[i + 1] = '\0';
                break;
            }
        }
        
        while (strcmp(pcmd->name, cmdline) && pcmd != NULL)
            pcmd = pcmd->prev;
            
        if (pcmd != NULL)
                (*pcmd->func)(this, cmdline + i + 1);
        else
            out->printf("\r\n%s not found", cmdline);
    }
exit:
    out->printf("\r\nExiting small cli\r\n");
}

literm_cmd* literm::get_cmds()
{
    return cmd_list;
}

Serial* literm::get_out()
{
    return out;
}

void literm::set_hostname(char *name)
{
    snprintf(prompt, sizeof(prompt) - 1, "%s > ", name);
}

void literm::set_welcome(char *message)
{
    snprintf(welcome, sizeof(welcome) - 1, "\r\n\r\n%s", message);
}

void literm::add_cmd(literm_cmd *_cmd)
{
    _cmd->prev = cmd_list;
    cmd_list = _cmd;
}