CLI.h 4.66 KB
/*
 * CLI.h - CLI library for Arduino/ESP8266 and others definitions
 *
 * Version 1.0, latest version, documentation and bugtracker available at:
 *              https://gitlab.lindenaar.net/arduino/CLI
 *
 * Copyright (c) 2019 Frederik Lindenaar
 *
 * This library is free software: you can redistribute it and/or modify it under
 * the terms of version 3 of the GNU General Public License as published by the
 * Free Software Foundation, or (at your option) a later version of the license.
 *
 * This code is distributed in the hope that it will be useful but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, visit <http://www.gnu.org/licenses/> to download it.
 */

#include <Stream.h>

#ifndef CLI_H
#define CLI_H

#ifndef CLI_MAX_CMDS
  #define CLI_MAX_CMDS  16
#endif // CLI_MAX_CMDS

#ifndef CLI_MAX_LINE
  #define CLI_MAX_LINE  80
#endif // CLI_MAX_LINE

class CLI;

struct CLI_Command_Param {
  const char *param PROGMEM;
  union {
    int int16;
    uint16_t uint16;
    int8_t int8;
    uint8_t uint8;
    int32_t int32;
    uint32_t uint32;
    char *str PROGMEM;
  };
};

struct CLI_Command_Flags {
  const char *command;
  uint8_t cmdlen, flags, intparam;
};

const char *CLI_STR_skipSep(const char *str);
const char *CLI_STR_findSep(const char *str);
const char *CLI_STR_parseInt(const char *, int &, int = -32768, int = 32767);
const char *CLI_STR_parse_HEX_byte(const char *, uint8_t &);
const struct CLI_Command_Param *CLI_STR_parseParam_P (const char *, const struct CLI_Command_Param params[]);
const char *CLI_STR_parseFlags_P (const char *, const struct CLI_Command_Flags params[], uint8_t, uint8_t, uint8_t *);

class CLI_Command {
  friend class Help_Command;
  friend class CLI;
  protected:
    const char *command, *description, *usagehelp;
    bool matches(const char *cmd, uint8_t cmdlen);
  public:
    CLI_Command(CLI &cli , const char *command PROGMEM, const char *description PROGMEM, const char *help PROGMEM = NULL);
    virtual bool setparams(const char *params);
    virtual bool execute(CLI &cli) = 0;
};


class Help_Command : public CLI_Command {
  CLI &_cli;
#if CLI_MAX_CMDS < 255
    uint8_t _cmd_idx;
#else
    uint16_t _cmd_idx;
#endif
    bool _cmd_list;
  public:
    Help_Command(CLI &cli);
    bool setparams(const char *);
    bool execute(CLI &cli);
};


class EEPROM_Dump_Command : public CLI_Command {
    int _offset;
  public:
    EEPROM_Dump_Command(CLI &cli);
    bool setparams(const char *);
    bool execute(CLI &cli);
};

class Reset_Command : public CLI_Command {
    int _resetting;
  public:
    Reset_Command(CLI &cli);
    bool execute(CLI &cli);
};

class I2C_Scan_Command : public CLI_Command {
    uint8_t _address, _found;
  public:
    I2C_Scan_Command(CLI &cli);
    bool setparams(const char *);
    bool execute(CLI &cli);
};

class I2C_Dump_Command : public CLI_Command {
    uint8_t _address;
    bool _large;
    uint16_t _length, _offset;
  public:
    I2C_Dump_Command(CLI &cli);
    bool setparams(const char *);
    bool execute(CLI &cli);
};


class CLI : public Stream {
    enum CLI_State { STATE_INIT, STATE_READY, STATE_INPUT, STATE_PARSE, STATE_EXEC } _state;
#if CLI_MAX_CMDS < 255
    uint8_t _command_count;
#else
    uint16_t _command_count;
#endif
    CLI_Command *_commands[CLI_MAX_CMDS];
#if CLI_MAX_LINE < 255
    uint8_t _line_len;
#else
    uint16_t _line_len;
#endif
    char _cmdbuffer[CLI_MAX_LINE];
    //    const char *_params;
    CLI_Command *_current_cmd;
  protected:
    Stream *_stream;
    const char *_banner, *_prompt;
  public:
    CLI(Stream &stream, const char *banner PROGMEM = NULL, const char *prompt PROGMEM = NULL);
    void add_command(CLI_Command *cmd);
    CLI_Command *get_command(int);
    CLI_Command *get_command(const char *, int);
#if CLI_MAX_CMDS < 256
    uint8_t find_command(const char *, int);
    inline uint8_t command_count() {
#else
    uint16_t find_command(const char *, int);
    inline uint16_t command_count() {
#endif
      return _command_count;
    };

    inline int available() {
      return _stream->available();
    };

    inline int peek() {
      return _stream->peek();
    };

    inline int read() {
      return _stream->read();
    };

    inline size_t write(uint8_t c) {
      return _stream->write(c);
    };

    size_t print_P (const char *str PROGMEM);
    void print2digits(uint8_t num, char filler = '0', uint8_t base=10);
    void print_mem(uint16_t addr, const uint8_t buff[], uint8_t len, uint8_t width=16);
    void printtab();

    bool process();
};

#endif // CLI_H