Sharg 1.1.0
The argument parser for bio-c++ tools.
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages Concepts
Loading...
Searching...
No Matches
format_tdl.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2023, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2023, Knut Reinert & MPI für molekulare Genetik
4// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5// shipped with this file and also available at: https://github.com/seqan/sharg-parser/blob/master/LICENSE.md
6// -----------------------------------------------------------------------------------------------------------
7
13#pragma once
14
15#include <concepts>
16#include <numeric>
17
19#include <sharg/validators.hpp>
20
21#include <tdl/ParamDocumentToCTD.h>
22#include <tdl/ParamDocumentToCWL.h>
23
24namespace sharg::detail
25{
26
31inline auto to_tdl(bool v)
32{
33 return tdl::BoolValue(v);
34}
35
37auto to_tdl(std::integral auto v)
38{
39 return tdl::IntValue(v);
40}
41
43auto to_tdl(std::floating_point auto v)
44{
45 return tdl::DoubleValue(v);
46}
47
49inline auto to_tdl(std::string const & v)
50{
51 return tdl::StringValue(v);
52}
53
55auto to_tdl(auto SHARG_DOXYGEN_ONLY(v))
56{
57 return tdl::BoolValue(false);
58}
59
68class format_tdl : format_base
69{
70public:
72 enum class FileFormat
73 {
74 CTD,
75 CWL,
76 };
77
79 std::vector<std::function<void(std::string_view)>> parser_set_up_calls;
81 std::vector<std::function<void(std::string_view)>> positional_option_calls; // singled out to be printed on top
83 unsigned positional_option_count{0};
85 std::vector<std::string> command_names{};
86
88 tdl::ToolInfo info;
89
91 FileFormat fileFormat;
92
107 parser_meta_data meta;
108
109public:
116 format_tdl(FileFormat fileFormat) : fileFormat{fileFormat}
117 {}
118
119 format_tdl(format_tdl const &) = default;
120 format_tdl & operator=(format_tdl const &) = default;
121 format_tdl(format_tdl &&) = default;
122 format_tdl & operator=(format_tdl &&) = default;
123 ~format_tdl() = default;
124
128 template <typename option_type, typename config_type>
129 void add_option(option_type & value, config_type const & config)
130 {
131 auto description = config.description;
132 description += (config.required ? std::string{" "} : detail::to_string(" Default: ", value, ". "));
133 description += config.validator.get_help_page_message();
134
135 auto tags = std::set<std::string>{};
136 if (config.required)
137 {
138 tags.insert("required");
139 }
140 if (config.advanced)
141 {
142 tags.insert("advanced");
143 }
144 if constexpr (std::same_as<std::filesystem::path, option_type>)
145 {
146 auto valueAsStr = to_string(value);
147 store_help_page_element(
148 [this, config, description, valueAsStr, _tags = tags](std::string_view)
149 {
150 auto tags = _tags;
151
152 // Check if validator is a file,directory,input and/or output paremeter
153 using Validator = std::decay_t<decltype(config.validator)>;
154 if constexpr (std::is_base_of_v<sharg::input_file_validator, Validator>)
155 {
156 tags.insert("file");
157 }
158 else if constexpr (std::is_base_of_v<sharg::input_directory_validator, Validator>)
159 {
160 tags.insert("directory");
161 }
162 else if constexpr (std::is_base_of_v<sharg::output_file_validator, Validator>)
163 {
164 tags.insert("file");
165 tags.insert("output");
166 }
167 else if constexpr (std::is_base_of_v<sharg::output_directory_validator, Validator>)
168 {
169 tags.insert("directory");
170 tags.insert("output");
171 }
172
173 info.params.push_back(tdl::Node{
174 .name = config.long_id,
175 .description = description,
176 .tags = std::move(tags),
177 .value = tdl::StringValue{valueAsStr},
178 });
179 info.cliMapping.emplace_back("--" + config.long_id, config.long_id);
180 },
181 config);
182 }
183 else
184 {
185 store_help_page_element(
186 [this, config, value, description, tags](std::string_view)
187 {
188 info.params.push_back(tdl::Node{
189 .name = config.long_id,
190 .description = description,
191 .tags = std::move(tags),
192 .value = to_tdl(value),
193 });
194 info.cliMapping.emplace_back("--" + config.long_id, config.long_id);
195 },
196 config);
197 }
198 }
199
203 template <typename config_type>
204 void add_flag(bool & value, config_type const & config)
205 {
206 store_help_page_element(
207 [this, config, value](std::string_view)
208 {
209 info.params.push_back(tdl::Node{
210 .name = config.long_id,
211 .description = config.description,
212 .tags = {},
213 .value = to_tdl(value),
214 });
215 },
216 config);
217 }
218
222 template <typename option_type, typename config_type>
223 void add_positional_option(option_type & value, config_type const & config)
224 {
225 std::string msg = config.validator.get_help_page_message();
226
227 positional_option_calls.push_back(
228 [this, &value, config, msg](std::string_view)
229 {
230 auto id = "positional_" + std::to_string(positional_option_count);
231 ++positional_option_count;
232 auto description =
233 config.description +
234 // a list at the end may be empty and thus have a default value
235 ((detail::is_container_option<option_type>) ? detail::to_string(" Default: ", value, ". ")
236 : std::string{" "})
237 + msg;
238
239 info.params.push_back(tdl::Node{
240 .name = id,
241 .description = description,
242 .tags = {},
243 .value = tdl::StringValue{},
244 });
245 if (!config.long_id.empty())
246 {
247 info.cliMapping.emplace_back("--" + config.long_id, config.long_id);
248 }
249 });
250 }
251
257 void parse(parser_meta_data & parser_meta, std::vector<std::string> const & executable_name)
258 {
259 meta = parser_meta;
260
261 // each call will evaluate the function print_list_item()
262 for (auto f : positional_option_calls)
263 f(meta.app_name);
264
265 // each call will evaluate the function print_list_item()
266 for (auto f : parser_set_up_calls)
267 f(meta.app_name);
268
269 info.metaInfo = tdl::MetaInfo{
270 .version = meta.version,
271 .name = meta.app_name,
272 .docurl = meta.url,
273 .category = "",
274 .description = std::accumulate(begin(meta.description),
275 end(meta.description),
276 std::string{},
277 [](auto a, auto v)
278 {
279 return a + v + '\n';
280 }),
281 // .citations = {meta.citation},
282 };
283 if (!executable_name.empty())
284 {
285 info.metaInfo.executableName = executable_name[0];
286 }
287 for (size_t i{1}; i < executable_name.size(); ++i)
288 {
289 auto name = "subcommand_" + std::to_string(i);
290 info.params.push_back(tdl::Node{
291 .name = name,
292 .value = tdl::StringValue(executable_name[i]),
293 });
294 info.cliMapping.emplace_back("", name);
295 }
296
297 if (fileFormat == FileFormat::CTD)
298 {
299 std::cout << tdl::convertToCTD(info);
300 }
301 else if (fileFormat == FileFormat::CWL)
302 {
303 std::cout << tdl::convertToCWL(info) << "\n";
304 }
305 else
306 {
307 throw std::runtime_error("unsupported file format (this is a bug)");
308 }
309 std::exit(EXIT_SUCCESS); // program should not continue from here
310 }
311
315 void add_section(std::string const & SHARG_DOXYGEN_ONLY(title), bool const SHARG_DOXYGEN_ONLY(advanced_only))
316 {}
317
321 void add_subsection(std::string const & SHARG_DOXYGEN_ONLY(title), bool const SHARG_DOXYGEN_ONLY(advanced_only))
322 {}
323
327 void add_line(std::string const & SHARG_DOXYGEN_ONLY(text),
328 bool SHARG_DOXYGEN_ONLY(is_paragraph),
329 bool const SHARG_DOXYGEN_ONLY(advanced_only))
330 {}
331
335 void add_list_item(std::string const & SHARG_DOXYGEN_ONLY(key),
336 std::string const & SHARG_DOXYGEN_ONLY(desc),
337 bool const SHARG_DOXYGEN_ONLY(advanced_only))
338 {}
339
340private:
349 void store_help_page_element(std::function<void(std::string_view)> printer, config<auto> const & config)
350 {
351 if (config.hidden)
352 return;
353 parser_set_up_calls.push_back(std::move(printer));
354 }
355};
356
357} // namespace sharg::detail
T accumulate(T... args)
T begin(T... args)
T empty(T... args)
T end(T... args)
T exit(T... args)
Provides the format_base struct containing all helper functions that are needed in all formats.
T insert(T... args)
T parse(T... args)
T push_back(T... args)
T size(T... args)
T to_string(T... args)
Provides some standard validators for (positional) options.