1 /*****************************************************************************
2  *
3  * CLIPP - command line interfaces for modern C++
4  *
5  * released under MIT license
6  *
7  * (c) 2017-2018 André Müller; foss@andremueller-online.de
8  *
9  *****************************************************************************/
10 
11 #include "testing.h"
12 
13 
14 //-------------------------------------------------------------------
test(int lineNo,bool expected,const clipp::group & cli)15 void test(int lineNo, bool expected, const clipp::group& cli)
16 {
17     if(cli.flags_are_prefix_free() != expected) {
18 
19         std::cout << "prefix '" << cli.common_flag_prefix() << "'" << std::endl;
20 
21         throw std::runtime_error{"failed test " + std::string(__FILE__) +
22             " in line " + std::to_string(lineNo)};
23     }
24 }
25 
26 
27 //-------------------------------------------------------------------
28 clipp::group
make_cli_1()29 make_cli_1()
30 {
31     using namespace clipp;
32 
33     auto copyMode = "copy mode:" % (
34         command("copy") | command("move"),
35         option("--all")         % "copy all",
36         option("--replace")     % "replace existing files",
37         option("-f", "--force") % "don't ask for confirmation"
38     );
39 
40     auto compareMode = "compare mode:" % (
41         command("compare"),
42         (command("date") | command("content")),
43         option("-b", "--binary") % "compare files byte by byte",
44         option("-q", "--quick")  % "use heuristics for faster comparison"
45     );
46 
47     auto mergeAlgo = (
48         command("diff")  % "merge using diff"  |
49         command("patch") % "merge using patch" |
50         (   command("inside") % "merge based on content",
51             "content based merge options:" % (
52               option("--git-style") % "emulate git's merge behavior",
53               option("-m", "--marker") & value("marker") % "merge marker symbol"
54             )
55         )
56     );
57 
58     auto mergeMode = "merge mode:" % (
59         command("merge"),
60         mergeAlgo,
61         required("-o") & value("outdir") % "target directory for merge result",
62         option("--show-conflicts")       % "show merge conflicts during run"
63     );
64 
65     auto firstOpt = "user interface options:" % (
66         option("-v", "--verbose")     % "show detailed output",
67         option("-i", "--interactive") % "use interactive mode"
68     );
69     auto lastOpt = "mode-independent options:" % (
70         values("files")             % "input files",
71         option("-r", "--recursive") % "descend into subdirectories",
72         option("-h", "--help")      % "show help"
73     );
74 
75     return (
76         firstOpt,
77         copyMode | compareMode | mergeMode | command("list"),
78         lastOpt);
79 }
80 
81 //-------------------------------------------------------------------
main()82 int main()
83 {
84     using namespace clipp;
85 
86     try {
87         test( __LINE__ , true, group{} );
88 
89         test( __LINE__ , true, ( option("-a"), option("-b") ));
90 
91         test( __LINE__ , true, ( option(""), option("-b") ));
92         test( __LINE__ , true, ( option("-a"), option("") ));
93 
94         test( __LINE__ , true, ( option("-a"), option("-b"), option("--a") ));
95         test( __LINE__ , true, ( option(""), option("-b"), option("--a") ));
96         test( __LINE__ , true, ( option("-a"), option(""), option("--a") ));
97         test( __LINE__ , true, ( option("-a"), option("-b"), option("") ));
98 
99         test( __LINE__ , true, (
100             option("-a"), option("--a"), option("-b"), option("--b")
101         ));
102 
103         test( __LINE__ , true, (
104             option("-a"), option("--a-a"), option("-b"), option("--b-b")
105         ));
106 
107         test( __LINE__ , true, (
108             (option("-a"), option("--a-a")) % "a",
109             (option("-b"), option("--b-b")) % "b"
110         ));
111 
112         test( __LINE__ , true, ( value("-a"), option("-a"), option("-b") ));
113         test( __LINE__ , true, ( option("-a"), value("-a"), option("-b") ));
114         test( __LINE__ , true, ( option("-a"), option("-b"), value("-b") ));
115 
116         test( __LINE__ , true, ( option("-a"), option("-b"), value("") ));
117 
118         test( __LINE__ , true, (
119             option("-a"), option("--a"), option("-b"), value("-b"), option("--b")
120         ));
121 
122         test( __LINE__ , true, (
123             option("-a"), option("--a-a"), option("-b"), option("--b-b")
124         ));
125 
126         test( __LINE__ , true, (
127             (option("-a"), option("--a-a")) % "a",
128             (option("-b"), option("--b-b")) % "b"
129         ));
130 
131         //same flags are not an error - TODO is this OK?
132         test( __LINE__ , true, (
133             (option("-a"), option("-a")) % "a",
134             (option("-b"), option("-b")) % "b"
135         ));
136 
137         test( __LINE__ , true, (
138             (option("-a") & value("-a"), option("--a-a")) % "a",
139             (option("-b"), option("--b-b") & values("-a")) % "b"
140         ));
141 
142 
143         test( __LINE__ , false, ( option("-a"), option("-ab") ));
144 
145         test( __LINE__ , false, ( option("-ab"), option("-a") ));
146 
147         test( __LINE__ , false, (
148             option("-a"), option("-aa"), option("-b"), option("--b-b")
149         ));
150 
151         test( __LINE__ , false, (
152             (option("-a"), option("--a")) % "a",
153             (option("-b"), option("-abba")) % "b"
154         ));
155 
156         test( __LINE__ , false, (
157             (option("-a") & value("a"), option("--a")) % "a",
158             (option("-b"), option("-abba") & values("-b")) % "b"
159         ));
160 
161         test( __LINE__, true, make_cli_1() );
162 
163     }
164     catch(std::exception& e) {
165         std::cerr << e.what() << std::endl;
166         return 1;
167     }
168 }
169