From 6be9c7746f92aa721782a4d0eaff5f901fc528cd Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 13 Mar 2018 10:34:57 +0200 Subject: Setup command line infrastructure for new command --- bdep/bdep.cli | 9 +++- bdep/bdep.cxx | 13 +++--- bdep/buildfile | 8 +++- bdep/common.cli | 1 + bdep/init.cli | 2 +- bdep/new-parsers.cxx | 114 ++++++++++++++++++++++++++++++++++++++++++++++ bdep/new-parsers.hxx | 38 ++++++++++++++++ bdep/new-types.hxx | 70 +++++++++++++++++++++++++++++ bdep/new.cli | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ bdep/new.cxx | 25 +++++++++++ bdep/new.hxx | 19 ++++++++ bdep/project.cli | 21 +++++---- doc/cli.sh | 2 +- 13 files changed, 427 insertions(+), 20 deletions(-) create mode 100644 bdep/new-parsers.cxx create mode 100644 bdep/new-parsers.hxx create mode 100644 bdep/new-types.hxx create mode 100644 bdep/new.cli create mode 100644 bdep/new.cxx create mode 100644 bdep/new.hxx diff --git a/bdep/bdep.cli b/bdep/bdep.cli index 172eb48..12992d9 100644 --- a/bdep/bdep.cli +++ b/bdep/bdep.cli @@ -59,9 +59,9 @@ namespace bdep "" } - bool config + bool new { - "\l{bdep-config(1)} \- manage project's build configurations" + "\l{bdep-new(1)} \- create and initialize new project" } bool init @@ -73,6 +73,11 @@ namespace bdep { "\l{bdep-sync(1)} \- synchronize project and configurations" } + + bool config + { + "\l{bdep-config(1)} \- manage project's build configurations" + } }; // Make sure these don't conflict with command names above. diff --git a/bdep/bdep.cxx b/bdep/bdep.cxx index 39f08ad..ef4a6ec 100644 --- a/bdep/bdep.cxx +++ b/bdep/bdep.cxx @@ -22,9 +22,10 @@ // #include -#include +#include #include #include +#include using namespace std; using namespace bdep; @@ -34,11 +35,11 @@ using namespace bdep; // Once this is done, use the "final" values of the common options to do // global initializations (verbosity level, etc). // -// If O is-a project_options, then also handle the @ arguments and -// place them into project_options::config_name. +// If O is-a configuration_name_options, then also handle the @ +// arguments and place them into configuration_name_options::config_name. // static inline bool -cfg_name (project_options* o, const char* a) +cfg_name (configuration_name_options* o, const char* a) { string n (a); @@ -264,10 +265,10 @@ try break; \ } - //COMMAND_IMPL (new_, new, "new"); - COMMAND_IMPL (config, config, "config"); + COMMAND_IMPL (new_, new, "new"); COMMAND_IMPL (init, init, "init"); COMMAND_IMPL (sync, sync, "sync"); + COMMAND_IMPL (config, config, "config"); assert (false); fail << "unhandled command"; diff --git a/bdep/buildfile b/bdep/buildfile index 5afe7c2..7559ed0 100644 --- a/bdep/buildfile +++ b/bdep/buildfile @@ -21,7 +21,8 @@ project-options \ help-options \ config-options \ init-options \ -sync-options +sync-options \ +new-options exe{bdep}: {hxx ixx txx cxx}{** -{$options_topics} -*-odb -version} \ {hxx ixx cxx}{$options_topics} \ @@ -55,6 +56,7 @@ if $cli.configured cli.cxx{config-options}: cli{config} cli.cxx{init-options}: cli{init} cli.cxx{sync-options}: cli{sync} + cli.cxx{new-options}: cli{new} # Option length must be the same to get commands/topics/options aligned. # @@ -67,9 +69,11 @@ if $cli.configured cli.cxx{common-options}: cli.options += --short-usage --long-usage # Both. cli.cxx{bdep-options}: cli.options += --short-usage - cli.options += --long-usage # All other pages -- long usage. + cli.cxx{new-options}: cli.options += \ +--cxx-prologue "#include " + # Include the generated cli files into the distribution and don't remove # them when cleaning in src (so that clean results in a state identical to # distributed). diff --git a/bdep/common.cli b/bdep/common.cli index 80c01db..21b504d 100644 --- a/bdep/common.cli +++ b/bdep/common.cli @@ -3,6 +3,7 @@ // license : MIT; see accompanying LICENSE file include ; +include ; "\section=1" "\name=bdep-common-options" diff --git a/bdep/init.cli b/bdep/init.cli index 77c84a4..e4b7e2d 100644 --- a/bdep/init.cli +++ b/bdep/init.cli @@ -23,7 +23,7 @@ namespace bdep \c{\b{bdep init} [] [] [] []\n \b{bdep init} [] [] \b{--empty|-E}\n \b{bdep init} [] [] \b{--config-add|-A} [\b{@}]\n - \b{bdep init} [] [] \b{--config-create|-C} [\b{@}] \\\n + \b{bdep init} [] [] \b{--config-create|-C} [\b{@}]\n \ \ \ \ \ \ \ \ \ \ []} \c{ = \b{--directory}|\b{-d} \n diff --git a/bdep/new-parsers.cxx b/bdep/new-parsers.cxx new file mode 100644 index 0000000..d5b8e6e --- /dev/null +++ b/bdep/new-parsers.cxx @@ -0,0 +1,114 @@ +// file : bdep/new-parsers.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include // bdep::cli namespace, cmd_new_*_options + +namespace bdep +{ + namespace cli + { + using type = cmd_new_type; + using lang = cmd_new_lang; + + // Parse comma-separated list of of options starting from the first comma + // at pos. + // + template + static O + parse_options (const char* o, const string v, size_t pos) + { + // Use vector_scanner to parse the comma-separated list as options. + // + vector os; + for (size_t i (pos), j; i != string::npos; ) + { + j = i + 1; + i = v.find (',', j); + os.push_back (string (v, j, i != string::npos ? i - j : i)); + } + + vector_scanner s (os); + + try + { + O r; + r.parse (s, + unknown_mode::fail /* unknown_option */, + unknown_mode::fail /* unknown_argument */); + return r; + } + catch (const unknown_option& e) + { + throw invalid_value (o, e.option ()); + } + catch (const unknown_argument& e) + { + throw invalid_value (o, e.argument ()); + } + } + + void parser:: + parse (type& r, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (!s.more ()) + throw missing_value (o); + + string v (s.next ()); + size_t i (v.find (',')); + string l (v, 0, i); + + if (l == "exe") + { + r.type = type::exe; + r.exe_opt = parse_options (o, v, i); + } + else if (l == "lib") + { + r.type = type::lib; + r.lib_opt = parse_options (o, v, i); + } + else if (l == "bare") + { + r.type = type::bare; + r.bare_opt = parse_options (o, v, i); + } + else + throw invalid_value (o, l); + + xs = true; + } + + void parser:: + parse (lang& r, bool& xs, scanner& s) + { + const char* o (s.next ()); + + if (!s.more ()) + throw missing_value (o); + + string v (s.next ()); + size_t i (v.find (',')); + string l (v, 0, i); + + if (l == "c") + { + r.lang = lang::c; + r.c_opt = parse_options (o, v, i); + } + else if (l == "c++") + { + r.lang = lang::cxx; + r.cxx_opt = parse_options (o, v, i); + } + else + throw invalid_value (o, l); + + xs = true; + } + } +} diff --git a/bdep/new-parsers.hxx b/bdep/new-parsers.hxx new file mode 100644 index 0000000..c496314 --- /dev/null +++ b/bdep/new-parsers.hxx @@ -0,0 +1,38 @@ +// file : bdep/new-parsers.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +// CLI parsers, included into the generated source files. +// + +#ifndef BDEP_NEW_PARSERS_HXX +#define BDEP_NEW_PARSERS_HXX + +#include + +namespace bdep +{ + namespace cli + { + class scanner; + + template + struct parser; + + template <> + struct parser + { + static void + parse (cmd_new_type&, bool&, scanner&); + }; + + template <> + struct parser + { + static void + parse (cmd_new_lang&, bool&, scanner&); + }; + } +} + +#endif // BDEP_NEW_PARSERS_HXX diff --git a/bdep/new-types.hxx b/bdep/new-types.hxx new file mode 100644 index 0000000..2612f62 --- /dev/null +++ b/bdep/new-types.hxx @@ -0,0 +1,70 @@ +// file : bdep/new-types.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BDEP_NEW_TYPES_HXX +#define BDEP_NEW_TYPES_HXX + +namespace bdep +{ + // We could have defined cmd_new_*_options in a separate .cli file, include + // that here, and so on. Or we can abuse templates and keep everything + // together. + + // --type + // + class cmd_new_exe_options; + class cmd_new_lib_options; + class cmd_new_bare_options; + + template + struct cmd_new_type_template + { + enum type_type {exe, lib, bare} type; + + operator type_type () const {return type;} + + union + { + EXE exe_opt; + LIB lib_opt; + BARE bare_opt; + }; + + // Default is bare with no options. + // + cmd_new_type_template (): type (bare) {bare_opt = BARE ();} + }; + + using cmd_new_type = cmd_new_type_template<>; + + // --lang + // + class cmd_new_c_options; + class cmd_new_cxx_options; + + template + struct cmd_new_lang_template + { + enum lang_type {c, cxx} lang; + + operator lang_type () const {return lang;} + + union + { + C c_opt; + CXX cxx_opt; + }; + + // Default is C++ with no options. + // + cmd_new_lang_template (): lang (cxx) {cxx_opt = CXX ();} + }; + + using cmd_new_lang = cmd_new_lang_template<>; +} + +#endif // BDEP_NEW_TYPES_HXX diff --git a/bdep/new.cli b/bdep/new.cli new file mode 100644 index 0000000..ddf61c0 --- /dev/null +++ b/bdep/new.cli @@ -0,0 +1,125 @@ +// file : bdep/new.cli +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +include ; +include ; + +"\section=1" +"\name=bdep-new" +"\summary=create and initialize new project" + +namespace bdep +{ + { + " + + + + ", + + "\h|SYNOPSIS| + + \c{\b{bdep new} [] [\b{--no-init}] \n + \b{bdep new} [] \b{--config-add|-A} [\b{@}] \n + \b{bdep new} [] \b{--config-create|-C} [\b{@}] \n + \ \ \ \ \ \ \ \ \ []} + + \c{ = [] []\n + = \b{--type}|\b{-t} (\b{exe}|\b{lib}|\b{bare})[\b{,}...]\n + = \b{--lang}|\b{-l} (\b{c}|\b{c++})[\b{,}...]\n + = ( | )...} + + \h|DESCRIPTION| + + The \cb{new} command... + + The first variant, unless the \cb{--no-init} is specified, initializes + an empty configuration set, as if by performing \cb{init --empty}. + + Recognized \cb{c++} language options: + + \dl| + + \li|\cb{cxx} + + Use the \cb{.cxx}, \cb{.hxx}, \cb{.ixx}, \cb{.txx}, and \cb{.mxx} + source file extensions (default).| + + \li|\cb{cpp} + + Use the \cb{.cpp}, \cb{.hpp}, \cb{.ipp}, \cb{.tpp}, and \cb{.mpp} + source file extensions.|| + " + } + + //--type options + // + class cmd_new_exe_options + { + }; + + class cmd_new_lib_options + { + }; + + class cmd_new_bare_options + { + }; + + // --lang options + // + class cmd_new_c_options + { + }; + + class cmd_new_cxx_options + { + bool cpp; + bool cxx; + }; + + class cmd_new_options: configuration_name_options + { + "\h|NEW OPTIONS|" + + bool --no-init + { + "Don't initialize an empty build configuration set." + } + + dir_path --config-add|-A + { + "", + "Add an existing build configuration ." + } + + dir_path --config-create|-C + { + "", + "Create a new build configuration in ." + } + + cmd_new_type --type|-t + { + "[,...]", + "Specify project type and options. Valid values for are \cb{exe} + (executable project) \cb{lib} (library project), and \cb{bare} (bare + project without any source code, default). Valid values for are + type-specific." + } + + cmd_new_lang --lang|-l + { + "[,...]", + "Specify language type and options. Valid values for are \cb{c}, + and \cb{c++} (default). Valid values for are language-specific." + } + + bool --no-git + { + "Don't initialize a \cb{git(1)} repository inside the project nor + generate any \cb{.gitignore} files." + } + }; +} diff --git a/bdep/new.cxx b/bdep/new.cxx new file mode 100644 index 0000000..f2975c8 --- /dev/null +++ b/bdep/new.cxx @@ -0,0 +1,25 @@ +// file : bdep/new.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include + +using namespace std; + +namespace bdep +{ + using type = cmd_new_type; + using lang = cmd_new_lang; + + int + cmd_new (const cmd_new_options& o, cli::scanner& args) + { + tracer trace ("new"); + + //@@ TODO: validate options (cpp/cxx, -A/-C, etc). + + return 0; + } +} diff --git a/bdep/new.hxx b/bdep/new.hxx new file mode 100644 index 0000000..a9afbe8 --- /dev/null +++ b/bdep/new.hxx @@ -0,0 +1,19 @@ +// file : bdep/new.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BDEP_NEW_HXX +#define BDEP_NEW_HXX + +#include +#include + +#include + +namespace bdep +{ + int + cmd_new (const cmd_new_options&, cli::scanner& args); +} + +#endif // BDEP_NEW_HXX diff --git a/bdep/project.cli b/bdep/project.cli index cbf33a3..7680d99 100644 --- a/bdep/project.cli +++ b/bdep/project.cli @@ -8,10 +8,22 @@ include ; namespace bdep { + // Common options for commands that accept @. + // + class configuration_name_options: common_options + { + // Storage for configuration names specified as @. + // + // Note that we leave it undocumented so that it's not mentioned in + // documentation. + // + strings --config-name; + }; + // Common options for commands that operate on project/packages (prj-spec // and pkg-spec) and configurations (cfg-spec). // - class project_options: common_options + class project_options: configuration_name_options { bool --all|-a { @@ -30,13 +42,6 @@ namespace bdep "Specify the build configuration to use as an id." }; - // Storage for configuration names specified as @. - // - // Note that we leave it undocumented so that it's not mentioned in - // documentation. - // - strings --config-name; - dir_paths --directory|-d { "", diff --git a/doc/cli.sh b/doc/cli.sh index 08b6ff6..bac954e 100755 --- a/doc/cli.sh +++ b/doc/cli.sh @@ -56,7 +56,7 @@ o="--suppress-undocumented --output-prefix bdep- --class-doc bdep::common_option compile "common" $o --output-suffix "-options" --class-doc bdep::common_options=long compile "bdep" $o --output-prefix "" --class-doc bdep::commands=short --class-doc bdep::topics=short -pages="config help init sync" +pages="config help init sync new" for p in $pages; do compile $p $o -- cgit v1.1