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.
 
 

373 lines
14 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 us = usage_lines(cli,fmt).str();
// std::cout << "\n======================================\n\n" << us << "\n";
// return;
if(us != expected) {
std::cout << "\nEXPECTED:\n" << expected << "\nOBSERVED:\n" << us << '\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(9)
.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_group("(", ")")
.surround_joinable("$($", "$)$")
.max_flags_per_param_in_doc(2)
.max_flags_per_param_in_usage(1)
.line_spacing(0)
.paragraph_spacing(3)
.alternatives_min_split_size(3)
.merge_alternative_flags_with_common_prefix(true)
.merge_joinable_with_common_prefix(true)
.split_alternatives(true);
test(__LINE__, fmt, group( option("-a") ), " [-a]");
test(__LINE__, fmt, group( option("-a", "--all") ), " [-a]");
test(__LINE__, fmt, group( option("-a").repeatable(true) ), " ,,,[-a]...");
test(__LINE__, fmt, group( required("-a") ), " -a");
test(__LINE__, fmt, group( required("-a", "--all") ), " -a");
test(__LINE__, fmt, group( required("-a").repeatable(true) ), " ,,,-a...");
test(__LINE__, fmt, group( command("-a") ), " -a");
test(__LINE__, fmt, group( command("-a", "--all") ), " -a");
test(__LINE__, fmt, group( command("-a").repeatable(true) ), " ,,,-a...");
test(__LINE__, fmt, (
value("geometry file"),
option("-translate") & value("x") & value("y") & value("z"),
option("-rotate") & value("azimuth") & value("polar")),
" <geometry file>#[-translate%<x>%<y>%<z>]#[-rotate%<azimuth>%<polar>]");
test(__LINE__, fmt, joinable( values("string")), " ,,,<string>...");
test(__LINE__, fmt, (
(option("-o", "--out") & value("output file")) % "output filename",
with_prefix("-f", option("align") >> []{} | option("noalign") >> []{} ) % "control alignment"),
" [-o%<output file>]#[-f§(§align|noalign§)§]");
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>]#[-r%<ratio>]#[-m%[<lines=5>]]");
test(__LINE__, fmt, (
"input files" % values("file"),
"compress results" % option("-c", "--compress"),
"lines to be ignored" % repeatable( option("-i", "--ignore") & integers("line") )),
" ,,,<file>...#[-c]#,,,[-i%,,,<line>...]...");
test(__LINE__, fmt, (
value("file").if_missing([]{}).if_repeated([](int){}),
required("-t") & values("target").if_missing([]{}).if_blocked([]{}),
option("--http") | option("--ftp").if_conflicted([]{}),
any_other()),
" <file>#-t%,,,<target>...#[--§(§http|ftp§)§]#,,,[<?>]...");
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]#-i%<input dir>#-o%<output dir>");
test(__LINE__, fmt, (
values("directory") % "input files",
option("-c", "--compress") % "compress results",
(option("-i", "--ignore") & values("line")) % "lines to be ignored"),
" ,,,<directory>...#[-c]#[-i%,,,<line>...]");
test(__LINE__, fmt, (
value("infile") % "input filename",
value("outfile") % "output filename",
option("-s", "--split") % "split files" ),
" <infile>%<outfile>%[-s]");
test(__LINE__, fmt, (
option("-a") % "activates a",
option("-b") % "activates b",
option("-c", "--noc") % "deactivates c",
option("--hi")([]{}) % "says hi"),
" [-a]%[-b]%[-c]%[--hi]");
test(__LINE__, fmt, (
command("make"),
value("file") % "name of file to make",
option("-f", "--force") % "overwrite existing file"),
" make%<file>%[-f]");
test(__LINE__, fmt, (
option("-a") % "activates a",
option("-b") % "activates b",
option("-c", "--noc") % "deactivates c",
option("--hi")([]{}) % "says hi"),
" [-a]%[-b]%[-c]%[--hi]");
test(__LINE__, fmt,
joinable(repeatable( option(",") , opt_number("number"))),
" ,,,([,]%[<number>])...");
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."),
" ship#new%,,,<name>...\n"
" ship#<name>#move#<x>#<y>#[--speed=%<kn>]\n"
" ship#shoot%<x>%<y>\n"
" mine#§(§set|remove§)§#<x>#<y>#[--§(§moored|drifting§)§]\n"
" -h\n"
" --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")
)),
" help\n"
" build#§(§new|add§)§#,,,<file>...#[-v]#[-b%[<size=10>]]#[--§(§init|no-init§)§]\n"
" query#<infile>#-o%<outfile>#[-f%<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"),
" <file>#[-rbs]#$($[:vim]%[:st3]%[:atom]%[:emacs]$)$");
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]#[y]#[a]%[b]#[-g]%[-h]#[-e]%[-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")
,
" make#<wordfile>#-dict%<dictionary>#[--progress]#[-v]\n"
" find#,,,<infile>...#-dict%<dictionary>#[-o%<outfile>]#[-§(§split|nosplit§)§]#[-v]\n"
" help#[-v]");
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")
)
)
),
" help\n"
" build#§(§new|add§)§#<file>\n"
" query#-i%<infile>#[-p]\n"
" info#space\n"
" info#statistics#§(§words|chars§)§\n"
" remove#a§(§ny|ll§)§#<regex>\n"
" modify#[-c]#[-u]#[-m%<size>]");
test(__LINE__, fmt, (
value("input file"),
option("-r", "--recursive"),
option("-o") & value("output format"),
option("-utf16")),
" <input file>#[-r]#[-o%<output format>]#[-utf16]");
test(__LINE__, fmt,
joinable( repeatable(option("a")([]{})|option("b")([]{})) ),
" ,,,[a|b]...");
test(__LINE__, fmt, (
"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"
)
),
" [-v]%[-i]#§(§copy|move§)§#[--all]#[--replace]#[-f]#,,,<files>...%[-r]%[-h]\n"
" [-v]%[-i]#compare#§(§date|content§)§#[-b]#[-q]#,,,<files>...%[-r]%[-h]\n"
" [-v]%[-i]#merge#§(§diff|patch§)§#-o%<outdir>#[--show-conflicts]#,,,<files>...%[-r]%[-h]\n"
" [-v]%[-i]#merge#content#[--git-style]#[-m%<marker>]#-o%<outdir>#[--show-conflicts]#,,,<files>...%[-r]%[-h]\n"
" [-v]%[-i]#list#,,,<files>...%[-r]%[-h]");
test(__LINE__, fmt, (
command("new"),
value("filename"),
(option("-e", "--encoding") & value("enc")).doc("'utf8' or 'cp1252'")
), " new#<filename>#[-e%<enc>]");
test(__LINE__, fmt, ( command("auto") | ( command("label"), value("character") )),
" §(§auto^(label%<character>)§)§");
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>...#-s%<expr>#[a§(§ny|ll§)§]");
test(__LINE__, fmt, ( value(""), option("-x"), option("-y") ),
" <?>%[-x]%[-y]");
}
catch(std::exception& e) {
std::cerr << e.what() << std::endl;
return 1;
}
}