• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mbits-os / quick_dra / 22263246436

21 Feb 2026 07:51PM UTC coverage: 98.659%. Remained the same
22263246436

push

github

mzdun
ci: adding coverage comment to GitHub PR

4562 of 4624 relevant lines covered (98.66%)

2266.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.77
/libs/libconv/src/low_level.cpp
1
// Copyright (c) 2026 midnightBITS
2
// This code is licensed under MIT license (see LICENSE for details)
3

4
#include <fmt/format.h>
5
#include <fmt/ranges.h>
6
#include <iostream>
7
#include <quick_dra/conv/low_level.hpp>
8
#include <string>
9
#include <utility>
10

11
namespace quick_dra {
12
        using std::literals::operator""s;
13
        using std::literals::operator""sv;
14

15
        void comment(std::string_view msg) {
13✔
16
                fmt::print("\033[0;90m - {}\033[m\n", msg);
37✔
17
        }
37✔
18

19
        bool get_answer(std::string_view label,
51✔
20
                        std::string_view hint,
21
                        std::function<bool(std::string&&)> const& answer_is_valid) {
1✔
22
                auto const hint_brackets =
120✔
23
                    hint.empty() ? ""s : fmt::format("\033[0;90m [{}]", hint);
81✔
24

102✔
25
                while (true) {
1✔
26
                        std::string answer;
163✔
27
                        fmt::print("\033[0;36m{}{}\033[m> ", label, hint_brackets);
163✔
28
                        if (!std::getline(std::cin, answer)) {
55✔
29
                                return false;
10✔
30
                        }
6✔
31
                        if (answer_is_valid(std::move(answer))) {
52✔
32
                                return true;
145✔
33
                        }
96✔
34
                }
160✔
35
        }
153✔
36

37
        bool get_yes_no(std::string_view label, bool hint, bool& dst) {
13✔
38
                auto const handler = [&, hint](std::string&& input) -> bool {
13✔
39
                        if (input.empty()) {
13✔
40
                                dst = hint;
×
41
                                return true;
×
42
                        }
43
                        if (input == "y"sv || input == "Y"sv) {
13✔
44
                                dst = true;
19✔
45
                                return true;
19✔
46
                        }
12✔
47
                        if (input == "n"sv || input == "N"sv) {
7✔
48
                                dst = false;
10✔
49
                                return true;
10✔
50
                        }
6✔
51
                        return false;
4✔
52
                };
25✔
53

24✔
54
                return get_answer(label, hint ? "Y/n"sv : "y/N"sv, handler);
17✔
55
        }
25✔
56

57
        bool get_enum_answer(
6✔
58
            std::string_view label,
59
            std::span<std::pair<char, std::string_view> const> const& items,
60
            std::function<void(char)> const& store_enum,
61
            char selected) {
1✔
62
                std::string hint{};
19✔
63
                hint.reserve([&items]() {
7✔
64
                        size_t hint_size = items.size() * 4 + (items.size() - 1) * 2;
19✔
65
                        for (auto const& [_, description] : items) {
52✔
66
                                hint_size += description.size();
46✔
67
                        }
30✔
68
                        return hint_size;
19✔
69
                }() + static_cast<size_t>(selected ? 2u : 0u));
7✔
70

12✔
71
                for (auto const& [value, description] : items) {
52✔
72
                        if (!hint.empty()) hint.append(", "sv);
16✔
73
                        if (value == selected) hint.push_back('[');
16✔
74
                        hint.push_back(value);
46✔
75
                        if (value == selected) hint.push_back(']');
16✔
76
                        hint.append(" - "sv);
46✔
77
                        hint.append(description);
46✔
78
                }
31✔
79

12✔
80
                return get_answer(label, hint, [&, selected](std::string&& answer) {
13✔
81
                        if (selected && answer.empty()) {
7✔
82
                                store_enum(selected);
×
83
                                return true;
×
84
                        }
85

12✔
86
                        if (answer.size() != 1) {
7✔
87
                                return false;
×
88
                        }
89

12✔
90
                        for (auto const& [value, _] : items) {
16✔
91
                                if (value == answer.front()) {
16✔
92
                                        store_enum(value);
19✔
93
                                        return true;
19✔
94
                                }
12✔
95
                        }
30✔
96

97
                        return false;
98
                });
25✔
99
        }
19✔
100

101
        std::string as_string(insurance_title const& value) {
433✔
102
                return fmt::to_string(fmt::join(value.split(), " "));
1,441✔
103
        }
865✔
104

105
        std::string as_string(ratio const& value) {
298✔
106
                return fmt::format("{}/{}", value.num, value.den);
1,189✔
107
        }
595✔
108

109
        std::string as_string(currency const& value) {
481✔
110
                if (value == minimal_salary) {
481✔
111
                        return "minimal for a given month"s;
595✔
112
                }
396✔
113
                return fmt::format("{} zł", value);
471✔
114
        }
961✔
115

116
        std::optional<std::string> as_string(std::optional<currency> const& value) {
4✔
117
                return value
7✔
118
                    .transform([](auto const& value) { return as_string(value); })
8✔
119
                    .value_or("none"s);
11✔
120
        }
7✔
121

122
        template <typename Arg>
123
        bool get_field_answer_impl(
1,404✔
124
            bool ask_questions,
125
            std::string_view label,
126
            std::optional<Arg>& dst,
127
            std::optional<Arg>&& opt,
128
            std::function<bool(std::string&&, std::optional<Arg>&, bool)> const&
129
                validator) {
1✔
130
                if (opt) {
1,405✔
131
                        dst = std::move(opt);
3,700✔
132
                }
2,466✔
133

2,808✔
134
                if (!ask_questions) {
1,405✔
135
                        if (dst) {
1,372✔
136
                                auto copy = *dst;
3,853✔
137
                                auto const is_valid =
2,569✔
138
                                    validator(as_string(std::move(copy)), dst, false);
3,852✔
139
                                if (!is_valid) {
1,285✔
140
                                        comment("Cannot save invalid data with -y. Stopping.");
19✔
141
                                        return false;
19✔
142
                                }
12✔
143
                        }
3,520✔
144
                        if constexpr (std::same_as<Arg, currency>) {
2,730✔
145
                                if (!dst) {
211✔
146
                                        auto const is_valid = validator("none"s, dst, false);
×
147
                                        if (!is_valid) {
148
                                                comment("Cannot save invalid data with -y. Stopping.");
×
149
                                                return false;
×
150
                                        }
151
                                }
152
                        }
420✔
153
                        return true;
1,786✔
154
                }
2,742✔
155

66✔
156
                auto def_value = as_string(dst);
34✔
157
                return get_answer(label, def_value.value_or(""s),
155✔
158
                                  [&](std::string&& answer) {
78✔
159
                                          if (answer.empty() && def_value) {
34✔
160
                                                  answer = *def_value;
37✔
161
                                          }
24✔
162
                                          return validator(std::move(answer), dst, true);
100✔
163
                                  });
100✔
164
        }
2,842✔
165

166
        bool get_field_answer(bool ask_questions,
765✔
167
                              std::string_view label,
168
                              std::optional<std::string>& dst,
169
                              std::optional<std::string>&& opt,
170
                              std::function<bool(std::string&&,
171
                                                 std::optional<std::string>&,
172
                                                 bool)> const& validator) {
1✔
173
                return get_field_answer_impl(ask_questions, label, dst, std::move(opt),
2,296✔
174
                                             validator);
2,295✔
175
        }
1,531✔
176

177
        bool get_field_answer(bool ask_questions,
213✔
178
                              std::string_view label,
179
                              std::optional<insurance_title>& dst,
180
                              std::optional<insurance_title>&& opt,
181
                              std::function<bool(std::string&&,
182
                                                 std::optional<insurance_title>&,
183
                                                 bool)> const& validator) {
1✔
184
                return get_field_answer_impl(ask_questions, label, dst, std::move(opt),
640✔
185
                                             validator);
639✔
186
        }
427✔
187

188
        static constexpr auto magic_currency = "minimal"sv;
189
        bool get_field_answer(bool ask_questions,
213✔
190
                              std::string_view label,
191
                              std::optional<currency>& dst,
192
                              std::optional<currency>&& opt,
193
                              std::function<bool(std::string&&,
194
                                                 std::optional<currency>&,
195
                                                 bool)> const& validator) {
1✔
196
                std::function<bool(std::string&&, std::optional<currency>&, bool)> const
426✔
197
                    wrapped = [validator](std::string&& in,
853✔
198
                                          std::optional<currency>& out,
426✔
199
                                          bool ask_questions) {
1✔
200
                            if (in.starts_with(magic_currency)) {
214✔
201
                                    in = magic_currency;
298✔
202
                            }
198✔
203
                            return validator(std::move(in), out, ask_questions);
640✔
204
                    };
640✔
205
                return get_field_answer_impl(ask_questions, label, dst, std::move(opt),
640✔
206
                                             wrapped);
852✔
207
        }
640✔
208

209
        bool get_field_answer(
213✔
210
            bool ask_questions,
211
            std::string_view label,
212
            std::optional<ratio>& dst,
213
            std::optional<ratio>&& opt,
214
            std::function<bool(std::string&&, std::optional<ratio>&, bool)> const&
215
                validator) {
1✔
216
                return get_field_answer_impl(ask_questions, label, dst, std::move(opt),
640✔
217
                                             validator);
639✔
218
        }
427✔
219
}  // namespace quick_dra
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc