You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
519 lines
20 KiB
519 lines
20 KiB
/*****************************************************************************
|
|
*
|
|
* CLIPP - command line interfaces for modern C++
|
|
*
|
|
* released under MIT license
|
|
*
|
|
* (c) 2017-2018 André Müller; foss@andremueller-online.de
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "testing.h"
|
|
|
|
using namespace clipp;
|
|
|
|
//-------------------------------------------------------------------
|
|
void test(int lineNo, const doc_formatting& fmt,
|
|
const group& cli, const std::string& expected)
|
|
{
|
|
auto doc = documentation(cli,fmt).str();
|
|
|
|
// std::cout << "\n====================================\n\n" << doc << "\n";
|
|
// return;
|
|
|
|
if(doc != expected) {
|
|
std::cout << "\nEXPECTED:\n" << expected << "\nOBSERVED:\n" << doc << '\n';
|
|
|
|
throw std::runtime_error{"failed " + std::string( __FILE__ ) +
|
|
" in line " + std::to_string(lineNo)};
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
int main()
|
|
{
|
|
try {
|
|
|
|
auto fmt = doc_formatting{}
|
|
.first_column(3)
|
|
.doc_column(45)
|
|
.last_column(80)
|
|
.empty_label("?")
|
|
.param_separator("%")
|
|
.group_separator("#")
|
|
.alternative_param_separator("|")
|
|
.alternative_group_separator("^")
|
|
.flag_separator("~")
|
|
.surround_labels("<", ">")
|
|
.surround_optional("[", "]")
|
|
.surround_repeat(",,,", "...")
|
|
.surround_alternatives("§(§", "§)§")
|
|
.surround_alternative_flags("^(^", "^)^")
|
|
.surround_group("(", ")")
|
|
.surround_joinable("$($", "$)$")
|
|
.max_flags_per_param_in_doc(2)
|
|
.max_flags_per_param_in_usage(1)
|
|
.line_spacing(1)
|
|
.paragraph_spacing(3)
|
|
.alternatives_min_split_size(3)
|
|
.merge_alternative_flags_with_common_prefix(false)
|
|
.merge_joinable_with_common_prefix(true)
|
|
.split_alternatives(true);
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
(option("-o", "--out") & value("output file")) % "output filename",
|
|
with_prefix("-f", option("align") >> []{} | option("noalign") >> []{} ) % "control alignment"
|
|
),
|
|
" ^(^-o~--out^)^%<output file> output filename\n"
|
|
"\n"
|
|
" -falign|-fnoalign control alignment");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
(option("-n", "--count") & value("count")) % "number of iterations",
|
|
(option("-r", "--ratio") & value("ratio")) % "compression ratio",
|
|
(option("-m") & opt_value("lines=5")) % "merge lines (default: 5)"
|
|
),
|
|
" ^(^-n~--count^)^%<count> number of iterations\n"
|
|
"\n"
|
|
" ^(^-r~--ratio^)^%<ratio> compression ratio\n"
|
|
"\n"
|
|
" -m%<lines=5> merge lines (default: 5)");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
"input files" % values("file"),
|
|
"compress results" % option("-c", "--compress"),
|
|
"lines to be ignored" % repeatable( option("-i", "--ignore") & integers("line") )
|
|
),
|
|
" ,,,<file>... input files\n"
|
|
"\n"
|
|
" -c~--compress compress results\n"
|
|
"\n"
|
|
" ^(^-i~--ignore^)^%<line> lines to be ignored");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
option("-r", "--recursive") % "recurse into subdirectories",
|
|
(required("-i", "--in" ) & value("input dir")) % "sets path to input directory",
|
|
(required("-o", "--out") & value("output dir")) % "sets path to output directory"
|
|
),
|
|
" -r~--recursive recurse into subdirectories\n"
|
|
"\n"
|
|
" ^(^-i~--in^)^%<input dir> sets path to input directory\n"
|
|
"\n"
|
|
" ^(^-o~--out^)^%<output dir> sets path to output directory");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
value("infile") % "input filename",
|
|
value("outfile") % "output filename",
|
|
option("-s", "--split") % "split files"
|
|
),
|
|
" <infile> input filename\n"
|
|
"\n"
|
|
" <outfile> output filename\n"
|
|
"\n"
|
|
" -s~--split split files");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
option("-a") % "activates a",
|
|
option("-b") % "activates b",
|
|
option("-c", "--noc") % "deactivates c",
|
|
option("--hi")([]{}) % "says hi"
|
|
),
|
|
" -a activates a\n"
|
|
"\n"
|
|
" -b activates b\n"
|
|
"\n"
|
|
" -c~--noc deactivates c\n"
|
|
"\n"
|
|
" --hi says hi");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
command("make"),
|
|
value("file") % "name of file to make",
|
|
option("-f", "--force") % "overwrite existing file"
|
|
),
|
|
" <file> name of file to make\n"
|
|
"\n"
|
|
" -f~--force overwrite existing file");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
option("-a") % "activates a",
|
|
option("-b") % "activates b",
|
|
option("-c", "--noc") % "deactivates c",
|
|
option("--hi")([]{}) % "says hi"
|
|
),
|
|
" -a activates a\n"
|
|
"\n"
|
|
" -b activates b\n"
|
|
"\n"
|
|
" -c~--noc deactivates c\n"
|
|
"\n"
|
|
" --hi says hi");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
( command("ship"), ( ( command("new"), values("name") ) |
|
|
( value("name"),
|
|
command("move"), value("x"), value("y"), (option("--speed=") & value("kn")) % "Speed in knots [default: 10]") |
|
|
( command("shoot"), value("x"), value("y") ) ) )
|
|
| ( command("mine"),
|
|
( command("set" )
|
|
| command("remove") ),
|
|
value("x"), value("y"),
|
|
( option("--moored" ) % "Moored (anchored) mine."
|
|
| option("--drifting") % "Drifting mine.")
|
|
)
|
|
| command("-h", "--help") % "Show this screen."
|
|
| command("--version")([]{}) % "Show version."
|
|
),
|
|
" --speed=%<kn> Speed in knots [default: 10]\n"
|
|
"\n"
|
|
" --moored Moored (anchored) mine.\n"
|
|
"\n"
|
|
" --drifting Drifting mine.\n"
|
|
"\n"
|
|
" -h~--help Show this screen.\n"
|
|
"\n"
|
|
" --version Show version.");
|
|
|
|
|
|
test(__LINE__, fmt, ( command("help")
|
|
| ( command("build"),
|
|
( command("new") | command("add") ),
|
|
values("file"),
|
|
option("-v", "--verbose") % "print detailed report",
|
|
option("-b", "--buffer") & opt_value(
|
|
"size=10") % "sets buffer size in KiByte",
|
|
( option("--init") | option("--no-init") ) % "do or don't initialize"
|
|
)
|
|
| ( command("query"), value("infile"),
|
|
required("-o", "--out") & value("outfile"),
|
|
option("-f", "--out-format") % "determine output format"
|
|
& value("format")
|
|
)
|
|
),
|
|
" -v~--verbose print detailed report\n"
|
|
"\n"
|
|
" <size=10> sets buffer size in KiByte\n"
|
|
"\n"
|
|
" --init|--no-init do or don't initialize\n"
|
|
"\n"
|
|
" -f~--out-format determine output format");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
value("file"),
|
|
joinable(
|
|
option("-r") % "open read-only",
|
|
option("-b") % "use backup file",
|
|
option("-s") % "use swap file"
|
|
),
|
|
joinable(
|
|
option(":vim") >> []{}, option(":st3") >> []{},
|
|
option(":atom") >> []{}, option(":emacs") >> []{}
|
|
) % "editor(s) to use; multiple possible"
|
|
),
|
|
" -r open read-only\n"
|
|
"\n"
|
|
" -b use backup file\n"
|
|
"\n"
|
|
" -s use swap file\n"
|
|
"\n"
|
|
" :vim%:st3%:atom%:emacs editor(s) to use; multiple possible");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
(option("x") % "sets X", option("y") % "sets Y"),
|
|
(option("a") % "activates A", option("b") % "activates B") % "documented group 1:" ,
|
|
"documented group 2:" % (option("-g") % "activates G", option("-h") % "activates H"),
|
|
"activates E or F" % (option("-e"), option("-f"))
|
|
),
|
|
" x sets X\n"
|
|
"\n"
|
|
" y sets Y\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" documented group 1:\n\n"
|
|
" a activates A\n"
|
|
"\n"
|
|
" b activates B\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" documented group 2:\n\n"
|
|
" -g activates G\n"
|
|
"\n"
|
|
" -h activates H\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" -e%-f activates E or F");
|
|
|
|
|
|
test(__LINE__, fmt, ( ( command("make"), value("wordfile"), required("-dict") & value("dictionary"), option("--progress", "-p")) | (
|
|
command("find"), values("infile"), required("-dict") & value("dictionary"),
|
|
(option("-o", "--output") & value("outfile")) % "write to file instead of stdout",
|
|
( option("-split" ) | option("-nosplit"))) | command("help"),
|
|
option("-v", "--version").call([]{}) % "show version"
|
|
),
|
|
" ^(^-o~--output^)^%<outfile> write to file instead of stdout\n"
|
|
"\n"
|
|
" -v~--version show version");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
command("help") |
|
|
( command("build"),
|
|
"build commands" %
|
|
( command("new") % "make new database"
|
|
| command("add") % "append to existing database"
|
|
),
|
|
value("file")
|
|
) |
|
|
( command("query"),
|
|
"query settings" %
|
|
( required("-i", "--input") & value("infile") % "input file",
|
|
option("-p", "--pretty-print") % "human friendly output")
|
|
) |
|
|
( command("info"),
|
|
"database info modes" % (
|
|
command("space") % "detailed memory occupation analysis" |
|
|
(
|
|
command("statistics"),
|
|
"statistics analysis" % (
|
|
command("words") % "word frequency table" |
|
|
command("chars") % "character frequency table"
|
|
)
|
|
)
|
|
)
|
|
) |
|
|
"remove mode" % (
|
|
command("remove"),
|
|
"modify" % ( command("any") | command("all") ),
|
|
value("regex") % "regular expression filter"
|
|
) |
|
|
( command("modify"),
|
|
"modification opererations" % (
|
|
option("-c", "--compress") % "compress database in-memory",
|
|
option("-u", "--unique") % "keep only unique entries",
|
|
option("-m", "--memlimit") % "max. size in RAM" & value("size")
|
|
)
|
|
)
|
|
),
|
|
" build commands\n\n"
|
|
" new make new database\n"
|
|
"\n"
|
|
" add append to existing database\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" query settings\n\n"
|
|
" <infile> input file\n"
|
|
"\n"
|
|
" -p~--pretty-print human friendly output\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" database info modes\n\n"
|
|
" space detailed memory occupation analysis\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" statistics analysis\n\n"
|
|
" words word frequency table\n"
|
|
"\n"
|
|
" chars character frequency table\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" remove mode\n\n"
|
|
" any|all modify\n"
|
|
"\n"
|
|
" <regex> regular expression filter\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" modification opererations\n\n"
|
|
" -c~--compress compress database in-memory\n"
|
|
"\n"
|
|
" -u~--unique keep only unique entries\n"
|
|
"\n"
|
|
" -m~--memlimit max. size in RAM");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
command("new"),
|
|
value("filename"),
|
|
(option("-e", "--encoding") & value("enc")).doc("'utf8' or 'cp1252'")
|
|
),
|
|
" ^(^-e~--encoding^)^%<enc> 'utf8' or 'cp1252'");
|
|
|
|
|
|
test(__LINE__, fmt, (
|
|
values("file") % "input filenames",
|
|
(required("-s") & value("expr")) % "string to look for",
|
|
option("any") % "report as soon as any matches" |
|
|
option("all") % "report only if all match"
|
|
),
|
|
" ,,,<file>... input filenames\n"
|
|
"\n"
|
|
" -s%<expr> string to look for\n"
|
|
"\n"
|
|
" any report as soon as any matches\n"
|
|
"\n"
|
|
" all report only if all match");
|
|
|
|
|
|
auto complexcli = (
|
|
"user interface options:" % (
|
|
option("-v", "--verbose") % "show detailed output",
|
|
option("-i", "--interactive") % "use interactive mode"
|
|
),
|
|
"copy mode:" % (
|
|
command("copy") | command("move"),
|
|
option("--all") % "copy all",
|
|
option("--replace") % "replace existing files",
|
|
option("-f", "--force") % "don't ask for confirmation"
|
|
) |
|
|
"compare mode:" % (
|
|
command("compare"),
|
|
(command("date") | command("content")),
|
|
option("-b", "--binary") % "compare files byte by byte",
|
|
option("-q", "--quick") % "use heuristics for faster comparison"
|
|
) |
|
|
"merge mode:" % (
|
|
command("merge"),
|
|
(
|
|
command("diff") % "merge using diff" |
|
|
command("patch") % "merge using patch" |
|
|
( command("content") % "merge based on content",
|
|
"content based merge options:" % (
|
|
option("--git-style") % "emulate git's merge behavior",
|
|
option("-m", "--marker") & value("marker") % "merge marker symbol"
|
|
)
|
|
)
|
|
),
|
|
required("-o") & value("outdir") % "target directory for merge result",
|
|
option("--show-conflicts") % "show merge conflicts during run"
|
|
) |
|
|
command("list"),
|
|
"mode-independent options:" % (
|
|
values("files") % "input files",
|
|
option("-r", "--recursive") % "descend into subdirectories",
|
|
option("-h", "--help") % "show help"
|
|
)
|
|
);
|
|
|
|
|
|
test(__LINE__, fmt, complexcli,
|
|
" user interface options:\n\n"
|
|
" -v~--verbose show detailed output\n"
|
|
"\n"
|
|
" -i~--interactive use interactive mode\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" copy mode:\n\n"
|
|
" --all copy all\n"
|
|
"\n"
|
|
" --replace replace existing files\n"
|
|
"\n"
|
|
" -f~--force don't ask for confirmation\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" compare mode:\n\n"
|
|
" -b~--binary compare files byte by byte\n"
|
|
"\n"
|
|
" -q~--quick use heuristics for faster\n"
|
|
" comparison\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" merge mode:\n\n"
|
|
" diff merge using diff\n"
|
|
"\n"
|
|
" patch merge using patch\n"
|
|
"\n"
|
|
" content merge based on content\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" content based merge options:\n\n"
|
|
" --git-style emulate git's merge behavior\n"
|
|
"\n"
|
|
" <marker> merge marker symbol\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" <outdir> target directory for merge result\n"
|
|
"\n"
|
|
" --show-conflicts show merge conflicts during run\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
" mode-independent options:\n\n"
|
|
" ,,,<files>... input files\n"
|
|
"\n"
|
|
" -r~--recursive descend into subdirectories\n"
|
|
"\n"
|
|
" -h~--help show help");
|
|
|
|
|
|
fmt.first_column(7) .doc_column(20) .last_column(50);
|
|
|
|
test(__LINE__, fmt, complexcli,
|
|
" user interface options:\n\n"
|
|
" -v~--verbose\n"
|
|
" show detailed output\n\n\n\n"
|
|
" -i~--interactive\n"
|
|
" use interactive mode\n\n\n\n"
|
|
" copy mode:\n\n"
|
|
" --all copy all\n\n"
|
|
" --replace\n"
|
|
" replace existing files\n\n\n\n"
|
|
" -f~--force\n"
|
|
" don't ask for confirmation\n\n\n\n"
|
|
" compare mode:\n\n"
|
|
" -b~--binary\n"
|
|
" compare files byte by byte\n\n\n\n"
|
|
" -q~--quick\n"
|
|
" use heuristics for faster\n"
|
|
" comparison\n\n\n\n"
|
|
" merge mode:\n\n"
|
|
" diff merge using diff\n\n"
|
|
" patch merge using patch\n\n"
|
|
" content merge based on content\n\n\n\n"
|
|
" content based merge options:\n\n"
|
|
" --git-style\n"
|
|
" emulate git's merge behavior\n\n\n\n"
|
|
" <marker>\n"
|
|
" merge marker symbol\n\n\n\n"
|
|
" <outdir> target directory for merge\n"
|
|
" result\n\n\n\n"
|
|
" --show-conflicts\n"
|
|
" show merge conflicts during\n"
|
|
" run\n\n\n\n"
|
|
" mode-independent options:\n\n"
|
|
" ,,,<files>...\n"
|
|
" input files\n\n\n\n"
|
|
" -r~--recursive\n"
|
|
" descend into subdirectories\n\n\n\n"
|
|
" -h~--help\n"
|
|
" show help");
|
|
|
|
}
|
|
catch(std::exception& e) {
|
|
std::cerr << e.what() << std::endl;
|
|
return 1;
|
|
}
|
|
}
|