diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 100cfe2..3dbb7c6 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -16,9 +16,11 @@ FetchContent_Declare(toml11 ) FetchContent_MakeAvailable(ftxui toml11) +find_package(Boost CONFIG COMPONENTS program_options REQUIRED) + add_executable(katja-cli main.cpp) target_sources(katja-cli PUBLIC FILE_SET all_my_modules TYPE CXX_MODULES FILES - component.cpp page.cpp + component.cpp configuration.cpp ) target_include_directories(katja-cli PRIVATE ${Boost_INCLUDE_DIR}) target_link_libraries(katja-cli @@ -27,5 +29,6 @@ target_link_libraries(katja-cli PRIVATE ftxui::dom PRIVATE ftxui::component PRIVATE toml11::toml11 + PRIVATE Boost::program_options ) set_target_properties(katja-cli PROPERTIES RUNTIME_OUTPUT_NAME katja) diff --git a/cli/configuration.cpp b/cli/configuration.cpp new file mode 100644 index 0000000..45669b3 --- /dev/null +++ b/cli/configuration.cpp @@ -0,0 +1,79 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +module; + +#include +#include + +#include + +import katja.database; +import katja.repository; + +export module katja.configuration; + +import katja.component; + +export namespace katja +{ + struct repository_configuration + { + std::string path; + }; + + class configuration + { + public: + using repositories_t = std::forward_list>; + + private: + repositories_t repositories; + + public: + void add(const std::string& name, repository_configuration&& repository) + { + this->repositories.emplace_front(name, std::move(repository)); + } + + repositories_t::iterator begin() + { + return this->repositories.begin(); + } + + repositories_t::iterator end() + { + return this->repositories.end(); + } + + repositories_t::const_iterator cbegin() + { + return this->repositories.cbegin(); + } + + repositories_t::const_iterator cend() + { + return this->repositories.cend(); + } + }; +} + +TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(katja::repository_configuration, path); + +export namespace katja +{ + configuration read_configuration() + { + auto raw_root = toml::parse("katja.toml"); + configuration result; + + for (const auto& [root_name, root_value] : raw_root.as_table()) + { + auto repository_value = toml::get(root_value); + result.add(root_name, std::move(repository_value)); + } + return result; + } +} diff --git a/cli/main.cpp b/cli/main.cpp index 5502800..8a8a377 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -7,36 +7,65 @@ module; #include #include +#include -#include -#include -#include #include import katja.database; import katja.repository; import katja.sbo; -import katja.page; +import katja.configuration; + +static void get_updates(std::shared_ptr repository, katja::package_database&& installed_database) +{ + const std::vector packages = repository->get_updates(installed_database); + + for (const auto& package_identifier : packages) + { + std::cout << package_identifier.to_string() << std::endl; + } + std::cout << std::endl << "Updates " << '(' << packages.size() << ')' << std::endl; +} + +static void search_names(std::shared_ptr repository, const std::string& needle) +{ + const std::vector packages = repository->search_names("x86-64", needle); + + for (const auto& package_identifier : packages) + { + std::cout << package_identifier.to_string() << std::endl; + } +} int main(int argc, const char **argv) { - auto configuration = toml::parse("katja.toml"); + katja::configuration configuration = katja::read_configuration(); katja::package_database installed_database = katja::read_installed_database(); - for (const auto& [repository_name, repository_value] : configuration.as_table()) + if (argc == 1) { - std::filesystem::path slackbuild_repository{ repository_value.at("path").as_string() }; - auto repository = std::make_shared(slackbuild_repository); - - auto screen = ftxui::ScreenInteractive::Fullscreen(); - - auto container = Screen(std::vector>{ - { "Home", ftxui::Make() }, - { "Updates", ftxui::Make(repository, std::move(installed_database)) }, - { "Search", ftxui::Make(repository, "x86-64") } - }, screen.ExitLoopClosure()); - - screen.Loop(container); + return EXIT_FAILURE; } + if (strcmp("updates", argv[1]) == 0) + { + for (const auto& [repository_name, repository_configuration] : configuration) + { + std::filesystem::path slackbuild_repository{ repository_configuration.path }; + auto repository = std::make_shared(slackbuild_repository); + + get_updates(repository, std::move(installed_database)); + } + } + else if (strcmp("search", argv[1]) == 0 && argc == 3) + { + for (const auto& [repository_name, repository_configuration] : configuration) + { + std::filesystem::path slackbuild_repository{ repository_configuration.path }; + auto repository = std::make_shared(slackbuild_repository); + + search_names(repository, std::string(argv[2])); + } + } + return EXIT_SUCCESS; } diff --git a/cli/page.cpp b/cli/page.cpp deleted file mode 100644 index 44b7e73..0000000 --- a/cli/page.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ -module; - -#include - -#include - -import katja.database; -import katja.repository; - -export module katja.page; - -import katja.component; - -export namespace katja -{ - class PageBase : public ftxui::ComponentBase - { - public: - virtual void Load() = 0; - }; - - using Page = std::shared_ptr; - using Pages = std::vector; - - class ScreenContainer final : public ftxui::ComponentBase - { - int menu_selected{ 0 }; - ftxui::Component menu; - ftxui::Component content; - std::vector menu_entries; - Pages menu_pages; - std::function on_enter; - - public: - ScreenContainer(std::vector> pages, std::function on_enter) - : on_enter(on_enter) - { - ftxui::Components menu_pages; - - std::transform(std::cbegin(pages), std::cend(pages), std::back_inserter(menu_entries), - [](const std::pair& pair) { return pair.first; }); - std::transform(std::cbegin(pages), std::cend(pages), std::back_inserter(this->menu_pages), - [](const std::pair& pair) { return pair.second; }); - std::copy(std::cbegin(this->menu_pages), std::cend(this->menu_pages), std::back_inserter(menu_pages)); - - ftxui::MenuOption menu_option = ftxui::MenuOption::Horizontal(); - this->menu = ftxui::Toggle(&this->menu_entries, &this->menu_selected); - - this->content = ftxui::Container::Tab(std::move(menu_pages), &this->menu_selected); - } - - ftxui::Element OnRender() override - { - return ftxui::vbox({ - this->menu->Render(), - ftxui::separator(), - this->content->Render() - }); - } - - bool OnEvent(ftxui::Event event) override - { - if (event == ftxui::Event::CtrlQ && this->on_enter) - { - on_enter(); - return true; - } - int previously = this->menu_selected; - bool result{ false }; - - if (event == ftxui::Event::CtrlP) - { - result = menu->OnEvent(ftxui::Event::ArrowLeft); - } - else if (event == ftxui::Event::CtrlN) - { - result = menu->OnEvent(ftxui::Event::ArrowRight); - } - if (previously != this->menu_selected) - { - this->menu_pages.at(this->menu_selected)->Load(); - } - if (!result) - { - result = this->menu_pages.at(this->menu_selected)->OnEvent(event); - } - return result; - } - }; - - ftxui::Component Screen(std::vector> pages, std::function on_enter) - { - return std::make_shared(std::move(pages), on_enter); - } - - class WelcomePage final : public PageBase - { - public: - void Load() override - { - } - - ftxui::Element OnRender() override - { - return ftxui::paragraph("Select an action in the menu."); - } - }; - - class UpdatesPage final : public PageBase - { - ftxui::Component updatable = PackageList("Updates"); - std::shared_ptr repository; - package_database database; - - public: - UpdatesPage(std::shared_ptr repository, package_database database) - : repository(repository), database(database) - { - } - - void Load() override - { - this->updatable = PackageList("Updates", repository->get_updates(this->database)); - } - - ftxui::Element OnRender() override - { - return this->updatable->Render(); - } - }; - - class SearchPage final : public PageBase - { - std::string needle; - ftxui::Component search_input; - ftxui::Component type_input; - std::shared_ptr repository; - std::string architecture; - ftxui::Component search_results = PackageList("Results"); - int search_type{ 0 }; - - public: - SearchPage(std::shared_ptr repository, const std::string& architecture) - : repository(repository), architecture(architecture) - { - ftxui::InputOption search_input_option = { .multiline = false }; - this->search_input = ftxui::Input(&this->needle, "Search", search_input_option); - this->type_input = ftxui::Radiobox(std::vector{ "Names", "Description" }, &this->search_type); - } - - void Load() override - { - this->needle.erase(); - } - - ftxui::Element OnRender() override - { - std::vector lines; - - ftxui::FlexboxConfig config; - config.justify_content = ftxui::FlexboxConfig::JustifyContent::SpaceAround; - config.align_items = ftxui::FlexboxConfig::AlignItems::FlexStart; - config.direction = ftxui::FlexboxConfig::Direction::Row; - config.wrap = ftxui::FlexboxConfig::Wrap::NoWrap; - config.SetGap(3, 0); - - return ftxui::vbox({ - ftxui::flexbox({ - this->search_input->Render(), - ftxui::window(ftxui::text("Search in"), type_input->Render()) - }, config), - this->search_results->Render() | ftxui::flex - }); - } - - bool OnEvent(ftxui::Event event) override - { - if (event == ftxui::Event::Return) - { - if (!this->needle.empty()) - { - std::vector result = - this->repository->search_names(this->architecture, this->needle); - this->search_results = PackageList("Search", std::move(result)); - } - return true; - } - else if (event == ftxui::Event::ArrowUp || event == ftxui::Event::ArrowDown) - { - this->search_results->OnEvent(event); - return true; - } - else - { - return this->search_input->OnEvent(event); - } - return false; - } - }; -} diff --git a/katja.conf.dist b/katja.toml.dist similarity index 100% rename from katja.conf.dist rename to katja.toml.dist