| 1 | // SPDX-FileCopyrightText: 2023 Philippe Proulx <eeppeliteloop@gmail.com> |
| 2 | // SPDX-License-Identifier: CC-BY-SA-4.0 |
| 3 | |
| 4 | // Render with Asciidoctor |
| 5 | |
| 6 | = argpar |
| 7 | 15 March 2024 |
| 8 | :bt2: Babeltrace{nbsp}2 |
| 9 | ifdef::env-github[] |
| 10 | :toc: macro |
| 11 | endif::[] |
| 12 | ifndef::env-github[] |
| 13 | :toc: left |
| 14 | endif::[] |
| 15 | :idprefix: |
| 16 | :idseparator: - |
| 17 | |
| 18 | **argpar**, an https://efficios.com/[EfficiOS] project, is yet another |
| 19 | open-source command-line argument parser for C/{cpp} programs. |
| 20 | |
| 21 | ifdef::env-github[] |
| 22 | toc::[] |
| 23 | endif::[] |
| 24 | |
| 25 | == Features |
| 26 | |
| 27 | The most important features of argpar are: |
| 28 | |
| 29 | * A single MIT-licensed, independent C99 source file and its header that |
| 30 | you can copy as is into your own project. |
| 31 | |
| 32 | * Declarative description of expected options: |
| 33 | + |
| 34 | [source,c] |
| 35 | ---- |
| 36 | enum my_opt_id { |
| 37 | MY_OPT_ID_DATA, |
| 38 | MY_OPT_ID_SQUEEZE, |
| 39 | MY_OPT_ID_MEOW, |
| 40 | }; |
| 41 | |
| 42 | static const struct argpar_opt_descr descrs[] = { |
| 43 | { MY_OPT_ID_DATA, 'd', NULL, false }, |
| 44 | { MY_OPT_ID_SQUEEZE, '\0', "squeeze", true }, |
| 45 | { MY_OPT_ID_MEOW, 'm', "meow", true }, |
| 46 | ARGPAR_OPT_DESCR_SENTINEL, |
| 47 | }; |
| 48 | ---- |
| 49 | |
| 50 | * Supports short (`-k`) and long (`--kernel`) options. |
| 51 | + |
| 52 | Multiple short options may be concatenated, and the argument of the |
| 53 | last one may be "`attached`" (`-xvfmyfile`). |
| 54 | + |
| 55 | The argument of a long option may follow a space (`--meow{nbsp}mix`) or |
| 56 | an `=` sign (`--meow=mix`). |
| 57 | |
| 58 | * Supports repeated options: |
| 59 | + |
| 60 | ---- |
| 61 | --meow=mix salut -f4 /path/to/file --meow blend -cqc |
| 62 | ---- |
| 63 | |
| 64 | * Fully documented, `const`-correct C99 API based on an argument |
| 65 | iterator. |
| 66 | + |
| 67 | The `argpar_iter_next()` function produces items in the same order that |
| 68 | it parses original arguments, including non-option items. This means, |
| 69 | for example, that for: |
| 70 | + |
| 71 | ---- |
| 72 | --hello --count=23 /path/to/file -ab --type file -- magie |
| 73 | ---- |
| 74 | + |
| 75 | `argpar_iter_next()` produces the following items, in this order: |
| 76 | |
| 77 | ** Option item: `--hello`. |
| 78 | ** Option item: `--count` with argument `23`. |
| 79 | ** Non-option item: `/path/to/file`. |
| 80 | ** Option item: `-a`. |
| 81 | ** Option item: `-b`. |
| 82 | ** Option item: `--type` with argument `file`. |
| 83 | ** Non-option item: `--`. |
| 84 | ** Non-option item: `magie`. |
| 85 | |
| 86 | * On parsing error, provides a detailed error object including the index |
| 87 | of the argument (in `argv`) that caused the error as well as the name, |
| 88 | if available, of the unknown option. |
| 89 | |
| 90 | == Known limitations |
| 91 | |
| 92 | Compared to other similar open-source command-line argument parsers, |
| 93 | argpar has the following known limitations: |
| 94 | |
| 95 | * Doesn't support abbreviated long options. |
| 96 | + |
| 97 | For example, if your option descriptor describes `--fraction`, then |
| 98 | `argpar_iter_next()` won't parse `--frac=23`: it will return an unknown |
| 99 | option error instead. |
| 100 | |
| 101 | * Doesn't explicitly support "`end of option`" (`--`). |
| 102 | + |
| 103 | This is valid: |
| 104 | + |
| 105 | ---- |
| 106 | --hello=world --meow -- mix --hut=23 |
| 107 | ---- |
| 108 | + |
| 109 | `argpar_iter_next()` provides the `--` argument as a non-option item. |
| 110 | |
| 111 | * Doesn't support a non-option argument having the form of an option, |
| 112 | for example if you need to pass the exact relative path `--calorie`. |
| 113 | + |
| 114 | In that case, you would need to pass `./--calorie`. There's no generic |
| 115 | way to escape `-` as of this version. This is in part because argpar |
| 116 | doesn't support "`end of option`" (`--`). |
| 117 | + |
| 118 | As a workaround, because argpar offers an iterator API, you may: |
| 119 | + |
| 120 | . Stop using `argpar_iter_next()` from the first `--` non-option item |
| 121 | __**ITEM**__. |
| 122 | . Use `argpar_item_non_opt_orig_index()` with __**ITEM**__ to get the |
| 123 | original index __**I**__ of the first `--` within `argv` (as passed |
| 124 | to `argpar_iter_create()`). |
| 125 | . Read the remaining non-option arguments from `argv`, starting at |
| 126 | __**I**__{nbsp}+{nbsp}1. |
| 127 | |
| 128 | * Doesn't handle the `-h`/`--help` option in a special way (doesn't show |
| 129 | some automatic usage message). |
| 130 | |
| 131 | * Doesn't provide direct access to the value of an option. |
| 132 | + |
| 133 | This is because argpar offers an iterator API to support positional and |
| 134 | repeated options. |
| 135 | |
| 136 | == Build argpar |
| 137 | |
| 138 | To use argpar in your own project, simply copy the `argpar/argpar.c` and |
| 139 | `argpar/argpar.h` files and you're ready to go. |
| 140 | |
| 141 | To build this project, make sure you have |
| 142 | https://docs.gtk.org/glib/[GLib]{nbsp}2 (required by the tests), and |
| 143 | then: |
| 144 | |
| 145 | . **If you build from a Git clone**, run: |
| 146 | + |
| 147 | [role="term"] |
| 148 | ---- |
| 149 | $ ./bootstrap |
| 150 | ---- |
| 151 | + |
| 152 | This generates the `configure` script and other important files. |
| 153 | |
| 154 | . Configure the project: |
| 155 | + |
| 156 | [role="term"] |
| 157 | ---- |
| 158 | $ ./configure |
| 159 | ---- |
| 160 | + |
| 161 | See `./configure --help` for more options. |
| 162 | |
| 163 | . Build the project: |
| 164 | + |
| 165 | [role="term"] |
| 166 | ---- |
| 167 | $ make |
| 168 | ---- |
| 169 | |
| 170 | == Build the API documentation |
| 171 | |
| 172 | To build the API documentation, make sure you have |
| 173 | https://www.doxygen.nl/[Doxygen], and then: |
| 174 | |
| 175 | * From the root of the project, run: |
| 176 | + |
| 177 | ---- |
| 178 | $ doxygen |
| 179 | ---- |
| 180 | |
| 181 | Open `api-doc/html/index.html` with Netscape Navigator. |
| 182 | |
| 183 | == Run the tests |
| 184 | |
| 185 | To run the argpar tests: |
| 186 | |
| 187 | . <<build-argpar,Build the project>>. |
| 188 | |
| 189 | . Run the tests: |
| 190 | + |
| 191 | [role="term"] |
| 192 | ---- |
| 193 | $ make check |
| 194 | ---- |
| 195 | |
| 196 | == Community |
| 197 | |
| 198 | argpar uses https://review.lttng.org/admin/repos/argpar,general[Gerrit] |
| 199 | for code review. |
| 200 | |
| 201 | To report a bug, https://github.com/efficios/argpar/issues/new[create a |
| 202 | GitHub issue]. |