| helics 3.6.1

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