Sharg 1.1.2-rc.1
The argument parser for bio-c++ tools.
Loading...
Searching...
No Matches
format_tdl.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006-2024, Knut Reinert & Freie Universität Berlin
2// SPDX-FileCopyrightText: 2016-2024, Knut Reinert & MPI für molekulare Genetik
3// SPDX-License-Identifier: BSD-3-Clause
4
10#pragma once
11
12#if !SHARG_HAS_TDL
13
15
16namespace sharg::detail
17{
18// A dummy class that is used when TDL is not available.
19// This reduces the number of '#if's in the code.
20// It will always throw when parse is called.
21// For the user, the behavior of the parser will be the same as if `parser::init()` would check for TDL availability.
22class format_tdl : public format_help
23{
24public:
25 enum class FileFormat
26 {
27 CTD,
28 CWL
29 };
30
31 format_tdl(format_tdl const &) = default;
32 format_tdl & operator=(format_tdl const &) = default;
33 format_tdl(format_tdl &&) = default;
34 format_tdl & operator=(format_tdl &&) = default;
35 ~format_tdl() = default;
36
38 {}
39
40 void parse(parser_meta_data &, std::vector<std::string> const &)
41 {
42 throw validation_error{"Validation failed for option --export-help: "
43 "Value must be one of "
44 + detail::supported_exports + "."};
45 }
46
48};
49
50} // namespace sharg::detail
51
52#else
53# include <concepts>
54# include <numeric>
55
57# include <sharg/validators.hpp>
58
59# include <tdl/tdl.h>
60
61namespace sharg::detail
62{
63
68inline auto to_tdl(bool v)
69{
70 return tdl::BoolValue(v);
71}
72
75{
76 return tdl::IntValue(v);
77}
78
81{
82 return tdl::DoubleValue(static_cast<double>(v));
83}
84
86inline auto to_tdl(std::string const & v)
87{
88 return tdl::StringValue(v);
89}
90
92auto to_tdl(auto SHARG_DOXYGEN_ONLY(v)) // NOLINT(performance-unnecessary-value-param)
93{
94 return tdl::BoolValue(false);
95}
96
106{
107public:
109 enum class FileFormat : uint8_t
110 {
111 CTD,
112 CWL,
113 };
114
118 std::vector<std::function<void(std::string_view)>> positional_option_calls; // singled out to be printed on top
121
123 tdl::ToolInfo info;
124
126 tdl::Node::Children parameters;
127
130
146
147public:
156
157 format_tdl(format_tdl const &) = default;
158 format_tdl & operator=(format_tdl const &) = default;
159 format_tdl(format_tdl &&) = default;
161 ~format_tdl() = default;
162
166 template <typename option_type, typename validator_t>
167 void add_option(option_type & value, config<validator_t> const & config)
168 {
169 auto description = config.description;
170
172 description += ((config.required) ? std::string{} : get_default_message(value, value));
173 else
174 description += get_default_message(value, config.default_message);
175
176 if (auto const & validator_message = config.validator.get_help_page_message(); !validator_message.empty())
177 description += ". " + validator_message;
178
179 auto tags = std::set<std::string>{};
180 if (config.required)
181 {
182 tags.insert("required");
183 }
184 if (config.advanced)
185 {
186 tags.insert("advanced");
187 }
189 {
190 auto valueAsStr = to_string(value);
192 [this, config, description, valueAsStr, _tags = tags](std::string_view)
193 {
194 auto tags = _tags;
195
196 // Check if validator is a file,directory,input and/or output paremeter
197 using Validator = std::decay_t<decltype(config.validator)>;
199 {
200 tags.insert("file");
201 }
203 {
204 tags.insert("directory");
205 }
207 {
208 tags.insert("file");
209 tags.insert("output");
210 }
212 {
213 tags.insert("directory");
214 tags.insert("output");
215 }
216
217 // gcc 15 doesn't like having the push_back as a one-liner.
218 parameters.push_back(tdl::Node{.name = config.long_id, .description = description});
219
220 auto & node = parameters.back();
221 node.tags = std::move(tags);
222 node.value = tdl::StringValue{valueAsStr};
223
224 info.cliMapping.emplace_back("--" + config.long_id, config.long_id);
225 },
226 config);
227 }
228 else
229 {
231 [this, config, value, description, tags](std::string_view)
232 {
233 // gcc 15 with hardened flags (fedora-flags) doesn't like having the push_back as a one-liner.
234 parameters.push_back(tdl::Node{.name = config.long_id, .description = description});
235
236 auto & node = parameters.back();
237 node.tags = std::move(tags);
238 node.value = to_tdl(value);
239
240 info.cliMapping.emplace_back("--" + config.long_id, config.long_id);
241 },
242 config);
243 }
244 }
245
249 template <typename validator_t>
250 void add_flag(bool & value, config<validator_t> const & config)
251 {
253 [this, config, value](std::string_view)
254 {
255 parameters.push_back(tdl::Node{
256 .name = config.long_id,
257 .description = config.description,
258 .tags = {},
259 .value = to_tdl(value),
260 });
261 },
262 config);
263 }
264
268 template <typename option_type, typename validator_t>
269 void add_positional_option(option_type & value, config<validator_t> const & config)
270 {
271 // a list at the end may be empty and thus have a default value
272 auto positional_default_message = [&value]() -> std::string
273 {
275 {
276 return get_default_message(value, value);
277 }
278 else
279 {
280 (void)value; // Silence unused variable warning.
281 return {};
282 }
283 };
284
285 auto positional_validator_message = [&config]() -> std::string
286 {
287 if (auto const & validator_message = config.validator.get_help_page_message(); !validator_message.empty())
288 return ". " + validator_message;
289 else
290 return {};
291 };
292
294 [this,
295 config,
296 default_message = positional_default_message(),
297 validator_message = positional_validator_message()](std::string_view)
298 {
299 auto id = "positional_" + std::to_string(positional_option_count);
301 auto description = config.description + default_message + validator_message;
302
303 parameters.push_back(tdl::Node{.name = id, .description = description});
304
305 auto & node = parameters.back();
306
308 {
309 node.value = tdl::StringValueList{};
310 }
311 else
312 {
313 node.value = tdl::StringValue{};
314 node.tags.insert("required");
315 }
316 });
317 }
318
324 void parse(parser_meta_data & parser_meta, std::vector<std::string> const & executable_name)
325 {
326 meta = parser_meta;
327
328 // each call will evaluate the function print_list_item()
329 for (auto && f : positional_option_calls)
330 f(meta.app_name);
331
332 // each call will evaluate the function print_list_item()
333 for (auto && f : parser_set_up_calls)
334 f(meta.app_name);
335
336 info.metaInfo = tdl::MetaInfo{
338 .name = meta.app_name,
339 .docurl = meta.url,
340 .category = "",
341 .description = std::accumulate(begin(meta.description),
342 end(meta.description),
343 std::string{},
344 [](auto const & a, auto const & v)
345 {
346 return a + v + '\n';
347 }),
348 // .citations = {meta.citation},
349 };
350 if (!executable_name.empty())
351 {
352 info.metaInfo.executableName = executable_name[0];
353 }
354 for (size_t i{1}; i < executable_name.size(); ++i)
355 {
356 parameters = {tdl::Node{
357 .name = executable_name[executable_name.size() - i],
358 .tags = {"basecommand"},
359 .value = parameters,
360 }};
361 }
362 info.params = std::move(parameters);
363
365 {
366 std::cout << tdl::convertToCTD(info);
367 }
368 else if (fileFormat == FileFormat::CWL)
369 {
370 std::cout << tdl::convertToCWL(info) << "\n";
371 }
372 else
373 {
374 throw std::runtime_error("unsupported file format (this is a bug)");
375 }
376 std::exit(EXIT_SUCCESS); // program should not continue from here
377 }
378
382 void add_section(std::string const & SHARG_DOXYGEN_ONLY(title), bool const SHARG_DOXYGEN_ONLY(advanced_only))
383 {}
384
388 void add_subsection(std::string const & SHARG_DOXYGEN_ONLY(title), bool const SHARG_DOXYGEN_ONLY(advanced_only))
389 {}
390
394 void add_line(std::string const & SHARG_DOXYGEN_ONLY(text),
395 bool SHARG_DOXYGEN_ONLY(is_paragraph),
396 bool const SHARG_DOXYGEN_ONLY(advanced_only))
397 {}
398
402 void add_list_item(std::string const & SHARG_DOXYGEN_ONLY(key),
403 std::string const & SHARG_DOXYGEN_ONLY(desc),
404 bool const SHARG_DOXYGEN_ONLY(advanced_only))
405 {}
406
407private:
416 template <typename validator_t>
418 {
419 if (config.hidden)
420 return;
421 parser_set_up_calls.push_back(std::move(printer));
422 }
423};
424
425} // namespace sharg::detail
426
427#endif
T accumulate(T... args)
The format that contains all helper functions needed in all formats.
Definition format_base.hpp:31
static std::string get_default_message(option_type const &option, default_type const &value)
Returns the default message for the help page.
Definition format_base.hpp:197
A generalized format to create different tool description files.
Definition format_tdl.hpp:106
std::vector< std::function< void(std::string_view)> > positional_option_calls
Vector of functions that stores add_positional_option calls.
Definition format_tdl.hpp:118
FileFormat fileFormat
Targeted tool description format.
Definition format_tdl.hpp:129
unsigned positional_option_count
Keeps track of the number of positional options.
Definition format_tdl.hpp:120
void add_section(std::string const &title, bool const advanced_only)
Adds a print_section call to parser_set_up_calls.
Definition format_tdl.hpp:382
format_tdl & operator=(format_tdl const &)=default
Defaulted.
void add_subsection(std::string const &title, bool const advanced_only)
Adds a print_subsection call to parser_set_up_calls.
Definition format_tdl.hpp:388
std::vector< std::function< void(std::string_view)> > parser_set_up_calls
Vector of functions that stores all calls except add_positional_option.
Definition format_tdl.hpp:116
void add_flag(bool &value, config< validator_t > const &config)
Adds a sharg::print_list_item call to be evaluated later on.
Definition format_tdl.hpp:250
FileFormat
Supported tool description file formats.
Definition format_tdl.hpp:110
@ CTD
Support for CTD format.
@ CWL
Support for CWL format.
void add_option(option_type &value, config< validator_t > const &config)
Adds a sharg::print_list_item call to be evaluated later on.
Definition format_tdl.hpp:167
void add_line(std::string const &text, bool is_paragraph, bool const advanced_only)
Adds a print_line call to parser_set_up_calls.
Definition format_tdl.hpp:394
format_tdl & operator=(format_tdl &&)=default
Defaulted.
void parse(parser_meta_data &parser_meta, std::vector< std::string > const &executable_name)
Initiates the printing of the help page to std::cout.
Definition format_tdl.hpp:324
tdl::Node::Children parameters
all collected parameters
Definition format_tdl.hpp:126
tdl::ToolInfo info
TDL DS filled with tool meta information.
Definition format_tdl.hpp:123
void add_positional_option(option_type &value, config< validator_t > const &config)
Adds a sharg::print_list_item call to be evaluated later on.
Definition format_tdl.hpp:269
format_tdl(format_tdl &&)=default
Defaulted.
format_tdl(format_tdl const &)=default
Defaulted.
format_tdl(FileFormat fileFormat)
Construct from a file format.
Definition format_tdl.hpp:154
void add_list_item(std::string const &key, std::string const &desc, bool const advanced_only)
Adds a sharg::print_list_item call to parser_set_up_calls.
Definition format_tdl.hpp:402
void store_help_page_element(std::function< void(std::string_view)> printer, config< validator_t > const &config)
Adds a function object to parser_set_up_calls if the annotation in spec does not prevent it.
Definition format_tdl.hpp:417
~format_tdl()=default
Defaulted.
parser_meta_data meta
Stores all meta information about the application.
Definition format_tdl.hpp:145
Whether the option type is considered to be a container.
Definition detail/concept.hpp:38
T empty(T... args)
T exit(T... args)
Provides the format_base struct containing all helper functions that are needed in all formats.
Provides the format_help struct that print the help page to the command line and the two child format...
auto to_tdl(bool v)
converts a value into the corresponding tdl value type
Definition format_tdl.hpp:68
std::string to_string(value_types &&... values)
Streams all parameters via std::ostringstream and returns a concatenated string.
Definition to_string.hpp:40
T insert(T... args)
T is_same_v
T push_back(T... args)
T size(T... args)
Option struct that is passed to the sharg::parser::add_option() function.
Definition config.hpp:43
std::string description
The description to be shown on any (exported) help page.
Definition config.hpp:68
std::string long_id
The long identifier for the option (e.g. "age", making the option callable via --age).
Definition config.hpp:62
bool hidden
Whether the option should be hidden.
Definition config.hpp:117
bool advanced
Whether the option should only be displayed on the advanced help page.
Definition config.hpp:105
bool required
Whether the option is required.
Definition config.hpp:129
validator_t validator
A sharg::validator that verifies the value after parsing (callable).
Definition config.hpp:135
std::string default_message
The default message to be shown on any (exported) help page.
Definition config.hpp:87
Stores all parser related meta information of the sharg::parser.
Definition auxiliary.hpp:45
std::vector< std::string > description
A more detailed description that is displayed on the help page in the section "DESCRIPTION"....
Definition auxiliary.hpp:97
std::string app_name
The application name that will be displayed on the help page.
Definition auxiliary.hpp:51
std::string version
The version information MAJOR.MINOR.PATH (e.g. 3.1.3)
Definition auxiliary.hpp:54
std::string url
A link to your github/gitlab project with the newest release.
Definition auxiliary.hpp:71
T to_string(T... args)
Provides some standard validators for (positional) options.
Hide me