aboutsummaryrefslogtreecommitdiff
path: root/libbutl
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-09-10 19:05:23 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-09-11 19:09:24 +0300
commit377cec303eea81fb18b294eb47a54587643dbd01 (patch)
tree8437bff2e99415b49f22bbd325aa47c768716d7f /libbutl
parent2b14f09675c10d999779858ae31934b7eef55b89 (diff)
Add support for arguments in default options files helpers
Diffstat (limited to 'libbutl')
-rw-r--r--libbutl/default-options.ixx11
-rw-r--r--libbutl/default-options.mxx50
-rw-r--r--libbutl/default-options.txx51
3 files changed, 90 insertions, 22 deletions
diff --git a/libbutl/default-options.ixx b/libbutl/default-options.ixx
index 7e4c378..4a551ac 100644
--- a/libbutl/default-options.ixx
+++ b/libbutl/default-options.ixx
@@ -12,4 +12,15 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
cmd_ops,
[] (const default_options_entry<O>&, const O&) {});
}
+
+ template <typename O, typename AS>
+ inline AS
+ merge_default_arguments (const default_options<O>& def_ops,
+ const AS& cmd_args)
+ {
+ return merge_default_arguments (
+ def_ops,
+ cmd_args,
+ [] (const default_options_entry<O>&, const AS&) {});
+ }
}
diff --git a/libbutl/default-options.mxx b/libbutl/default-options.mxx
index e9f92d3..aeb246d 100644
--- a/libbutl/default-options.mxx
+++ b/libbutl/default-options.mxx
@@ -6,6 +6,7 @@
#endif
#ifndef __cpp_lib_modules_ts
+#include <string>
#include <vector>
#include <utility> // move(), forward(), make_pair()
@@ -50,17 +51,21 @@ LIBBUTL_MODEXPORT namespace butl
template <typename O>
struct default_options_entry
{
- path file;
- O options;
- bool remote;
+ path file;
+ O options;
+ small_vector<std::string, 1> arguments;
+ bool remote;
};
template <typename O>
using default_options = small_vector<default_options_entry<O>, 4>;
- // Search for and load (using scanner S and parsing in the U::fail mode for
- // both options and arguments) the specified list of options files in the
- // specified directories returning a vector of option class instances (O).
+ // Search for and load the specified list of options files in the specified
+ // directories returning a vector of option class instances (O). If args is
+ // false, only options are allowed and are parsed using scanner S in the
+ // U::fail mode. If args is true, then both options and arguments are
+ // allowed in any order with options parsed in the U::stop mode.
+ //
// Pass each default options file path to the specified function prior to
// load (can be used for tracing, etc). The function signature is:
//
@@ -106,33 +111,44 @@ LIBBUTL_MODEXPORT namespace butl
const optional<dir_path>& home_dir,
const optional<dir_path>& extra_dir,
const default_options_files&,
- F&&);
+ F&&,
+ bool args = false);
- // Merge the default options and the command line options.
+ // Merge the default options/arguments and the command line
+ // options/arguments.
//
- // Note that this is the default implementation and in some cases you may
+ // Note that these are the default implementations and in some cases you may
// want to provide an options class-specific version that verifies/sanitizes
- // the default options (e.g., you may not want to allow certain options to
- // be specified in the default options files) or warns/prompts about
- // potentially dangerous options if they came from the remote options files.
+ // the default options/arguments (e.g., you may not want to allow certain
+ // options to be specified in the default options files) or warns/prompts
+ // about potentially dangerous options if they came from the remote options
+ // files.
//
template <typename O>
O
merge_default_options (const default_options<O>&, const O& cmd_ops);
- // As above but pass each default option to the specified function prior to
- // merging. The function signature is:
+ template <typename O, typename AS>
+ AS
+ merge_default_arguments (const default_options<O>&, const AS& cmd_args);
+
+ // As above but pass each default option/argument entry to the specified
+ // function prior to merging. The function signature is:
//
// void (const default_options_entry<O>&, const O& cmd_ops)
//
- // This version can be used to verify the default options. For example, you
- // may want to disallow certain options from being specified in the default
- // options files.
+ // This version can be used to verify the default options/arguments. For
+ // example, you may want to disallow certain options/arguments from being
+ // specified in the default options files.
//
template <typename O, typename F>
O
merge_default_options (const default_options<O>&, const O&, F&&);
+ template <typename O, typename AS, typename F>
+ AS
+ merge_default_arguments (const default_options<O>&, const AS&, F&&);
+
// Find a common start (parent) directory stopping at home or root
// (excluding).
//
diff --git a/libbutl/default-options.txx b/libbutl/default-options.txx
index 730d588..5245bd6 100644
--- a/libbutl/default-options.txx
+++ b/libbutl/default-options.txx
@@ -31,6 +31,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
template <typename O, typename S, typename U, typename F>
bool
load_default_options_files (const dir_path& d,
+ bool args,
bool remote,
const small_vector<path, 2>& fs,
F&& fn,
@@ -42,7 +43,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
bool r (true);
- auto load = [&fs, &fn, &def_ops, &r] (const dir_path& d, bool remote)
+ auto load = [args, &fs, &fn, &def_ops, &r] (const dir_path& d, bool rem)
{
using namespace std;
@@ -54,7 +55,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
{
if (file_exists (p)) // Follows symlinks.
{
- fn (p, remote, false /* overwrite */);
+ fn (p, rem, false /* overwrite */);
S s (p.string ());
@@ -65,14 +66,26 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
// this in CLI.
//
O o;
- o.parse (s, U::fail, U::fail);
+ small_vector<std::string, 1> as;
+
+ if (args)
+ {
+ while (s.more ())
+ {
+ if (!o.parse (s, U::fail, U::stop))
+ as.push_back (s.next ());
+ }
+ }
+ else
+ o.parse (s, U::fail, U::fail);
if (o.no_default_options ())
r = false;
def_ops.push_back (default_options_entry<O> {move (p),
move (o),
- remote});
+ move (as),
+ rem});
}
}
catch (std::system_error& e)
@@ -102,7 +115,8 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
const optional<dir_path>& home_dir,
const optional<dir_path>& extra_dir,
const default_options_files& ofs,
- F&& fn)
+ F&& fn,
+ bool args)
{
if (sys_dir)
assert (sys_dir->absolute () && sys_dir->normalized ());
@@ -192,6 +206,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
if (load_extra && extra_dir->sub (d))
{
load = load_default_options_files<O, S, U> (*extra_dir,
+ args,
false /* remote */,
ofs.files,
std::forward<F> (fn),
@@ -204,6 +219,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
if (load && options_dir_exists (od))
load = load_default_options_files<O, S, U> (od,
+ args,
remote,
ofs.files,
std::forward<F> (fn),
@@ -219,6 +235,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
if (load && load_extra)
load = load_default_options_files<O, S, U> (*extra_dir,
+ args,
false /* remote */,
ofs.files,
std::forward<F> (fn),
@@ -230,6 +247,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
if (options_dir_exists (d))
load = load_default_options_files<O, S, U> (d,
+ args,
false /* remote */,
ofs.files,
std::forward<F> (fn),
@@ -238,6 +256,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
if (load && sys_dir && options_dir_exists (*sys_dir))
load_default_options_files<O, S, U> (*sys_dir,
+ args,
false /* remote */,
ofs.files,
std::forward<F> (fn),
@@ -269,4 +288,26 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
r.merge (cmd_ops);
return r;
}
+
+ template <typename O, typename AS, typename F>
+ AS
+ merge_default_arguments (const default_options<O>& def_ops,
+ const AS& cmd_args,
+ F&& fn)
+ {
+ AS r;
+ for (const default_options_entry<O>& e: def_ops)
+ {
+ fn (e, cmd_args);
+ r.insert (r.end (), e.arguments.begin (), e.arguments.end ());
+ }
+
+ // Optimize for the common case.
+ //
+ if (r.empty ())
+ return cmd_args;
+
+ r.insert (r.end (), cmd_args.begin (), cmd_args.end ());
+ return r;
+ }
}