AP_Menu.h 6.5 KB

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