Fixes for fmt
This commit is contained in:
parent
b440c81474
commit
5b402e48dd
6 changed files with 0 additions and 209 deletions
|
@ -48,7 +48,6 @@ CPMAddPackage(
|
||||||
URL
|
URL
|
||||||
"https://github.com/linuxnyasha/fmt_import/archive/refs/heads/linuxnyasha-patch-1.zip"
|
"https://github.com/linuxnyasha/fmt_import/archive/refs/heads/linuxnyasha-patch-1.zip"
|
||||||
# Fixes for fmt module and constexpr fmt::formatted_size
|
# Fixes for fmt module and constexpr fmt::formatted_size
|
||||||
OPTIONS "CMAKE_CXX_FLAGS -DFMT_ATTACH_TO_GLOBAL_MODULE"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(CPM_USE_LOCAL_PACKAGES ${TMP})
|
set(CPM_USE_LOCAL_PACKAGES ${TMP})
|
||||||
|
@ -98,7 +97,6 @@ endif()
|
||||||
if(BUILD_STATIC_LIBS)
|
if(BUILD_STATIC_LIBS)
|
||||||
add_library(utempl_static)
|
add_library(utempl_static)
|
||||||
if(NOT BUILD_SHARED_LIBS)
|
if(NOT BUILD_SHARED_LIBS)
|
||||||
add_library(utempl ALIAS utempl_static)
|
|
||||||
add_library(utempl::utempl ALIAS utempl_static)
|
add_library(utempl::utempl ALIAS utempl_static)
|
||||||
endif()
|
endif()
|
||||||
configure(utempl_static)
|
configure(utempl_static)
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import utempl;
|
|
||||||
import std;
|
|
||||||
|
|
||||||
auto main() -> int {
|
|
||||||
utempl::menu::Menu{}
|
|
||||||
.With<{"This is 0"}>([] {
|
|
||||||
std::cout << "You entered 0" << std::endl;
|
|
||||||
})
|
|
||||||
.With<{"Some Long", "S"}>([] {
|
|
||||||
std::cout << "It aligns the output to the longest element" << std::endl;
|
|
||||||
})
|
|
||||||
.Run<"[{0}]{2} - |{1}|\n">();
|
|
||||||
};
|
|
|
@ -1,25 +1,7 @@
|
||||||
module;
|
|
||||||
#include <fmt/compile.h>
|
|
||||||
export module utempl.string;
|
export module utempl.string;
|
||||||
import std;
|
import std;
|
||||||
// import fmt;
|
// import fmt;
|
||||||
|
|
||||||
namespace utempl {
|
|
||||||
export template <std::size_t>
|
|
||||||
struct ConstexprString;
|
|
||||||
} // namespace utempl
|
|
||||||
|
|
||||||
export {
|
|
||||||
template <std::size_t Size>
|
|
||||||
struct fmt::formatter<utempl::ConstexprString<Size>> : public fmt::formatter<std::string_view> {
|
|
||||||
constexpr auto parse(format_parse_context& ctx) const {
|
|
||||||
return ctx.begin();
|
|
||||||
};
|
|
||||||
constexpr auto format(const utempl::ConstexprString<Size>& str, auto& ctx) const {
|
|
||||||
return fmt::formatter<std::string_view>::format({str.begin()}, ctx);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
export namespace utempl {
|
export namespace utempl {
|
||||||
|
|
||||||
template <std::size_t Size>
|
template <std::size_t Size>
|
||||||
|
@ -77,11 +59,6 @@ struct ConstexprString {
|
||||||
constexpr ConstexprString(ConstexprString&&) = default;
|
constexpr ConstexprString(ConstexprString&&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <ConstexprString Str>
|
|
||||||
consteval auto GetFmtCompiledString() {
|
|
||||||
return FMT_COMPILE(Str.data.begin());
|
|
||||||
};
|
|
||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
constexpr auto operator<<(std::ostream& stream, const ConstexprString<N>& str) -> std::ostream& {
|
constexpr auto operator<<(std::ostream& stream, const ConstexprString<N>& str) -> std::ostream& {
|
||||||
stream << static_cast<std::string_view>(str);
|
stream << static_cast<std::string_view>(str);
|
||||||
|
|
147
src/menu.cpp
147
src/menu.cpp
|
@ -1,147 +0,0 @@
|
||||||
module;
|
|
||||||
#include <cstdio>
|
|
||||||
export module utempl.menu;
|
|
||||||
|
|
||||||
import fmt;
|
|
||||||
import std;
|
|
||||||
import utempl.string;
|
|
||||||
import utempl.optional;
|
|
||||||
import utempl.tuple;
|
|
||||||
import utempl.utils;
|
|
||||||
import utempl.type_list;
|
|
||||||
|
|
||||||
namespace utempl {
|
|
||||||
|
|
||||||
constexpr auto CountDigits(std::size_t num) -> std::size_t {
|
|
||||||
std::size_t count = 0;
|
|
||||||
do { // NOLINT
|
|
||||||
++count;
|
|
||||||
num /= 10; // NOLINT
|
|
||||||
} while(num != 0);
|
|
||||||
return count;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr auto GetDigit(std::size_t num, std::size_t index) -> std::size_t {
|
|
||||||
for(std::size_t i = 0; i < index; ++i) {
|
|
||||||
num /= 10; // NOLINT
|
|
||||||
}
|
|
||||||
return num % 10; // NOLINT
|
|
||||||
};
|
|
||||||
|
|
||||||
template <std::size_t num>
|
|
||||||
consteval auto ToString() {
|
|
||||||
constexpr std::size_t digits = CountDigits(num);
|
|
||||||
return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
|
|
||||||
return ConstexprString{std::array{static_cast<char>('0' + GetDigit(num, digits - 1 - Is))..., '\0'}};
|
|
||||||
}(std::make_index_sequence<digits>());
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Range>
|
|
||||||
constexpr auto GetMax(Range&& range) {
|
|
||||||
std::remove_cvref_t<decltype(range[0])> response = 0;
|
|
||||||
for(const auto& element : range) {
|
|
||||||
response = element > response ? element : response;
|
|
||||||
};
|
|
||||||
return response;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace menu {
|
|
||||||
|
|
||||||
template <std::size_t N1, std::size_t N2>
|
|
||||||
struct CallbackMessage {
|
|
||||||
ConstexprString<N1> message;
|
|
||||||
Optional<ConstexprString<N2>> need;
|
|
||||||
consteval CallbackMessage(const char (&need)[N2], const char (&message)[N1]) : // NOLINT
|
|
||||||
message(std::move(message)), need(std::move(need)) {};
|
|
||||||
consteval CallbackMessage(const char (&message)[N1]) : message(std::move(message)), need(std::nullopt) {}; // NOLINT
|
|
||||||
};
|
|
||||||
template <std::size_t N1, std::size_t N2>
|
|
||||||
CallbackMessage(const char (&)[N1], const char (&)[N2]) -> CallbackMessage<N2, N1>; // NOLINT
|
|
||||||
|
|
||||||
template <std::size_t N1>
|
|
||||||
CallbackMessage(const char (&)[N1]) -> CallbackMessage<N1, 0>; // NOLINT
|
|
||||||
|
|
||||||
export template <Tuple storage = Tuple{}, typename... Fs>
|
|
||||||
struct Menu {
|
|
||||||
private:
|
|
||||||
template <ConstexprString fmt, ConstexprString message, ConstexprString alignment, ConstexprString neededInput>
|
|
||||||
static consteval auto FormatMessage() {
|
|
||||||
constexpr auto fmtlib = GetFmtCompiledString<fmt>();
|
|
||||||
// + 1 - NULL Terminator
|
|
||||||
constexpr auto size = fmt::formatted_size(fmtlib,
|
|
||||||
static_cast<std::string_view>(neededInput),
|
|
||||||
static_cast<std::string_view>(message),
|
|
||||||
static_cast<std::string_view>(alignment)) +
|
|
||||||
1;
|
|
||||||
std::array<char, size> data{};
|
|
||||||
fmt::format_to(data.begin(),
|
|
||||||
fmtlib,
|
|
||||||
static_cast<std::string_view>(neededInput),
|
|
||||||
static_cast<std::string_view>(message),
|
|
||||||
static_cast<std::string_view>(alignment));
|
|
||||||
return ConstexprString<size>(data);
|
|
||||||
};
|
|
||||||
template <ConstexprString fmt, std::size_t I>
|
|
||||||
static consteval auto FormatMessageFor() {
|
|
||||||
constexpr ConstexprString message = Get<I>(storage).message;
|
|
||||||
constexpr ConstexprString neededInput = [&] {
|
|
||||||
if constexpr(Get<I>(storage).need) {
|
|
||||||
return *Get<I>(storage).need;
|
|
||||||
} else {
|
|
||||||
return ToString<I>();
|
|
||||||
};
|
|
||||||
}();
|
|
||||||
constexpr ConstexprString alignment =
|
|
||||||
CreateStringWith<GetMaxSize() - (Get<I>(storage).need ? Get<I>(storage).need->size() : CountDigits(I))>(' ');
|
|
||||||
return FormatMessage<fmt, message, alignment, neededInput>();
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
Tuple<Fs...> functionStorage;
|
|
||||||
|
|
||||||
static consteval auto GetMaxSize() -> std::size_t {
|
|
||||||
return [&]<auto... Is>(std::index_sequence<Is...>) {
|
|
||||||
constexpr auto list = ListFromTuple(storage);
|
|
||||||
return GetMax(std::array{(std::remove_cvref_t<decltype(*std::declval<decltype(Get<Is>(list))>().need)>::kSize != 0
|
|
||||||
? std::remove_cvref_t<decltype(*std::declval<decltype(Get<Is>(list))>().need)>::kSize
|
|
||||||
: CountDigits(Is))...});
|
|
||||||
}(std::index_sequence_for<Fs...>());
|
|
||||||
};
|
|
||||||
template <CallbackMessage message, std::invocable F>
|
|
||||||
constexpr auto With(F&& f) const {
|
|
||||||
return Menu<storage + Tuple{message}, Fs..., std::remove_cvref_t<F>>{.functionStorage =
|
|
||||||
this->functionStorage + Tuple(std::forward<F>(f))};
|
|
||||||
};
|
|
||||||
template <ConstexprString fmt, ConstexprString enter = "|> ">
|
|
||||||
constexpr auto Run(std::istream& in = std::cin, std::FILE* out = stdout) const -> std::size_t {
|
|
||||||
return [&]<auto... Is>(std::index_sequence<Is...>) -> std::size_t {
|
|
||||||
constexpr auto message = ((FormatMessageFor<fmt, Is>() + ...) + enter);
|
|
||||||
auto result = std::fwrite(message.begin(), 1, message.size(), out);
|
|
||||||
if(result < message.size()) {
|
|
||||||
return EOF;
|
|
||||||
};
|
|
||||||
if(std::fflush(out) != 0) {
|
|
||||||
return EOF;
|
|
||||||
};
|
|
||||||
std::string input;
|
|
||||||
std::getline(in, input);
|
|
||||||
(
|
|
||||||
[&]<auto I, CallbackMessage message = Get<I>(storage)>(Wrapper<I>) {
|
|
||||||
if constexpr(message.need) {
|
|
||||||
if(*message.need == input) {
|
|
||||||
Get<I>(this->functionStorage)();
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
if(ToString<I>() == input) {
|
|
||||||
Get<I>(this->functionStorage)();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}(Wrapper<Is>{}),
|
|
||||||
...);
|
|
||||||
return 0;
|
|
||||||
}(std::index_sequence_for<Fs...>());
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace menu
|
|
||||||
} // namespace utempl
|
|
|
@ -2,7 +2,6 @@ export module utempl;
|
||||||
export import utempl.type_list;
|
export import utempl.type_list;
|
||||||
export import utempl.tuple;
|
export import utempl.tuple;
|
||||||
export import utempl.string;
|
export import utempl.string;
|
||||||
export import utempl.menu;
|
|
||||||
export import utempl.loopholes;
|
export import utempl.loopholes;
|
||||||
export import utempl.attributes;
|
export import utempl.attributes;
|
||||||
export import utempl.meta_info;
|
export import utempl.meta_info;
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
module;
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
export module tests.menu;
|
|
||||||
import utempl;
|
|
||||||
|
|
||||||
namespace utempl {
|
|
||||||
|
|
||||||
TEST(Menu, Basic) {
|
|
||||||
testing::internal::CaptureStdout();
|
|
||||||
std::istringstream stream("t\n");
|
|
||||||
int value = 0;
|
|
||||||
menu::Menu{}
|
|
||||||
.With<{"t", "This is t"}>([&] {
|
|
||||||
std::cout << "Success!" << std::endl;
|
|
||||||
value = 1;
|
|
||||||
})
|
|
||||||
.Run<"[{0}]{2} - ({1})\n">(stream);
|
|
||||||
auto captured = testing::internal::GetCapturedStdout();
|
|
||||||
EXPECT_EQ(captured, "[t] - (This is t)\n|> Success!\n");
|
|
||||||
EXPECT_EQ(value, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace utempl
|
|
Loading…
Reference in a new issue