summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdwin van Leeuwen <edwinvanl@tuta.io>2022-06-18 12:41:40 +0100
committerEdwin van Leeuwen <edwinvanl@tuta.io>2022-06-18 12:41:40 +0100
commitc5b87af882a6e8ecff61d97882c73c94adb114d3 (patch)
tree9194e4ccb1e35f6559fe7584c13b64722d20eab3
parent21b9d2a9a35551229af05e43bd6895a3441094ed (diff)
parent69cca38f7e467fff8df9ab79da249acac49c56b2 (diff)
Merge branch 'release/1.0.0'v1.0.0
-rw-r--r--.gitignore6
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--CMakeLists.txt56
-rw-r--r--README.md4
-rw-r--r--TODO.md5
-rw-r--r--aur/PKGBUILD6
-rw-r--r--src/item.hpp250
-rw-r--r--src/logger.hpp45
-rw-r--r--src/main.cpp872
-rw-r--r--src/rttt.hpp48
-rw-r--r--src/rttt/config.hpp (renamed from src/config.hpp)5
-rw-r--r--src/rttt/future.hpp (renamed from src/future.hpp)13
-rw-r--r--src/rttt/hackernews.hpp (renamed from src/hackernews.hpp)194
-rw-r--r--src/rttt/item.hpp206
-rw-r--r--src/rttt/logger.hpp75
-rw-r--r--src/rttt/prompt.hpp (renamed from src/prompt.hpp)55
-rw-r--r--src/rttt/reddit.hpp (renamed from src/reddit.hpp)215
-rw-r--r--src/rttt/request.hpp (renamed from src/request.hpp)16
-rw-r--r--src/rttt/rss.hpp (renamed from src/rss.hpp)98
-rw-r--r--src/rttt/socket.hpp (renamed from src/socket.hpp)9
-rw-r--r--src/rttt/storage.hpp (renamed from src/storage.hpp)17
-rw-r--r--src/rttt/text.hpp101
-rw-r--r--src/rttt/thing.hpp184
-rw-r--r--src/rttt/twitter.hpp467
-rw-r--r--src/rttt/ui_ftxui.hpp360
-rw-r--r--src/rttt/view.hpp (renamed from src/view.hpp)38
-rw-r--r--src/ui.hpp563
-rw-r--r--test/catch_future.cpp4
-rw-r--r--test/catch_hackernews.cpp163
-rw-r--r--test/catch_item.cpp10
-rw-r--r--test/catch_login.cpp59
-rw-r--r--test/catch_prompt.cpp2
-rw-r--r--test/catch_reddit.cpp5
-rw-r--r--test/catch_rss.cpp10
-rw-r--r--test/catch_rttt.cpp8
-rw-r--r--test/catch_storage.cpp14
-rw-r--r--test/catch_text.cpp65
-rw-r--r--test/catch_thing.cpp18
-rw-r--r--test/catch_twitter.cpp170
-rw-r--r--test/catch_ui.cpp20
-rw-r--r--test/catch_view.cpp45
-rw-r--r--test/include/rttt/fake_thing.hpp31
-rw-r--r--test/source_skeleton.hpp36
-rw-r--r--test/tweets_by_user.json1
-rw-r--r--test/tweets_conversation.json1
45 files changed, 2823 insertions, 1749 deletions
diff --git a/.gitignore b/.gitignore
index bfbd9c7..3c8bee4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,3 +26,9 @@ install_manifest.txt
login_credentials.hpp
aur/*/
+
+CPackConfig.cmake
+CPackSourceConfig.cmake
+analysis.svg
+analysis.txt
+gmon.out \ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f47fae7..9f753b7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -13,7 +13,7 @@ build:arch:
image: testcab/yay
stage: build
script:
- - yay -Sy --noconfirm cmake git cpr nlohmann-json pugixml
+ - yay -Syu --noconfirm cmake git cpr nlohmann-json pugixml fmt
- cd aur
# If this does not work, then try CI_COMMIT_REF_SLUG
- echo $CI_COMMIT_REF_NAME
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6b9914d..d664a74 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,12 +46,32 @@ if (NOT nlohmann_json_FOUND)
endif()
endif()
-# Build imtui as a static lib.
-set(BUILD_SHARED_LIBS OFF)
-FetchContent_Declare(imtui
- GIT_REPOSITORY https://github.com/ggerganov/imtui
- GIT_TAG "aa55479de6ea4d3bc0f730aaf91e20c299b61742")
-FetchContent_MakeAvailable(imtui)
+find_package(ftxui)
+
+if (NOT ftxui_FOUND)
+ set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
+ FetchContent_Declare(ftxui
+ GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
+ GIT_TAG b63aa9e
+ #GIT_TAG v3.0.0
+ )
+
+ FetchContent_GetProperties(ftxui)
+ if(NOT ftxui_POPULATED)
+ FetchContent_Populate(ftxui)
+ add_subdirectory(${ftxui_SOURCE_DIR} ${ftxui_BINARY_DIR} EXCLUDE_FROM_ALL)
+ endif()
+endif()
+
+
+find_package(fmt)
+if (NOT fmt_FOUND)
+FetchContent_Declare(fmt
+ GIT_REPOSITORY https://github.com/fmtlib/fmt.git
+ GIT_TAG master
+)
+FetchContent_MakeAvailable(fmt)
+endif()
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
@@ -85,15 +105,20 @@ add_executable(${TARGET} ${SOURCES})
target_include_directories(${TARGET} PRIVATE
.
+ src/
+ test/include/
)
-target_link_libraries(${TARGET} PRIVATE
- ${CURL_LIBRARIES}
- ${CPR_LIBS}
- nlohmann_json::nlohmann_json
- Threads::Threads
- pugixml::pugixml
- imtui-ncurses
+target_link_libraries(${TARGET}
+ PRIVATE ${CURL_LIBRARIES}
+ PRIVATE ${CPR_LIBS}
+ PRIVATE nlohmann_json::nlohmann_json
+ PRIVATE Threads::Threads
+ PRIVATE pugixml::pugixml
+ PRIVATE ftxui::screen
+ PRIVATE ftxui::dom
+ PRIVATE ftxui::component # No
+ PRIVATE fmt::fmt
)
target_compile_options(${TARGET} PRIVATE -Wall -Wextra -Wpedantic -Werror)
@@ -120,7 +145,10 @@ foreach(TESTFILE ${TESTFILES})
nlohmann_json::nlohmann_json
Threads::Threads
pugixml::pugixml
- imtui-ncurses
+ PRIVATE ftxui::screen
+ PRIVATE ftxui::dom
+ PRIVATE ftxui::component # No
+ PRIVATE fmt::fmt
)
endif()
endforeach()
diff --git a/README.md b/README.md
index 635383b..a1a2ea2 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,9 @@
Read-the-things-tui (rttt) lets you read the things from the terminal. The things currently include RSS/Atom, hackernews and Reddit. It is a terminal application written in C++ and originally based on [hnterm](https://github.com/ggerganov/hnterm.git), but with added support for other things (Reddit/RSS/Atom).
-![screenshot](https://gitlab.com/BlackEdder/rttt/-/wikis/uploads/a6f6435591d28be270c8f783032dba37/rttt.png)
+![screenshot1](https://gitlab.com/BlackEdder/rttt/-/wikis/uploads/974e093e08d802d484f0fb454fc5d933/rttt_hntop.png)
+
+![screenshot2](https://gitlab.com/BlackEdder/rttt/-/wikis/uploads/db45a0db2ba991283fb96da6e21fd574/rttt_help.png)
## Installing
diff --git a/TODO.md b/TODO.md
index 9e3e4b9..1ab4862 100644
--- a/TODO.md
+++ b/TODO.md
@@ -6,6 +6,9 @@ This is a very rough list of ideas and future todo items.
# TODOs
+- [ ] Twitter support
+- [ ] Add gcc version information to README
+
## Refactor
- [ ] Use cpr getcallback support instead of my own version of it: https://docs.libcpr.org/advanced-usage.html#asynchronous-callbacks
@@ -34,6 +37,8 @@ while (!myqueue.empty())
## Features
+- [ ] Save completion history
+- [ ] Call from outside to open a certain path
- [ ] Save colourscheme to config
- [ ] Bold? text/font?
- Can we rely on terminals colour/bold/etc coding?
diff --git a/aur/PKGBUILD b/aur/PKGBUILD
index c0441eb..36b87d1 100644
--- a/aur/PKGBUILD
+++ b/aur/PKGBUILD
@@ -2,19 +2,19 @@
pkgname=rttt-git
_pkgname='rttt'
pkgrel=1
-pkgver=v0.6.0.r8.b4e22d4
+pkgver=v0.8.8.r37.df62981
pkgdesc="Read-the-things-tui (rttt) lets you read RSS/Atom, hackernews and Reddit from the terminal."
arch=("x86_64")
url="https://gitlab.com/BlackEdder/rttt"
license=('GPL3')
-depends=('pugixml' 'curl' 'cpr' 'nlohmann-json')
+depends=('pugixml' 'curl' 'cpr' 'nlohmann-json' 'fmt')
makedepends=('git' 'cmake')
provides=("${pkgname%-git}")
conflicts=("${pkgname%-git}")
install=
source=(
# "git+https://gitlab.com/BlackEdder/rttt#branch=${BRANCH:-master}"
-# "git+https://gitlab.com/BlackEdder/rttt#branch=${BRANCH:-feature/aur}"
+# "git+https://gitlab.com/BlackEdder/rttt#branch=${BRANCH:-feature/ftxui}"
"git+https://gitlab.com/BlackEdder/rttt#branch=${BRANCH:-PLACEHOLDER}"
)
sha512sums=('SKIP')
diff --git a/src/item.hpp b/src/item.hpp
deleted file mode 100644
index 0fe27a8..0000000
--- a/src/item.hpp
+++ /dev/null
@@ -1,250 +0,0 @@
-#pragma once
-
-#include <cassert>
-#include <optional>
-#include <string>
-#include <variant>
-#include <vector>
-
-namespace rttt {
-
-namespace hackernews {
-using ItemId = int;
-using ItemIds = std::vector<ItemId>;
-
-struct Story {
- std::string by = "";
- int descendants = 0;
- ItemId id = 0;
- ItemIds kids;
- int score = 0;
- uint64_t time = 0;
- std::string text = "";
- std::string title = "";
- std::string url = "";
- std::string domain = "";
-};
-
-struct Comment {
- std::string by = "";
- ItemId id = 0;
- ItemIds kids;
- ItemId parent = 0;
- std::string text = "";
- uint64_t time = 0;
-};
-} // namespace hackernews
-
-namespace rss {
-struct Story {
- std::string by = "";
- uint64_t time = 0;
- std::string text = "";
- std::string title = "";
- std::string domain = "";
- std::string url = "";
-
- int id;
- std::string key = "";
-};
-} // namespace rss
-
-// Forward declarations
-namespace reddit {
-struct Story;
-struct Comment;
-} // namespace reddit
-
-struct unknown_type {};
-
-using ItemVariant =
- std::variant<reddit::Comment, reddit::Story, hackernews::Comment,
- hackernews::Story, rss::Story, rttt::unknown_type>;
-
-namespace reddit {
-struct Story {
- std::string by = "";
- int descendants = 0;
- int score = 0;
- int vote = 0;
- uint64_t time = 0;
- std::string text = "";
- std::string title = "";
- std::string domain = "";
- std::string url = "";
- std::string fullname = "";
-
- std::vector<ItemVariant> kids;
-
- std::string id = "";
-};
-
-struct Comment {
- std::string by = "";
- std::string text = "";
- std::string id = "";
- std::string fullname = "";
- uint64_t time = 0;
- int score = 0;
- int vote = 0;
-
- std::vector<ItemVariant> kids;
-};
-
-} // namespace reddit
-
-inline std::optional<std::string> try_id_string(const ItemVariant &item) {
- if (std::holds_alternative<reddit::Story>(item)) {
- auto value = std::get<reddit::Story>(item);
- if (value.id.empty())
- return std::nullopt;
- return value.id;
- }
- if (std::holds_alternative<reddit::Comment>(item)) {
- auto value = std::get<reddit::Comment>(item);
- if (value.id.empty())
- return std::nullopt;
- return value.id;
- }
- if (std::holds_alternative<hackernews::Story>(item)) {
- auto value = std::get<hackernews::Story>(item);
- if (value.id == 0)
- return std::nullopt;
- return std::to_string(value.id);
- }
- if (std::holds_alternative<hackernews::Comment>(item)) {
- auto value = std::get<hackernews::Comment>(item);
- if (value.id == 0)
- return std::nullopt;
- return std::to_string(value.id);
- }
- if (std::holds_alternative<rss::Story>(item)) {
- auto value = std::get<rss::Story>(item);
- if (value.id == 0)
- return std::nullopt;
- return std::to_string(value.id);
- }
- return std::nullopt;
-}
-
-inline std::optional<uint64_t> try_time(const ItemVariant &item) {
- std::optional<uint64_t> opt;
- std::visit(
- [&opt](const auto &data) {
- if constexpr (!std::is_same<const rttt::unknown_type &,
- decltype(data)>::value) {
- opt = data.time;
- }
- },
- item);
- return opt;
-}
-
-std::optional<int> try_vote(const ItemVariant &item) {
- std::optional<int> opt;
- std::visit(
- [&opt](const auto &data) {
- // TODO: make a constexpr is_reddit template function
- if constexpr (std::is_same<const rttt::reddit::Story &,
- decltype(data)>::value ||
- std::is_same<const rttt::reddit::Comment &,
- decltype(data)>::value) {
- opt = data.vote;
- }
- },
- item);
- return opt;
-}
-
-std::optional<std::string> try_fullname(const ItemVariant &item) {
- std::optional<std::string> opt;
- std::visit(
- [&opt](const auto &data) {
- // TODO: make a constexpr is_reddit template function
- if constexpr (std::is_same<const rttt::reddit::Story &,
- decltype(data)>::value ||
- std::is_same<const rttt::reddit::Comment &,
- decltype(data)>::value) {
- opt = data.fullname;
- }
- },
- item);
- return opt;
-}
-
-template <typename C, typename = void> struct has_url : std::false_type {};
-
-template <typename C>
-struct has_url<
- C, typename std::enable_if<std::is_same<decltype(std::declval<C>().url),
- std::string>::value>::type>
- : std::true_type {};
-
-inline std::optional<std::string> try_url(const ItemVariant &item) {
- std::optional<std::string> opt;
- std::visit(
- [&opt](const auto &data) {
- if constexpr (has_url<decltype(data)>::value)
- opt = data.url;
- },
- item);
- return opt;
-}
-
-template <typename C, typename = void> struct has_title : std::false_type {};
-
-template <typename C>
-struct has_title<
- C, typename std::enable_if<std::is_same<decltype(std::declval<C>().title),
- std::string>::value>::type>
- : std::true_type {};
-
-inline std::optional<std::string> try_title(const ItemVariant &item) {
- std::optional<std::string> opt;
- std::visit(
- [&opt](const auto &data) {
- if constexpr (has_title<decltype(data)>::value)
- opt = data.title;
- },
- item);
- return opt;
-}
-
-inline std::optional<std::string> try_text(const ItemVariant &item) {
- std::optional<std::string> opt;
- std::visit(
- [&opt](const auto &data) {
- if constexpr (!std::is_same<const rttt::unknown_type &,
- decltype(data)>::value) {
- opt = data.text;
- }
- },
- item);
- return opt;
-}
-
-inline std::optional<std::vector<ItemVariant>>
-try_kids(const ItemVariant &item) {
- if (std::holds_alternative<reddit::Story>(item)) {
- return std::get<reddit::Story>(item).kids;
- }
- if (std::holds_alternative<reddit::Comment>(item)) {
- return std::get<reddit::Comment>(item).kids;
- }
- if (std::holds_alternative<hackernews::Comment>(item) ||
- std::holds_alternative<hackernews::Story>(item)) {
- assert(false); // kids work different here, so not supported (yet?)
- }
-
- return std::nullopt;
-}
-
-template <typename C, typename = void> struct has_text : std::false_type {};
-
-template <typename C>
-struct has_text<
- C, typename std::enable_if<std::is_same<decltype(std::declval<C>().text),
- std::string>::value>::type>
- : std::true_type {};
-
-} // namespace rttt
diff --git a/src/logger.hpp b/src/logger.hpp
deleted file mode 100644
index cac8039..0000000
--- a/src/logger.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-
-#include <locale.h>
-#include <stdio.h>
-#include <time.h>
-#include <iostream>
-
-#include <chrono>
-#include <deque>
-#include <string>
-
-namespace logger {
-
-namespace {
-// Anonymous namespace makes this private to this namespace (basically a global)
-std::deque<std::string> queue;
-std::optional<std::string> maybe_file;
-} // namespace
-
-inline void push_back(const std::string &message) {
- time_t t =
- std::chrono::system_clock::to_time_t(std::chrono::system_clock().now());
- char buf[70];
- std::strftime(buf, 70, "[%H:%M:%S] ", std::localtime(&t));
- auto line = std::string(buf) + message;
- if (maybe_file.has_value()) {
- std::ofstream log_file;
- log_file.open(maybe_file.value(), std::ios_base::app);
- log_file << line << std::endl;
- log_file.close();
- }
- queue.push_back(line);
-}
-
-inline std::string at(const size_t i) { return queue.at(i); }
-
-inline size_t size() { return queue.size(); }
-
-inline void pop_front() { queue.pop_front(); }
-
-void to_file(const std::string &filename) {
- maybe_file = filename;
-}
-
-} // namespace logger
diff --git a/src/main.cpp b/src/main.cpp
index 58728aa..c5833f0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,42 +1,32 @@
-// Documentation for imgui:
-// https://pixtur.github.io/mkdocs-for-imgui/site/api-imgui/ImGui--Dear-ImGui-end-user/#settingsini-utilities
-
-#include "imgui/imgui.h"
-#include "imtui/imtui.h"
-
-#include "config.hpp"
-#include "hackernews.hpp"
-#include "logger.hpp"
-#include "prompt.hpp"
-#include "reddit.hpp"
-#include "rss.hpp"
-#include "rttt.hpp"
-#include "storage.hpp"
-#include "ui.hpp"
-#include "view.hpp"
-
-// Figure out why this is needed
-#define EMSCRIPTEN_KEEPALIVE
-
-#include "imtui/imtui-impl-ncurses.h"
-
-#include <functional>
-#include <list>
-#include <map>
-#include <ranges>
+#include <chrono>
+#include <iostream>
+#include <sstream>
#include <string>
-#include <unordered_set>
+#include <thread>
#include <vector>
-// global vars
-bool g_updated = false;
-ImTui::TScreen *g_screen = nullptr;
+#include "ftxui/component/component.hpp"
+#include "ftxui/component/screen_interactive.hpp"
+#include "ftxui/dom/elements.hpp"
+#include "ftxui/dom/flexbox_config.hpp"
+#include "ftxui/component/captured_mouse.hpp"
+
+#include "rttt/config.hpp"
+#include "rttt/fake_thing.hpp"
+#include "rttt/logger.hpp"
+#include "rttt/prompt.hpp"
+#include "rttt/text.hpp"
+#include "rttt/thing.hpp"
+#include "rttt/ui_ftxui.hpp"
+
+/*
+- [ ] Selecting text with the mouse in fxtui
+*/
// helper functions
namespace {
-[[maybe_unused]] std::map<std::string, std::string>
-parseCmdArguments(int argc, char **argv) {
+std::map<std::string, std::string> parse_arguments(int argc, char **argv) {
int last = argc;
std::map<std::string, std::string> res;
for (int i = 1; i < last; ++i) {
@@ -51,599 +41,283 @@ parseCmdArguments(int argc, char **argv) {
return res;
}
-} // namespace
-
-using namespace rttt;
-
-rttt::active_storage<std::string, ui::WindowData> path_cache;
-
-hackernews::state state_hn;
-rss::state state_rss;
-reddit::state state_reddit;
-prompt::state state_prompt;
-ui::state state_ui;
-ui::WindowData switch_path(ui::WindowData &&current_window,
- const std::string &from, const std::string &to) {
- assert(path_cache.contains(from));
- // Store current status of the window (highlighted item etc)
- auto prev_window_mode = current_window.path.mode;
- path_cache.at(from) = current_window;
+rttt::active_storage<std::string, rttt::ui::scroll_window_state>
+ window_state_cache =
+ rttt::active_storage<std::string, rttt::ui::scroll_window_state>(
+ 0, 0, 3500);
- if (path_cache.contains(to)) {
- current_window = path_cache.at(to);
+auto switch_path(const rttt::Path &from, const rttt::Path &to,
+ const rttt::ui::scroll_window_state &window_state) {
+ if (window_state_cache.contains(from.name)) {
+ window_state_cache.at(from.name) = window_state;
+ window_state_cache.mark_active(from.name);
} else {
- current_window.path = rttt::parse_path(to);
- current_window.scroll_state = rttt::ui::scroll_window_state();
-
- // Change default view if we switch to feed mode
- if (current_window.path.mode == rttt::list_mode::feed &&
- prev_window_mode != rttt::list_mode::feed)
- current_window.scroll_state.ui_view_mode = view::mode::text;
- path_cache.insert({current_window.path.name, current_window});
+ window_state_cache.insert({from.name, window_state});
}
-
- // We currently mark path displayed in windows already as active, so this is
- // not needed here
- // pathCache.mark_active(from);
- // pathCache.mark_active(to);
- return std::move(current_window);
-}
-
-auto dispatch_drawing_stories(ui::WindowData &&window) {
- if (window.path.type == rttt::SiteType::HN) {
- auto result = hackernews::get_stories(std::move(state_hn.items),
- state_hn.idsMap[window.path.name]);
- state_hn.items = std::move(std::get<0>(result));
- // In case highlighted_item is not cached anymore
- auto maybe_id = try_id_string(window.scroll_state.highlighted_item);
- if (maybe_id.has_value()) {
- auto id = std::stoi(maybe_id.value());
- if (!state_hn.items.contains(id))
- window.scroll_state.highlighted_item = ItemVariant();
- }
- window.scroll_state =
- rttt::ui::drawItems(std::move(window.scroll_state), std::get<1>(result),
- window.path.mode, state_ui.item_view_states);
-
- } else if (window.path.type == rttt::SiteType::Reddit) {
- if (reddit::items.contains(window.path.name)) {
- auto result = reddit::get_stories(std::move(reddit::items), window.path);
- reddit::items = std::move(std::get<0>(result));
- window.scroll_state = rttt::ui::drawItems(
- std::move(window.scroll_state), std::get<1>(result), window.path.mode,
- state_ui.item_view_states);
- }
- } else if (window.path.type == rttt::SiteType::RSS) {
- // Technically this temporary is not needed, but compilation (type
- // inference?) will fail without it
- auto vec = rttt::rss::get_items(state_rss, window.path);
- auto v = vec | std::views::transform(
- [](const auto &item) { return std::pair(0, item); });
- window.scroll_state =
- rttt::ui::drawItems(std::move(window.scroll_state), v, window.path.mode,
- state_ui.item_view_states);
- } else {
- assert(false);
+ if (!window_state_cache.contains(to.name)) {
+ window_state_cache.insert({to.name, rttt::ui::scroll_window_state()});
+ window_state_cache.at(to.name).layout = rttt::thing::default_view_mode(to);
}
- return window;
+ window_state_cache.mark_active(to.name);
+ return std::make_tuple(to, window_state_cache.at(to.name));
}
+} // namespace
-auto dispatch_drawing_comments(ui::WindowData &&window) {
- if (window.path.type == rttt::SiteType::Reddit) {
- if (reddit::items.contains(window.path.name)) {
- reddit::items.mark_active(window.path.name);
- if (!reddit::items.at(window.path.name).empty()) {
- constexpr auto dig = [](auto &item) -> std::vector<ItemVariant> * {
- auto maybe_id = try_id_string(item);
- if (!maybe_id.has_value() ||
- view::is_collapsed(state_ui.item_view_states, maybe_id.value()))
- return nullptr;
-
- if (std::holds_alternative<reddit::Story>(item))
- return &std::get<reddit::Story>(item).kids;
- assert(std::holds_alternative<reddit::Comment>(item));
- return &std::get<reddit::Comment>(item).kids;
- };
- auto view =
- rttt::flat_view_with_depth(reddit::items.at(window.path.name), dig);
- window.scroll_state =
- rttt::ui::drawItems(std::move(window.scroll_state), view,
- window.path.mode, state_ui.item_view_states);
- }
- }
- } else if (window.path.type == rttt::SiteType::HN) {
- int id = std::stoi(window.path.id);
- if (state_hn.items.contains(id)) {
- std::vector<int> item_ids{id};
- auto dig = [](auto &m_id) -> std::vector<int> * {
- if (!state_hn.items.contains(m_id) ||
- view::is_collapsed(state_ui.item_view_states, std::to_string(m_id)))
- return nullptr;
- auto &item = state_hn.items.at(m_id);
- if (std::holds_alternative<hackernews::Story>(item)) {
- return &(std::get<hackernews::Story>(item).kids);
- }
- if (std::holds_alternative<hackernews::Comment>(item)) {
- return &(std::get<hackernews::Comment>(item).kids);
- }
- return nullptr;
- };
- auto view =
- rttt::flat_view_with_depth(item_ids, dig) |
- std::views::transform([](auto pair) {
- if (!state_hn.items.contains(pair.second)) {
- state_hn.items.insert({pair.second, hackernews::Comment()});
- } else {
- state_hn.items.mark_active(pair.second);
- }
- return std::pair(pair.first, state_hn.items.at(pair.second));
- });
- window.scroll_state =
- rttt::ui::drawItems(std::move(window.scroll_state), view,
- window.path.mode, state_ui.item_view_states);
- } else {
- state_hn.items.insert({id, rttt::unknown_type()});
- }
- } else {
- assert(false);
- }
- return window;
-}
+rttt::ui::state ui_state;
+rttt::prompt::state prompt_state;
+rttt::thing::state thing_state;
-void mark_update(rttt::Path &path, const ItemVariant &item) {
- if (path.type == rttt::SiteType::HN) {
- auto maybe = try_id_string(item);
- assert(maybe);
- state_hn.items.mark_for_update(std::stoi(maybe.value()));
- } else if (path.type == rttt::SiteType::Reddit) {
- assert(reddit::items.contains(path.name));
- reddit::items.mark_for_update(path.name);
- } else if (path.type == rttt::SiteType::RSS) {
- assert(std::holds_alternative<rss::Story>(item));
- state_rss.items.mark_for_update(std::get<rss::Story>(item).key);
+int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) {
+ auto argm = parse_arguments(argc, argv);
+ if (argm.find("--help") != argm.end() || argm.find("-h") != argm.end()) {
+ printf("Usage: rttt [-h]\n");
+ printf(" -h, --help : print this help\n");
+ printf(" --log : save messages to log.txt\n");
+ return -1;
}
-}
-
-extern "C" {
-EMSCRIPTEN_KEEPALIVE
-bool render_frame() {
- using namespace rttt;
-
- bool isActive = g_updated;
- isActive |= ImTui_ImplNcurses_NewFrame();
- ImTui_ImplText_NewFrame();
-
- ImGui::NewFrame();
- if (ImGui::GetIO().DisplaySize.x < 50) {
- state_ui.nWindows = 1;
+ if (argm.find("--log") != argm.end()) {
+ logger::to_file("log.txt");
}
- /*
-Order of key bindings is quite important, because it interacts with the order
-of window focus etc. We have to bind these here, because otherwise the url
-popup can close before these are executed and pressing the numbers there will
-also change the number