Skip to content

Commit b47e77e

Browse files
committed
Major comments, more use of Cli::ArgMatch.
1 parent 8747cfe commit b47e77e

3 files changed

Lines changed: 213 additions & 159 deletions

File tree

docs/guide.adoc

Lines changed: 110 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -884,43 +884,117 @@ Level 2 selected.
884884
----
885885

886886

887-
=== How Parsing Works
887+
=== Multiple Files
888+
Options don't have to be defined all in one source file. Separate source
889+
files can each define options of interest to that file and get them populated
890+
when the command line is processed.
891+
892+
When you instantiate Dim::Cli you're creating a handle to the globally shared
893+
configuration. So multiple translation units can each create one and use it to
894+
update the shared configuration.
895+
896+
The following example has a logMsg function in log.cpp with its own "-1"
897+
option while main.cpp registers "--version":
898+
899+
[source, C++]
900+
----
901+
// main.cpp
902+
int main(int argc, char * argv[]) {
903+
Dim::Cli cli;
904+
cli.versionOpt("1.0");
905+
if (!cli.parse(argc, argv))
906+
return cli.printError(cerr);
907+
// do stuff that might call logMsg()...
908+
return EX_OK;
909+
}
910+
----
911+
912+
[source, C++, test file log]
913+
----
914+
// log.cpp
915+
static Dim::Cli cli;
916+
static auto & failEarly = cli.opt<bool>("1").desc("Exit on first error");
917+
918+
void logMsg(string & msg) {
919+
cerr << msg << endl;
920+
if (*failEarly)
921+
exit(EX_SOFTWARE);
922+
}
923+
----
924+
925+
[source, shell session]
926+
----
927+
$ a.out --help
928+
Usage: a.out [OPTIONS]
929+
930+
Options:
931+
-1 Exit on first error
932+
933+
--help Show this message and exit.
934+
--version Show version and exit.
935+
----
936+
937+
Multiple files and commands go well togather, see the Subcommands section for
938+
<<#in-seperate-file, additional examples>>.
939+
940+
941+
=== Parsing
888942
The parsing process goes through the 3 phases shown below and allows registered
889943
application code (actions) to be invoked at various points in the process.
890944

891-
Parsing phase 1 (extract values from args):
945+
[discrete]
946+
===== Phase 1: Values from Args
892947

893-
--> Expand --> Expand -----> Before --> Map Args to -->
894-
Environment Response .-> Actions Opt Values
948+
--> Expand --> Expand ---> Before --> Map Args -->
949+
Environment Response .-> Actions to Values
895950
Variables Files | |
896-
'--<---'
897-
898-
Parsing phase 2 (parse values into opts):
899-
900-
.----> Transform --> Parse --+----> Check --+-->
901-
| .-> Actions Action ^ .-> Actions |
902-
| | | | | | |
903-
--+--+ '--<---' | '--<---' |
904-
^ | | |
905-
| '----> Implicit Value --------' |
906-
| (When optional value not present) |
907-
| |
908-
'-------------------------<----------------------'
951+
'---<--'
952+
953+
A single argument can map to multiple values but it may also take multiple
954+
arguments to get one value:
955+
956+
[%autowidth]
957+
|===
958+
| 1 arg -> 3 values | -xvfone | extract=true, verbose=true, file=one
959+
| 2 args -> 1 value | -f one | file=one
960+
|===
961+
962+
963+
[discrete]
964+
===== Phase 2: Values into Opts
965+
966+
Each value is transformed, parsed into, and then checked by the actions
967+
registered to its target opt.
968+
969+
.----> Transform --> Parse --+----> Check --+-->
970+
| .-> Actions Action ^ .-> Actions |
971+
| | | | | | |
972+
--+--+ '---<--' | '---<--' |
973+
^ | | |
974+
| '----> Implicit Value --------' |
975+
| (When optional value not present) |
976+
| |
977+
'-------------------------<-----------------------'
909978
For each value found
910979

911-
Parsing phase 3 (after actions):
980+
981+
[discrete]
982+
===== Phase 3: After Actions
983+
984+
All the after actions of each eligible opt are run. Opts are eligible if they
985+
are top level or assigned to the command that was selected.
912986

913987
--+----> After --+-->
914988
^ .-> Actions |
915989
| | | |
916-
| '------' |
990+
| '---<--' |
917991
| |
918992
'-------<-------'
919993
For each opt defined
920994

921995

922-
=== Environment Variable
923-
You can specify an environment variable that will have its contents
996+
==== Environment Variables
997+
You can specify one or more environment variables that will have their contents
924998
prepended to the command line. This happens before response file expansion
925999
and any before actions.
9261000

@@ -981,7 +1055,7 @@ Words: 'a' 'b' 'c' 'd'
9811055
----
9821056

9831057

984-
=== Response Files
1058+
==== Response Files
9851059
A response file is a collection of frequently used or generated arguments
9861060
saved as text, often with a ".rsp" extension, that is substituted into the
9871061
command line when referenced.
@@ -1138,6 +1212,8 @@ option name that the value was matched with on the command line and its
11381212
position in argv[]. For bool arguments the val string will always be
11391213
either "0" or "1".
11401214

1215+
allow
1216+
deny
11411217

11421218
==== Parse Actions
11431219
Sometimes, you want an argument to completely change the execution flow. For
@@ -1147,7 +1223,7 @@ a non-crazy --version use <<#version-option, opt.versionOpt()>>).
11471223

11481224
Parsing actions are bound to options and get invoked when a value becomes
11491225
available for it. Any std::function compatible object that accepts references
1150-
to cli, opt, and string as parameters can be used. The function should:
1226+
to cli, opt, and const string as parameters can be used. The function should:
11511227

11521228
* Parse the source string and use the result to update the option value (or
11531229
value vector).
@@ -1319,61 +1395,21 @@ Range is from 2 to 5
13191395
----
13201396

13211397

1322-
=== Multiple Files
1323-
Options don't have to be defined all in one source file. Separate source
1324-
files can each define options of interest to that file and get them populated
1325-
when the command line is processed.
1398+
=== Execution
1399+
The cli.exec() method executes the action of the matched command. Used for
1400+
subcommands, also an option when splitting the configuration, parsing, and/or
1401+
execution code across multiple files (or libraries).
13261402

1327-
When you instantiate Dim::Cli you're creating a handle to the globally shared
1328-
configuration. So multiple translation units can each create one and use it to
1329-
update the shared configuration.
1403+
Registered application code (actions) is invoked at various points in the
1404+
process.
13301405

1331-
The following example has a logMsg function in log.cpp with its own "-1"
1332-
option while main.cpp registers "--version":
1333-
1334-
[source, C++]
1335-
----
1336-
// main.cpp
1337-
int main(int argc, char * argv[]) {
1338-
Dim::Cli cli;
1339-
cli.versionOpt("1.0");
1340-
if (!cli.parse(argc, argv))
1341-
return cli.printError(cerr);
1342-
// do stuff that might call logMsg()...
1343-
return EX_OK;
1344-
}
1345-
----
1346-
1347-
[source, C++, test file log]
1348-
----
1349-
// log.cpp
1350-
static Dim::Cli cli;
1351-
static auto & failEarly = cli.opt<bool>("1").desc("Exit on first error");
1352-
1353-
void logMsg(string & msg) {
1354-
cerr << msg << endl;
1355-
if (*failEarly)
1356-
exit(EX_SOFTWARE);
1357-
}
1358-
----
1359-
1360-
[source, shell session]
1361-
----
1362-
$ a.out --help
1363-
Usage: a.out [OPTIONS]
1364-
1365-
Options:
1366-
-1 Exit on first error
1367-
1368-
--help Show this message and exit.
1369-
--version Show version and exit.
1370-
----
1371-
1372-
Multiple files and commands go well togather, see the Subcommands section for
1373-
<<#in-seperate-file, additional examples>>.
1406+
---> Before Exec --> Command ---> After Exec -->
1407+
.-> Actions Action .-> Actions
1408+
| | | |
1409+
'---<--' '---<--'
13741410

13751411

1376-
=== Subcommands
1412+
==== Subcommands
13771413
Git style subcommands are created by either cli.command("cmd"), which changes
13781414
the cli objects context to the command, or with opt.command("cmd"), which
13791415
changes the command that option is for. Once the cli object context has been

libs/dimcli/cli.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ bool Cli::OptIndex::includeOptAfter(
863863
Cli::OptBase & opt,
864864
const string & cmd
865865
) {
866-
// Should opt activate its after actions if cmd is selected?
866+
// Include opt's after actions if top level or its cmd is selected.
867867
return opt.command().empty()
868868
|| opt.command() == cmd
869869
|| opt.allCmds();
@@ -2777,7 +2777,12 @@ bool Cli::parseValue(
27772777
const string & srcName,
27782778
const char ptr[]
27792779
) {
2780-
if (!opt.match(name, pos, srcType, srcName)) {
2780+
ArgMatch match;
2781+
match.name = name;
2782+
match.pos = (int) pos;
2783+
match.src.type = srcType;
2784+
match.src.name = srcName;
2785+
if (!opt.match(match)) {
27812786
string prefix = "Too many '" + name + "' values";
27822787
string detail = "The maximum number of values is "
27832788
+ intToString(opt, opt.maxSize()) + ".";

0 commit comments

Comments
 (0)