nuno revised this gist 1 month ago. Go to revision
1 file changed, 76 insertions
gistfile1.txt(file created)
| @@ -0,0 +1,76 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | ||
| 3 | + | # ============================================ | |
| 4 | + | # Command Registry | |
| 5 | + | # ============================================ | |
| 6 | + | ||
| 7 | + | declare -A _LOADED_COMMANDS=() | |
| 8 | + | ||
| 9 | + | readonly _COMMAND_NAMESPACE="cmd" | |
| 10 | + | readonly _COMMAND_AUTO_LOAD_HOOK="on_load" | |
| 11 | + | ||
| 12 | + | # ============================================ | |
| 13 | + | # Helpers | |
| 14 | + | # ============================================ | |
| 15 | + | ||
| 16 | + | function command::loaded() { [[ -n "${_LOADED_COMMANDS["$1"]:-}" ]]; } | |
| 17 | + | ||
| 18 | + | # Convert path-style name to namespace | |
| 19 | + | # e.g. service/wireguard -> service::wireguard | |
| 20 | + | function command::to_namespace() { echo "${1//\//:}"; } | |
| 21 | + | ||
| 22 | + | # Build fully qualified function name | |
| 23 | + | # e.g. command::fn "add" "run" -> cmd::add::run | |
| 24 | + | # e.g. command::fn "service/wg" "run" -> cmd::service::wg::run | |
| 25 | + | function command::fn() { | |
| 26 | + | local name namespace | |
| 27 | + | namespace=$(command::to_namespace "$1") | |
| 28 | + | echo "${_COMMAND_NAMESPACE}::${namespace}::${2}" | |
| 29 | + | } | |
| 30 | + | ||
| 31 | + | function command::has_function() { declare -F "$(command::fn "$1" "$2")" >/dev/null 2>&1; } | |
| 32 | + | function command::is_auto_load() { declare -F "$(command::fn "$1" on_load)" >/dev/null 2>&1; } | |
| 33 | + | function command::exists() { command::has_function "$1" run; } | |
| 34 | + | ||
| 35 | + | # ============================================ | |
| 36 | + | # Runner | |
| 37 | + | # ============================================ | |
| 38 | + | ||
| 39 | + | function command::run() { | |
| 40 | + | local cmd="$1" | |
| 41 | + | shift | |
| 42 | + | local fn | |
| 43 | + | fn=$(command::fn "$cmd" run) | |
| 44 | + | core::call_function "$fn" "$@" | |
| 45 | + | } | |
| 46 | + | ||
| 47 | + | function core::call_function() { | |
| 48 | + | local fn="$1" | |
| 49 | + | shift | |
| 50 | + | "$fn" "$@" | |
| 51 | + | } | |
| 52 | + | ||
| 53 | + | # ============================================ | |
| 54 | + | # Loader | |
| 55 | + | # ============================================ | |
| 56 | + | ||
| 57 | + | function load_command() { | |
| 58 | + | local name="$1" | |
| 59 | + | ||
| 60 | + | command::loaded "$name" && return 0 | |
| 61 | + | ||
| 62 | + | local path | |
| 63 | + | path="$(ctx::commands)/${name}.command.sh" | |
| 64 | + | ||
| 65 | + | if [[ ! -f "$path" ]]; then | |
| 66 | + | log::error "Command not found: ${name} (${path})" | |
| 67 | + | return 1 | |
| 68 | + | fi | |
| 69 | + | ||
| 70 | + | source "$path" | |
| 71 | + | _LOADED_COMMANDS["$name"]=1 | |
| 72 | + | ||
| 73 | + | core::call_if_exists "$(command::fn "$name" on_load)" | |
| 74 | + | ||
| 75 | + | return 0 | |
| 76 | + | } | |
Newer
Older