#!/usr/bin/env bash # core/command_mixins.sh # Mixin infrastructure — loads mixin files and provides command::mixin # ============================================ # Active mixin tracking (per-process) # ============================================ declare -a _ACTIVE_MIXINS=() # ============================================ # Auto-load all mixin files # ============================================ function command::_load_mixins() { local mixin_file local -a mixin_paths=( "${WGCTL_DIR}/core/mixins/"*.mixin.sh "${WGCTL_DIR}/commands/mixins/"*.mixin.sh ) for mixin_file in "${mixin_paths[@]:-}"; do [[ -f "$mixin_file" ]] && source "$mixin_file" done } # ============================================ # command::mixin # Called from cmd::::on_load to opt into a mixin # ============================================ function command::mixin() { local name="${1:-}" [[ -z "$name" ]] && log::error "command::mixin: missing name" && return 1 local register_fn="command::mixin::${name}::register" if declare -f "$register_fn" >/dev/null 2>&1; then # Track for reset/process — avoid duplicates local m already=false for m in "${_ACTIVE_MIXINS[@]:-}"; do [[ "$m" == "$name" ]] && already=true && break done $already || _ACTIVE_MIXINS+=("$name") "$register_fn" else log::error "Unknown mixin: ${name} (no command::mixin::${name}::register found)" return 1 fi } # ============================================ # command::_reset_mixins # Called by command::run before each invocation # ============================================ function command::_reset_mixin_state() { # Reset values but keep _ACTIVE_MIXINS populated local m for m in "${_ACTIVE_MIXINS[@]:-}"; do local reset_fn="command::mixin::${m}::reset" declare -f "$reset_fn" >/dev/null 2>&1 && "$reset_fn" done } function command::_reset_mixins() { _ACTIVE_MIXINS=() local reset_fn mixin_file # Reset all known mixins regardless of active state for mixin_file in \ "${WGCTL_DIR}/core/mixins/"*.mixin.sh \ "${WGCTL_DIR}/commands/mixins/"*.mixin.sh; do [[ -f "$mixin_file" ]] || continue local mixin_name mixin_name=$(basename "$mixin_file" .mixin.sh) reset_fn="command::mixin::${mixin_name}::reset" declare -f "$reset_fn" >/dev/null 2>&1 && "$reset_fn" done } # ============================================ # command::_preprocess_flags # Called by command::run — strips mixin flags from args # ============================================ function command::_preprocess_flags() { local -n _args_ref="$1" local -a _filtered=() for _arg in "${_args_ref[@]:-}"; do local _consumed=false local _mixin for _mixin in "${_ACTIVE_MIXINS[@]:-}"; do local _process_fn="command::mixin::${_mixin}::process" if declare -f "$_process_fn" >/dev/null 2>&1; then if "$_process_fn" "$_arg"; then _consumed=true break fi fi done $_consumed || _filtered+=("$_arg") done if [[ ${#_filtered[@]} -gt 0 ]]; then _args_ref=("${_filtered[@]}") else _args_ref=() fi }