helics  2.8.1
helicsCLI11.hpp
1 /*
2 Copyright (c) 2017-2021,
3 Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable
4 Energy, LLC. See the top-level NOTICE for additional details. All rights reserved.
5 SPDX-License-Identifier: BSD-3-Clause
6 */
7 
8 #pragma once
9 
10 #define CLI11_EXPERIMENTAL_OPTIONAL 0
11 #include "helics/external/CLI11/CLI11.hpp"
12 
13 #include <string>
14 #include <utility>
15 #include <vector>
16 #undef CLI11_EXPERIMENTAL_OPTIONAL
17 #include "core-types.hpp"
18 #include "helics-time.hpp"
19 #if defined HELICS_SHARED_LIBRARY || !defined HELICS_STATIC_CORE_LIBRARY
20 # include "../application_api/timeOperations.hpp"
21 # include "../application_api/typeOperations.hpp"
22 
25 using helics::to_string;
26 #else
27 # include "../utilities/timeStringOps.hpp"
28 # include "coreTypeOperations.hpp"
29 
30 using helics::core::coreTypeFromString;
31 using helics::core::to_string;
33 inline helics::Time loadTimeFromString(const std::string& str, time_units defUnit)
34 {
35  return gmlc::utilities::loadTimeFromString<helics::Time>(str, defUnit);
36 }
37 
38 #endif
39 #include "helicsVersion.hpp"
40 namespace helics {
41 class helicsCLI11App: public CLI::App {
42  public:
43  explicit helicsCLI11App(std::string app_description = "", const std::string& app_name = ""):
44  CLI::App(std::move(app_description), app_name, nullptr)
45  {
46  set_help_flag("-h,-?,--help", "Print this help message and exit");
47  set_config("--config-file,--config",
48  "helics_config.toml",
49  "specify base configuration file");
50  set_version_flag("--version", helics::versionString);
51  add_option_group("quiet")->immediate_callback()->add_flag("--quiet",
52  quiet,
53  "silence most print output");
54  }
55 
56  enum class parse_output : int {
57  ok = 0,
58  help_call = 1,
59  help_all_call = 2,
60  version_call = 4,
61  parse_error = -4,
62  };
63  bool quiet{false};
64  bool passConfig{true};
65  parse_output last_output{parse_output::ok};
66 
67  template<typename... Args>
68  parse_output helics_parse(Args&&... args) noexcept
69  {
70  try {
71  parse(std::forward<Args>(args)...);
72  last_output = parse_output::ok;
73  remArgs = remaining_for_passthrough();
74  if (passConfig) {
75  auto* opt = get_option_no_throw("--config");
76  if (opt != nullptr && opt->count() > 0) {
77  remArgs.push_back(opt->as<std::string>());
78  remArgs.emplace_back("--config");
79  }
80  }
81 
82  return parse_output::ok;
83  }
84  catch (const CLI::CallForHelp& ch) {
85  if (!quiet) {
86  exit(ch);
87  }
88  last_output = parse_output::help_call;
89  return parse_output::help_call;
90  }
91  catch (const CLI::CallForAllHelp& ca) {
92  if (!quiet) {
93  exit(ca);
94  }
95  last_output = parse_output::help_all_call;
96  return parse_output::help_all_call;
97  }
98  catch (const CLI::CallForVersion& cv) {
99  if (!quiet) {
100  exit(cv);
101  }
102  last_output = parse_output::version_call;
103  return parse_output::version_call;
104  }
105  catch (const CLI::Error& ce) {
106  CLI::App::exit(ce);
107  last_output = parse_output::parse_error;
108  return parse_output::parse_error;
109  }
110  catch (...) {
111  last_output = parse_output::parse_error;
112  return parse_output::parse_error;
113  }
114  }
115  std::vector<std::string>& remainArgs() { return remArgs; }
116  void remove_helics_specifics()
117  {
118  set_help_flag();
119  set_config();
120  try {
121  remove_option(get_option_no_throw("-v"));
122  remove_subcommand(get_option_group("quiet"));
123  }
124  catch (const CLI::Error&) {
125  // must have been removed earlier
126  }
127  }
129  void add_callback(std::function<void()> cback)
130  {
131  if (cbacks.empty()) {
132  callback([this]() {
133  for (auto& cb : cbacks) {
134  cb();
135  }
136  });
137  }
138  cbacks.push_back(std::move(cback));
139  }
140 
141  void addTypeOption(bool includeEnvironmentVariable = true)
142  {
143  auto* og = add_option_group("network type")->immediate_callback();
144  auto* typeOption =
145  og->add_option_function<std::string>(
146  "--coretype,-t,--type,--core",
147  [this](const std::string& val) {
148  coreType = coreTypeFromString(val);
149  if (coreType == core_type::UNRECOGNIZED) {
150  throw CLI::ValidationError(val + " is NOT a recognized core type");
151  }
152  },
153  "type of the core to connect to")
154  ->default_str("(" + to_string(coreType) + ")");
155  if (includeEnvironmentVariable) {
156  typeOption->envname("HELICS_CORE_TYPE");
157  }
158  }
159  core_type getCoreType() const { return coreType; }
161  void setDefaultCoreType(core_type type) { coreType = type; }
162 
163  private:
164  std::vector<std::function<void()>> cbacks;
165  std::vector<std::string> remArgs;
166  core_type coreType{core_type::DEFAULT};
167 };
168 } // namespace helics
169 
170 // use the CLI lexical cast function overload to convert a string into a time
171 namespace CLI {
172 namespace detail {
173  template<>
174  inline bool lexical_cast<helics::Time>(const std::string& input, helics::Time& output)
175  {
176  try {
177  output = loadTimeFromString(input, time_units::ms);
178  }
179  catch (std::invalid_argument&) {
180  return false;
181  }
182  return true;
183  }
184 
185  template<>
186  constexpr const char* type_name<helics::Time>()
187  {
188  return "TIME";
189  }
190 } // namespace detail
191 } // namespace CLI
helics-time.hpp
core-types.hpp
helics::core_type
core_type
Definition: core-types.hpp:37
helics::helicsCLI11App::add_callback
void add_callback(std::function< void()> cback)
Definition: helicsCLI11.hpp:129
helics::to_string
std::string to_string(core_type type)
Definition: typeOperations.cpp:12
helics::Time
TimeRepresentation< count_time< 9 > > Time
Definition: helics-time.hpp:27
coreTypeOperations.hpp
helics::helicsCLI11App
Definition: helicsCLI11.hpp:41
helics::core_type::UNRECOGNIZED
@ UNRECOGNIZED
unknown
helics::versionString
constexpr auto versionString
Definition: helicsVersion.hpp:16
helics::core_type::DEFAULT
@ DEFAULT
ZMQ if available or UDP.
helics
the main namespace for the helics co-simulation library User functions will be in the helics namespac...
Definition: AsyncFedCallInfo.hpp:14
helics::helicsCLI11App::setDefaultCoreType
void setDefaultCoreType(core_type type)
Definition: helicsCLI11.hpp:161
helics::coreTypeFromString
core_type coreTypeFromString(std::string type) noexcept
Definition: typeOperations.cpp:17
helics::loadTimeFromString
Time loadTimeFromString(const std::string &timeString)
Definition: timeOperations.cpp:19
helicsVersion.hpp