Simple Menu for user config at startup etc

Committer:
skyscraper
Date:
Sun Mar 29 16:00:36 2020 +0000
Revision:
0:694155408133
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
skyscraper 0:694155408133 1 ///
skyscraper 0:694155408133 2 /// @file userMenu.h
skyscraper 0:694155408133 3 /// @brief Simple commandline menu subsystem.
skyscraper 0:694155408133 4 /// @discussion
skyscraper 0:694155408133 5 /// Menu derived from old version of ArduPilot, used in ArduIMU.V3
skyscraper 0:694155408133 6 /// Originally from https://code.google.com/archive/p/ardu-imu/downloads
skyscraper 0:694155408133 7 ///
skyscraper 0:694155408133 8 /// The Menu class implements a simple CLI that accepts commands typed by
skyscraper 0:694155408133 9 /// the user, and passes the arguments to those commands to a function
skyscraper 0:694155408133 10 /// defined as handing the command.
skyscraper 0:694155408133 11 ///
skyscraper 0:694155408133 12 /// Commands are defined in an array of Menu::command structures passed
skyscraper 0:694155408133 13 /// to the constructor. Each entry in the array defines one command.
skyscraper 0:694155408133 14 ///
skyscraper 0:694155408133 15 /// Arguments passed to the handler function are pre-converted to both
skyscraper 0:694155408133 16 /// long and float for convenience.
skyscraper 0:694155408133 17
skyscraper 0:694155408133 18 #ifndef SKYSCRAPER_MBED_USER_MENU_H_INCLUDED
skyscraper 0:694155408133 19 #define SKYSCRAPER_MBED_USER_MENU_H_INCLUDED
skyscraper 0:694155408133 20
skyscraper 0:694155408133 21 #include <inttypes.h>
skyscraper 0:694155408133 22
skyscraper 0:694155408133 23 //#define MENU_COMMANDLINE_MAX 32
skyscraper 0:694155408133 24 //#define MENU_ARGS_MAX 4
skyscraper 0:694155408133 25 //#define MENU_COMMAND_MAX 14
skyscraper 0:694155408133 26
skyscraper 0:694155408133 27 /// Class defining and handling one menu tree
skyscraper 0:694155408133 28 class Menu {
skyscraper 0:694155408133 29 public:
skyscraper 0:694155408133 30
skyscraper 0:694155408133 31
skyscraper 0:694155408133 32 static constexpr uint8_t commandlineLenMax = 32U; ///< maximum input line length
skyscraper 0:694155408133 33 static constexpr uint8_t argsLenMax = 4U; ///< maximum number of arguments
skyscraper 0:694155408133 34 static constexpr uint8_t commandNameLenMax = 14; ///< maximum length of a command name
skyscraper 0:694155408133 35 /// argument passed to a menu function
skyscraper 0:694155408133 36 ///
skyscraper 0:694155408133 37 /// Space-delimited arguments are parsed from the commandline and
skyscraper 0:694155408133 38 /// separated into these structures.
skyscraper 0:694155408133 39 ///
skyscraper 0:694155408133 40 /// If the argument cannot be parsed as a float or a long, the value
skyscraper 0:694155408133 41 /// of f or i respectively is undefined. You should range-check
skyscraper 0:694155408133 42 /// the inputs to your function.
skyscraper 0:694155408133 43 ///
skyscraper 0:694155408133 44 struct arg {
skyscraper 0:694155408133 45 arg(): str{nullptr}, i{0},f{0.0}{}
skyscraper 0:694155408133 46 const char *str; ///< string form of the argument
skyscraper 0:694155408133 47 long i; ///< integer form of the argument (if a number)
skyscraper 0:694155408133 48 float f; ///< floating point form of the argument (if a number)
skyscraper 0:694155408133 49 };
skyscraper 0:694155408133 50
skyscraper 0:694155408133 51 /// menu command function
skyscraper 0:694155408133 52 ///
skyscraper 0:694155408133 53 /// Functions called by menu array entries are expected to be of this
skyscraper 0:694155408133 54 /// type.
skyscraper 0:694155408133 55 ///
skyscraper 0:694155408133 56 /// @param argc The number of valid arguments, including the
skyscraper 0:694155408133 57 /// name of the command in argv[0]. Will never be
skyscraper 0:694155408133 58 /// more than argsLenMax.
skyscraper 0:694155408133 59 /// @param argv Pointer to an array of Menu::arg structures
skyscraper 0:694155408133 60 /// detailing any optional arguments given to the
skyscraper 0:694155408133 61 /// command. argv[0] is always the name of the
skyscraper 0:694155408133 62 /// command, so that the same function can be used
skyscraper 0:694155408133 63 /// to handle more than one command.
skyscraper 0:694155408133 64 ///
skyscraper 0:694155408133 65 typedef int8_t (*func)(uint8_t argc, const struct arg *argv);
skyscraper 0:694155408133 66
skyscraper 0:694155408133 67 /// menu pre-prompt function
skyscraper 0:694155408133 68 ///
skyscraper 0:694155408133 69 /// Called immediately before waiting for the user to type a command; can be
skyscraper 0:694155408133 70 /// used to display help text or status, for example.
skyscraper 0:694155408133 71 ///
skyscraper 0:694155408133 72 /// If this function returns false, the menu exits.
skyscraper 0:694155408133 73 ///
skyscraper 0:694155408133 74 typedef bool (*preprompt)(void);
skyscraper 0:694155408133 75
skyscraper 0:694155408133 76 /// menu command description
skyscraper 0:694155408133 77 ///
skyscraper 0:694155408133 78 struct command {
skyscraper 0:694155408133 79 /// Name of the command, as typed or received.
skyscraper 0:694155408133 80 /// Command names are limited in size to keep this structure compact.
skyscraper 0:694155408133 81 ///
skyscraper 0:694155408133 82 const char command[commandNameLenMax];
skyscraper 0:694155408133 83
skyscraper 0:694155408133 84 /// The function to call when the command is received.
skyscraper 0:694155408133 85 ///
skyscraper 0:694155408133 86 /// The argc argument will be at least 1, and no more than
skyscraper 0:694155408133 87 /// argsLenMax. The argv array will be populated with
skyscraper 0:694155408133 88 /// arguments typed/received up to argsLenMax. The command
skyscraper 0:694155408133 89 /// name will always be in argv[0].
skyscraper 0:694155408133 90 ///
skyscraper 0:694155408133 91 /// Commands may return -2 to cause the menu itself to exit.
skyscraper 0:694155408133 92 /// The "?", "help" and "exit" commands are always defined, but
skyscraper 0:694155408133 93 /// can be overridden by explicit entries in the command array.
skyscraper 0:694155408133 94 ///
skyscraper 0:694155408133 95 int8_t (*func)(uint8_t argc, const struct arg *argv); ///< callback function
skyscraper 0:694155408133 96 };
skyscraper 0:694155408133 97
skyscraper 0:694155408133 98 /// constructor
skyscraper 0:694155408133 99 ///
skyscraper 0:694155408133 100 /// Note that you should normally not call the constructor directly. Use
skyscraper 0:694155408133 101 /// the MENU and MENU2 macros defined below.
skyscraper 0:694155408133 102 ///
skyscraper 0:694155408133 103 /// @param prompt The prompt to be displayed with this menu.
skyscraper 0:694155408133 104 /// @param commands An array of ::command structures in program memory (PROGMEM).
skyscraper 0:694155408133 105 /// @param entries The number of entries in the menu.
skyscraper 0:694155408133 106 ///
skyscraper 0:694155408133 107 Menu(const char *prompt, const struct command *commands, uint8_t entries, preprompt ppfunc = 0);
skyscraper 0:694155408133 108
skyscraper 0:694155408133 109 /// menu runner
skyscraper 0:694155408133 110 void run(void);
skyscraper 0:694155408133 111
skyscraper 0:694155408133 112 private:
skyscraper 0:694155408133 113 /// Implements the default 'help' command.
skyscraper 0:694155408133 114 ///
skyscraper 0:694155408133 115 void _help(void); ///< implements the 'help' command
skyscraper 0:694155408133 116
skyscraper 0:694155408133 117 /// calls the function for the n'th menu item
skyscraper 0:694155408133 118 ///
skyscraper 0:694155408133 119 /// @param n Index for the menu item to call
skyscraper 0:694155408133 120 /// @param argc Number of arguments prepared for the menu item
skyscraper 0:694155408133 121 ///
skyscraper 0:694155408133 122 int8_t _call(uint8_t n, uint8_t argc);
skyscraper 0:694155408133 123
skyscraper 0:694155408133 124 const char *_prompt; ///< prompt to display
skyscraper 0:694155408133 125 const command *_commands; ///< array of commands
skyscraper 0:694155408133 126 const uint8_t _entries; ///< size of the menu
skyscraper 0:694155408133 127 const preprompt _ppfunc; ///< optional pre-prompt action
skyscraper 0:694155408133 128
skyscraper 0:694155408133 129 static char _inbuf[commandlineLenMax]; ///< input buffer
skyscraper 0:694155408133 130 static arg _argv[argsLenMax+ 1]; ///< arguments
skyscraper 0:694155408133 131 };
skyscraper 0:694155408133 132
skyscraper 0:694155408133 133 /// Macros used to define a menu.
skyscraper 0:694155408133 134 ///
skyscraper 0:694155408133 135 /// The commands argument should be an arary of Menu::command structures, one
skyscraper 0:694155408133 136 /// per command name. The array does not need to be terminated with any special
skyscraper 0:694155408133 137 /// record.
skyscraper 0:694155408133 138 ///
skyscraper 0:694155408133 139 /// Use name.run() to run the menu.
skyscraper 0:694155408133 140 ///
skyscraper 0:694155408133 141 /// The MENU2 macro supports the optional pre-prompt printing function.
skyscraper 0:694155408133 142 ///
skyscraper 0:694155408133 143 #define MENU(name, prompt, commands) \
skyscraper 0:694155408133 144 static constexpr char __menu_name__ ##name[] = prompt; \
skyscraper 0:694155408133 145 static Menu name(__menu_name__ ##name, commands, sizeof(commands) / sizeof(commands[0]))
skyscraper 0:694155408133 146
skyscraper 0:694155408133 147 #define MENU2(name, prompt, commands, preprompt) \
skyscraper 0:694155408133 148 static constexpr char __menu_name__ ##name[] = prompt; \
skyscraper 0:694155408133 149 static Menu name(__menu_name__ ##name, commands, sizeof(commands) / sizeof(commands[0]), preprompt)
skyscraper 0:694155408133 150
skyscraper 0:694155408133 151 #endif