Compare commits
15 Commits
c09929d2f7
...
master
Author | SHA1 | Date | |
---|---|---|---|
a577a3c254 | |||
bd5fe465a7 | |||
ea56f6ee0a | |||
e0eba95ff4 | |||
51943a5123 | |||
0014abc9c7 | |||
e91759c70d | |||
8b0447668b | |||
95c409ad95 | |||
ebfda949ea | |||
984d1f3aed | |||
8710c31c1f | |||
f4eeb3d0e1 | |||
40d98cdbb6 | |||
28613af006 |
@ -7,6 +7,12 @@ add_executable(${PROJECT_NAME}
|
|||||||
Page.cpp
|
Page.cpp
|
||||||
stringutil.hpp
|
stringutil.hpp
|
||||||
stringutil.cpp
|
stringutil.cpp
|
||||||
|
Tui.cpp
|
||||||
|
Tui.hpp
|
||||||
|
Command.hpp
|
||||||
|
Command.cpp
|
||||||
|
Pager.cpp
|
||||||
|
Pager.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE LibXml2::LibXml2 cpr::cpr)
|
target_link_libraries(${PROJECT_NAME} PRIVATE LibXml2::LibXml2 cpr::cpr)
|
||||||
|
59
src/Command.cpp
Normal file
59
src/Command.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// _____ _ _____
|
||||||
|
// |_ _|____ _| ||_ _|_ __
|
||||||
|
// | |/ _ \ \/ / __|| | \ \ / /
|
||||||
|
// | | __/> <| |_ | | \ V /
|
||||||
|
// |_|\___/_/\_\\__||_| \_/
|
||||||
|
// Author: Love Billenius <lovebillenius@disroot.org>
|
||||||
|
// License: GPL-3
|
||||||
|
|
||||||
|
#include "Command.hpp"
|
||||||
|
|
||||||
|
#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{}};
|
||||||
|
}
|
||||||
|
}
|
49
src/Command.hpp
Normal file
49
src/Command.hpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// _____ _ _____
|
||||||
|
// |_ _|____ _| ||_ _|_ __
|
||||||
|
// | |/ _ \ \/ / __|| | \ \ / /
|
||||||
|
// | | __/> <| |_ | | \ V /
|
||||||
|
// |_|\___/_/\_\\__||_| \_/
|
||||||
|
// Author: Love Billenius <lovebillenius@disroot.org>
|
||||||
|
// License: GPL-3
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
46
src/Page.cpp
46
src/Page.cpp
@ -19,46 +19,37 @@
|
|||||||
#include "libxml/xpath.h"
|
#include "libxml/xpath.h"
|
||||||
|
|
||||||
|
|
||||||
bool is_number(std::string_view s){
|
bool is_number(const std::string_view s) {
|
||||||
return std::all_of(s.begin(), s.end(), [](unsigned char c ){
|
return std::ranges::all_of(s, [](const unsigned char c) {
|
||||||
return std::isdigit(c);
|
return std::isdigit(c);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void italize_numbers(std::string &content, size_t leave_chars = 0) {
|
void italize_numbers(std::string &content, size_t leave_chars = 0) {
|
||||||
size_t end = content.size();
|
size_t end = content.size();
|
||||||
|
|
||||||
// Process backwards, word by word
|
// Process backwards, word by word
|
||||||
for (;;) {
|
for (;;) {
|
||||||
size_t space = content.rfind(' ', end - 1);
|
const size_t space = content.rfind(' ', end - 1);
|
||||||
size_t begin = (space == std::string::npos) ? 0 : space + 1;
|
const size_t begin = (space == std::string::npos) ? 0 : space + 1;
|
||||||
size_t word_length = end - begin;
|
const size_t word_length = end - begin;
|
||||||
|
|
||||||
if (is_number(content.substr(begin, word_length))) {
|
if (is_number(content.substr(begin, word_length))) {
|
||||||
content.insert(end, ansi::CLEAR);
|
content.insert(end, ansi::CLEAR);
|
||||||
content.insert(begin, ansi::ITALIC);
|
content.insert(begin, ansi::ITALIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (space == std::string::npos)
|
if (space == std::string::npos)
|
||||||
break;
|
break;
|
||||||
if (leave_chars >= space)
|
if (leave_chars >= space)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
end = space;
|
end = space;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pretty_format_page(std::string &content) {
|
|
||||||
content.insert(0, ansi::BOLD);
|
|
||||||
size_t line_end = content.find("\n");
|
|
||||||
content.insert(line_end, ansi::CLEAR);
|
|
||||||
|
|
||||||
italize_numbers(content, line_end + ansi::CLEAR.size());
|
Page::Page(const int number): m_number(number), m_subpage(fetchSubpage()) {
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Page::Page(const uint_fast8_t number): m_number(number), m_subpage(fetchSubpage()) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Page Page::operator--(int) const {
|
Page Page::operator--(int) const {
|
||||||
@ -75,6 +66,18 @@ Page &Page::operator-=(int) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 Page::str() const {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
||||||
@ -83,10 +86,9 @@ std::string Page::str() const {
|
|||||||
while (std::getline(stream, line))
|
while (std::getline(stream, line))
|
||||||
ret += line + "\n";
|
ret += line + "\n";
|
||||||
|
|
||||||
string_utils::limitConsecutiveWhitespace(ret, MAX_WHITESPACE);
|
string_utils::limit_consecutive_whitespace(ret, MAX_WHITESPACE);
|
||||||
string_utils::removeTrailingWhitespace(ret);
|
string_utils::remove_trailing_whitespace(ret);
|
||||||
|
|
||||||
pretty_format_page(ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
src/Page.hpp
17
src/Page.hpp
@ -12,17 +12,16 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
static constexpr uint_fast8_t DEFAULT_NUMBER = 100;
|
static constexpr int DEFAULT_NUMBER = 100;
|
||||||
static constexpr uint_fast8_t MAX_WHITESPACE = 2;
|
static constexpr int MAX_WHITESPACE = 2;
|
||||||
|
|
||||||
class Page
|
class Page {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
uint_fast8_t m_number{};
|
int m_number;
|
||||||
std::string m_subpage;
|
std::string m_subpage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Page(uint_fast8_t number = DEFAULT_NUMBER);
|
explicit Page(int number = DEFAULT_NUMBER);
|
||||||
|
|
||||||
Page operator--(int) const;
|
Page operator--(int) const;
|
||||||
|
|
||||||
@ -32,7 +31,9 @@ public:
|
|||||||
|
|
||||||
Page &operator-=(int);
|
Page &operator-=(int);
|
||||||
|
|
||||||
std::string str() const;
|
[[nodiscard]] std::string str_pretty() const;
|
||||||
|
|
||||||
|
[[nodiscard]] std::string str() const;
|
||||||
|
|
||||||
bool refresh();
|
bool refresh();
|
||||||
|
|
||||||
@ -40,6 +41,4 @@ private:
|
|||||||
[[nodiscard]] std::string url() const;
|
[[nodiscard]] std::string url() const;
|
||||||
|
|
||||||
[[nodiscard]] std::string fetchSubpage() const;
|
[[nodiscard]] std::string fetchSubpage() const;
|
||||||
|
|
||||||
[[nodiscard]] bool contentEquals(const std::vector<std::string> &subpagesOther) const;
|
|
||||||
};
|
};
|
||||||
|
50
src/Pager.cpp
Normal file
50
src/Pager.cpp
Normal 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
40
src/Pager.hpp
Normal 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;
|
||||||
|
};
|
130
src/Tui.cpp
Normal file
130
src/Tui.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
// _____ _ _____
|
||||||
|
// |_ _|____ _| ||_ _|_ __
|
||||||
|
// | |/ _ \ \/ / __|| | \ \ / /
|
||||||
|
// | | __/> <| |_ | | \ 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);
|
||||||
|
}
|
25
src/Tui.hpp
Normal file
25
src/Tui.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// _____ _ _____
|
||||||
|
// |_ _|____ _| ||_ _|_ __
|
||||||
|
// | |/ _ \ \/ / __|| | \ \ / /
|
||||||
|
// | | __/> <| |_ | | \ V /
|
||||||
|
// |_|\___/_/\_\\__||_| \_/
|
||||||
|
// Author: Love Billenius <lovebillenius@disroot.org>
|
||||||
|
// License: GPL-3
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "Pager.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class Tui {
|
||||||
|
public:
|
||||||
|
Tui(Pager pager);
|
||||||
|
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private:;
|
||||||
|
|
||||||
|
static void clear_console();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Pager m_pager;
|
||||||
|
};
|
18
src/ansi.hpp
18
src/ansi.hpp
@ -1,11 +1,17 @@
|
|||||||
|
// _____ _ _____
|
||||||
|
// |_ _|____ _| ||_ _|_ __
|
||||||
|
// | |/ _ \ \/ / __|| | \ \ / /
|
||||||
|
// | | __/> <| |_ | | \ V /
|
||||||
|
// |_|\___/_/\_\\__||_| \_/
|
||||||
|
// Author: Love Billenius <lovebillenius@disroot.org>
|
||||||
|
// License: GPL-3
|
||||||
|
|
||||||
namespace ansi
|
#pragma once
|
||||||
{
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
constexpr std::string_view BOLD = "\033[1m";
|
namespace ansi {
|
||||||
constexpr std::string_view ITALIC = "\033[3m";
|
constexpr std::string_view BOLD = "\033[1m";
|
||||||
constexpr std::string_view CLEAR = "\033[0m";
|
constexpr std::string_view ITALIC = "\033[3m";
|
||||||
|
constexpr std::string_view CLEAR = "\033[0m";
|
||||||
} // namespace ansi
|
} // namespace ansi
|
||||||
|
14
src/main.cpp
14
src/main.cpp
@ -1,8 +1,14 @@
|
|||||||
#include <iostream>
|
// _____ _ _____
|
||||||
|
// |_ _|____ _| ||_ _|_ __
|
||||||
|
// | |/ _ \ \/ / __|| | \ \ / /
|
||||||
|
// | | __/> <| |_ | | \ V /
|
||||||
|
// |_|\___/_/\_\\__||_| \_/
|
||||||
|
// Author: Love Billenius <lovebillenius@disroot.org>
|
||||||
|
// License: GPL-3
|
||||||
|
|
||||||
#include "Page.hpp"
|
#include "Tui.hpp"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
const auto page = Page();
|
Tui tui(Pager{});
|
||||||
std::cout << page.str() << std::endl;
|
tui.run();
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
// _____ _ _____
|
||||||
|
// |_ _|____ _| ||_ _|_ __
|
||||||
|
// | |/ _ \ \/ / __|| | \ \ / /
|
||||||
|
// | | __/> <| |_ | | \ V /
|
||||||
|
// |_|\___/_/\_\\__||_| \_/
|
||||||
|
// Author: Love Billenius <lovebillenius@disroot.org>
|
||||||
|
// License: GPL-3
|
||||||
|
|
||||||
#include "stringutil.hpp"
|
#include "stringutil.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -6,28 +14,28 @@
|
|||||||
|
|
||||||
|
|
||||||
namespace string_utils {
|
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::ranges::all_of(str, [](const unsigned char c) -> bool {
|
||||||
return std::isspace(c);
|
return std::isspace(c);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeTrailingWhitespace(std::string &str) {
|
void remove_trailing_whitespace(std::string &str) {
|
||||||
auto shouldRemoveTrailingWhitespace = [&str]() -> bool {
|
auto shouldRemoveTrailingWhitespace = [&str]() -> bool {
|
||||||
std::size_t last_newline = str.find_last_of('\n');
|
std::size_t last_newline = str.find_last_of('\n');
|
||||||
|
|
||||||
if (last_newline == std::string::npos)
|
if (last_newline == std::string::npos)
|
||||||
return isAllWhitespace(str);
|
return is_all_whitespace(str);
|
||||||
|
|
||||||
const std::string last_line = str.substr(last_newline + 1);
|
const std::string last_line = str.substr(last_newline + 1);
|
||||||
return isAllWhitespace(last_line);
|
return is_all_whitespace(last_line);
|
||||||
};
|
};
|
||||||
|
|
||||||
while (shouldRemoveTrailingWhitespace()) {
|
while (shouldRemoveTrailingWhitespace()) {
|
||||||
const std::size_t last_newline = str.find_last_of('\n');
|
const std::size_t last_newline = str.find_last_of('\n');
|
||||||
|
|
||||||
if (last_newline == std::string::npos) {
|
if (last_newline == std::string::npos) {
|
||||||
if (isAllWhitespace(str))
|
if (is_all_whitespace(str))
|
||||||
str.clear();
|
str.clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -36,11 +44,11 @@ namespace string_utils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeTabs(std::string &str) {
|
void remove_tabs(std::string &str) {
|
||||||
std::erase(str, '\t');
|
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::istringstream stream(str);
|
||||||
std::string line;
|
std::string line;
|
||||||
std::ostringstream processedStream;
|
std::ostringstream processedStream;
|
||||||
@ -49,7 +57,7 @@ namespace string_utils {
|
|||||||
bool hasAddedRealTextJet = false;
|
bool hasAddedRealTextJet = false;
|
||||||
|
|
||||||
while (std::getline(stream, line)) {
|
while (std::getline(stream, line)) {
|
||||||
const bool onlySpace = isAllWhitespace(line);
|
const bool onlySpace = is_all_whitespace(line);
|
||||||
|
|
||||||
if (!hasAddedRealTextJet) {
|
if (!hasAddedRealTextJet) {
|
||||||
if (onlySpace)
|
if (onlySpace)
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
// _____ _ _____
|
||||||
|
// |_ _|____ _| ||_ _|_ __
|
||||||
|
// | |/ _ \ \/ / __|| | \ \ / /
|
||||||
|
// | | __/> <| |_ | | \ V /
|
||||||
|
// |_|\___/_/\_\\__||_| \_/
|
||||||
|
// Author: Love Billenius <lovebillenius@disroot.org>
|
||||||
|
// License: GPL-3
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -15,7 +23,7 @@ namespace string_utils {
|
|||||||
* @return true If all characters in the string are whitespace.
|
* @return true If all characters in the string are whitespace.
|
||||||
* @return false Otherwise.
|
* @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.
|
* @brief Removes trailing whitespace lines from the given string.
|
||||||
@ -25,14 +33,14 @@ namespace string_utils {
|
|||||||
*
|
*
|
||||||
* @param str The string from which to remove trailing whitespace lines.
|
* @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.
|
* @brief Removes all tab characters from the given string.
|
||||||
*
|
*
|
||||||
* @param str The string from which to remove tab characters.
|
* @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.
|
* @brief Limits the number of consecutive whitespace lines in the given string.
|
||||||
@ -43,6 +51,6 @@ namespace string_utils {
|
|||||||
* @param str The string to process.
|
* @param str The string to process.
|
||||||
* @param maxWhitespace The maximum allowed consecutive whitespace lines.
|
* @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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user