helics 3.7.0
Loading...
Searching...
No Matches
helicsCLI11.hpp
1/*
2Copyright (c) 2017-2026,
3Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Energy
4Innovation LLC. See the top-level NOTICE for additional details. All rights reserved.
5SPDX-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
33
34#else
35# include "../utilities/timeStringOps.hpp"
36# include "coreTypeOperations.hpp"
37
38using helics::core::coreTypeFromString;
40using helics::core::to_string;
42inline 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"
49namespace helics {
50class 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
206namespace CLI::detail {
207template<>
208inline 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
219template<>
220constexpr const char* type_name<helics::Time>()
221{
222 return "TIME";
223}
224} // namespace CLI::detail
Definition helicsCLI11.hpp:50
void add_callback(std::function< void()> cback)
Definition helicsCLI11.hpp:137
void setDefaultCoreType(CoreType type)
Definition helicsCLI11.hpp:196
std::string systemInfo()
Definition helicsVersion.cpp:196
the main namespace for the helics co-simulation library User functions will be in the helics namespac...
Definition AsyncFedCallInfo.hpp:14
CoreType
Definition CoreTypes.hpp:46
@ DEFAULT
ZMQ if available or UDP.
@ UNRECOGNIZED
unknown
CoreType coreTypeFromString(std::string_view type) noexcept
Definition typeOperations.cpp:20
std::string to_string(CoreType type)
Definition typeOperations.cpp:15
Time loadTimeFromString(std::string_view timeString)
Definition timeOperations.cpp:21
constexpr auto versionString
Definition helicsVersion.hpp:18
TimeRepresentation< count_time< 9 > > Time
Definition helicsTime.hpp:27
std::string systemInfo()
Definition typeOperations.cpp:30