From 720c5a33b6a49cf328fdd7611f49153cf8f60247 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 8 Apr 2020 14:51:57 +0300 Subject: Separate tests and examples into individual packages Also make cli module to be explicitly enabled via the config.cli configuration variable. --- cli-examples/.gitignore | 21 +++++++++++++ cli-examples/LICENSE | 1 + cli-examples/README | 15 ++++++++++ cli-examples/build/.gitignore | 3 ++ cli-examples/build/bootstrap.build | 9 ++++++ cli-examples/build/root.build | 27 +++++++++++++++++ cli-examples/buildfile | 4 +++ cli-examples/features/.gitignore | 1 + cli-examples/features/README | 20 +++++++++++++ cli-examples/features/buildfile | 8 +++++ cli-examples/features/driver.cxx | 61 ++++++++++++++++++++++++++++++++++++++ cli-examples/features/options.cli | 39 ++++++++++++++++++++++++ cli-examples/file/.gitignore | 1 + cli-examples/file/README | 38 ++++++++++++++++++++++++ cli-examples/file/buildfile | 11 +++++++ cli-examples/file/driver.cxx | 35 ++++++++++++++++++++++ cli-examples/file/options.cli | 7 +++++ cli-examples/file/test.ops | 7 +++++ cli-examples/hello/.gitignore | 1 + cli-examples/hello/README | 26 ++++++++++++++++ cli-examples/hello/buildfile | 9 ++++++ cli-examples/hello/driver.cxx | 58 ++++++++++++++++++++++++++++++++++++ cli-examples/hello/hello.cli | 18 +++++++++++ cli-examples/manifest | 15 ++++++++++ 24 files changed, 435 insertions(+) create mode 100644 cli-examples/.gitignore create mode 120000 cli-examples/LICENSE create mode 100644 cli-examples/README create mode 100644 cli-examples/build/.gitignore create mode 100644 cli-examples/build/bootstrap.build create mode 100644 cli-examples/build/root.build create mode 100644 cli-examples/buildfile create mode 100644 cli-examples/features/.gitignore create mode 100644 cli-examples/features/README create mode 100644 cli-examples/features/buildfile create mode 100644 cli-examples/features/driver.cxx create mode 100644 cli-examples/features/options.cli create mode 100644 cli-examples/file/.gitignore create mode 100644 cli-examples/file/README create mode 100644 cli-examples/file/buildfile create mode 100644 cli-examples/file/driver.cxx create mode 100644 cli-examples/file/options.cli create mode 100644 cli-examples/file/test.ops create mode 100644 cli-examples/hello/.gitignore create mode 100644 cli-examples/hello/README create mode 100644 cli-examples/hello/buildfile create mode 100644 cli-examples/hello/driver.cxx create mode 100644 cli-examples/hello/hello.cli create mode 100644 cli-examples/manifest (limited to 'cli-examples') diff --git a/cli-examples/.gitignore b/cli-examples/.gitignore new file mode 100644 index 0000000..e1d6ab8 --- /dev/null +++ b/cli-examples/.gitignore @@ -0,0 +1,21 @@ +# Compiler/linker output. +# +*.d +*.t +*.i +*.ii +*.o +*.obj +*.so +*.dll +*.a +*.lib +*.exp +*.pdb +*.ilk +*.exe +*.exe.dlls/ +*.exe.manifest +*.pc + +driver diff --git a/cli-examples/LICENSE b/cli-examples/LICENSE new file mode 120000 index 0000000..ea5b606 --- /dev/null +++ b/cli-examples/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/cli-examples/README b/cli-examples/README new file mode 100644 index 0000000..11589d2 --- /dev/null +++ b/cli-examples/README @@ -0,0 +1,15 @@ +This package contains a number of examples that show how to use the CLI +language and compiler to implement command line interface parsing in C++. +The following list gives an overview of each example. See the README files +in example directories for more information on each example. + +hello + A simple "Hello, world!" example that shows how to implement a very basic + command line interface using CLI. + +features + Shows how to use various features of the CLI language. + +file + Shows how to allow the users of your application to supply options in + files in addition to the command line. diff --git a/cli-examples/build/.gitignore b/cli-examples/build/.gitignore new file mode 100644 index 0000000..4a730a3 --- /dev/null +++ b/cli-examples/build/.gitignore @@ -0,0 +1,3 @@ +config.build +root/ +bootstrap/ diff --git a/cli-examples/build/bootstrap.build b/cli-examples/build/bootstrap.build new file mode 100644 index 0000000..c50c6ac --- /dev/null +++ b/cli-examples/build/bootstrap.build @@ -0,0 +1,9 @@ +# file : build/bootstrap.build +# license : MIT; see accompanying LICENSE file + +project = cli-examples + +using version +using config +using dist +using test diff --git a/cli-examples/build/root.build b/cli-examples/build/root.build new file mode 100644 index 0000000..53bde39 --- /dev/null +++ b/cli-examples/build/root.build @@ -0,0 +1,27 @@ +# file : build/root.build +# license : MIT; see accompanying LICENSE file + +cxx.std = latest + +using cxx + +hxx{*}: extension = hxx +ixx{*}: extension = ixx +txx{*}: extension = txx +cxx{*}: extension = cxx + +if ($cxx.target.system == 'win32-msvc') + cxx.poptions += -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS + +if ($cxx.class == 'msvc') + cxx.coptions += /wd4251 /wd4275 /wd4800 + +using cli + +# Every exe{} in this subproject is by default a test. +# +exe{*}: test = true + +# Specify the test target for cross-testing. +# +test.target = $cxx.target diff --git a/cli-examples/buildfile b/cli-examples/buildfile new file mode 100644 index 0000000..53d51dd --- /dev/null +++ b/cli-examples/buildfile @@ -0,0 +1,4 @@ +# file : buildfile +# license : MIT; see accompanying LICENSE file + +./: {*/ -build/} doc{LICENSE README} manifest diff --git a/cli-examples/features/.gitignore b/cli-examples/features/.gitignore new file mode 100644 index 0000000..c6e608b --- /dev/null +++ b/cli-examples/features/.gitignore @@ -0,0 +1 @@ +options.?xx diff --git a/cli-examples/features/README b/cli-examples/features/README new file mode 100644 index 0000000..9416320 --- /dev/null +++ b/cli-examples/features/README @@ -0,0 +1,20 @@ +This example shows how to use various features of the CLI language. + +The example consists of the following files: + +options.cli + Command line interface description in the CLI language. + +options.hxx +options.ixx +options.cxx + Command line interface implementation in C++. These files are generated + by the CLI compiler from hello.cli using the following command line: + + cli options.cli + +driver.cxx + Driver for the example. It first instantiates the option class which parses + the command line. The driver then examines and prints the option values. + +To run the example you can try various command lines suggested in options.cli. diff --git a/cli-examples/features/buildfile b/cli-examples/features/buildfile new file mode 100644 index 0000000..5051eae --- /dev/null +++ b/cli-examples/features/buildfile @@ -0,0 +1,8 @@ +# file : features/buildfile +# license : MIT; see accompanying LICENSE file + +exe{driver}: {hxx cxx}{* -options} cli.cxx{options} doc{README} + +cxx.poptions =+ "-I$out_base" + +cli.cxx{options}: cli{options} diff --git a/cli-examples/features/driver.cxx b/cli-examples/features/driver.cxx new file mode 100644 index 0000000..c14b5c7 --- /dev/null +++ b/cli-examples/features/driver.cxx @@ -0,0 +1,61 @@ +// file : features/driver.cxx +// author : Boris Kolpackov +// license : MIT; see accompanying LICENSE file + +#include +#include +#include + +#include "options.hxx" + +using namespace std; + +int +main (int argc, char* argv[]) +{ + try + { + features::options o (argc, argv); + + // --out-dir | -o + // + if (!o.out_dir ().empty ()) + cerr << "output dir: " << o.out_dir () << endl; + + // --first-name & --last-name + // + cerr << "first name: " << o.first_name () << endl + << "last name : " << o.last_name () << endl; + + // --vector | -v & --set | -s + // + if (!o.vector ().empty ()) + { + copy (o.vector ().begin (), o.vector ().end (), + ostream_iterator (cerr, " ")); + cerr << endl; + } + + if (!o.set ().empty ()) + { + copy (o.set ().begin (), o.set ().end (), + ostream_iterator (cerr, " ")); + cerr << endl; + } + + // --map | -m + // + typedef map str_map; + const str_map& m = o.map (); + str_map::const_iterator i (m.find ("a")); + + if (i != m.end ()) + cerr << "value for the 'a' key: " << i->second << endl; + + } + catch (const cli::exception& e) + { + cerr << e << endl; + return 1; + } +} diff --git a/cli-examples/features/options.cli b/cli-examples/features/options.cli new file mode 100644 index 0000000..ea055b3 --- /dev/null +++ b/cli-examples/features/options.cli @@ -0,0 +1,39 @@ +include ; +include ; +include ; +include ; + +// We can place the options classes into namespaces which mapped to C++ +// namespaces. +// +namespace features +{ + class options + { + // We can have several aliases for the same option. The first one is used + // to derive the accessor name. + // + std::string --out-dir | -o; + + // We can use both assignment and constructor notations to provide the + // default option value. + // + std::string --first-name = "John"; + std::string --last-name ("Mr John Doe", 8, 3); + + // We can use containers to to collect option value. If we have a command + // line like this: -v 1 -v 2 -v 1 -s 1 -s 2 -s 1 then the vector returned + // by the vector() accessor will contain three elements: 1, 2, and 1 while + // the set returned by the set() accessor will contain two elements: 1 and + // 2. + // + std::vector --vector | -v; + std::set --set | -s; + + // We can also use maps. In this case the option value is expected to have + // two parts: the key and the value, separated by '='. For example: -m a=A + // -m =B -m c= -m d (same as -m d=). + // + std::map --map | -m; + }; +} diff --git a/cli-examples/file/.gitignore b/cli-examples/file/.gitignore new file mode 100644 index 0000000..c6e608b --- /dev/null +++ b/cli-examples/file/.gitignore @@ -0,0 +1 @@ +options.?xx diff --git a/cli-examples/file/README b/cli-examples/file/README new file mode 100644 index 0000000..289fc64 --- /dev/null +++ b/cli-examples/file/README @@ -0,0 +1,38 @@ +This example shows how to allow the users of your application to supply +options in files in addition to the command line. + +The example consists of the following files: + +options.cli + Command line interface description in the CLI language. + +options.hxx +options.ixx +options.cxx + Command line interface implementation in C++. These files are generated + by the CLI compiler from options.cli using the following command line: + + cli --generate-file-scanner hello.cli + + We use the --generate-file-scanner CLI compiler option to include the + argv_file_scanner scanner implementation which provides support for + reading options from files in addition to the command line. + +driver.cxx + Driver for the example. It first creates the argv_file_scanner object + and indicates that the values for the --options-file option should be + recognized as files containing additional options. It then passes this + scanner object to the option class which parses the command line. The + driver then prints the option values. + +test.ops + Sample options file. + +To run this example you can try the following command line: + +$ ./driver --verbose 2 --val 1 --options-file test.ops --val 4 + +The output will be: + +verbosity: 5 +values: 1 2 3 4 diff --git a/cli-examples/file/buildfile b/cli-examples/file/buildfile new file mode 100644 index 0000000..89675d8 --- /dev/null +++ b/cli-examples/file/buildfile @@ -0,0 +1,11 @@ +# file : file/buildfile +# license : MIT; see accompanying LICENSE file + +exe{driver}: {hxx cxx}{* -options} cli.cxx{options} doc{README} +exe{driver}: test.arguments = --options-file +exe{driver}: file{test.ops}: test.input = true # Added after test.arguments. + +cxx.poptions =+ "-I$out_base" + +cli.cxx{options}: cli{options} +cli.options = --generate-file-scanner diff --git a/cli-examples/file/driver.cxx b/cli-examples/file/driver.cxx new file mode 100644 index 0000000..b53574c --- /dev/null +++ b/cli-examples/file/driver.cxx @@ -0,0 +1,35 @@ +// file : file/driver.cxx +// author : Boris Kolpackov +// license : MIT; see accompanying LICENSE file + +#include +#include +#include + +#include "options.hxx" + +using namespace std; + +int +main (int argc, char* argv[]) +{ + try + { + cli::argv_file_scanner s (argc, argv, "--options-file"); + options o (s); + + cout << "verbosity: " << o.verbose () << endl + << "values: "; + + copy (o.val ().begin (), + o.val ().end (), + ostream_iterator (cout, " ")); + + cerr << endl; + } + catch (const cli::exception& e) + { + cerr << e << endl; + return 1; + } +} diff --git a/cli-examples/file/options.cli b/cli-examples/file/options.cli new file mode 100644 index 0000000..3e6db5a --- /dev/null +++ b/cli-examples/file/options.cli @@ -0,0 +1,7 @@ +include ; + +class options +{ + int --verbose; + std::vector --val; +}; diff --git a/cli-examples/file/test.ops b/cli-examples/file/test.ops new file mode 100644 index 0000000..65fcf07 --- /dev/null +++ b/cli-examples/file/test.ops @@ -0,0 +1,7 @@ +# Sample options file. Empty lines and lines starting with '#' are +# ignored. +# +--verbose 5 + +--val 2 +--val=3 diff --git a/cli-examples/hello/.gitignore b/cli-examples/hello/.gitignore new file mode 100644 index 0000000..d73130a --- /dev/null +++ b/cli-examples/hello/.gitignore @@ -0,0 +1 @@ +hello.?xx diff --git a/cli-examples/hello/README b/cli-examples/hello/README new file mode 100644 index 0000000..dd14b01 --- /dev/null +++ b/cli-examples/hello/README @@ -0,0 +1,26 @@ +This is a "Hello, world!" example that shows how to implement a very basic +command line interface using CLI. + +The example consists of the following files: + +hello.cli + Command line interface description in the CLI language. + +hello.hxx +hello.ixx +hello.cxx + Command line interface implementation in C++. These files are generated + by the CLI compiler from hello.cli using the following command line: + + cli hello.cli + +driver.cxx + Driver for the example. It first instantiates the option class which parses + the command line. The driver then examines the options and prints the + greeting string for each name passed as an argument. + +To run the example you can try the following command lines: + +$ ./driver --help +$ ./driver John Jane +$ ./driver --greeting Hi --exclamations 3 John Jane diff --git a/cli-examples/hello/buildfile b/cli-examples/hello/buildfile new file mode 100644 index 0000000..8197d9e --- /dev/null +++ b/cli-examples/hello/buildfile @@ -0,0 +1,9 @@ +# file : hello/buildfile +# license : MIT; see accompanying LICENSE file + +exe{driver}: {hxx cxx}{* -hello} cli.cxx{hello} doc{README} +exe{driver}: test.arguments = --greeting Hi John Jane + +cxx.poptions =+ "-I$out_base" + +cli.cxx{hello}: cli{hello} diff --git a/cli-examples/hello/driver.cxx b/cli-examples/hello/driver.cxx new file mode 100644 index 0000000..bc37564 --- /dev/null +++ b/cli-examples/hello/driver.cxx @@ -0,0 +1,58 @@ +// file : hello/driver.cxx +// author : Boris Kolpackov +// license : MIT; see accompanying LICENSE file + +#include + +#include "hello.hxx" + +using namespace std; + +void +usage (ostream& os) +{ + os << "usage: driver [options] " << endl + << "options:" << endl; + options::print_usage (os); +} + +int +main (int argc, char* argv[]) +{ + try + { + int end; // End of options. + options o (argc, argv, end); + + if (o.help ()) + { + usage (cout); + return 0; + } + + if (end == argc) + { + cerr << "no names provided" << endl; + usage (cerr); + return 1; + } + + // Print the greetings. + // + for (int i = end; i < argc; i++) + { + cout << o.greeting () << ", " << argv[i]; + + for (unsigned int j = 0; j < o.exclamations (); j++) + cout << '!'; + + cout << endl; + } + } + catch (const cli::exception& e) + { + cerr << e << endl; + usage (cerr); + return 1; + } +} diff --git a/cli-examples/hello/hello.cli b/cli-examples/hello/hello.cli new file mode 100644 index 0000000..b75e1b8 --- /dev/null +++ b/cli-examples/hello/hello.cli @@ -0,0 +1,18 @@ +include ; + +class options +{ + bool --help {"Print usage information and exit."}; + + std::string --greeting = "Hello" + { + "", + "Use as a greeting phrase instead of the default \"Hello\"." + }; + + unsigned int --exclamations = 1 + { + "", + "Print exclamation marks instead of 1 by default." + }; +}; diff --git a/cli-examples/manifest b/cli-examples/manifest new file mode 100644 index 0000000..9ef14f3 --- /dev/null +++ b/cli-examples/manifest @@ -0,0 +1,15 @@ +: 1 +name: cli-examples +version: 1.2.0-b.6.z +project: cli +summary: Examples of using the CLI language and compiler for C++ +license: MIT +description-file: README +url: https://www.codesynthesis.com/projects/cli/ +doc-url: https://www.codesynthesis.com/projects/cli/doc/guide/ +src-url: https://git.codesynthesis.com/cgit/cli/cli/tree/cli-examples +email: cli-users@codesynthesis.com ; Mailing list +build-email: builds@codesynthesis.com +requires: c++14 +depends: * build2 >= 0.13.0- +depends: * bpkg >= 0.13.0- -- cgit v1.1