diff --git a/container/plugins/root/example.cc b/container/plugins/root/example.cc deleted file mode 100644 index 63c3fd4..0000000 --- a/container/plugins/root/example.cc +++ /dev/null @@ -1,145 +0,0 @@ -// docker-finance | modern accounting for the power-user -// -// Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation either version 3 of the License or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not see . - -//! \file -//! \author Aaron Fiore (Founder, Evergreen Crypto LLC) -//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter -//! \since docker-finance 1.0.0 - -// NOTE: API headers are included by default - -//! \namespace dfi::plugin -//! \brief docker-finance plugins -//! \warning All plugins (repo/custom) must exist within this namespace -//! and work within their own inner namespace -//! \since docker-finance 1.0.0 -namespace dfi::plugin -{ -//! \namespace dfi::plugin::my_plugin_namespace -//! \brief docker-finance plugin example namespace -//! \details An example namespace used only within this example file -//! \warning Not a real namespace - for example purposes only -//! \since docker-finance 1.0.0 -namespace my_plugin_namespace -{ -//! \brief Example plugin function 1 -//! \details Directly access docker-finance crypto abstractions and -//! print hundreds of SHA2-256 libsodium-generated hashes of -//! Crypto++-generated cryptographically secure random numbers -//! \ingroup cpp_plugin_impl -void example1() -{ - using g_Random = dfi::crypto::cryptopp::Random; - using g_Hash = dfi::crypto::libsodium::Hash; - g_Random r; - g_Hash h; - for (size_t i{}; i < std::numeric_limits::max(); i++) - { - uint32_t num = r.generate(); - std::cout << h.encode(num) << " = " << num << "\n"; - } -} - -//! \brief Example plugin function 2 -//! \details Directly access underlying docker-finance shell environment -//! \ingroup cpp_plugin_impl -void example2() -{ - namespace common = ::dfi::common; - - auto print_env = [](const std::string& env) { - std::cout << env << "=" << common::get_env(env) << "\n"; - }; - - // Container env - std::cout - << "\nShell environment (container)\n-----------------------------\n"; - print_env("DOCKER_FINANCE_CLIENT_FLOW"); - print_env("DOCKER_FINANCE_CONTAINER_CMD"); - print_env("DOCKER_FINANCE_CONTAINER_CONF"); - print_env("DOCKER_FINANCE_CONTAINER_EDITOR"); - print_env("DOCKER_FINANCE_CONTAINER_FLOW"); - print_env("DOCKER_FINANCE_CONTAINER_PLUGINS"); - print_env("DOCKER_FINANCE_CONTAINER_REPO"); - print_env("DOCKER_FINANCE_CONTAINER_SHARED"); - print_env("DOCKER_FINANCE_DEBUG"); - print_env("DOCKER_FINANCE_VERSION"); - - std::cout << "\nSame as previous but executing commands in " - "shell\n------------------------------------------------\n"; - common::exec("printenv | grep ^DOCKER_FINANCE | sort"); - - // Caller env - std::cout << "\nShell environment (caller)\n--------------------------\n"; - print_env("global_arg_delim_1"); - print_env("global_arg_delim_2"); - print_env("global_arg_delim_3"); - print_env("global_arg_subcommand"); - print_env("global_basename"); - print_env("global_child_profile"); - print_env("global_child_profile_flow"); - print_env("global_child_profile_journal"); - print_env("global_conf_fetch"); - print_env("global_conf_hledger"); - print_env("global_conf_meta"); - print_env("global_conf_subscript"); - // TODO(unassigned): read array from shell? ROOT impl simply calls stdlib getenv() - // print_env("global_hledger_cmd"); - print_env("global_parent_profile"); - print_env("global_usage"); -} - -//! \brief Example plugin function 3 -//! \details Execute docker-finance shell commands -//! \ingroup cpp_plugin_impl -void example3() -{ - namespace common = ::dfi::common; - - const std::string base{ - common::get_env("global_basename") + " " - + common::get_env("global_parent_profile") - + common::get_env("global_arg_delim_1") - + common::get_env("global_child_profile") + " "}; - - auto make_cmd = [&base](const std::string& arg) { - return std::string{base + arg}; - }; - - auto exec_cmd = [&make_cmd](const std::string& cmd) { - // shell 0 = success - common::throw_ex_if( - common::exec("bash -i -c '" + make_cmd(cmd) + "'"), "command failed"); - }; - - std::cout << "\nImporting journals...\n"; - exec_cmd("import 1>/dev/null"); - - std::cout << "\nShowing BTC balance...\n"; - exec_cmd("hledger bal assets liabilities cur:BTC"); - - std::cout << "\nGenerating income tax snippet...\n"; - const std::string delim{common::get_env("global_arg_delim_2")}; - exec_cmd( - "taxes all" + delim + "account tag" + delim + "income write" + delim - + "off | tail -n3"); -} - -} // namespace my_plugin_namespace -} // namespace dfi::plugin - -// # vim: sw=2 sts=2 si ai et diff --git a/container/plugins/root/example/example.cc b/container/plugins/root/example/example.cc new file mode 100644 index 0000000..da77750 --- /dev/null +++ b/container/plugins/root/example/example.cc @@ -0,0 +1,81 @@ +// docker-finance | modern accounting for the power-user +// +// Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation either version 3 of the License or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not see . + +//! \file +//! \author Aaron Fiore (Founder, Evergreen Crypto LLC) +//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter +//! \since docker-finance 1.0.0 + +// NOTE: `dfi` API headers are included by default + +//! \namespace dfi::plugin +//! \brief docker-finance plugins +//! \warning All plugins (repo/custom) must exist within this namespace +//! and work within their own inner namespace +//! \since docker-finance 1.0.0 +namespace dfi::plugin +{ +//! \namespace dfi::plugin::example +//! \brief docker-finance plugin example namespace +//! \details An example namespace used only within this example file +//! +//! \warning +//! This namespace *MUST* match the parent plugin directory, +//! e.g., `example/anyfile.cc` must be `dfi::plugin::example` +//! in order to benefit from the plugin auto-loader. +//! Otherwise, use general common file loader. +//! +//! \note Not a real namespace - for example purposes only +//! \since docker-finance 1.1.0 +namespace example +{ +//! \brief Example auto-loader +//! \param arg String to pass to auto-loader (use-case is plugin-implementation defined) +void load(const std::string& arg = {}) +{ + // Any code can follow here: run example functions, etc. + // For this example, get absolute path of this plugin's implementation and load. + ::dfi::plugin::common::PluginPath path("repo/example/internal/example.cc"); + ::dfi::common::load(path.absolute()); + + // For this example, expect and pass a line of code to the interpreter after loading + // NOTE: the following arg code can utilize any code that was loaded/interpreted in load() + if (!arg.empty()) + ::dfi::common::line(arg); +} + +//! \brief Example auto-unloader +//! \param arg String to pass to auto-unloader (use-case is plugin-implementation defined) +void unload(const std::string& arg = {}) +{ + // For this example, expect and pass a line of code to the interpreter before unloading. + // NOTE: the following arg code can utilize any code that was previously loaded/interpreted + if (!arg.empty()) + ::dfi::common::line(arg); + + // Any code can follow here: run example functions, etc. + // For this example, get absolute path of this plugin's implementation and unload. + ::dfi::plugin::common::PluginPath path("repo/example/internal/example.cc"); + ::dfi::common::unload(path.absolute()); +} + +// NOTE: to auto-reload this plugin, load()/unload() here or utilize one of the `dfi::plugin::reload()` functions. + +} // namespace example +} // namespace dfi::plugin + +// # vim: sw=2 sts=2 si ai et diff --git a/container/plugins/root/example/internal/example.cc b/container/plugins/root/example/internal/example.cc new file mode 100644 index 0000000..73f81c6 --- /dev/null +++ b/container/plugins/root/example/internal/example.cc @@ -0,0 +1,125 @@ +// docker-finance | modern accounting for the power-user +// +// Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation either version 3 of the License or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not see . + +//! \file +//! \author Aaron Fiore (Founder, Evergreen Crypto LLC) +//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter +//! \since docker-finance 1.1.0 + +// NOTE: `dfi` API headers are included by default + +#include "./example.hh" + +#include + +namespace dfi::plugin::example +{ +std::string Example::make_cmd(const std::string& base, const std::string& arg) +{ + return std::string{base + arg}; +} + +void Example::exec_cmd(const std::string& cmd) +{ + namespace common = ::dfi::common; + + const std::string base{ + common::get_env("global_basename") + " " + + common::get_env("global_parent_profile") + + common::get_env("global_arg_delim_1") + + common::get_env("global_child_profile") + " "}; + + common::throw_ex_if( + common::exec("bash -i -c '" + Example::make_cmd(base, cmd) + "'"), + "command failed"); +} + +void Example::print_env(const std::string& env) +{ + std::cout << env << "=" << ::dfi::common::get_env(env) << "\n"; +}; + +void Example::example1() +{ + using g_Random = dfi::crypto::cryptopp::Random; + using g_Hash = dfi::crypto::libsodium::Hash; + g_Random r; + g_Hash h; + for (size_t i{}; i < 5; i++) + { + uint32_t num = r.generate(); + std::cout << h.encode(num) << " = " << num << "\n"; + } +} + +void Example::example2() +{ + // Container environment + std::cout + << "\nShell environment (container)\n-----------------------------\n"; + Example::print_env("DOCKER_FINANCE_CLIENT_FLOW"); + Example::print_env("DOCKER_FINANCE_CONTAINER_CMD"); + Example::print_env("DOCKER_FINANCE_CONTAINER_CONF"); + Example::print_env("DOCKER_FINANCE_CONTAINER_EDITOR"); + Example::print_env("DOCKER_FINANCE_CONTAINER_FLOW"); + Example::print_env("DOCKER_FINANCE_CONTAINER_PLUGINS"); + Example::print_env("DOCKER_FINANCE_CONTAINER_REPO"); + Example::print_env("DOCKER_FINANCE_CONTAINER_SHARED"); + Example::print_env("DOCKER_FINANCE_DEBUG"); + Example::print_env("DOCKER_FINANCE_VERSION"); + + std::cout << "\nSame as previous but executing commands in " + "shell\n------------------------------------------------\n"; + ::dfi::common::exec("printenv | grep ^DOCKER_FINANCE | sort"); + + // Caller environment + std::cout << "\nShell environment (caller)\n--------------------------\n"; + Example::print_env("global_arg_delim_1"); + Example::print_env("global_arg_delim_2"); + Example::print_env("global_arg_delim_3"); + Example::print_env("global_arg_subcommand"); + Example::print_env("global_basename"); + Example::print_env("global_child_profile"); + Example::print_env("global_child_profile_flow"); + Example::print_env("global_child_profile_journal"); + Example::print_env("global_conf_fetch"); + Example::print_env("global_conf_hledger"); + Example::print_env("global_conf_meta"); + Example::print_env("global_conf_subscript"); + // TODO(unassigned): read array from shell? ROOT impl simply calls stdlib getenv() + // Example::print_env("global_hledger_cmd"); + Example::print_env("global_parent_profile"); + Example::print_env("global_usage"); +} + +void Example::example3() +{ + std::cout << "\nImporting journals...\n"; + Example::exec_cmd("import 1>/dev/null"); + + std::cout << "\nShowing BTC balance...\n"; + Example::exec_cmd("hledger bal assets liabilities cur:BTC"); + + std::cout << "\nGenerating income tax snippet...\n"; + const std::string delim{::dfi::common::get_env("global_arg_delim_2")}; + Example::exec_cmd( + "taxes all" + delim + "account tag" + delim + "income write" + delim + + "off | tail -n3"); +} +} // namespace dfi::plugin::example + +// # vim: sw=2 sts=2 si ai et diff --git a/container/plugins/root/example/internal/example.hh b/container/plugins/root/example/internal/example.hh new file mode 100644 index 0000000..e11bca6 --- /dev/null +++ b/container/plugins/root/example/internal/example.hh @@ -0,0 +1,68 @@ +// docker-finance | modern accounting for the power-user +// +// Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation either version 3 of the License or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not see . + +//! \file +//! \author Aaron Fiore (Founder, Evergreen Crypto LLC) +//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter +//! \since docker-finance 1.1.0 + +#ifndef CONTAINER_PLUGINS_ROOT_EXAMPLE_INTERNAL_EXAMPLE_HH_ +#define CONTAINER_PLUGINS_ROOT_EXAMPLE_INTERNAL_EXAMPLE_HH_ + +#include + +// NOTE: `dfi` API headers are included by default + +namespace dfi::plugin::example +{ +//! \brief An example plugin implementation class +//! +//! \warning When implementing pluggables, prefer member functions with +//! definitions within source file(s) over certain lambdas to prevent +//! root segfaults. TODO(afiore): investigate. +//! +//! \note For demonstration purposes only +//! +//! \ingroup cpp_plugin_impl +//! \since docker-finance 1.1.0 +class Example +{ + public: + //! \brief Example plugin function 1 + //! \details Directly access docker-finance crypto abstractions and + //! print a handful of SHA2-256 libsodium-generated hashes of + //! Crypto++-generated cryptographically secure random numbers + void example1(); + + //! \brief Example plugin function 2 + //! \details Directly access underlying docker-finance shell environment + void example2(); + + //! \brief Example plugin function 3 + //! \details Execute docker-finance shell commands + void example3(); + + protected: + std::string make_cmd(const std::string& base, const std::string& arg); + void exec_cmd(const std::string& cmd); + void print_env(const std::string& env); +}; +} // namespace dfi::plugin::example + +#endif // CONTAINER_PLUGINS_ROOT_EXAMPLE_INTERNAL_EXAMPLE_HH_ + +// # vim: sw=2 sts=2 si ai et