Option groups

A large list of options can be divided into subgroups, with each subgroup being enabled by a top level option. Within each subgroup, the option parameter names have a separate namespace. An option in a subgroup may use the same short one character name or a long name than an option in a different subgroup.

<optclass name="testoptions">

  <option>
    <name>clustkey</name>
    <type>bool</type>
    <longopt>clustkey</longopt>
    <descr>Cluster key management</descr>

    <group>
      <option>
	<name>clustkey_generate</name>
	<type>bool</type>
	<longopt>generate</longopt>
	<descr>Generate a new cluster key</descr>

	<group>
	  <option>
	    <name>clustkey_name</name>
	    <type>string</type>
	    <opt>n</opt>
	    <longopt>name</longopt>
	    <descr>Cluster key's name</descr>
	    <hasvalue />
	    <argdescr>name</argdescr>
	  </option>

	  <option>
	    <name>clustkey_bits</name>
	    <type>int</type>
	    <opt>b</opt>
	    <longopt>bits</longopt>
	    <descr>Key's bit size</descr>
	    <hasvalue />
	    <argdescr>bits</argdescr>
	    <default>1024</default>
	  </option>

	  <option>
	    <name>clustkey_expire</name>
	    <type>ymd_interval</type>
	    <opt>e</opt>
	    <longopt>expires</longopt>
	    <descr>Key's expiration</descr>
	    <hasvalue />
	    <argdescr>interval</argdescr>
	    <default>x::ymd::interval("5 years")</default>
	  </option>

	  <option>
	    <name>clustkey_type</name>
	    <type>string</type>
	    <opt>t</opt>
	    <longopt>type</longopt>
	    <descr>Key type (rsa or dsa)</descr>
	    <hasvalue />
	    <argdescr>interval</argdescr>
	    <default>"rsa"</default>
	  </option>

	  <arg>
	    <name>directory</name>
	    <required />
	  </arg>
	</group>
      </option>

      <option>
	<name>clustkey_remove</name>
	<type>bool</type>
	<opt>r</opt>
	<longopt>remove</longopt>
	<descr>Remove key</descr>

	<group>
	  <arg>
	    <name>directory</name>
	    <required />
	  </arg>
	  <arg>
	    <name>keyname</name>
	    <required />
	  </arg>
	</group>
      </option>

      <option>
	<name>clustkey_list</name>
	<type>bool</type>
	<opt>l</opt>
	<longopt>list</longopt>
	<descr>List existing keys</descr>
	<group>
	  <arg>
	    <name>directory</name>
	    <required />
	  </arg>
	</group>
      </option>

      <option>
	<name>clustkey_export</name>
	<type>bool</type>
	<opt>e</opt>
	<longopt>export</longopt>
	<descr>Export updated cluster keys to a node key directory</descr>
	<group>
	  <arg>
	    <name>directory</name>
	    <required />
	  </arg>
	  <arg>
	    <name>nodekeydirectory</name>
	    <required />
	  </arg>
	</group>
      </option>
    </group>
  </option>

  <option>
    <name>nodekey</name>
    <type>bool</type>
    <longopt>nodekey</longopt>
    <descr>Node key management</descr>

    <group>
      <option>
	<name>nodekey_generate</name>
	<type>bool</type>
	<longopt>generate</longopt>
	<descr>Generate a new node key</descr>

	<group>
	  <option>
	    <name>nodekey_name</name>
	    <type>string</type>
	    <opt>n</opt>
	    <longopt>name</longopt>
	    <descr>Node key's name</descr>
	    <hasvalue />
	    <argdescr>name</argdescr>
	  </option>

	  <option>
	    <name>nodekey_bits</name>
	    <type>int</type>
	    <opt>b</opt>
	    <longopt>bits</longopt>
	    <descr>Key's bit size</descr>
	    <hasvalue />
	    <argdescr>bits</argdescr>
	    <default>1024</default>
	  </option>

	  <option>
	    <name>nodekey_expire</name>
	    <type>ymd_interval</type>
	    <opt>e</opt>
	    <longopt>expires</longopt>
	    <descr>Key's expiration</descr>
	    <hasvalue />
	    <argdescr>interval</argdescr>
	    <default>x::ymd::interval("1 year")</default>
	  </option>

	  <option>
	    <name>nodekey_signkey</name>
	    <type>string</type>
	    <opt>k</opt>
	    <longopt>signkey</longopt>
	    <hasvalue />
	    <descr>Signing cluster key (default: newest)</descr>
	    <argdescr>keyname</argdescr>

	    <group>
	      <arg>
		<name>directory</name>
		<required />
	      </arg>
	      <arg>
		<name>clusterkeydirectory</name>
		<required />
	      </arg>
	    </group>
	  </option>
	</group>
      </option>
    </group>
  </option>
  <defaultoptions />
</optclass>

This example defines two options, --clustkey and --nodekey. These two options are the only two options that are initially defined. When one of them gets specified, the remaining options must come from its group. It's as if the group becomes the effective option list, for the remaining options, and the initial list of --clustkey and --nodekey is no longer in effect. This means that, for example, after specifying --clustkey, --nodekey can no longer be specified, the only remaning options are the one that are listed in the group.

All option names must be unique, name gives the name of the member object in the option class, but different groups may use option with the same opt and longopt. In this example the --clustkey option group contains the --generate, --remove, --list, and --export; and the --nodekey option group contains a single option --generate which is a different option. Either --clustkey or --nodekey must be specified first, to open the respective option group, then --generate selects the specified option in the option group.

Groups may be nested within other group. In this example, the first --generate option is a group containing the --name, --bits, --expires, and --type options. The second --generate option, in the --nodekey group, contains its own --name, --bits, --expires, and --signkey options.

A group option's type would typically be bool, but it may be any type, and have a value. The option's group takes effect after the option's value gets set.

This example also has several groups that do not contain any options, only a list of args. As stated previously, args are generally ignored. This is used to adjust the indentation produced by the default --help option.