Stop the application on EOF

This commit is contained in:
Alexander Kobjolke 2023-04-18 22:15:40 +02:00
parent 0d42589648
commit 342c6069a2

View file

@ -6,25 +6,28 @@
#include <variant> #include <variant>
#include <thread> #include <thread>
#include <sstream> #include <sstream>
#include <optional>
using namespace std::chrono_literals; using namespace std::chrono_literals;
template <typename Message> struct ConsoleIO { template <typename Message> struct ConsoleIO {
static auto ReadlineS(std::istream& is, std::function<Message(std::string)> f) { static auto ReadlineS(std::istream& is, std::function<Message(std::optional<std::string>)> f) {
return [=,&is] { return [=,&is] {
std::string line; if (std::string line; std::getline(is, line)) {
std::getline(is, line); return f(std::make_optional(line));
return f(line); } else {
return f(std::nullopt);
}
}; };
} }
static std::function<Message()> static std::function<Message()>
Readline(std::function<Message(std::string)> f) { Readline(std::function<Message(std::optional<std::string>)> f) {
return ReadlineS (std::ref(std::cin), f); return ReadlineS (std::ref(std::cin), f);
} }
static std::function<Message()> static std::function<Message()>
Prompt(std::string prompt, std::function<Message(std::string)> f) { Prompt(std::string prompt, std::function<Message(std::optional<std::string>)> f) {
return [=] { return [=] {
std::cout << prompt << std::flush; std::cout << prompt << std::flush;
return Readline (f)(); return Readline (f)();
@ -79,36 +82,53 @@ template <typename ModelT, typename MessageT> struct AppT {
// user defined // user defined
using Model = int; struct Model {
bool done{false};
struct SetState { int value{0};
Model s;
}; };
using Message = std::variant<SetState>; struct SetValue {
int s;
};
struct Stop {
};
using Message = std::variant<SetValue, Stop>;
auto userInputToMsg(const std::optional<std::string>& s) -> Message {
if (s) {
std::stringstream sstr(*s);
int r;
sstr >> r;
return SetValue { r };
} else {
return Stop{};
}
auto strToState (const std::string& s) -> Message {
std::stringstream sstr(s);
int r;
sstr >> r;
return SetState { r };
} }
int main() { int main() {
using App = AppT<int, Message>; using App = AppT<Model, Message>;
App app; App app;
return app.run(App::Config{ return app.run(App::Config{
[]() -> App::InitResult { []() -> App::InitResult {
return {23, {App::Console::Prompt("> ", strToState)}}; return {{false, 23}, {App::Console::Prompt("> ", userInputToMsg)}};
}, // init }, // init
[](const App::Model &state, [](App::Model state,
const App::Message &msg) -> App::UpdateResult { const App::Message &msg) -> App::UpdateResult {
return {std::get<SetState>(msg).s, if (auto stop = std::get_if<Stop>(&msg); stop) {
{App::Console::Prompt("> ", strToState)}}; state.done = true;
return {state, {}};
} else {
state.value = std::get<SetValue>(msg).s;
return {state, {App::Console::Prompt("> ", userInputToMsg)}};
}
}, // update }, // update
[](const App::Model &state) -> App::ViewResult { [](const App::Model &state) -> App::ViewResult {
return "Model " + std::to_string(state); return "Model " + std::to_string(state.value);
}, // view }, // view
[](const App::Model &state) -> bool { return state == 42; } // done [](const App::Model &state) -> bool { return state.done; } // done
}); });
} }