txtv/src/Tui.cpp
2025-01-24 14:20:03 +01:00

131 lines
4.0 KiB
C++

// _____ _ _____
// |_ _|____ _| ||_ _|_ __
// | |/ _ \ \/ / __|| | \ \ / /
// | | __/> <| |_ | | \ V /
// |_|\___/_/\_\\__||_| \_/
// Author: Love Billenius <lovebillenius@disroot.org>
// License: GPL-3
#include "Tui.hpp"
#include <iostream>
#include <optional>
#include <ostream>
#include <utility>
#include "Command.hpp"
#include "Pager.hpp"
Tui::Tui(Pager pager) : m_pager(std::move(pager)) {
}
std::optional<int> get_page_number(const std::string_view line) {
const size_t space = line.find_first_of(' ');
if (space == std::string::npos)
return std::nullopt;
int number = 0;
const size_t size = line.size();
for (size_t i = space; i < size; i++) {
const char c = line[i];
if (!std::isdigit(c))
return std::nullopt;
number = number * 10 + (c - '0');
}
return number;
}
void printHelp() {
std::cout
<< "Available Commands:\n"
<< " r, refresh : Refresh the current view.\n"
<< " n, >, next : Move to the next item.\n"
<< " p, <, previous : Move to the previous item.\n"
<< " x, exit, q, quit : Exit the application.\n"
<< " seek <number>, s <number> : Seek to the specified number.\n"
<< " help, h, ? : Display this help message."
<< std::endl;
}
void Tui::run() {
clear_console();
std::cout << m_pager->str_pretty() << std::endl;
for (;;) {
std::cout << "Enter a command: ";
std::flush(std::cout);
Command::Command command;
try {
command = Command::readCommand();
} catch (const Command::NoNumberException &e) {
std::cout << e.what() << std::endl;
continue;
}
bool should_exit = false;
bool should_output = false;
auto visitor = [this, &should_exit, &should_output]<typename T0>(T0 &&arg) {
using T = std::decay_t<T0>;
if constexpr (std::is_same_v<T, Command::None>) {
std::cout << "Invalid command!" << std::endl;
} else if constexpr (std::is_same_v<T, Command::Next>) {
try {
std::cout << "Fetching..." << std::endl;
m_pager += 1;
} catch (const std::runtime_error &e) {
std::cout << e.what() << std::endl;
return;
}
should_output = true;
} else if constexpr (std::is_same_v<T, Command::Previous>) {
try {
std::cout << "Fetching..." << std::endl;
m_pager -= 1;
} catch (const std::runtime_error &e) {
std::cout << e.what() << std::endl;
return;
}
should_output = true;
} else if constexpr (std::is_same_v<T, Command::Refresh>) {
m_pager.clear();
should_output = true;
} else if constexpr (std::is_same_v<T, Command::Exit>) {
should_exit = true;
} else if constexpr (std::is_same_v<T, Command::Help>) {
printHelp();
} else if constexpr (std::is_same_v<T, Command::Seek>) {
const Command::Seek &seek = arg;
const int number = seek.number;
try {
std::cout << "Fetching..." << std::endl;
m_pager.seek(number);
} catch (const std::runtime_error &e) {
std::cout << e.what() << std::endl;
return;
}
should_output = true;
}
};
std::visit(visitor, command);
if (should_exit)
return;
clear_console();
if (should_output)
std::cout << m_pager->str_pretty() << std::endl;
}
}
void Tui::clear_console() {
const auto CMD =
#ifdef _WIN32 || _WIN64
"cls";
#else
"clear";
#endif
system(CMD);
}