forked from EvergreenCrypto/docker-finance
Merge pull request #215 into master
c68a668container: finance: completion: add 'help' to `plugins` (Aaron Fiore)c336451container: finance: lib_plugins: update usage help (Aaron Fiore)745a16econtainer: finance: completion: add `root` (Aaron Fiore)3348666container: root: rootlogon.C: remove default help() (Aaron Fiore)ed16344container: finance: add lib_root impl (macro/plugin support) (Aaron Fiore)
This commit is contained in:
@@ -129,13 +129,26 @@ function docker-finance::completion()
|
|||||||
find "${DOCKER_FINANCE_CONTAINER_REPO}"/plugins/finance "${_args[@]}" -printf 'repo/%P\n' 2>/dev/null
|
find "${DOCKER_FINANCE_CONTAINER_REPO}"/plugins/finance "${_args[@]}" -printf 'repo/%P\n' 2>/dev/null
|
||||||
})
|
})
|
||||||
declare -r _plugins
|
declare -r _plugins
|
||||||
mapfile -t _reply < <(compgen -W "${_plugins[*]}" -- "$_cur")
|
mapfile -t _reply < <(compgen -W "help ${_plugins[*]}" -- "$_cur")
|
||||||
;;
|
;;
|
||||||
reports)
|
reports)
|
||||||
mapfile -t _reply < <(compgen -W "help all${global_arg_delim_2} type${global_arg_delim_2} interval${global_arg_delim_2} year${global_arg_delim_2}" -- "$_cur")
|
mapfile -t _reply < <(compgen -W "help all${global_arg_delim_2} type${global_arg_delim_2} interval${global_arg_delim_2} year${global_arg_delim_2}" -- "$_cur")
|
||||||
;;
|
;;
|
||||||
root)
|
root)
|
||||||
# TODO: currently no-op
|
compopt +o nospace
|
||||||
|
|
||||||
|
[ -z "$DOCKER_FINANCE_CONTAINER_REPO" ] && lib_utils::die_fatal
|
||||||
|
[ -z "$DOCKER_FINANCE_CONTAINER_PLUGINS" ] && lib_utils::die_fatal
|
||||||
|
|
||||||
|
local -r _args=("-type" "f" "-not" "-path" "*/internal/*" "-not" "-path" "*/impl/*" "-not" "-path" "*/common/*" "!" "-name" "rootlogon.C")
|
||||||
|
local _root
|
||||||
|
mapfile -t _root < <({
|
||||||
|
find "${DOCKER_FINANCE_CONTAINER_PLUGINS}"/root "${_args[@]}" -printf 'plugins/custom/%P\n' 2>/dev/null
|
||||||
|
find "${DOCKER_FINANCE_CONTAINER_REPO}"/plugins/root "${_args[@]}" -printf 'plugins/repo/%P\n' 2>/dev/null
|
||||||
|
find "${DOCKER_FINANCE_CONTAINER_REPO}"/src/root/macro "${_args[@]}" -printf 'macro/%P\n' 2>/dev/null
|
||||||
|
})
|
||||||
|
declare -r _root
|
||||||
|
mapfile -t _reply < <(compgen -W "help ${_root[*]}" -- "$_cur")
|
||||||
;;
|
;;
|
||||||
taxes)
|
taxes)
|
||||||
mapfile -t _reply < <(compgen -W "help all${global_arg_delim_2} tag${global_arg_delim_2} account${global_arg_delim_2} year${global_arg_delim_2} write${global_arg_delim_2}" -- "$_cur")
|
mapfile -t _reply < <(compgen -W "help all${global_arg_delim_2} tag${global_arg_delim_2} account${global_arg_delim_2} year${global_arg_delim_2} write${global_arg_delim_2}" -- "$_cur")
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# docker-finance | modern accounting for the power-user
|
# docker-finance | modern accounting for the power-user
|
||||||
#
|
#
|
||||||
# Copyright (C) 2024 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
# Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -65,18 +65,39 @@ function lib_plugins::__parse_args()
|
|||||||
local -r _usage="
|
local -r _usage="
|
||||||
\e[32mDescription:\e[0m
|
\e[32mDescription:\e[0m
|
||||||
|
|
||||||
Execute a categorical plugin
|
Execute a categorical shell plugin (non-\`root\`)
|
||||||
|
|
||||||
|
NOTE: for \`root\` plugins, see \`root help\`
|
||||||
|
|
||||||
\e[32mUsage:\e[0m
|
\e[32mUsage:\e[0m
|
||||||
|
|
||||||
$ $global_usage <repo${global_arg_delim_1}plugin | custom${global_arg_delim_1}plugin> [args]
|
$ $global_usage [help | [TAB COMPLETION]] [args]
|
||||||
|
|
||||||
|
\e[32mArguments:\e[0m
|
||||||
|
|
||||||
|
[None | help]: show this usage help
|
||||||
|
|
||||||
|
[TAB COMPLETION]: run given shell plugin
|
||||||
|
|
||||||
|
custom = custom plugins in custom plugin location
|
||||||
|
repo = repository plugins in repository location
|
||||||
|
|
||||||
|
[args]: arguments to plugin
|
||||||
|
|
||||||
\e[32mExamples:\e[0m
|
\e[32mExamples:\e[0m
|
||||||
|
|
||||||
\e[37;2m# Execute a repository plugin in '${_repo}'\e[0m
|
\e[37;2m# See this usage help\e[0m
|
||||||
|
$ $global_usage help
|
||||||
|
|
||||||
|
\e[37;2m# The output of tab completion\e[0m
|
||||||
|
$ $global_usage \\\t\\\t
|
||||||
|
custom/billing/invoice.bash help repo/timew_to_timeclock.bash
|
||||||
|
custom/billing/manage.bash repo/example.bash
|
||||||
|
|
||||||
|
\e[37;2m# Execute a repository shell plugin in '${_repo}'\e[0m
|
||||||
$ $global_usage repo${global_arg_delim_1}example.bash \"I'm in repo\"
|
$ $global_usage repo${global_arg_delim_1}example.bash \"I'm in repo\"
|
||||||
|
|
||||||
\e[37;2m# Execute a custom plugin in '${_custom}'\e[0m
|
\e[37;2m# Execute a custom shell plugin in '${_custom}'\e[0m
|
||||||
$ $global_usage custom${global_arg_delim_1}example.bash \"I'm in custom\"
|
$ $global_usage custom${global_arg_delim_1}example.bash \"I'm in custom\"
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|||||||
234
container/src/finance/lib/internal/lib_root.bash
Normal file
234
container/src/finance/lib/internal/lib_root.bash
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# docker-finance | modern accounting for the power-user
|
||||||
|
#
|
||||||
|
# Copyright (C) 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#
|
||||||
|
# "Libraries"
|
||||||
|
#
|
||||||
|
|
||||||
|
[ -z "$DOCKER_FINANCE_CONTAINER_REPO" ] && exit 1
|
||||||
|
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_utils.bash" || exit 1
|
||||||
|
|
||||||
|
#
|
||||||
|
# Facade
|
||||||
|
#
|
||||||
|
|
||||||
|
function lib_root::root()
|
||||||
|
{
|
||||||
|
lib_root::__parse_root "$@"
|
||||||
|
lib_root::__root "$@"
|
||||||
|
lib_utils::catch $?
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Implementation
|
||||||
|
#
|
||||||
|
|
||||||
|
function lib_root::__parse_root()
|
||||||
|
{
|
||||||
|
[ -z "$global_usage" ] && lib_utils::die_fatal
|
||||||
|
|
||||||
|
local -r _arg="$1"
|
||||||
|
local -r _usage="
|
||||||
|
\e[32mDescription:\e[0m
|
||||||
|
|
||||||
|
docker-finance ROOT.cern interpreter
|
||||||
|
|
||||||
|
\e[32mUsage:\e[0m
|
||||||
|
|
||||||
|
$ $global_usage [help | [TAB COMPLETION]] [args]
|
||||||
|
|
||||||
|
\e[32mArguments:\e[0m
|
||||||
|
|
||||||
|
None: start interactive interpreter w/out running any given macro or plugins
|
||||||
|
|
||||||
|
[TAB COMPLETION]: load (and run) given macro/plugin when starting interpreter
|
||||||
|
|
||||||
|
macro = repository macros in repository location
|
||||||
|
plugins/custom = custom plugins in custom plugin location
|
||||||
|
plugins/repo = repository plugins in repository location
|
||||||
|
|
||||||
|
[args]: arguments to macro or plugin
|
||||||
|
|
||||||
|
\e[32mExamples:\e[0m
|
||||||
|
|
||||||
|
\e[37;2m# See this usage help\e[0m
|
||||||
|
$ $global_usage help
|
||||||
|
|
||||||
|
\e[37;2m# The output of tab completion\e[0m
|
||||||
|
$ $global_usage \\\t\\\t
|
||||||
|
help macro/crypto/random.C macro/test/unit.C plugins/custom/example.cc
|
||||||
|
macro/crypto/hash.C macro/test/benchmark.C macro/web/server.C plugins/repo/example.cc
|
||||||
|
|
||||||
|
\e[37;2m# Load and run the repo's Web server macro\e[0m
|
||||||
|
\e[37;2m# NOTE: this macro will maintain a running ROOT instance\e[0m
|
||||||
|
$ $global_usage macro/web/server.C
|
||||||
|
|
||||||
|
\e[37;2m# Load and run the repo's Hash macro with an argument\e[0m
|
||||||
|
\e[37;2m# NOTE: this macro will 'one-off' the ROOT instance\e[0m
|
||||||
|
$ $global_usage macro/crypto/hash.C 'this is a test message'
|
||||||
|
|
||||||
|
\e[37;2m# Load repo example plugin, run within instance\e[0m
|
||||||
|
$ $global_usage plugins/repo/example.cc
|
||||||
|
root [0]
|
||||||
|
Interpreting: '.L /home/business/docker-finance/plugins/root/example.cc'
|
||||||
|
root [1] dfi::plugin::my_plugin_namespace::example\\\t
|
||||||
|
example1
|
||||||
|
example2
|
||||||
|
example3
|
||||||
|
root [1] dfi::plugin::my_plugin_namespace::example2()
|
||||||
|
...
|
||||||
|
"
|
||||||
|
|
||||||
|
if [[ "$#" -gt 0 && ! "$_arg" =~ (^macro/|^plugins/) ]]; then
|
||||||
|
lib_utils::die_usage "$_usage"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Type determined by path stub
|
||||||
|
local -r _stub="${_arg#*/}"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Macro
|
||||||
|
#
|
||||||
|
|
||||||
|
if [[ "$_arg" =~ ^macro ]]; then
|
||||||
|
local -r _macro="$_stub"
|
||||||
|
|
||||||
|
# Repo macros
|
||||||
|
[ ! -f "${DOCKER_FINANCE_CONTAINER_REPO}/src/root/macro/${_macro}" ] \
|
||||||
|
&& lib_utils::die_fatal "repo macro not found '${_macro}'"
|
||||||
|
|
||||||
|
# TODO: currently, only repo macros are supported
|
||||||
|
# (no custom macros, use custom plugins instead)
|
||||||
|
|
||||||
|
# Per API (v1), requires path stub format
|
||||||
|
declare -gr global_arg_macro="$_stub"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Plugin
|
||||||
|
#
|
||||||
|
|
||||||
|
if [[ "$_arg" =~ ^plugins ]]; then
|
||||||
|
local -r _plugin="${_stub#*/}"
|
||||||
|
|
||||||
|
# Repo plugins
|
||||||
|
if [[ "$_stub" =~ ^repo ]]; then
|
||||||
|
[ ! -f "${DOCKER_FINANCE_CONTAINER_REPO}/plugins/root/${_plugin}" ] \
|
||||||
|
&& lib_utils::die_fatal "repo plugin not found '${_plugin}'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Custom plugins
|
||||||
|
if [[ "$_stub" =~ ^custom ]]; then
|
||||||
|
[ -z "$DOCKER_FINANCE_CONTAINER_PLUGINS" ] && lib_utils::die_fatal
|
||||||
|
[ ! -f "${DOCKER_FINANCE_CONTAINER_PLUGINS}/root/${_plugin}" ] \
|
||||||
|
&& lib_utils::die_fatal "custom plugin not found '${_plugin}'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Per API (v1), requires path stub format
|
||||||
|
declare -gr global_arg_plugin="$_stub"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function lib_root::__root()
|
||||||
|
{
|
||||||
|
lib_utils::deps_check "root"
|
||||||
|
|
||||||
|
local _exec=("root" "-l")
|
||||||
|
|
||||||
|
#
|
||||||
|
# Default
|
||||||
|
#
|
||||||
|
|
||||||
|
# Start interactive instance w/out loading/running macro or plugin
|
||||||
|
if [[ -z "$global_arg_macro" && -z "$global_arg_plugin" ]]; then
|
||||||
|
_exec+=("-e" "help()")
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Macro
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ ! -z "$global_arg_macro" ]; then
|
||||||
|
_exec+=("-e" "dfi::macro::load(\"${global_arg_macro}\")")
|
||||||
|
|
||||||
|
# NOTE:
|
||||||
|
#
|
||||||
|
# - Currently, only repo macros are supported
|
||||||
|
#
|
||||||
|
# * Per API (v1):
|
||||||
|
#
|
||||||
|
# - filename is named after class
|
||||||
|
# * classes begin uppercase
|
||||||
|
# * filename begins lowercase
|
||||||
|
#
|
||||||
|
# - run() static function is the entry point for all macros
|
||||||
|
#
|
||||||
|
local -r _file="${global_arg_macro##*/}"
|
||||||
|
local -r _stub="${_file^}"
|
||||||
|
|
||||||
|
local -r _class="${_stub%.*}"
|
||||||
|
local -r _caller="dfi::macro::${global_arg_macro%%/*}::${_class}"
|
||||||
|
|
||||||
|
# Per-API signatures (v1)
|
||||||
|
if [[ ${_class} == "Hash" ]]; then
|
||||||
|
# If no message is given, default to unique profile/subprofile
|
||||||
|
[[ -z "$global_parent_profile" || -z "$global_arg_delim_1" || -z "$global_child_profile" ]] && lib_utils::die_fatal
|
||||||
|
[ -z "${*:2}" ] \
|
||||||
|
&& _run="run(\"${global_parent_profile}${global_arg_delim_1}${global_child_profile}\")" \
|
||||||
|
|| _run="run(\"${*:2}\")"
|
||||||
|
else
|
||||||
|
_run="run()"
|
||||||
|
fi
|
||||||
|
_exec+=("-e" "${_caller}::${_run}")
|
||||||
|
|
||||||
|
# NOTE: when called via shell, server(s) are implied to
|
||||||
|
# require an interactive ROOT instance (not a 'one-off').
|
||||||
|
if [[ "${_class%.*}" != "Server" ]]; then
|
||||||
|
_exec+=('-q')
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Plugin
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ ! -z "$global_arg_plugin" ]; then
|
||||||
|
_exec+=("-e" "dfi::plugin::load(\"${global_arg_plugin}\")")
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Execute
|
||||||
|
#
|
||||||
|
|
||||||
|
# NOTE:
|
||||||
|
#
|
||||||
|
# This *MUST* be executed from within the macro directory,
|
||||||
|
# regardless of what is loaded (macro or plugin), as ROOT.cern
|
||||||
|
# will automatically load rootlogon.C (which `dfi` needs).
|
||||||
|
#
|
||||||
|
# Any loading or macros of plugins from within an interactive
|
||||||
|
# instance can use be completed with the `dfi` API.
|
||||||
|
#
|
||||||
|
lib_utils::print_debug "${_exec[@]}"
|
||||||
|
pushd "${DOCKER_FINANCE_CONTAINER_REPO}/src/root/macro" 1>/dev/null \
|
||||||
|
&& "${_exec[@]}" \
|
||||||
|
|| lib_utils::die_fatal "could not pushd"
|
||||||
|
}
|
||||||
|
|
||||||
|
# vim: sw=2 sts=2 si ai et
|
||||||
@@ -90,6 +90,7 @@ function lib_finance::finance()
|
|||||||
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_meta.bash" || exit 1
|
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_meta.bash" || exit 1
|
||||||
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_plugins.bash" || exit 1
|
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_plugins.bash" || exit 1
|
||||||
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_reports.bash" || exit 1
|
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_reports.bash" || exit 1
|
||||||
|
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_root.bash" || exit 1
|
||||||
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_taxes.bash" || exit 1
|
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_taxes.bash" || exit 1
|
||||||
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_times.bash" || exit 1
|
source "${DOCKER_FINANCE_CONTAINER_REPO}/src/finance/lib/internal/lib_times.bash" || exit 1
|
||||||
}
|
}
|
||||||
@@ -216,11 +217,7 @@ function lib_finance::reports()
|
|||||||
|
|
||||||
function lib_finance::root()
|
function lib_finance::root()
|
||||||
{
|
{
|
||||||
# TODO: lib_root, add extendable arguments
|
lib_root::root "$@"
|
||||||
lib_utils::deps_check "root"
|
|
||||||
# NOTE: will automatically load rootlogon.C
|
|
||||||
pushd "${DOCKER_FINANCE_CONTAINER_REPO}/src/root/macro" 1>/dev/null \
|
|
||||||
&& root -l
|
|
||||||
lib_utils::catch $?
|
lib_utils::catch $?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -196,9 +196,6 @@ void rootlogon()
|
|||||||
gInterpreter->ProcessLine(".L ../src/hash.hh");
|
gInterpreter->ProcessLine(".L ../src/hash.hh");
|
||||||
gInterpreter->ProcessLine(".L ../src/random.hh");
|
gInterpreter->ProcessLine(".L ../src/random.hh");
|
||||||
gInterpreter->ProcessLine(".L ../src/utility.hh");
|
gInterpreter->ProcessLine(".L ../src/utility.hh");
|
||||||
|
|
||||||
// Help usage
|
|
||||||
help();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CONTAINER_SRC_ROOT_MACRO_ROOTLOGON_C_
|
#endif // CONTAINER_SRC_ROOT_MACRO_ROOTLOGON_C_
|
||||||
|
|||||||
Reference in New Issue
Block a user