Command done
This commit is contained in:
		@@ -7,6 +7,10 @@ add_executable(${PROJECT_NAME}
 | 
				
			|||||||
        Page.cpp
 | 
					        Page.cpp
 | 
				
			||||||
        stringutil.hpp
 | 
					        stringutil.hpp
 | 
				
			||||||
        stringutil.cpp
 | 
					        stringutil.cpp
 | 
				
			||||||
 | 
					        Tui.cpp
 | 
				
			||||||
 | 
					        Tui.h
 | 
				
			||||||
 | 
					        Command.h
 | 
				
			||||||
 | 
					        Command.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(${PROJECT_NAME} PRIVATE LibXml2::LibXml2 cpr::cpr)
 | 
					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;
 | 
					    return *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::string Page::str() const {
 | 
					std::string Page::str_pretty() const {
 | 
				
			||||||
    std::string ret;
 | 
					    std::string ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::istringstream stream(m_subpage);
 | 
					    std::istringstream stream(m_subpage);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Page &operator-=(int);
 | 
					    Page &operator-=(int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [[nodiscard]] std::string str() const;
 | 
					    [[nodiscard]] std::string str_pretty() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool refresh();
 | 
					    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 "Page.hpp"
 | 
				
			||||||
 | 
					#include "Tui.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char *argv[]) {
 | 
					int main(int argc, char *argv[]) {
 | 
				
			||||||
    const auto page = Page();
 | 
					    Tui tui = Page();
 | 
				
			||||||
    std::cout << page.str() << std::endl;
 | 
					    tui.run();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user