Many applications use command-\/line options and environment variables as a way to override configuration values. In Elektra this can be automated by providing a specification that maps command-\/line options and environment variables to keys in the K\+DB.

The function {\ttfamily elektra\+Get\+Opts} uses this specification together with {\ttfamily argv} and {\ttfamily envp} and creates new keys in the {\ttfamily proc} namespace for any command-\/line option or environment variable it finds. Because the {\ttfamily proc} namespace is used, these values will be preferred over any stored values in a cascading lookup.

There is also the {\ttfamily gopts} plugin. It is a global plugin and should be mounted via {\ttfamily kdb\+Ensure}. This plugin extracts {\ttfamily argv} and {\ttfamily envp} via OS specific A\+P\+Is and then calls {\ttfamily elektra\+Get\+Opts}. The advantage of using {\ttfamily gopts} is that it retrieves command-\/line options before any validation plugins are called. This means that values passed on the command-\/line can be validated.

To use {\ttfamily elektra\+Get\+Opts} you need to link against {\ttfamily elektra-\/opts}, {\ttfamily elektra-\/meta} and {\ttfamily elektra-\/ease}.

To define a command-\/line option either set the {\ttfamily opt} metakey to the short option you want to use, or set {\ttfamily opt/long} to the long option you want to use. For short options, only the first character of the given value will be used (\textquotesingle{}\textbackslash{}0\textquotesingle{} is ignored). Short and long options can be used simultaneously.

Additionally a key can also be associated with multiple short/long options. To achieve this treat {\ttfamily opt} as an array. For example for two options {\ttfamily -\/a} and {\ttfamily -\/b} you would set {\ttfamily opt=\#1}, {\ttfamily opt/\#0=a} and {\ttfamily opt/\#1=b}. If not explicitly stated otherwise, you can replace {\ttfamily opt} with any {\ttfamily opt/\#} array element in all meta-\/keys mentioned in this document. This of course includes long options (i.\+e. {\ttfamily opt/\#0/long}, etc.).

While you can specify multiple options (or environment variables, see below) for a single key, only one of them can be used at the same time. Using two or more options (or variables) that are all linked to the same key, will result in an error.

Per default an option is expected to have an argument. Arguments to short and long options are given in the same way as with {\ttfamily getopt\+\_\+long(3)} (i.\+e. {\ttfamily -\/oarg}, {\ttfamily -\/o arg}, {\ttfamily -\/-\/option arg} or {\ttfamily -\/-\/option=arg}).

To change whether an option expects an argument set {\ttfamily opt/arg} to either {\ttfamily \char`\"{}none\char`\"{}} or {\ttfamily \char`\"{}optional\char`\"{}} (the default is {\ttfamily \char`\"{}required\char`\"{}}).


\begin{DoxyItemize}
\item If you choose {\ttfamily \char`\"{}none\char`\"{}}, the corresponding key will be set to {\ttfamily \char`\"{}1\char`\"{}}, if the option is used. This value can be changed by setting {\ttfamily opt/flagvalue}.
\item An option that is set to {\ttfamily \char`\"{}optional\char`\"{}} is treated the same as with {\ttfamily \char`\"{}none\char`\"{}}, except that you can also set the value with the long option form {\ttfamily -\/-\/option=value}. This also means that {\ttfamily opt/flagvalue} is used, if no argument is given. Contrary to {\ttfamily getopt\+\_\+long(3)} options with optional arguments can still have short forms. They just cannot have an argument in this form.
\end{DoxyItemize}

Elektra also supports parsing environment variables in a similar manner. For these there are however, less configuration options. You can simply specify one or more environment variables for a key using the {\ttfamily env} metakey (or {\ttfamily env/\#} meta-\/array for multiple).

Both options and environment variables expose special behavior, if used in combination with arrays.

If an option is specified on a key with basename {\ttfamily \#}, the option can be used repeatedly. All occurrences will be collected into the array.

Environment variables obviously cannot be repeated, instead a behavior similar that used for P\+A\+TH is adopted. On Windows the variable will be split at each \textquotesingle{};\textquotesingle{} character. On all other systems \textquotesingle{}\+:\textquotesingle{} is used as a separator.

All unused elements of {\ttfamily argv} are be collected into an array. You can access this array by specifying {\ttfamily args=remaining} on a key with basename {\ttfamily \#}. The array will be copied into this key. As is the case with getopt(3) processing of options will stop, if {\ttfamily -\/-\/} is encountered in {\ttfamily argv}.

When the help option {\ttfamily -\/-\/help} is encountered in {\ttfamily argv}, {\ttfamily elektra\+Get\+Opts} only reads the specification, but does not create any keys in the {\ttfamily proc} namespace. It will however, generate a help message that can be accessed with {\ttfamily elektra\+Get\+Opts\+Help\+Message}.

The help message consists of a usage line and an options list. The program name for the usage line is taken from {\ttfamily argv\mbox{[}0\mbox{]}}. If the value contains a slash ({\ttfamily /}) it will be considered a path and only the part after the last slash will be used.

The options list will contain exactly one entry for each key that has at least one option. Each entry has to parts. First all the options for the key are listed and then (possibly on the next line, if there are a lot of options), the description for the key is listed. The description is taken from the {\ttfamily opt/help} or alternatively the {\ttfamily description} metakey.

{\bfseries{Note\+:}} {\ttfamily opt/help} is specified {\itshape only once per key}. That means even if the key uses {\ttfamily opt/\#0}, {\ttfamily opt/\#1}, etc. (unlike most other metadata) the description will always be taken from {\ttfamily opt/help} directly, because there can only be one description. In general we recommend using {\ttfamily description}, because it is used by other parts of Elektra as well. {\ttfamily opt/help} is intended to provide a less verbose description more suitable for the command-\/line.

The help message can be modified in a few different ways\+:


\begin{DoxyItemize}
\item The {\ttfamily usage} argument of {\ttfamily elektra\+Get\+Opts\+Help\+Message} can be used to replace the default usage line.
\item The {\ttfamily prefix} argument of {\ttfamily elektra\+Get\+Opts\+Help\+Message} can be used to insert text between the usage line and the options list.
\item An option can can be hidden from the help message by setting {\ttfamily opt/hidden} to {\ttfamily \char`\"{}1\char`\"{}}. This hides both the long and short form of the option. If you want to hide just one form, use an array of two options an hide just one index.
\item If the option has an {\ttfamily \char`\"{}optional\char`\"{}} or {\ttfamily \char`\"{}required\char`\"{}} argument, the string {\ttfamily A\+RG} will be used as a placeholder by default. You can change this, by setting {\ttfamily opt/arg/help} for the corresponding option.
\end{DoxyItemize}

The order of precedence is simple\+:


\begin{DoxyItemize}
\item If a short option for a key is found, it will always be used.
\item If none of the short options for a key are found, we look for long options.
\item Neither short nor long options are found, environment variables are considered.
\end{DoxyItemize}


\begin{DoxyItemize}
\item Both options and environment variables can only be specified on a single key. If you need to have the value of one option/environment variable in multiple keys, you may use {\ttfamily fallback}s.
\item {\ttfamily -\/} cannot be used as short options, because it would collide with, the \char`\"{}option end marker\char`\"{}.
\item {\ttfamily help} cannot be used as a long option, because it would collide with the help option.
\end{DoxyItemize}

The following specification describes the command line interface similar to the one used by {\ttfamily rm}. (It is based of {\ttfamily rm (G\+NU coreutils) 8.\+30}).


\begin{DoxyCode}{0}
\DoxyCodeLine{[force]}
\DoxyCodeLine{opt = f}
\DoxyCodeLine{opt/long = force}
\DoxyCodeLine{opt/arg = none}
\DoxyCodeLine{description = ignore nonexistent files and arguments, never prompt}
\DoxyCodeLine{}
\DoxyCodeLine{[interactive]}
\DoxyCodeLine{opt = \#1}
\DoxyCodeLine{opt/\#0 = i}
\DoxyCodeLine{opt/\#0/long = interactive}
\DoxyCodeLine{opt/\#0/arg = optional}
\DoxyCodeLine{opt/\#0/flagvalue = always}
\DoxyCodeLine{opt/\#1 = I}
\DoxyCodeLine{opt/\#1/flagvalue = once}
\DoxyCodeLine{opt/\#1/arg = none}
\DoxyCodeLine{opt/arg/name = WHEN}
\DoxyCodeLine{description = prompt according to WHEN: never, once (-I), or always (-i); without WHEN, prompt always}
\DoxyCodeLine{}
\DoxyCodeLine{[singlefs]}
\DoxyCodeLine{opt/long = one-file-system}
\DoxyCodeLine{opt/arg = none}
\DoxyCodeLine{description = when removing a hierarchy recursively, skip any directory that is on a file system different from that of the corresponding line argument}
\DoxyCodeLine{}
\DoxyCodeLine{[nopreserve]}
\DoxyCodeLine{opt/long = no-preserve-root}
\DoxyCodeLine{opt/arg = none}
\DoxyCodeLine{description = do not treat '/' specially}
\DoxyCodeLine{}
\DoxyCodeLine{[preserve]}
\DoxyCodeLine{opt/long = preserve-root}
\DoxyCodeLine{opt/arg = optional}
\DoxyCodeLine{opt/arg/name = all}
\DoxyCodeLine{opt/flagvalue = root}
\DoxyCodeLine{description = do not remove '/' (default); with 'all', reject any command line argument on a separate device from its parent}
\DoxyCodeLine{}
\DoxyCodeLine{[recursive]}
\DoxyCodeLine{opt = \#1}
\DoxyCodeLine{opt/\#0 = r}
\DoxyCodeLine{opt/\#0/long = recursive}
\DoxyCodeLine{opt/\#0/arg = none}
\DoxyCodeLine{opt/\#1 = R}
\DoxyCodeLine{opt/\#1/arg = none}
\DoxyCodeLine{description = remove directories and their contents recursively}
\DoxyCodeLine{}
\DoxyCodeLine{[emptydirs]}
\DoxyCodeLine{opt = d}
\DoxyCodeLine{opt/long = dir}
\DoxyCodeLine{opt/arg = none}
\DoxyCodeLine{description = remove empty directories}
\DoxyCodeLine{}
\DoxyCodeLine{[verbose]}
\DoxyCodeLine{opt = v}
\DoxyCodeLine{opt/long = verbose}
\DoxyCodeLine{opt/arg = none}
\DoxyCodeLine{env = VERBOSE}
\DoxyCodeLine{description = explain what is being done}
\DoxyCodeLine{}
\DoxyCodeLine{[showversion]}
\DoxyCodeLine{opt/long = version}
\DoxyCodeLine{opt/arg = none}
\DoxyCodeLine{description = output version information and exit}
\DoxyCodeLine{}
\DoxyCodeLine{[files/\#]}
\DoxyCodeLine{args = remaining}
\DoxyCodeLine{env = FILES}
\DoxyCodeLine{description = the files that shall be deleted}
\end{DoxyCode}


If this specification is used in a program called {\ttfamily erm} (for Elektra rm), which is called like this\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{FILES="one.txt:other.log" VERBOSE=1 erm -fi --recursive}
\end{DoxyCode}


The following keys will be created by {\ttfamily elektra\+Get\+Opts} (assuming the specification is mounted at {\ttfamily spec/sw/org/erm/\#0/current})\+:


\begin{DoxyItemize}
\item {\ttfamily proc/sw/org/erm/\#0/current/force = \char`\"{}1\char`\"{}}
\item {\ttfamily proc/sw/org/erm/\#0/current/interactive = \char`\"{}always\char`\"{}}
\item {\ttfamily proc/sw/org/erm/\#0/current/recursive = \char`\"{}1\char`\"{}}
\item {\ttfamily proc/sw/org/erm/\#0/current/verbose = \char`\"{}1\char`\"{}}
\item {\ttfamily proc/sw/org/erm/\#0/current/files \mbox{[}array\mbox{]} = \char`\"{}\#1\char`\"{}}
\item {\ttfamily proc/sw/org/erm/\#0/current/files/\#0 = \char`\"{}one.\+txt\char`\"{}}
\item {\ttfamily proc/sw/org/erm/\#0/current/files/\#1 = \char`\"{}other.\+log\char`\"{}}
\end{DoxyItemize}

Calling {\ttfamily F\+I\+L\+ES=\char`\"{}abcd.\+txt\char`\"{} erm 123.\+txt 456.\+txt} meanwhile will result in\+:


\begin{DoxyItemize}
\item {\ttfamily proc/sw/org/erm/\#0/current/files \mbox{[}array\mbox{]} = \char`\"{}\#1\char`\"{}}
\item {\ttfamily proc/sw/org/erm/\#0/current/files/\#0 = \char`\"{}123.\+txt\char`\"{}}
\item {\ttfamily proc/sw/org/erm/\#0/current/files/\#1 = \char`\"{}456.\+txt\char`\"{}}
\end{DoxyItemize}

N\+O\+TE\+: {\ttfamily proc/sw/org/erm/\#0/current/files \mbox{[}array\mbox{]} = \char`\"{}\#1\char`\"{}} means the {\ttfamily array} metadata of {\ttfamily proc/sw/org/erm/\#0/current/files} is {\ttfamily \#1}.

You can find a full working example \href{/home/mpranj/workspace/libelektra/examples/opts.c}{\texttt{ here}}. However, it uses a hard coded specification which is a bit harder to read. 