descriptionYet another command line options manager.
repository URLhttps://github.com/p-gen/ctxopt.git
ownerp.gen.progs@gmail.com
last changeSun, 19 Jun 2022 22:25:01 +0000 (20 00:25 +0200)
last refreshThu, 21 Nov 2024 07:35:19 +0000 (21 08:35 +0100)
content tags
add:
README.rst
**ctxopt**: yet another command line options manager.
#####################################################

|

For many uses, the traditional getopt function is enough to parse the
options in command lines.

However, cases exist where getopt shows its limits.
**ctxopt** is able to manage complex configurations of command line
options and excels when they appear in structured or independent blocs.

In **ctxopt**, each option has the possibility of starting a new context
in which the following command line options will be taken into account
and analyzed.
With this concept, it becomes easy, for example, to have repetitions
of identical options with each their independent sub-options.

Features:
---------

**ctxopt** has many features, its main ones are:

- Options are organized in a hierarchy of contexts.
- Options are easily declared using a syntax similar to BNF notation in
  each context.
- Any number of parameters can be assigned to each option.
- Parameters are not limited to just one character.
- The parameters associated with an option can be abbreviated as long as
  they do not conflict with another option in the same context.
- Parameters can be aggregated, even the long ones.
- Options evaluations trigger user-defined functions.
- Options can appear multiple times in one or more contexts.
- Options can be optional or mandatory.
- Option arguments can be optional or mandatory.
- Arguments can be multiple and their number controlled by simple rules.
- Arguments can have user-defined or built-in constraints.
- Options marked as mutually incompatibles are automatically detected.
- Command line options are normally evaluated in order but can be forced
  to be evaluated at the start of a context. They can also be asked to
  be reordered automatically to be evaluated before or after a set of
  other options in a context.
- Error functions can be customized.
- Automatic detection of missing|incompatible|unknown|... options or
  parameters.

Context notion illustrated by a tiny example:
---------------------------------------------

Imagine a situation where you want an option to be allowed only if
another option was previously given.

For example, you want the *group* option to be allowed only after
a *user* option.

With **ctxopt** its easy, you just have to define two contexts (at least one
is mandatory), tell the *user* option to switch to the second context
(named ``ctx1`` here) and define the *group* option in the second context.

+------------------+-----------------+--------------+-------------------+
| Defined contexts | Allowed options | Next context | Option parameters |
+==================+=================+==============+===================+
| ``main``         | user            | ``ctx1``     | ``-u`` ``-user``  |
+------------------+-----------------+--------------+-------------------+
| ``ctx1``         | group           |              | ``-g`` ``-group`` |
+------------------+-----------------+--------------+-------------------+

According to the situation summarized in this table, the following
command line (the context changes in brackets have been added only for
understanding and not part of the command line)

.. parsed-literal::
  prog[main] -u[ctx1] u1 -g g1 g2 -user[ctx1] u2 -group g3

will be understood as:

.. parsed-literal::
  Context main:  prog -u u1          -user u2
  Context ctx1:             -g g1 g2          -group g3

In this example, you can see that the previous context (``main`` here) is
automatically re-entered after the analysis of the *group* option because
the *user* option is unknown in the ``ctx1`` context.

See the file **example1.c** in the **examples** directory for details.

Usage:
------

To use **ctxopt**, the users must at least:

- include **ctxopt.h** and **ctxopt.c** in his code.
- define at least one context and describe its options.
- set at least one parameter's name for the options described in the contexts.
- write and attach an action callback function to each options.
- possibly register constraint and other things (optional).
- call ``ctxopt_init``.
- call ``ctxopt_analyze``.
- call ``ctxopt_evaluate``.

Optional steps include:

- register entering and/or exiting function for contexts.
- register arguments constraint checking functions.
- redefine non internal error functions.

For more, please read the provided man page.

Enough theory, here is a basic Hello World example:
---------------------------------------------------

.. code:: c
  :number-lines:

  #include "ctxopt.h"
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  /* Callback functions */
  /* ****************** */

  void name_action(char * ctx_name, char * opt_name, char * param,
                   int nb_values, char ** values, int nb_opt_data,
                   void ** opt_data, int nb_ctx_data, void** ctx_data)
  {
    int v;

    printf("Hello %s", values[0]); /* First command line argument after name *
                                    | (-n or -name).                         */

    for (v = 1; v < nb_values; v++) /* Other command line arguments.         */
      printf(", %s", values[v]);

    printf(".\n");
  }

  /* Program entry */
  /* ************* */

  int main(int argc, char * argv[])
  {
    int     nb_rem_args = 0;    /* Nb of remaining unprocessed arguments. */
    char ** rem_args    = NULL; /* Remaining arguments string array.      */

    ctxopt_init(argv[0], "stop_if_non_option=Yes allow_abbreviations=Yes");
    ctxopt_new_ctx("main", "[name... #<string>...]");
    ctxopt_add_opt_settings(parameters, "name", "-n -name");
    ctxopt_add_opt_settings(actions, "name", name_action, NULL);
    ctxopt_analyze(argc - 1, argv + 1, &nb_rem_args, &rem_args);

    if (nb_rem_args > 0)
    {
      printf("Non-arguments are not allowed.\n");
      exit(EXIT_FAILURE);
    }

    ctxopt_evaluate();

    if (argc == 1)
      printf("Hello world.\n");

    exit(EXIT_SUCCESS);
  }

Code explanations:
..................

Line 1:

  This ``#include`` gives access to the API necessary to use **ctxopt**.

Line 9:

  This function is the callback function call each time a parameter
  associated with the option **name** is seen in the command line.

Line 32:

  The init function is mandatory and must be called first.

Line 33:

  Here the first (and unique here) context called **main** here is
  created with the description of an option called **name**.

  The **name** option is defined as an optional possible multiple option
  taking mandatory possibly multiple arguments.
  It is the ``#`` which indicates the presence of an argument,
  ``<string>`` is just a decaration to clarify the meaning of this
  argument.

Line 34:

  It's now time to introduce the two parameters of the option **name**.
  These are the parameters looked for in the command line.

Line 35:

  Here the callback function defined line 9 is associated with the option
  **name**.

Line 36:

  Here the command line is parsed and errors like unknown parameter, not
  enough arguments... are detected. All errors detected during this phase
  are fatal.

Line 38:

  The remaining non-arguments, if any, are managed here.

Line 44:

  All the internal representation of the command line built during the
  analysis phase (line 36) is finally evaluated and the callback
  registered functions (here **name_action**) called.

Line 46:

  The special case where the command line only contains the program name
  is treated here.

Examples of running session:
............................

.. parsed-literal::

  **$ ./hello -n Alice Bob -name Carol**
  Hello Alice, Bob.
  Hello Carol.

  **$ ./hello -n**
  -n requires argument(s).

  Synopsis:
  hello \
    [-n|-name... #<string>...]

  Syntactic explanations:
  Only the parameters (prefixed by -) and the arguments, if any, must be entered.
  The following is just there to explain the other symbols displayed.

  #tag         : argument tag giving a clue to its meaning.
  [...]        : the object between square brackets is optional.
  ...          : the previous object can be repeated more than one time.

  **$ ./hello**
  Hello world.
shortlog
2022-06-19 pgenAdd comments in the list codemaster
2022-06-19 pgenOptimize and fix the list code
2022-06-19 pgenRemove unused code
2022-06-17 pgenFix a potiential sigsegv
2022-06-03 pgenAllow options not to be visible in help messages
2022-06-03 pgenUse a MPL-2.0 compatible with secondary Licenses
2022-05-17 pgenFix some comments and typos
2022-03-20 pgenMake ctxopt more robust.
2020-11-17 pgenImprove "unknown parameter" error message
2020-11-14 pgenImprove comments
2020-11-14 pgenAdd a "display usage on error" setting
2020-09-12 pgenAvoid using NULL as dummy argument
2020-09-11 pgenFix a potential use after free
2020-09-11 pgenUse ll_destroy when appropriate
2020-09-11 pgenFix a potential memory leak
2020-09-09 pgenMake ctxopt_free_memory(...) free more memory
...
heads
2 years ago master