From e2184615d928ee09fcbccc14caa1bdc40bb903be Mon Sep 17 00:00:00 2001 From: "DrZiplok@gmail.com" Date: Fri, 24 Sep 2010 07:31:59 +0000 Subject: [PATCH] Change the way pre-prompt printing works to avoid having to deal with "magic" menu entries. Add a default 'exit' command to back out of a menu. git-svn-id: https://arducopter.googlecode.com/svn/trunk@546 f9c3cf11-9bcb-44bc-f272-b75c42450872 --- libraries/AP_Common/include/menu.h | 21 +++++++++++++++++---- libraries/AP_Common/menu.cpp | 27 ++++++++++++++++----------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/libraries/AP_Common/include/menu.h b/libraries/AP_Common/include/menu.h index a55fc2771d..e74803c786 100644 --- a/libraries/AP_Common/include/menu.h +++ b/libraries/AP_Common/include/menu.h @@ -20,6 +20,11 @@ public: /// menu command function /// typedef int (*func)(uint8_t argc, const struct arg *argv); + + /// menu pre-prompt function + /// + /// If this function returns false, the menu exits. + typedef bool (*preprompt)(void); /// menu command description /// @@ -28,8 +33,6 @@ public: struct command { /// Name of the command, as typed or received. /// Command names are limited in size to keep this structure compact. - /// If the first command in the menu is named '*', it will be called - /// each time before printing the prompt. const char command[MENU_COMMAND_MAX]; /// The function to call when the command is received. @@ -37,6 +40,8 @@ public: /// 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. int (*func)(uint8_t argc, const struct arg *argv); ///< callback function }; @@ -46,7 +51,7 @@ public: /// @param commands An array of ::command structures. /// @param entries The number of entries in the menu. /// - Menu(const char *prompt, const struct command *commands, uint8_t entries); + Menu(const char *prompt, const struct command *commands, uint8_t entries, preprompt ppfunc = 0); /// menu runner void run(void); @@ -62,19 +67,27 @@ private: /// @param argc Number of arguments prepared for the menu item /// int _call(uint8_t n, uint8_t argc); + 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 static char _inbuf[MENU_COMMANDLINE_MAX]; ///< input buffer static arg _argv[MENU_ARGS_MAX + 1]; ///< arguments }; -/// Macro used to define a menu. +/// Macros used to define a menu. /// /// Use name.run() to run the menu. /// +/// The MENU2 macro supports the optional pre-prompt printing function. +/// #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])) +#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) + diff --git a/libraries/AP_Common/menu.cpp b/libraries/AP_Common/menu.cpp index 8fba5271af..1219a6ce45 100644 --- a/libraries/AP_Common/menu.cpp +++ b/libraries/AP_Common/menu.cpp @@ -17,10 +17,11 @@ char Menu::_inbuf[MENU_COMMANDLINE_MAX]; Menu::arg Menu::_argv[MENU_ARGS_MAX + 1]; // constructor -Menu::Menu(const prog_char *prompt, const Menu::command *commands, uint8_t entries) : +Menu::Menu(const prog_char *prompt, const Menu::command *commands, uint8_t entries, preprompt ppfunc) : _prompt(prompt), _commands(commands), - _entries(entries) + _entries(entries), + _ppfunc(ppfunc) { } @@ -35,12 +36,10 @@ Menu::run(void) // loop performing commands for (;;) { - // if the first command is called '*', call it before displaying the menu - if ("*", _commands[0].command) { - if (-2 == _call(0, 0)) - return; - } - + // run the pre-prompt function, if one is defined + if ((NULL != _ppfunc) && !_ppfunc()) + return; + // loop reading characters from the input len = 0; Serial.printf("%S] ", _prompt); @@ -91,12 +90,18 @@ Menu::run(void) ret = _call(i, argc); if (-2 == ret) return; + break; } } - // if the menu doesn't provide more comprehensive help, print the command list - if ((i == _entries) && (!strcmp(_argv[0].str, "?") || (!strcmp_P(_argv[0].str, PSTR("help"))))) - _help(); + // implicit commands + if (i == _entries) { + if (!strcmp(_argv[0].str, "?") || (!strcmp_P(_argv[0].str, PSTR("help")))) { + _help(); + } else if (!strcmp_P(_argv[0].str, PSTR("exit"))) { + return; + } + } } }