40 const cmdopts_t *cmds; |
40 const cmdopts_t *cmds; |
41 const gpointer userdata; |
41 const gpointer userdata; |
42 size_t valno; |
42 size_t valno; |
43 }; |
43 }; |
44 |
44 |
45 // ------------------------------------------------------------- """ ]] |
45 // -------------------------------------------------------------- """ ]] |
46 |
46 |
47 This struct describes command as a whole and links to argument descriptions. |
47 This struct describes command as a whole and links to argument descriptions. |
48 This struct is also used to describe individual subcommands, as they are quite |
48 This struct is also used to describe individual subcommands, as they are quite |
49 similar to normal command, because they can have their own options, arguments |
49 similar to normal command, because they can have their own options, arguments |
50 and subcommands. The fields of this struct: |
50 and subcommands. The fields of this struct: |
51 |
51 |
52 * 'name' - name of the command or subcommand. |
52 * 'name' - name of the command or subcommand. |
53 |
53 |
54 * 'flags' - currently there's only one flag: |
54 * 'flags' - currently there's only one flag: |
55 |
55 |
56 + 'cmd_safe' - command is safe to execute in main mcabberrc during |
56 + 'cmd_safe' - command is safe to execute in main mcabberrc during |
57 initialization. Have no meaning for subcommands. |
57 initialization. Have no meaning for subcommands. |
58 + 'cmd_default' - default value of no flags enabled. |
58 + 'cmd_default' - default value of no flags enabled. |
59 |
59 |
60 * 'check' - execution environment checker for command. This callback is used to |
60 * 'check' - execution environment checker for command. This callback is used |
61 do general checks before even parsing command line. You can write your own |
61 to do general checks before even parsing command line. You can write your |
62 checker or use standard ones, for example - 'cmd_check_online', that checks, |
62 own checker or use standard ones, for example - 'cmd_check_online', that |
63 if you are currently online. |
63 checks, if you are currently online. |
64 |
64 |
65 * 'handle' - command function. It is executed only if command line was |
65 * 'handle' - command function. It is executed only if command line was |
66 successfully parsed and argument values passed the type checking. Unused in |
66 successfully parsed and argument values passed the type checking. Unused in |
67 subcommands. |
67 subcommands. |
68 |
68 |
69 * 'opts' - pointer to the array of 'cmdopt_t' structs, describing command-line |
69 * 'opts' - pointer to the array of 'cmdopt_t' structs, describing command-line |
70 options ("-f bar") and switches ("-x"), that this command accepts. |
70 options ("-f bar") and switches ("-x"), that this command accepts. Array |
|
71 must end with option, that have 0 as short option character. |
71 |
72 |
72 * 'args' - similarly, pointer to the array of 'cmdarg_t' structs, that describe |
73 * 'args' - similarly, pointer to the array of 'cmdarg_t' structs, that describe |
73 command-line positional arguments (in order). |
74 command-line positional arguments (in order). Array must end with argument, |
|
75 that have NULL name. |
74 |
76 |
75 * 'cmds' - pointer to the array of subcommands of this command (or subcommand). |
77 * 'cmds' - pointer to the array of subcommands of this command (or subcommand). |
76 How parser switches to subcommands we will describe later. |
78 How parser switches to subcommands we will describe later. Array must end |
|
79 with subcommand, that have NULL name. |
77 |
80 |
78 * 'userdata' - arbitrary pointer, where you can put some data, that should |
81 * 'userdata' - arbitrary pointer, where you can put some data, that should |
79 accompany this command or subcommand. Unused by parser. |
82 accompany this command or subcommand. Unused by parser. |
80 |
83 |
81 * 'valno' - this is internal value, that is initialized at command definition |
84 * 'valno' - this is internal value, that is initialized at command definition |
82 time, you should not modify it. Currently unused in subcommands. |
85 time, you should not modify it. Currently unused in subcommands. |
83 |
86 |
84 ## Command function, 'cmd_handler_t' |
87 ## Command function, 'cmd_handler_t' |
85 |
88 |
86 [[!format c """ // ------------------------------------------------------------- |
89 [[!format c """// -------------------------------------------------------------- |
87 |
90 |
88 typedef gchar *(*cmd_handler_t) (cmdopts_t *command, cmdarg_value_t *values); |
91 typedef gchar *(*cmd_handler_t) (cmdopts_t *command, cmdarg_value_t *values); |
89 |
92 |
90 // ------------------------------------------------------------- """ ]] |
93 // -------------------------------------------------------------- """ ]] |
91 |
94 |
92 Command function is passed it's command definition struct (mainly to give it |
95 Command function is passed it's command definition struct (mainly to give it |
93 access to userdata) and dynamically allocated array of parsed argument values. |
96 access to userdata) and dynamically allocated array of parsed argument values. |
94 |
97 |
95 It should return NULL in case all went smoothly, or dynamically allocated error |
98 It should return NULL in case all went smoothly, or dynamically allocated error |
176 + 'chreq' - shortcut for "argument must have a valid value". |
180 + 'chreq' - shortcut for "argument must have a valid value". |
177 + 'special' - this is special type of argument - subcommand or switch. |
181 + 'special' - this is special type of argument - subcommand or switch. |
178 |
182 |
179 * 'defval' - default value for argument in "unchecked" form - i.e., in the form |
183 * 'defval' - default value for argument in "unchecked" form - i.e., in the form |
180 of string, as it appears on command line (we'll discuss type checkers and |
184 of string, as it appears on command line (we'll discuss type checkers and |
181 what can they do to value later). Before parsing command line, parser will |
185 what can they do to value later). Before parsing command line, parser will |
182 assign this value to corresponding value structure. |
186 assign this value to corresponding value structure. |
183 |
187 |
184 * 'type' - pointer to structure, describing argument type. |
188 * 'type' - pointer to structure, describing argument type. |
185 |
189 |
186 * 'chkdata' - if type needs some additional info, it is a place to supply it. |
190 * 'chkdata' - if type needs some additional info, it is a place to supply it. |
187 |
191 |
188 * 'userdata' - place for arbitrary info, that should accompany this argument or |
192 * 'userdata' - place for arbitrary info, that should accompany this argument or |
189 option. Unused by parser. |
193 option. Unused by parser. |
190 |
194 |
191 Now, let's discuss general case - option with argument or positional argument. |
195 Now, let's discuss general case - option with argument or positional argument. |
192 |
196 |
193 When parser encounters such argument, it checks 'catchall' and 'plain' flags and |
197 When parser encounters such argument, it checks 'catchall' and 'plain' flags and |
194 crops argument value from command line accordingly, then it assigns it to the |
198 crops argument value from command line accordingly, then it assigns it to the |
195 'value.arg' field of 'cmdarg_value_t' struct in array 'values' with index, given |
199 'value.arg' field of 'cmdarg_value_t' struct in array 'values' with index, given |
196 in 'pos'. Also it marks such value as 'visited' and puts a link to argument |
200 in 'pos'. Also it marks such value as 'visited' and puts a link to argument |
197 description into value's 'src' field. More about effect of these actions later, |
201 description into value's 'src' field. More about effect of these actions later, |
198 in 'cmdarg_value_t' section. |
202 in 'cmdarg_value_t' section. |
199 |
203 |
200 However, if argument struct is a part of option description struct, and have |
204 However, if argument struct is a part of option description struct, and have |
201 flag 'switch' set, parser will not try to parse value. Instead it will increase |
205 flag 'switch' set, parser will not try to parse value. Instead it will increase |
202 the count in 'value.swc' in corresponding 'cmdarg_value_t' struct. Argument name |
206 the count in 'value.swc' in corresponding 'cmdarg_value_t' struct. Argument |
203 for switches is essentially ignored, but for safety sake it is recommended to |
207 name for switches is essentially ignored, but for safety sake it is recommended |
204 duplicate switch long option name here. Flags 'catchall' and 'plain' obviously |
208 to duplicate switch long option name here. Flags 'catchall' and 'plain' |
205 have no effect. Flag 'check' makes switch a trigger, that flips between 'on' and |
209 obviously have no effect. Flag 'check' makes switch a trigger, that flips |
206 'off' for every occurence of flag on command line. Flags 'required' and 'subcmd' |
210 between 'on' and 'off' for every occurence of flag on command line. Flags |
207 also have no effect for obvious reasons. Default value is ignored for switches, |
211 'required' and 'subcmd' also have no effect for obvious reasons. Default value |
208 they always start with count 0 (off). Since switch is internal type, argument |
212 is ignored for switches, they always start with count 0 (off). Since switch is |
209 type field is ignored as well. Flags and source fields of value are updated as |
213 internal type, argument type field is ignored as well. Flags and source fields |
210 usual. |
214 of value are updated as usual. |
211 |
215 |
212 If flag 'subcmd' is set for positional argument, parser crops argument value |
216 If flag 'subcmd' is set for positional argument, parser crops argument value |
213 according to flags as usual, but instead of assigning it, walks through list of |
217 according to flags as usual, but instead of assigning it, walks through list of |
214 subcommands in command description struct and compares obtained value to |
218 subcommands in command description struct and compares obtained value to |
215 subcommand names. If it finds corresponding subcommand, it assigns pointer to |
219 subcommand names. If it finds corresponding subcommand, it assigns pointer to |
216 subcommand description struct to 'value.cmd' field of corresponding |
220 subcommand description struct to 'value.cmd' field of corresponding |
217 'cmdarg_value_t' struct and updates it's source and flags. Then, instead of |
221 'cmdarg_value_t' struct and updates it's source and flags. Then, instead of |
218 proceeding with parsing process, it recursively calls parser on remaining part |
222 proceeding with parsing process, it recursively calls parser on remaining part |
219 of command line, passing subparser subcommand description. Note, that if |
223 of command line, passing subparser subcommand description. Note, that if |
220 subcommand parser will end parsing before hitting end of command line, parser |
224 subcommand parser will end parsing before hitting end of command line, parser |
221 will proceed with parsing arguments for main command. Default value and argument |
225 will proceed with parsing arguments for main command. Default value and |
222 type fields are ignored for subcommands. |
226 argument type fields are ignored for subcommands. |
223 |
227 |
224 Now let's take a look at value structure, that you'll be dealing with the most |
228 Now let's take a look at value structure, that you'll be dealing with the most |
225 in the actual code. |
229 in the actual code. |
226 |
230 |
227 ## Argument value structure, 'cmdarg_value_t' |
231 ## Argument value structure, 'cmdarg_value_t' |
228 |
232 |
229 [[!format c """ // ------------------------------------------------------------- |
233 [[!format c """// -------------------------------------------------------------- |
230 |
234 |
231 typedef struct cmdarg_value_struct cmdarg_value_t; |
235 typedef struct cmdarg_value_struct cmdarg_value_t; |
232 |
236 |
233 typedef enum { |
237 typedef enum { |
234 cmdval_default = 0x0000, |
238 cmdval_default = 0x0000, |
235 cmdval_visited = 0x0100, |
239 cmdval_visited = 0x0100, |
236 cmdval_freeme = 0x0200, |
240 cmdval_freeme = 0x0200, |
237 } cmdval_flags_t; |
241 } cmdval_flags_t; |
238 |
242 |
239 struct cmdarg_value_struct { |
243 struct cmdarg_value_struct { |
240 cmdarg_t *src; |
244 const cmdarg_t *src; |
241 cmdval_flags_t flags; |
245 cmdval_flags_t flags; |
242 union { |
246 union { |
243 guint uint; |
247 guint uint; |
244 gint sint; |
248 gint sint; |
245 guint swc; |
249 guint swc; |
246 const gchar *roarg; |
250 const gchar *roarg; |
247 gchar *arg; |
251 gchar *arg; |
248 cmdopts_t *cmd; |
252 const cmdopts_t *cmd; |
249 struct { |
253 struct { |
250 gpointer bud; |
254 gpointer bud; |
251 gchar *resource; |
255 gchar *resource; |
252 } rjid; |
256 } rjid; |
253 gpointer ptr; |
257 gpointer ptr; |
254 } value; |
258 } value; |
255 }; |
259 }; |
256 |
260 |
257 // ------------------------------------------------------------- """ ]] |
261 // -------------------------------------------------------------- """ ]] |
258 |
262 |
259 Command may happen to be called recursively - i.e., something in command may |
263 Command may happen to be called recursively - i.e., something in command may |
260 cause the event, that will cause another call to the same command, thus we |
264 cause the event, that will cause another call to the same command, thus we |
261 cannot store actual values in command/argument definition struct, and have to |
265 cannot store actual values in command/argument definition struct, and have to |
262 allocate dynamic memory for them. This struct is designed exactly for this. |
266 allocate dynamic memory for them. This struct is designed exactly for this. |
263 Let's take a look at it's fields: |
267 Let's take a look at it's fields: |
264 |
268 |
265 * 'src' - this points to the argument description, from which this struct is |
269 * 'src' - this points to the argument description, from which this struct is |
266 holding value right now (note, that value can be initialized several times |
270 holding value right now (note, that value can be initialized several times |
267 during parsing process from different arguments). |
271 during parsing process from different arguments). |
289 |
293 |
290 ## Parsing |
294 ## Parsing |
291 |
295 |
292 Parser starts by allocating memory for values array, and then initializing it by |
296 Parser starts by allocating memory for values array, and then initializing it by |
293 walking through command description, looking at options and arguments and |
297 walking through command description, looking at options and arguments and |
294 assigning default values to corresponding entries in array. It also puts pointer |
298 assigning default values to corresponding entries in array. It also puts |
295 to the argument description into value's 'src' field. Thus, all used in command |
299 pointer to the argument description into value's 'src' field. Thus, all used in |
296 description values will have this field initialized, even if they were not |
300 command description values will have this field initialized, even if they were |
297 specified on command line. This comes handly later, when checking for reqired |
301 not specified on command line. This comes handly later, when checking for |
298 value presence. For switches parser just sets the counter to zero. Note, that |
302 reqired value presence. For switches parser just sets the counter to zero. |
299 parser does not descend into subcommands at this stage. It does the same |
303 Note, that parser does not descend into subcommands at this stage. It does the |
300 procedure for subcommand, but later, when it already knows which subcommand is |
304 same procedure for subcommand, but later, when it already knows which subcommand |
301 selected. Also note, that if several arguments have the same value index, parser |
305 is selected. Also note, that if several arguments have the same value index, |
302 will use latest encountered one to initialize the value. This is used for |
306 parser will use latest encountered one to initialize the value. This is used |
303 default value in "argument clustering", that I'll show you later. |
307 for default value in "argument clustering", that I'll show you later. |
304 |
308 |
305 Then parser calls command environment checker callback (if present), and if it |
309 Then parser calls command environment checker callback (if present), and if it |
306 returns error - terminates the process right now. Note, that subcommands can |
310 returns error - terminates the process right now. Note, that subcommands can |
307 also have checkers. |
311 also have checkers. |
308 |
312 |
309 Next parser does its job of parsing command line. Each time it extracts argument |
313 Next parser does its job of parsing command line. Each time it extracts |
310 value, it into 'value.arg' field of corresponding value entry and pointer to |
314 argument value, it into 'value.arg' field of corresponding value entry and |
311 argument description struct into 'src' field. Also it sets 'visited' flag on |
315 pointer to argument description struct into 'src' field. Also it sets 'visited' |
312 value. At this stage value is still just unchecked string, except for special |
316 flag on value. At this stage value is still just unchecked string, except for |
313 argument types. For switch occurence count in 'value.swc' gets increased each |
317 special argument types. For switch occurence count in 'value.swc' gets |
314 time argument was specified. Note however, that if several switches use the same |
318 increased each time argument was specified. Note however, that if several |
315 value index ("clustered switches"), counter gets reset, when switches change one |
319 switches use the same value index ("clustered switches"), counter gets reset, |
316 another in sequence - i.e. "-e -s -s -s" will count as three "-s", but "-s -s -e |
320 when switches change one another in sequence - i.e. "-e -s -s -s" will count as |
317 -s" will count as only one "-s". For subcommands parser checks for corresponding |
321 three "-s", but "-s -s -e -s" will count as only one "-s". For subcommands |
318 subcommand in 'cmds' list, assigns it to 'value.cmd' and recursively passes the |
322 parser checks for corresponding subcommand in 'cmds' list, assigns it to |
319 end of command line to be parsed with subcommand description. Note, that for |
323 'value.cmd' and recursively passes the end of command line to be parsed with |
320 subcommands parser does "checking on the spot" - if parsed argument value does |
324 subcommand description. Note, that for subcommands parser does "checking on the |
321 not match any subcommand, and argument have 'required' flag set, it raises error |
325 spot" - if parsed argument value does not match any subcommand, and argument |
322 immediately (if flag is not set, it merely assigns NULL and proceeds parsing |
326 have 'required' flag set, it raises error immediately (if flag is not set, it |
323 according to current command description). |
327 merely assigns NULL and proceeds parsing according to current command |
324 |
328 description). |
325 Then parser walks through array of values and performs value checking. Note, |
329 |
|
330 Then parser walks through array of values and performs value checking. Note, |
326 that all values, that need checking at this point should have 'src' field |
331 that all values, that need checking at this point should have 'src' field |
327 initialized - either set at default value assignment step, or during parsing, |
332 initialized - either set at default value assignment step, or during parsing, |
328 so, parser knows properties of value's argument. Parser only pays attention to |
333 so, parser knows properties of value's argument. Parser only pays attention to |
329 the values, that either have 'visited' flag set (i.e. provided by user) or that |
334 the values, that either have 'visited' flag set (i.e. provided by user) or that |
330 have 'check' flag in argument description (useful for mandatory arguments or |
335 have 'check' flag in argument description (useful for mandatory arguments or |
331 default values, that need convesion). If value corresponds to a switch, and |
336 default values, that need convesion). If value corresponds to a switch, and |
332 argument have 'check' flag set, switch occurence count is replaced by remainder |
337 argument have 'check' flag set, switch occurence count is replaced by remainder |
333 of division it by 2 (this way switch behaves like trigger). If it is a |
338 of division it by 2 (this way switch behaves like trigger). If it is a |
334 subcommand, and it have 'required' flag set, parser checks, if it have non-NULL |
339 subcommand, and it have 'required' flag set, parser checks, if it have non-NULL |
335 value. If it is usual argument (option or positional), and it does have 'type', |
340 value. If it is usual argument (option or positional), and it does have 'type', |
336 that have 'check' callback set, parser calls this checker, passing it value |
341 that have 'check' callback set, parser calls this checker, passing it value |
337 structure (again, value structure contains pointer to argument description, so, |
342 structure (again, value structure contains pointer to argument description, so, |
338 checker can access 'chkdata' field, supplied by user). If checker returns error |
343 checker can access 'chkdata' field, supplied by user). If checker returns error |
339 string and argument have 'required' flag set, parser raises error. If flag is |
344 string and argument have 'required' flag set, parser raises error. If flag is |
340 not set, parser just prints warning and proceeds with checking. |
345 not set, parser just prints warning and proceeds with checking. |
341 |
346 |
342 If checking was successful, parser calls command function, providing it with |
347 If checking was successful, parser calls command function, providing it with |
343 command description and values array. This function can also return error, but |
348 command description and values array. This function can also return error, but |
344 at this stage it does not change process, only causes error message to be |
349 at this stage it does not change process, only causes error message to be |
345 printed. |
350 printed. |
346 |
351 |
347 And finally parser frees allocated resources - walks through values array, |
352 And finally parser frees allocated resources - walks through values array, |
348 calling argument type 'free' callback on values, that have 'freeme' flag set and |
353 calling argument type 'free' callback on values, that have 'freeme' flag set and |
349 then frees the array itself. |
354 then frees the array itself. |
350 |
355 |
351 ## Argument type, 'cmdarg_type_t' |
356 ## Argument type, 'cmdarg_type_t' |
352 |
357 |
353 [[!format c """ // ------------------------------------------------------------- |
358 [[!format c """// -------------------------------------------------------------- |
354 |
359 |
355 typedef struct cmdarg_type_struct cmdarg_type_t; |
360 typedef struct cmdarg_type_struct cmdarg_type_t; |
356 |
361 |
357 typedef gchar *(*cmdarg_checker_t) (cmdarg_value_t *value); |
362 typedef gchar *(*cmdarg_checker_t) (cmdarg_value_t *value); |
358 typedef void (*cmdarg_destructor_t) (cmdarg_value_t *value); |
363 typedef void (*cmdarg_destructor_t) (cmdarg_value_t *value); |
375 |
380 |
376 * 'free' - if type checker may need to free some data afterwards, this callback |
381 * 'free' - if type checker may need to free some data afterwards, this callback |
377 should be set to corresponding function, and each time checker really needs |
382 should be set to corresponding function, and each time checker really needs |
378 value to be freed, it should set flag 'freeme' on value. |
383 value to be freed, it should set flag 'freeme' on value. |
379 |
384 |
380 * 'complete' - FIXME not yet designed callback, that will return list of |
385 * 'complete' - *FIXME* not yet designed callback, that will return list of |
381 possible completions according to given prefix. |
386 possible completions according to given prefix. |
382 |
387 |
383 After parsing command line parser performs argument value checking, that's where |
388 After parsing command line parser performs argument value checking, that's where |
384 it calls 'check' callbacks. Checker is given pointer to value structure, that |
389 it calls 'check' callbacks. Checker is given pointer to value structure, that |
385 it needs to check. Checker can modify value string (except when it is default |
390 it needs to check. Checker can modify value string (except when it is default |
386 value, but you have to supply your default values so, that they do not need |
391 value, but you have to supply your default values so, that they do not need |
387 modifying) or completely replace it with another string or even non-string |
392 modifying) or completely replace it with another string or even non-string |
388 object. If checker uses some resources (eg. allocates memory for replacement |
393 object. If checker uses some resources (eg. allocates memory for replacement |
389 value), it can set the flag 'freeme' on value to request call to value |
394 value), it can set the flag 'freeme' on value to request call to value |
390 destructor, when values array will be freed. If checker needs some additional |
395 destructor, when values array will be freed. If checker needs some additional |
391 data (eg. it is some generic checker, that needs list of valid values or other |
396 data (eg. it is some generic checker, that needs list of valid values or other |
392 parameters), these data can be supplied in 'chkdata' field. Checker function |
397 parameters), these data can be supplied in 'chkdata' field. Checker function |
393 should return NULL on success or error string, that will be g_free()'d by |
398 should return NULL on success or error string, that will be g_free()'d by |
394 parser. Take note, that if argument does not have 'reqired' flag set, parser |
399 parser. Take note, that if argument does not have 'reqired' flag set, parser |
395 will ignore checker error, so, it is recommended to nullify invalid value before |
400 will ignore checker error, so, it is recommended to nullify invalid value before |
396 returning error (but it is not required). |
401 returning error (but it is not required). |
397 |
402 |
398 # Examples |
403 # Examples |
399 |
404 |
400 When writing description for a command, first thing, you have to do - is to |
405 When writing description for a command, first thing, you have to do - is to |
401 determine, which values your command can get from user. You don't have to be |
406 determine, which values your command can get from user. You don't have to be |
402 shy - new interface is designed to encourage commands to be as flexible and |
407 shy - new interface is designed to encourage commands to be as flexible and |
403 option-rich as possible. |
408 option-rich as possible. |
404 |
409 |
405 Second - consider, which ones are to be specified as positional arguments, and |
410 Second - consider, which ones are to be specified as positional arguments, and |
406 which should become options or switches. |
411 which should become options or switches. |
407 |
412 |
408 Next you will want to decide, which checks and restrictions should you put on |
413 Next you will want to decide, which checks and restrictions should you put on |
409 values. Essentially, determine value type. |
414 values. Essentially, determine value type. |
410 |
415 |
411 And then you can begin writing command definition. So, let's start with |
416 And then you can begin writing command definition. So, let's start with |
412 something simple. |
417 something simple. |
413 |
418 |
414 ## Single-argument no-checks command |
419 ## Single-argument no-checks command |
415 |
420 |
416 Let's look at command like /say, that have only one argument, that should be |
421 Let's look at command like /say, that have only one argument, that should be |
470 ... |
475 ... |
471 // remove command |
476 // remove command |
472 cmd_undef (&def_ex1); |
477 cmd_undef (&def_ex1); |
473 ... |
478 ... |
474 |
479 |
475 [[!format c """ // ------------------------------------------------------------- |
480 [[!format c """// -------------------------------------------------------------- |
476 |
481 |
477 A lot of things to do to achieve a simple goal - does not look quite appealing |
482 A lot of things to do to achieve a simple goal - does not look quite appealing |
478 so far. Still, let's tweak our example a bit. |
483 so far. Still, let's tweak our example a bit. |
479 |
484 |
480 Remember the third step - decide, which checks should apply to our argument. |
485 Remember the third step - decide, which checks should apply to our argument. |
481 Now, look at our command - we check, if message is NULL or if message is empty. |
486 Now, look at our command - we check, if message is NULL or if message is empty. |
482 But imagine, that user has given us a message " " - it's of no big use to us, |
487 But imagine, that user has given us a message " " - it's of no big use to us, |
483 so, probably, we should also strip leading/trailing spaces before doing the |
488 so, probably, we should also strip leading/trailing spaces before doing the |
484 check. That's where argument types come into play. We can write argument |
489 check. That's where argument types come into play. We can write argument |
485 checker for that! But luckily, we already have built-in standard checker, that |
490 checker for that! But luckily, we already have built-in standard checker, that |
486 does exactly what we need - checks if string contains non-space characters. All |
491 does exactly what we need - checks if string contains non-space characters. All |
487 we need to do - to specify '&cmdarg_type_nonspace' as argument type and remove |
492 we need to do - to specify '&cmdarg_type_nonspace' as argument type and remove |
488 our check inside of the command: |
493 our check inside of the command: |
489 |
494 |
490 [[!format c """ // ------------------------------------------------------------- |
495 [[!format c """// -------------------------------------------------------------- |
491 |
496 |
492 ... |
497 ... |
493 cmdopts_t def_ex1 = { |
498 cmdopts_t def_ex1 = { |
494 "ex1", |
499 "ex1", |
495 cmd_default, |
500 cmd_default, |
581 scr_log_print (whereto, "Got the message: \"%s\".", values[0].value.arg); |
586 scr_log_print (whereto, "Got the message: \"%s\".", values[0].value.arg); |
582 return NULL; |
587 return NULL; |
583 } |
588 } |
584 ... |
589 ... |
585 |
590 |
586 // ------------------------------------------------------------- """ ]] |
591 // -------------------------------------------------------------- """ ]] |
587 |
592 |
588 Ok, that works, but what if user have aliases, and wants last specified option |
593 Ok, that works, but what if user have aliases, and wants last specified option |
589 to override the value? Currently, if -s was once specified, -l will not have any |
594 to override the value? Currently, if -s was once specified, -l will not have any |
590 effect, regardless of count or position in command line. Not that good. Let's |
595 effect, regardless of count or position in command line. Not that good. Let's |
591 use the trick, that I call "argument clustering". We'll specify the same value |
596 use the trick, that I call "argument clustering". We'll specify the same value |
592 index for both switches. Since 'value' struct have the pointer to the argument, |
597 index for both switches. Since 'value' struct have the pointer to the argument, |
593 it was initialized from last time, we can recognize, which switch was used last. |
598 it was initialized from last time, we can recognize, which switch was used last. |
594 By default this pointer points to the last argument with this index in command |
599 By default this pointer points to the last argument with this index in command |
595 definition - we can use that to specify default value. Now, to identify switches |
600 definition - we can use that to specify default value. Now, to identify |
596 we can use argument names, but 'argument' struct contains userdata field, where |
601 switches we can use argument names, but 'argument' struct contains userdata |
597 we can put our LPRINT_* constants and just use it directly. So, with clustered |
602 field, where we can put our LPRINT_* constants and just use it directly. So, |
598 switches, we will have: |
603 with clustered switches, we will have: |
599 |
604 |
600 [[!format c """ // ------------------------------------------------------------- |
605 [[!format c """// -------------------------------------------------------------- |
601 |
606 |
602 ... |
607 ... |
603 cmdopts_t def_ex1 = { |
608 cmdopts_t def_ex1 = { |
604 "ex1", |
609 "ex1", |
605 cmd_default, |
610 cmd_default, |
606 NULL, |
611 NULL, |
607 do_ex1, |
612 do_ex1, |
608 (cmdopt_t[3]){ |
613 (cmdopt_t[3]){ |
609 // Set both argument indices to 1, specify our constants in userdata |
614 // Set both argument indices to 1, specify our constants in userdata |
610 // field. Screen is default value, thus, it goes last. |
615 // field. Screen is default value, thus, it goes last. |
611 { 'l', "log", { "log", 1, cmdarg_switch, NULL, NULL, NULL, |
616 { 'l', "log", { "log", 1, cmdarg_switch, NULL, NULL, NULL, |
612 (gpointer)LPRINT_LOG } }, |
617 (gpointer)LPRINT_LOG } }, |
613 { 's', "screen", { "screen", 1, cmdarg_switch, NULL, NULL, NULL, |
618 { 's', "screen", { "screen", 1, cmdarg_switch, NULL, NULL, NULL, |
614 (gpointer)LPRINT_NORMAL } }, |
619 (gpointer)LPRINT_NORMAL } }, |
615 {0} |
620 {0} |
620 {NULL} |
625 {NULL} |
621 }, |
626 }, |
622 NULL, |
627 NULL, |
623 }; |
628 }; |
624 |
629 |
625 gchar *do_ex1 (cmdopts_t *command, cmdarg_value_t *values) |
630 gchar *do_ex1 (const cmdopts_t *command, cmdarg_value_t *values) |
626 { |
631 { |
627 scr_log_print ((guint)values[1].src -> userdata, |
632 scr_log_print ((guint)values[1].src -> userdata, |
628 "Got the message: \"%s\".", values[0].value.arg); |
633 "Got the message: \"%s\".", values[0].value.arg); |
629 return NULL; |
634 return NULL; |
630 } |
635 } |
631 ... |
636 ... |
632 |
637 |
633 // ------------------------------------------------------------- """ ]] |
638 // -------------------------------------------------------------- """ ]] |
634 |
639 |
635 That's much better. This trick may be quite useful not only with switches, but |
640 That's much better. This trick may be quite useful not only with switches, but |
636 also with options, sometimes even clustering options with arguments can be |
641 also with options, sometimes even clustering options with arguments can be |
637 handy. |
642 handy. |
638 |
643 |
639 ## Options |
644 ## Options |
640 |
645 |
641 Options are not much different from normal arguments, except there you'll see |
646 Options are not much different from normal arguments, except there you'll see |
642 'check' and 'required' mostly only in combination with default value - otherwise |
647 'check' and 'required' mostly only in combination with default value - otherwise |
643 it defeats the purpose - to be optional. |
648 it defeats the purpose - to be optional. |
644 |
649 |
645 [[!format c """ // ------------------------------------------------------------- |
650 [[!format c """// -------------------------------------------------------------- |
646 |
651 |
647 // TODO: |
652 // TODO: |
648 // example (not really used as of now - were too complex to deal using old |
653 // example (not really used as of now - were too complex to deal using old |
649 // interface). |
654 // interface). |
650 |
655 |
651 // ------------------------------------------------------------- """ ]] |
656 // -------------------------------------------------------------- """ ]] |
652 |
657 |
653 ## Subcommands |
658 ## Subcommands |
654 |
659 |
655 Now, let's discuss another internal argument type - subcommand. Since |
660 Now, let's discuss another internal argument type - subcommand. Since |
656 subcommands are quite common in mcabber, and since they have quite big impact on |
661 subcommands are quite common in mcabber, and since they have quite big impact on |
657 parsing process, they were made a part of parser. |
662 parsing process, they were made a part of parser. |
658 |
663 |
659 Currently, only positional arguments can be subcommands. You can have options or |
664 Currently, only positional arguments can be subcommands. You can have options or |
660 other arguments precede them, though in practice there's no examples of that so |
665 other arguments precede them, though in practice there's no examples of that so |
661 far. |
666 far. |
662 |
667 |
663 So, to indicate, that argument is a subcommand, you just add flag 'subcmd'. When |
668 So, to indicate, that argument is a subcommand, you just add flag 'subcmd'. |
664 parser will encounter such argument, it will look up command structure with |
669 When parser will encounter such argument, it will look up command structure with |
665 specified name in the list 'cmds' of command definition and proceed parsing, |
670 specified name in the list 'cmds' of command definition and proceed parsing, |
666 using that command definition instead of main one. A good example of command |
671 using that command definition instead of main one. A good example of command |
667 with several completely different subcommands would be '/color', so, let's look: |
672 with several completely different subcommands would be '/color', so, let's look: |
668 |
673 |
669 [[!format c """ // ------------------------------------------------------------- |
674 [[!format c """// -------------------------------------------------------------- |
670 |
675 |
671 static gchar *do_color (cmdopts_t *command, cmdarg_value_t *values); |
676 static gchar *do_color (const cmdopts_t *command, cmdarg_value_t *values); |
672 |
677 |
673 // We will put these values in subcommand definition 'userdata' fields |
678 // We will put these values in subcommand definition 'userdata' fields |
674 // to simplify the task of determining, which subcommand was actually selected. |
679 // to simplify the task of determining, which subcommand was actually selected. |
675 typedef enum { |
680 typedef enum { |
676 scmd_color_roster, |
681 scmd_color_roster, |