Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
cli/output.hpp
Go to the documentation of this file.
1
5#pragma once
6#include "cli.hpp"
7#include <cstdio>
8#include <filesystem>
9#include <map>
10#include <stdexcept>
11#include <string>
13#include <utility>
14#include <vector>
15
16namespace uni20::cli
17{
18namespace detail
19{
20inline output_format parse_output_format(std::string const& name)
21{
22 static std::map<std::string, output_format> const formats{{"terminal", output_format::terminal},
23 {"csv", output_format::csv},
24 {"tsv", output_format::tsv},
25 {"commented-csv", output_format::commented_csv},
26 {"commented-tsv", output_format::commented_tsv},
27 {"json", output_format::json},
28 {"named-json", output_format::named_json}};
29 auto found = formats.find(name);
30 if (found == formats.end()) throw std::invalid_argument("unknown output format: " + name);
31 return found->second;
32}
33
34inline std::pair<output_format, std::filesystem::path> parse_file_export(std::string const& specification)
35{
36 auto separator = specification.find(':');
37 if (separator == std::string::npos || separator + 1 == specification.size())
38 throw std::invalid_argument("export must be FORMAT:PATH with a nonempty path");
39 return {parse_output_format(specification.substr(0, separator)), specification.substr(separator + 1)};
40}
41} // namespace detail
42
44{
45 std::string format = "terminal";
46 std::string path = {};
48 std::vector<std::string> exports = {};
49 bool quiet = false;
50 bool plain = false;
51 bool no_preamble = false;
52 bool overwrite = false;
53 bool flush_each_row = false;
54
57 [[nodiscard]] output_session session(metadata_document initial = {},
58 std::map<std::string, std::string> metadata_keys = {}) const
59 {
60 auto primary_format = detail::parse_output_format(format);
61 output_session result(std::move(initial), quiet);
63 .flush_each_row = flush_each_row,
64 .preamble = !no_preamble,
65 .metadata_keys = std::move(metadata_keys),
66 .human_policy = plain || !path.empty()
68 : presentation::terminal_policy(stdout)};
69 if (path.empty())
70 result.standard_output(primary_format, options);
71 else
72 result.file(path, primary_format, options);
73 options.human_policy = presentation::plain_policy();
74 for (auto const& specification : exports)
75 {
76 auto [export_format, export_path] = detail::parse_file_export(specification);
77 result.file(std::move(export_path), export_format, options);
78 }
79 return result;
80 }
81};
82
85inline void add_output_options(CLI::App& app, output_options& options)
86{
87 auto* group = app.add_option_group("Output");
88 group->add_option("--format", options.format, "Result representation")
89 ->check(CLI::IsMember({"terminal", "csv", "tsv", "commented-csv", "commented-tsv", "json", "named-json"}))
90 ->capture_default_str();
91 group->add_option("--output", options.path, "Output file; omitted means stdout");
92 group->add_option("--export", options.exports, "Additional file export; repeat for multiple destinations")
93 ->type_name("FORMAT:PATH")
94 ->expected(1)
95 ->multi_option_policy(CLI::MultiOptionPolicy::TakeAll)
96 ->check([](std::string const& specification) {
97 try
98 {
99 (void)detail::parse_file_export(specification);
100 return std::string{};
101 }
102 catch (std::invalid_argument const& error)
103 {
104 return std::string(error.what());
105 }
106 });
107 group->add_flag("-q,--quiet", options.quiet, "Suppress session stdout, including machine output");
108 group->add_flag("--plain", options.plain, "Use plain human output");
109 group->add_flag("--no-preamble", options.no_preamble, "Omit the human preamble and commented-file metadata");
110 group->add_flag("--overwrite", options.overwrite, "Permit replacing an existing output file");
111 group->add_flag("--flush-each-row", options.flush_each_row, "Flush result streams after every accepted row");
112}
113} // namespace uni20::cli
Ordered, uniquely identified metadata. Copies are independent snapshots.
Definition metadata.hpp:306
An explicitly finalized set of owned result streams, with no global display changes.
Definition output_session.hpp:184
CLI11 option adapters, explicit parse outcomes and semantic application help.
Definition cli.cpp:6
void add_output_options(CLI::App &app, output_options &options)
Register output options on CLI11; call after initializing any application-specific defaults.
Definition cli/output.hpp:85
Definition data_table.cpp:8
output_policy plain_policy()
Build a policy for plain file/log rendering with no ANSI color.
Definition presentation.cpp:1195
output_format
Definition output_session.hpp:26
Owned output destinations layered on typed table subscriptions.
Definition cli/output.hpp:44
bool overwrite
Definition cli/output.hpp:52
output_session session(metadata_document initial={}, std::map< std::string, std::string > metadata_keys={}) const
Construct an unopened session.
Definition cli/output.hpp:57
bool quiet
Definition cli/output.hpp:49
bool no_preamble
Definition cli/output.hpp:51
std::string format
Definition cli/output.hpp:45
std::vector< std::string > exports
Additional FORMAT:PATH destinations, independent of the primary stdout or file destination.
Definition cli/output.hpp:48
bool flush_each_row
Definition cli/output.hpp:53
bool plain
Definition cli/output.hpp:50
std::string path
Definition cli/output.hpp:46
Definition output_session.hpp:47
bool overwrite
Definition output_session.hpp:49