wgctl/commands/shell.command.sh.bak

164 lines
No EOL
3.9 KiB
Bash

#!/usr/bin/env bash
# ============================================
# Private helpers
# ============================================
function cmd::shell::_prompt() {
local user host dir
user=$(whoami)
host=$(hostname -s)
dir=$(basename "$PWD")
printf "\033[1;32m%s@%s\033[0m:\033[0;36m%s\033[0m \033[1;34mwgctl\033[0m> " \
"$user" "$host" "$dir"
}
function cmd::shell::_is_wgctl_command() {
local cmd="$1"
# Check against known wgctl commands
local known=(
list add remove rm inspect block unblock
rule group audit logs watch fw config qr
rename keys ip service shell help
)
local c
for c in "${known[@]}"; do
[[ "$c" == "$cmd" ]] && return 0
done
return 1
}
function cmd::shell::_handle_builtin() {
local input="$1"
local first="${input%% *}"
case "$first" in
cd)
local dir="${input#cd }"
[[ "$dir" == "$input" ]] && dir="$HOME"
cd "$dir" 2>/dev/null || log::error "cd: $dir: No such file or directory"
return 0
;;
cd*) eval "$input" ;; # eval preserves shell state for cd
export|unset|source|.)
eval "$input"
return 0
;;
esac
return 1 # not a builtin
}
function cmd::shell::_execute() {
local input="$1"
local first="${input%% *}"
local rest="${input#"$first"}"
rest="${rest# }"
# Handle shell builtins first
cmd::shell::_handle_builtin "$input" && return 0
# Try as wgctl command via dispatcher
if cmd::shell::_is_wgctl_command "$first"; then
if [[ -n "$rest" ]]; then
wgctl::dispatch "$first" $rest || true # never exit REPL on failure
else
wgctl::dispatch "$first" || true
fi
return 0 # Always 0 to keep REPL running
fi
# Fall back to bash
bash -c "$input" || true # same for bash commands
}
function cmd::shell::_setup_history() {
HISTFILE="${HOME}/.wgctl_history"
HISTSIZE=1000
HISTFILESIZE=2000
history -r 2>/dev/null || true
}
function cmd::shell::_save_history() {
history -w 2>/dev/null || true
}
function cmd::shell::_banner() {
ui::section "wgctl shell"
printf "\n"
printf " Type wgctl commands directly, or any bash command.\n"
printf " Type \033[1mexit\033[0m or \033[1mquit\033[0m to leave.\n"
printf " Type \033[1mhelp\033[0m for wgctl commands.\n"
printf "\n"
}
# ============================================
# Run
# ============================================
function cmd::shell::on_load() {
: # no flags needed
}
function cmd::shell::help() {
cat <<EOF
Usage: wgctl shell
Start an interactive wgctl shell. Supports all wgctl commands
directly (no 'wgctl' prefix needed), plus any bash command.
Builtins handled: cd, export, unset, source
Everything else: passed to bash
Examples:
wgctl shell
wgctl> list
wgctl> inspect --name phone-nuno
wgctl> ls /etc/wireguard
wgctl> exit
EOF
}
function cmd::shell::run() {
cmd::shell::_banner
cmd::shell::_setup_history
while true; do
local input
# Read with readline support (-e) and custom prompt
IFS= read -r -e -p "$(cmd::shell::_prompt)" input || break
# Handle empty input
[[ -z "${input// }" ]] && continue
# Add to history
history -s "$input"
# Handle exit
case "${input%% *}" in
exit|quit) break ;;
esac
# Execute
cmd::shell::_execute "$input"
done
cmd::shell::_save_history
printf "\n Goodbye!\n\n"
}
# ============================================
# Tab completion (loaded when shell starts)
# ============================================
function cmd::shell::_setup_completion() {
local commands="list add remove inspect block unblock rule group audit logs watch fw config qr rename shell help"
function _wgctl_shell_complete() {
local cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
}
# Bind completion to the read prompt
bind 'set show-all-if-ambiguous on' 2>/dev/null || true
bind 'set completion-ignore-case on' 2>/dev/null || true
}