forked from ArduPilot/ardupilot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAP_Menu.h
171 lines (146 loc) · 6.54 KB
/
AP_Menu.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/// @file menu.h
/// @brief Simple commandline menu subsystem.
/// @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.
#pragma once
#include <inttypes.h>
#include <AP_HAL/AP_HAL.h>
#define MENU_COMMANDLINE_MAX 32 ///< maximum input line length
#define MENU_ARGS_MAX 3 ///< maximum number of arguments
#define MENU_COMMAND_MAX 14 ///< maximum size of a command name
/// Class defining and handling one menu tree
class Menu {
public:
/// 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 {
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)
};
/// 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.
///
FUNCTOR_TYPEDEF(func, int8_t, uint8_t, const struct arg *);
static void set_port(AP_HAL::BetterStream *port) {
_port = port;
}
/// 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.
///
FUNCTOR_TYPEDEF(preprompt, bool);
/// menu command description
///
struct command {
/// Name of the command, as typed or received.
/// Command names are limited in size to keep this structure compact.
///
const char command[MENU_COMMAND_MAX];
/// 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.
///
FUNCTOR_DECLARE(func, int8_t, uint8_t, const struct arg *);
};
/// 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.
/// @param entries The number of entries in the menu.
///
Menu(const char *prompt, const struct command *commands, uint8_t entries, preprompt ppfunc = 0);
/// set command line length limit
void set_limits(uint8_t commandline_max, uint8_t args_max);
/// menu runner
void run(void);
/// check for new input on the port. Can be used
/// to allow for the menu to operate asynchronously
/// this will return true if the user asked to exit the menu
bool check_input(void);
private:
/// Implements the default 'help' command.
///
void _help(void); ///< implements the 'help' command
/// 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
///
int8_t _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; ///< input buffer
static arg *_argv; ///< arguments
uint8_t _commandline_max;
uint8_t _args_max;
// allocate inbuf and args buffers
void _allocate_buffers(void);
// number of characters read so far from the port
uint8_t _input_len;
// check for next input character
bool _check_for_input(void);
// run one full entered command.
// return true if the menu loop should exit
bool _run_command(bool prompt_on_enter);
void _display_prompt();
// port to run on
static AP_HAL::BetterStream *_port;
};
/// Macros used to define a menu.
///
/// 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.
///
/// 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[] = prompt; \
static Menu name(__menu_name__ ## name, commands, ARRAY_SIZE(commands))
#define MENU2(name, prompt, commands, preprompt) \
static const char __menu_name__ ## name[] = prompt; \
static Menu name(__menu_name__ ## name, commands, ARRAY_SIZE(commands), preprompt)