Compare commits

..

9 Commits

Author SHA1 Message Date
a577a3c254 Remove get for operator 2025-01-24 14:20:22 +01:00
bd5fe465a7 Better output 2025-01-24 14:20:03 +01:00
ea56f6ee0a Format 2025-01-24 14:07:33 +01:00
e0eba95ff4 Use snake_case 2025-01-24 14:06:26 +01:00
51943a5123 Use hpp 2025-01-24 14:05:10 +01:00
0014abc9c7 Add caching 2025-01-24 14:04:42 +01:00
e91759c70d Add no-pretty 2025-01-24 13:43:10 +01:00
8b0447668b Use correct number type 2025-01-24 13:37:58 +01:00
95c409ad95 catch 2025-01-24 13:06:05 +01:00
12 changed files with 187 additions and 56 deletions

View File

@ -8,9 +8,11 @@ add_executable(${PROJECT_NAME}
stringutil.hpp
stringutil.cpp
Tui.cpp
Tui.h
Command.h
Tui.hpp
Command.hpp
Command.cpp
Pager.cpp
Pager.hpp
)
target_link_libraries(${PROJECT_NAME} PRIVATE LibXml2::LibXml2 cpr::cpr)

View File

@ -6,7 +6,7 @@
// Author: Love Billenius <lovebillenius@disroot.org>
// License: GPL-3
#include "Command.h"
#include "Command.hpp"
#include <iostream>

View File

@ -48,18 +48,8 @@ void italize_numbers(std::string &content, size_t leave_chars = 0) {
}
}
void pretty_format_page(std::string &content) {
content.insert(0, ansi::BOLD);
size_t line_end = content.find('\n');
if (line_end == std::string::npos)
line_end = content.size();
content.insert(line_end, ansi::CLEAR);
italize_numbers(content, line_end + ansi::CLEAR.size());
}
Page::Page(const uint_fast8_t number): m_number(number), m_subpage(fetchSubpage()) {
Page::Page(const int number): m_number(number), m_subpage(fetchSubpage()) {
}
Page Page::operator--(int) const {
@ -77,6 +67,18 @@ Page &Page::operator-=(int) {
}
std::string Page::str_pretty() const {
std::string content = str();
content.insert(0, ansi::BOLD);
size_t line_end = content.find('\n');
if (line_end == std::string::npos)
line_end = content.size();
content.insert(line_end, ansi::CLEAR);
italize_numbers(content, line_end + ansi::CLEAR.size());
return content;
}
std::string Page::str() const {
std::string ret;
std::istringstream stream(m_subpage);
@ -84,10 +86,9 @@ std::string Page::str_pretty() const {
while (std::getline(stream, line))
ret += line + "\n";
string_utils::limitConsecutiveWhitespace(ret, MAX_WHITESPACE);
string_utils::removeTrailingWhitespace(ret);
string_utils::limit_consecutive_whitespace(ret, MAX_WHITESPACE);
string_utils::remove_trailing_whitespace(ret);
pretty_format_page(ret);
return ret;
}

View File

@ -12,17 +12,16 @@
#include <string>
#include <cstdint>
static constexpr uint_fast8_t DEFAULT_NUMBER = 100;
static constexpr uint_fast8_t MAX_WHITESPACE = 2;
static constexpr int DEFAULT_NUMBER = 100;
static constexpr int MAX_WHITESPACE = 2;
class Page
{
class Page {
private:
uint_fast8_t m_number;
int m_number;
std::string m_subpage;
public:
explicit Page(uint_fast8_t number = DEFAULT_NUMBER);
explicit Page(int number = DEFAULT_NUMBER);
Page operator--(int) const;
@ -34,6 +33,8 @@ public:
[[nodiscard]] std::string str_pretty() const;
[[nodiscard]] std::string str() const;
bool refresh();
private:

50
src/Pager.cpp Normal file
View File

@ -0,0 +1,50 @@
// _____ _ _____
// |_ _|____ _| ||_ _|_ __
// | |/ _ \ \/ / __|| | \ \ / /
// | | __/> <| |_ | | \ V /
// |_|\___/_/\_\\__||_| \_/
// Author: Love Billenius <lovebillenius@disroot.org>
// License: GPL-3
#include "Pager.hpp"
Page &Pager::seek(const int number) {
Page &page = get_page_at(number);
m_page_number = number;
return page;
}
Pager &Pager::operator+=(const int number) {
seek(m_page_number + number);
return *this;
}
Pager &Pager::operator-=(const int number) {
seek(m_page_number - number);
return *this;
}
Page &Pager::operator*() {
return get_page_at(m_page_number);
}
Page *Pager::operator->() {
return &get_page_at(m_page_number);
}
void Pager::set(const int number) {
m_page_number = number;
}
void Pager::clear() {
m_pages.clear();
}
Page &Pager::get_page_at(const int number) {
if (!m_pages.contains(number)) {
const Page p(number);
m_pages[number] = p;
}
return m_pages.at(number);
}

40
src/Pager.hpp Normal file
View File

@ -0,0 +1,40 @@
// _____ _ _____
// |_ _|____ _| ||_ _|_ __
// | |/ _ \ \/ / __|| | \ \ / /
// | | __/> <| |_ | | \ V /
// |_|\___/_/\_\\__||_| \_/
// Author: Love Billenius <lovebillenius@disroot.org>
// License: GPL-3
#pragma once
#include <unordered_map>
#include "Page.hpp"
class Pager {
public:
Pager() = default;
Page &seek(int number);
Pager &operator+=(int number);
Pager &operator-=(int number);
Page &operator*();
Page *operator->();
void set(int number);
void clear();
private:
Page &get_page_at(int number);
private:
std::unordered_map<int, Page> m_pages{};
int m_page_number = 100;
};

View File

@ -6,19 +6,19 @@
// Author: Love Billenius <lovebillenius@disroot.org>
// License: GPL-3
#include "Tui.h"
#include "Tui.hpp"
#include <iostream>
#include <optional>
#include <ostream>
#include <utility>
#include "Command.h"
#include "Command.hpp"
#include "Pager.hpp"
Tui::Tui(Page page) : m_page(std::move(page)) {
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)
@ -50,7 +50,8 @@ void printHelp() {
}
void Tui::run() {
std::cout << m_page.str_pretty() << std::endl;
clear_console();
std::cout << m_pager->str_pretty() << std::endl;
for (;;) {
std::cout << "Enter a command: ";
std::flush(std::cout);
@ -62,22 +63,34 @@ void Tui::run() {
continue;
}
bool should_exit = false;
auto visitor = [this, &should_exit]<typename T0>(T0 &&arg) {
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>) {
m_page += 1;
std::cout << m_page.str_pretty() << std::endl;
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>) {
m_page -= 1;
std::cout << m_page.str_pretty() << std::endl;
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_page.refresh();
std::cout << m_page.str_pretty() << std::endl;
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>) {
@ -85,12 +98,33 @@ void Tui::run() {
} 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;
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);
}

View File

@ -7,15 +7,19 @@
// License: GPL-3
#pragma once
#include "Page.hpp"
#include "Pager.hpp"
class Tui {
public:
Tui(Page page);
Tui(Pager pager);
void run();
private:;
static void clear_console();
private:
Page m_page;
Pager m_pager;
};

View File

@ -6,10 +6,9 @@
// Author: Love Billenius <lovebillenius@disroot.org>
// License: GPL-3
#include "Page.hpp"
#include "Tui.h"
#include "Tui.hpp"
int main(int argc, char *argv[]) {
Tui tui = Page();
Tui tui(Pager{});
tui.run();
}

View File

@ -14,28 +14,28 @@
namespace string_utils {
bool isAllWhitespace(const std::string &str) {
bool is_all_whitespace(const std::string &str) {
return std::ranges::all_of(str, [](const unsigned char c) -> bool {
return std::isspace(c);
});
}
void removeTrailingWhitespace(std::string &str) {
void remove_trailing_whitespace(std::string &str) {
auto shouldRemoveTrailingWhitespace = [&str]() -> bool {
std::size_t last_newline = str.find_last_of('\n');
if (last_newline == std::string::npos)
return isAllWhitespace(str);
return is_all_whitespace(str);
const std::string last_line = str.substr(last_newline + 1);
return isAllWhitespace(last_line);
return is_all_whitespace(last_line);
};
while (shouldRemoveTrailingWhitespace()) {
const std::size_t last_newline = str.find_last_of('\n');
if (last_newline == std::string::npos) {
if (isAllWhitespace(str))
if (is_all_whitespace(str))
str.clear();
break;
}
@ -44,11 +44,11 @@ namespace string_utils {
}
}
void removeTabs(std::string &str) {
void remove_tabs(std::string &str) {
std::erase(str, '\t');
}
void limitConsecutiveWhitespace(std::string &str, const uint_fast8_t maxWhitespace) {
void limit_consecutive_whitespace(std::string &str, const uint_fast8_t maxWhitespace) {
std::istringstream stream(str);
std::string line;
std::ostringstream processedStream;
@ -57,7 +57,7 @@ namespace string_utils {
bool hasAddedRealTextJet = false;
while (std::getline(stream, line)) {
const bool onlySpace = isAllWhitespace(line);
const bool onlySpace = is_all_whitespace(line);
if (!hasAddedRealTextJet) {
if (onlySpace)

View File

@ -23,7 +23,7 @@ namespace string_utils {
* @return true If all characters in the string are whitespace.
* @return false Otherwise.
*/
bool isAllWhitespace(const std::string& str);
bool is_all_whitespace(const std::string& str);
/**
* @brief Removes trailing whitespace lines from the given string.
@ -33,14 +33,14 @@ namespace string_utils {
*
* @param str The string from which to remove trailing whitespace lines.
*/
void removeTrailingWhitespace(std::string& str);
void remove_trailing_whitespace(std::string& str);
/**
* @brief Removes all tab characters from the given string.
*
* @param str The string from which to remove tab characters.
*/
void removeTabs(std::string& str);
void remove_tabs(std::string& str);
/**
* @brief Limits the number of consecutive whitespace lines in the given string.
@ -51,6 +51,6 @@ namespace string_utils {
* @param str The string to process.
* @param maxWhitespace The maximum allowed consecutive whitespace lines.
*/
void limitConsecutiveWhitespace(std::string& str, uint_fast8_t maxWhitespace);
void limit_consecutive_whitespace(std::string& str, uint_fast8_t maxWhitespace);
}