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