Command done
This commit is contained in:
parent
28613af006
commit
40d98cdbb6
@ -7,6 +7,10 @@ add_executable(${PROJECT_NAME}
|
||||
Page.cpp
|
||||
stringutil.hpp
|
||||
stringutil.cpp
|
||||
Tui.cpp
|
||||
Tui.h
|
||||
Command.h
|
||||
Command.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE LibXml2::LibXml2 cpr::cpr)
|
||||
|
51
src/Command.cpp
Normal file
51
src/Command.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "Command.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace Command {
|
||||
Command readCommand() {
|
||||
if (!std::cin)
|
||||
return {Exit{}};
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line))
|
||||
return {Exit{}};
|
||||
|
||||
// Trim leading and trailing whitespaces
|
||||
constexpr std::string_view TO_TRIM = " \t\n\r";
|
||||
const size_t start = line.find_first_not_of(TO_TRIM);
|
||||
const size_t end = line.find_last_not_of(TO_TRIM);
|
||||
if (start == std::string::npos) return None{};
|
||||
const std::string_view line_trimmed(line.data() + start, end - start + 1);
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
if (line_trimmed == "r"sv || line_trimmed == "refresh"sv)
|
||||
return Refresh{};
|
||||
if (line_trimmed == "n"sv || line_trimmed == ">"sv || line_trimmed == "next"sv)
|
||||
return Next{};
|
||||
if (line_trimmed == "p"sv || line_trimmed == "<"sv || line_trimmed == "previous"sv)
|
||||
return Previous{};
|
||||
if (line_trimmed == "x"sv || line_trimmed == "exit"sv || line_trimmed == "q"sv || line_trimmed == "quit"sv)
|
||||
return Exit{};
|
||||
if (line_trimmed == "help"sv || line_trimmed == "?"sv || line_trimmed == "?"sv)
|
||||
return Help{};
|
||||
|
||||
if (line_trimmed.starts_with("seek") || line.starts_with("s ")) {
|
||||
const size_t space = line_trimmed.find(' ');
|
||||
if (space == std::string::npos)
|
||||
throw NoNumberException();
|
||||
int number = 0;
|
||||
const size_t size = line.size();
|
||||
for (size_t i = space + 1; i < size; ++i) {
|
||||
const char c = line_trimmed[i];
|
||||
if (!std::isdigit(c))
|
||||
throw NoNumberException();
|
||||
number = number * 10 + (c - '0');
|
||||
}
|
||||
|
||||
return {Seek{number}};
|
||||
}
|
||||
|
||||
return {None{}};
|
||||
}
|
||||
}
|
41
src/Command.h
Normal file
41
src/Command.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
|
||||
namespace Command {
|
||||
class NoNumberException final : public std::exception {
|
||||
public:
|
||||
[[nodiscard]] const char *what() const noexcept override {
|
||||
return "Seek option was used without a number";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Help {
|
||||
};
|
||||
|
||||
struct None {
|
||||
};
|
||||
|
||||
struct Next {
|
||||
};
|
||||
|
||||
struct Previous {
|
||||
};
|
||||
|
||||
struct Refresh {
|
||||
};
|
||||
|
||||
struct Exit {
|
||||
};
|
||||
|
||||
struct Seek {
|
||||
int number;
|
||||
};
|
||||
|
||||
using Command = std::variant<None, Help, Next, Previous, Refresh, Exit, Seek>;
|
||||
|
||||
Command readCommand();
|
||||
}
|
@ -74,7 +74,7 @@ Page &Page::operator-=(int) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string Page::str() const {
|
||||
std::string Page::str_pretty() const {
|
||||
std::string ret;
|
||||
|
||||
std::istringstream stream(m_subpage);
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
|
||||
Page &operator-=(int);
|
||||
|
||||
[[nodiscard]] std::string str() const;
|
||||
[[nodiscard]] std::string str_pretty() const;
|
||||
|
||||
bool refresh();
|
||||
|
||||
|
81
src/Tui.cpp
Normal file
81
src/Tui.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "Tui.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <utility>
|
||||
|
||||
#include "Command.h"
|
||||
|
||||
Tui::Tui(Page page) : m_page(std::move(page)) {
|
||||
}
|
||||
|
||||
|
||||
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() {
|
||||
std::cout << m_page.str_pretty() << std::endl;
|
||||
for (;;) {
|
||||
std::cout << "Enter a command: ";
|
||||
std::flush(std::cout);
|
||||
const Command::Command command = Command::readCommand();
|
||||
|
||||
bool should_exit = false;
|
||||
auto visitor = [this, &should_exit]<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>) {
|
||||
m_page += 1;
|
||||
std::cout << m_page.str_pretty() << std::endl;
|
||||
} else if constexpr (std::is_same_v<T, Command::Previous>) {
|
||||
m_page -= 1;
|
||||
std::cout << m_page.str_pretty() << std::endl;
|
||||
} else if constexpr (std::is_same_v<T, Command::Refresh>) {
|
||||
m_page.refresh();
|
||||
std::cout << m_page.str_pretty() << std::endl;
|
||||
} 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;
|
||||
m_page = Page(number);
|
||||
std::cout << m_page.str_pretty() << std::endl;
|
||||
}
|
||||
};
|
||||
std::visit(visitor, command);
|
||||
if (should_exit)
|
||||
return;
|
||||
}
|
||||
}
|
13
src/Tui.h
Normal file
13
src/Tui.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "Page.hpp"
|
||||
|
||||
|
||||
class Tui {
|
||||
public:
|
||||
Tui(Page page);
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
Page m_page;
|
||||
};
|
@ -1,8 +1,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "Page.hpp"
|
||||
#include "Tui.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
const auto page = Page();
|
||||
std::cout << page.str() << std::endl;
|
||||
Tui tui = Page();
|
||||
tui.run();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user