libk  kcli.md at tip

File mod/kcli/kcli.md from the latest check-in


kcli

kcli is a module that implements common routines used by command-line utilities, such as option parsing, usage display, and more.

syntax

kcli implements the unwritten standard for command line parsing that is adhered to by many UNIX programs. it operates on an array of tokens, whose role depends on their content and on preceeding flags. note that in flag names, dashes and underscores are equivalent. this is to prevent obnoxious behavior and enable the macros to define multi-word long flags.

  1. if the argument -- preceded the current argument, it is interpreted as a parameter.
  2. if an argument begins with - and is followed by any symbol besides -, the remainder of the its characters are interpreted as short flags.
  3. if an argument consists solely of --, it is ignored, and all further arguments are treated as parameters regardless of their form.
  4. if an argument begins with -- is longer than two characters, and does not begin with --@, it is interpreted as a long flag.
  5. if a flag takes a parameter, the cursor is incremented and the field it points to is interpreted as its parameter. if there are not enough arguments, parse fails.
  6. if an argument consists solely of @, it is treated as in step 7, except flags and parameters are read from standard in.
  7. if an argument begins with @, the remainder is interpreted as a filename. this file is loaded and interpreted according to this same set of rules, where spaces separate each parameter, and double or single quote marks can be used to escape strings. newlines are ignored.
  8. if an argument consists solely of -@, it is treated as in step 11, except flags and parameters are read from standard in.
  9. if an argument consists solely of --@, lines will be read from stdin and interpreted as individual parameters, not as flags.
  10. if an argument begins with --@, the remainder is interpreted as a filename. all of the file's lines will be interpreted as individual parameters, not as flags.
  11. if an argument begins with -@, the remainder is interpreted as a filename. this file is loaded and interpreted under the assumption that newlines separate each parameter.
  12. if no other rules apply, the argument is added to the parameter list.

note: in the future, kcore will parse arguments at startup before passing them on to the application. all libk control arguments are prefixed with -:. these will not be passed onto the application, and so will not be available for kcli to parse.

consider the following examples: 1. --no-arg-flag --arg-flag --other-flag will set the flag no-arg-flag, and set the field arg-flag to "--other-flag". 2. if -a names a flag and -b and -c name string fields, -abc b-field-value c-field-value parameter sets the short flag a, set the field b to "b-field-value", set c to "c-field-value", and add the parameter parameter 3. -s --long @args -- -s --long @args sets the flags s, long, and parses the file args for further parameters, then adds the parameters "-s""--long""@args" to the parameter list.

functions

kcli_usage(kcli_set, kiochan)

kcli_usage() takes a kcli_set and prints a succinct usage summary to a kiochan.

types

struct kcli_set

kcli_set is a struct containing information about your program, such as its name, a synopsis of its function, a pointer to an array of arguments, and a list of kcli_opts.

  • const char* name - program name (if null, will be determined from argv instead)
  • const char* version - a string describing the program version (if null, version will not be printed)
  • const char** args - the argv pointer passed to the entry function, representing the command-line arguments passed to the program.
  • size_t argc - the number of arguments in the argv array.
  • const char* desc - program description
  • const kcli_param* params - a list of options expected by the program.
  • size_t paramc - the number of params in the list to process.
  • const kcli_opt* opts - a list of options expected by the program.
  • size_t optc - the number of options in the list to process.

a kcli_set might be used like so:

#include <k/core.h>
#include <k/io.h>
#include <k/cli.h>
stat entry(kenv e) {
	kcli_flag aardvark;
	kcli_flag zebra;
	char* user;
	char* password;
	long age;
	kcli_param params[] = {
		{ "user", kcli_param_string, kcli_rule_required,
		  &user, "the user to log in as" }
		  // or Kcli_param(user,string,required,"the user to log in as"),

		{ "age", kcli_param_dec, kcli_rule_optional,
		  &age, "the age of the user" }
		  // or Kcli_param(age,dec,optional,"the age of the user"),
	};
	kcli_opt options[] = {
		{ 'a', "aardvark", kcli_opt_flag, &aardvark,
		  "a nocturnal burrowing mammal" },
		  // or Kcli_opt(aardvark, 'a', flag, "a nocturnal burrowing mammal")
		{ 'z', "zebra", kcli_opt_flag, &zebra,
		  "a striped equine" },
		{ 'p', "password", kcli_opt_string, &password,
		  "the password to log in with" }
	};
	kcli_set argset = {
		"demo", e.args, e.argc,
		"a demonstration of the kcli_set type",
		params, Kmsz(params),
		options, Kmsz(options)
	},
	size_t args_parsed = kcli_parse(argset);
	if (args_parsed == 0) { kcli_usage(me, e.err); return 1; }

	return 0;
}

struct kcli_opt

a kcli_opt is a representation of a command-line flag and its function. each option must have a unique id and/or a unique name.

  • rune id - the short single-character form of the flag as a UTF-8 codepoint (or initial NUL for no short form)
  • const char* name - the long string form of the flag (or NULL for no long form)
  • kcli_opt_kind kind - enum that describes how the flag will function
  • void* val - a pointer to an appropriate type to store the return value in.
  • const char* desc - a description of the flag's purpose and function (or NULL for no description)

enum kcli_opt_kind

  • kcli_opt_none - flag is disabled and will not be shown in usage
  • kcli_opt_string - flag tells kcli to add a string to the list of expected parameters; appropriate string will be returned
  • kcli_opt_int - flag tells kcli to add an integer to the last of expected parameters; must be bitwise-OR'd with default base
  • kcli_opt_oct - flag tells kcli to add an octal number to the list of expected parameters
  • kcli_opt_dec - flag tells kcli to add a decimal number to the list of expected parameters
  • kcli_opt_hex - flag tells kcli to add a hexdecimal number to the list of expected parameters
  • kcli_opt_flag - flag is an option: will return kcli_flag_on if entered at least once, kcli_flag_off otherwise.
  • kcli_opt_toggle - flag toggles value on and off: will return kcli_flag_on if entered an odd number of times, kcli_flag_off otherwise.
  • kcli_opt_accumulate - flag increments a value every time it is entered; often used to implement -v (--verbose)-style options (e.g. -vvvv would return a value of 4).
  • kcli_opt_enum - flag is one of a series of enumerated values, which will be matched against a table to yield the associated integer.

struct kcli_param

kcli_param describes a parameter that may be passed to the program whether or not any flags are passed.

  • const char* name - a short name for the parameter
  • kcli_param_kind kind - the kind of parameter passed
  • kcli_rule rule - whether or not the parameter is optional
  • void* val - a pointer to an appropriate type of variable to fill
  • const char* desc - a description of the parameter's function

enum kcli_param_kind

  • kcli_param_none - parameter is disabled and will not be expected or accepted
  • kcli_param_string - parameter will not be parsed; a raw string will be returned
  • kcli_param_enum - parameter will be matched against an enumeration table
  • kcli_param_int - parameter will be parsed as an integer; must be bitwise-OR'd with default base
  • kcli_param_oct - parameter will be parsed as an octal number
  • kcli_param_dec - parameter will be parsed as a decimal number
  • kcli_param_hex - parameter will be parsed as a hexadecimal number

enum kcli_rule

  • kcli_rule_forbidden - parameter may not be passed
  • kcli_rule_optional - parameter may or may not be passed
  • kcli_rule_required - parameter must be passed

enum kcli_flag

results that an option of kind kcli_opt_flag can return.

  • kcli_flag_off = 0 - flag is off
  • kcli_flag_on = 1 - flag is on

macros

Kcli_param(field, kind, class, description)

a convenience macro for filling out parameter lists.

Kcli_param(field,a,b,"description") is transformed into:

{ "field", kcli_param_a, kcli_rule_b, &field, "description" }

Kcli_opt(field, kind, class, description)

a convenience macro for filling out option lists.

Kcli_opt(name,'n',string,"description") is transformed into:

{ 'n', "name", kcli_opt_string, &name, "description" }