2010-09-24 02:50:02 -03:00
|
|
|
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*-
|
|
|
|
|
|
|
|
/// @file menu.h
|
|
|
|
/// @brief Simple commandline menu subsystem.
|
2010-09-30 01:28:10 -03:00
|
|
|
/// @discussion
|
|
|
|
/// The Menu class implements a simple CLI that accepts commands typed by
|
|
|
|
/// the user, and passes the arguments to those commands to a function
|
|
|
|
/// defined as handing the command.
|
|
|
|
///
|
|
|
|
/// Commands are defined in an array of Menu::command structures passed
|
|
|
|
/// to the constructor. Each entry in the array defines one command.
|
|
|
|
///
|
|
|
|
/// Arguments passed to the handler function are pre-converted to both
|
|
|
|
/// long and float for convenience.
|
2010-11-27 20:35:59 -04:00
|
|
|
|
2012-10-19 00:49:36 -03:00
|
|
|
#ifndef __AP_MENU_H__
|
|
|
|
#define __AP_MENU_H__
|
2010-09-24 02:50:02 -03:00
|
|
|
|
2011-11-24 14:28:14 -04:00
|
|
|
#include <inttypes.h>
|
|
|
|
|
2012-08-17 03:18:11 -03:00
|
|
|
#define MENU_COMMANDLINE_MAX 32 ///< maximum input line length
|
|
|
|
#define MENU_ARGS_MAX 4 ///< maximum number of arguments
|
|
|
|
#define MENU_COMMAND_MAX 14 ///< maximum size of a command name
|
2010-09-24 02:50:02 -03:00
|
|
|
|
|
|
|
/// Class defining and handling one menu tree
|
|
|
|
class Menu {
|
|
|
|
public:
|
2011-10-28 15:43:43 -03:00
|
|
|
/// argument passed to a menu function
|
|
|
|
///
|
|
|
|
/// Space-delimited arguments are parsed from the commandline and
|
|
|
|
/// separated into these structures.
|
|
|
|
///
|
|
|
|
/// If the argument cannot be parsed as a float or a long, the value
|
|
|
|
/// of f or i respectively is undefined. You should range-check
|
|
|
|
/// the inputs to your function.
|
|
|
|
///
|
|
|
|
struct arg {
|
2012-08-17 03:18:11 -03:00
|
|
|
const char *str; ///< string form of the argument
|
|
|
|
long i; ///< integer form of the argument (if a number)
|
|
|
|
float f; ///< floating point form of the argument (if a number)
|
2011-10-28 15:43:43 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
/// menu command function
|
|
|
|
///
|
|
|
|
/// Functions called by menu array entries are expected to be of this
|
|
|
|
/// type.
|
|
|
|
///
|
|
|
|
/// @param argc The number of valid arguments, including the
|
|
|
|
/// name of the command in argv[0]. Will never be
|
|
|
|
/// more than MENU_ARGS_MAX.
|
|
|
|
/// @param argv Pointer to an array of Menu::arg structures
|
|
|
|
/// detailing any optional arguments given to the
|
|
|
|
/// command. argv[0] is always the name of the
|
|
|
|
/// command, so that the same function can be used
|
|
|
|
/// to handle more than one command.
|
|
|
|
///
|
2012-08-17 03:18:11 -03:00
|
|
|
typedef int8_t (*func)(uint8_t argc, const struct arg *argv);
|
2011-10-28 15:43:43 -03:00
|
|
|
|
2012-11-21 01:17:16 -04:00
|
|
|
static void set_port(FastSerial *port) {
|
|
|
|
_port = port;
|
|
|
|
}
|
|
|
|
|
2011-10-28 15:43:43 -03:00
|
|
|
/// menu pre-prompt function
|
|
|
|
///
|
|
|
|
/// Called immediately before waiting for the user to type a command; can be
|
|
|
|
/// used to display help text or status, for example.
|
|
|
|
///
|
|
|
|
/// If this function returns false, the menu exits.
|
|
|
|
///
|
2012-08-17 03:18:11 -03:00
|
|
|
typedef bool (*preprompt)(void);
|
2011-10-28 15:43:43 -03:00
|
|
|
|
|
|
|
/// menu command description
|
|
|
|
///
|
|
|
|
struct command {
|
|
|
|
/// Name of the command, as typed or received.
|
|
|
|
/// Command names are limited in size to keep this structure compact.
|
|
|
|
///
|
2012-08-17 03:18:11 -03:00
|
|
|
const char command[MENU_COMMAND_MAX];
|
2011-10-28 15:43:43 -03:00
|
|
|
|
|
|
|
/// The function to call when the command is received.
|
|
|
|
///
|
|
|
|
/// The argc argument will be at least 1, and no more than
|
|
|
|
/// MENU_ARGS_MAX. The argv array will be populated with
|
|
|
|
/// arguments typed/received up to MENU_ARGS_MAX. The command
|
|
|
|
/// name will always be in argv[0].
|
|
|
|
///
|
|
|
|
/// Commands may return -2 to cause the menu itself to exit.
|
|
|
|
/// The "?", "help" and "exit" commands are always defined, but
|
|
|
|
/// can be overridden by explicit entries in the command array.
|
|
|
|
///
|
2012-08-17 03:18:11 -03:00
|
|
|
int8_t (*func)(uint8_t argc, const struct arg *argv); ///< callback function
|
2011-10-28 15:43:43 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
/// constructor
|
|
|
|
///
|
|
|
|
/// Note that you should normally not call the constructor directly. Use
|
|
|
|
/// the MENU and MENU2 macros defined below.
|
|
|
|
///
|
|
|
|
/// @param prompt The prompt to be displayed with this menu.
|
|
|
|
/// @param commands An array of ::command structures in program memory (PROGMEM).
|
|
|
|
/// @param entries The number of entries in the menu.
|
|
|
|
///
|
|
|
|
Menu(const char *prompt, const struct command *commands, uint8_t entries, preprompt ppfunc = 0);
|
|
|
|
|
|
|
|
/// menu runner
|
2012-08-17 03:18:11 -03:00
|
|
|
void run(void);
|
2011-01-30 16:13:07 -04:00
|
|
|
|
2010-09-24 02:50:02 -03:00
|
|
|
private:
|
2011-10-28 15:43:43 -03:00
|
|
|
/// Implements the default 'help' command.
|
|
|
|
///
|
2012-08-17 03:18:11 -03:00
|
|
|
void _help(void); ///< implements the 'help' command
|
2011-10-28 15:43:43 -03:00
|
|
|
|
|
|
|
/// calls the function for the n'th menu item
|
|
|
|
///
|
|
|
|
/// @param n Index for the menu item to call
|
|
|
|
/// @param argc Number of arguments prepared for the menu item
|
|
|
|
///
|
2012-08-17 03:18:11 -03:00
|
|
|
int8_t _call(uint8_t n, uint8_t argc);
|
2011-10-28 15:43:43 -03:00
|
|
|
|
2012-08-17 03:18:11 -03:00
|
|
|
const char * _prompt; ///< prompt to display
|
|
|
|
const command * _commands; ///< array of commands
|
|
|
|
const uint8_t _entries; ///< size of the menu
|
|
|
|
const preprompt _ppfunc; ///< optional pre-prompt action
|
2011-10-28 15:43:43 -03:00
|
|
|
|
2012-08-17 03:18:11 -03:00
|
|
|
static char _inbuf[MENU_COMMANDLINE_MAX]; ///< input buffer
|
|
|
|
static arg _argv[MENU_ARGS_MAX + 1]; ///< arguments
|
2012-11-21 01:17:16 -04:00
|
|
|
|
|
|
|
// port to run on
|
|
|
|
static FastSerial *_port;
|
2010-09-24 02:50:02 -03:00
|
|
|
};
|
|
|
|
|
2010-09-24 04:31:59 -03:00
|
|
|
/// Macros used to define a menu.
|
2010-09-24 02:50:02 -03:00
|
|
|
///
|
2010-09-30 01:28:10 -03:00
|
|
|
/// The commands argument should be an arary of Menu::command structures, one
|
|
|
|
/// per command name. The array does not need to be terminated with any special
|
|
|
|
/// record.
|
|
|
|
///
|
2010-09-24 02:50:02 -03:00
|
|
|
/// Use name.run() to run the menu.
|
|
|
|
///
|
2010-09-24 04:31:59 -03:00
|
|
|
/// The MENU2 macro supports the optional pre-prompt printing function.
|
|
|
|
///
|
2012-08-17 03:18:11 -03:00
|
|
|
#define MENU(name, prompt, commands) \
|
|
|
|
static const char __menu_name__ ## name[] PROGMEM = prompt; \
|
|
|
|
static Menu name(__menu_name__ ## name, commands, sizeof(commands) / sizeof(commands[0]))
|
2011-01-30 16:13:07 -04:00
|
|
|
|
2012-08-17 03:18:11 -03:00
|
|
|
#define MENU2(name, prompt, commands, preprompt) \
|
|
|
|
static const char __menu_name__ ## name[] PROGMEM = prompt; \
|
|
|
|
static Menu name(__menu_name__ ## name, commands, sizeof(commands) / sizeof(commands[0]), preprompt)
|
2010-09-30 01:28:10 -03:00
|
|
|
|
2012-10-19 00:49:36 -03:00
|
|
|
#endif // __AP_COMMON_MENU_H__
|