refactor: move command bank under system category, drop system alias tool
gates / consistency-and-conventions (push) Successful in 21s
gates / consistency-and-conventions (push) Successful in 21s
- rename bin/pos-bank -> bin/pos-system-bank with # POS: system bank header; CLI becomes 'pos system bank'; BANK_FILE storage seam and v2 escaped format unchanged - delete bin/pos-system-alias; remove its POS.md/howto sections and the system-alias INTERACTIVE_CMDS entry; pos ai alias untouched - update bin/pos comment + usage example, completions (gen), docs, tests/t-bank.sh CLI path, AGENT_TODO Done notes
This commit is contained in:
@@ -28,7 +28,7 @@ _pos_commands() {
|
||||
# ── Category list (sorted, filename-derived) ─────────────────────
|
||||
# Nested sub-tools (pos-<cat>-<a>-<b> where pos-<cat>-<a> exists) are
|
||||
# omitted from the cheat-sheet line — they are shown under their parent tool.
|
||||
# Category-less tools (pos-bank, pos-config, pos-tree) are emitted as their
|
||||
# Category-less tools (pos-config, pos-tree) are emitted as their
|
||||
# own line with an empty subcommand column; a name already present as a
|
||||
# category (pos-ai vs the ai category built from pos-ai-*) is NOT duplicated.
|
||||
_pos_category_list() {
|
||||
@@ -214,7 +214,7 @@ EXAMPLES
|
||||
|
||||
pos tree Show the command tree (categories + subcommands)
|
||||
|
||||
pos bank run <name> Run a saved command from the bank
|
||||
pos system bank run <name> Run a saved command from the bank
|
||||
|
||||
pos docker vbox create lab1 Create disposable Docker VM
|
||||
pos docker vbox create lab1 --dir . Create VM using current directory
|
||||
@@ -274,7 +274,7 @@ MAIN_LOG="$LOG_DIR/pos.log"
|
||||
log_cmd() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $* → exit $2" >> "$MAIN_LOG"; }
|
||||
|
||||
# Commands that read from stdin interactively — only log invocation
|
||||
INTERACTIVE_CMDS="bank docker-compose docker-vbox network-hotspot system-firewall media-mp4 media-yt-mp4 media-sync system-backup system-uninstall share-usb-server share-smb-server share-smb-client share-nfs-client share-nfs-server communication-telegram-listener communication-matrix-listener ai ai-gemini ai-openrouter ai-llamacpp ai-alias system-alias system-schedule entertainment-config config"
|
||||
INTERACTIVE_CMDS="system-bank docker-compose docker-vbox network-hotspot system-firewall media-mp4 media-yt-mp4 media-sync system-backup system-uninstall share-usb-server share-smb-server share-smb-client share-nfs-client share-nfs-server communication-telegram-listener communication-matrix-listener ai ai-gemini ai-openrouter ai-llamacpp ai-alias system-schedule entertainment-config config"
|
||||
|
||||
for ((i=n-1; i>=0; i--)); do
|
||||
cmd="pos"
|
||||
|
||||
@@ -1,488 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# POS: system alias — Manage persistent command aliases (wrapper scripts in ~/.local/bin/)
|
||||
# POS_SUBCMDS: create edit remove list show
|
||||
|
||||
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
|
||||
source "$(dirname "$0")/../lib/menu-lib.sh" 2>/dev/null || source "$(dirname "$0")/menu-lib.sh"
|
||||
|
||||
# ── Paths & constants ──────────────────────────────────────────
|
||||
ENV_FILE="${CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/linux_post_install}/aliases.env"
|
||||
|
||||
# ── Core helpers ───────────────────────────────────────────────
|
||||
|
||||
# Load aliases from ENV_FILE into parallel arrays.
|
||||
# Loop vars use _a* prefix to avoid dynamic-scope collisions with callers.
|
||||
_alias_load() {
|
||||
_ALIAS_NAMES=(); _ALIAS_COMMANDS=()
|
||||
[ -f "$ENV_FILE" ] || return 0
|
||||
local _an _ac
|
||||
while IFS='|' read -r _an _ac; do
|
||||
[[ "$_an" =~ ^[[:space:]]*# ]] && continue
|
||||
[[ -z "${_an// /}" ]] && continue
|
||||
_an="${_an## }"; _an="${_an%% }"
|
||||
[[ "$_an" =~ ^[a-zA-Z][a-zA-Z0-9_-]*$ ]] || continue
|
||||
_ac="${_ac## }"; _ac="${_ac%% }"
|
||||
_ALIAS_NAMES+=("$_an")
|
||||
_ALIAS_COMMANDS+=("$_ac")
|
||||
done < <(grep -v '^[[:space:]]*#' "$ENV_FILE" | grep -v '^[[:space:]]*$' || true)
|
||||
}
|
||||
|
||||
# Save parallel arrays back to ENV_FILE (atomic overwrite).
|
||||
_alias_save() {
|
||||
mkdir -p "$(dirname "$ENV_FILE")"
|
||||
{
|
||||
printf '%s\n' "# System aliases — managed by pos system alias (do not hand-edit)"
|
||||
printf '%s\n' "# Format: alias_name|command"
|
||||
local i
|
||||
for ((i = 0; i < ${#_ALIAS_NAMES[@]}; i++)); do
|
||||
printf '%s|%s\n' "${_ALIAS_NAMES[$i]}" "${_ALIAS_COMMANDS[$i]}"
|
||||
done
|
||||
} >"$ENV_FILE"
|
||||
chmod 600 "$ENV_FILE"
|
||||
}
|
||||
|
||||
# ── Wrapper scripts ────────────────────────────────────────────
|
||||
|
||||
_wrapper_path() {
|
||||
printf '%s/.local/bin/%s' "$HOME" "$1"
|
||||
}
|
||||
|
||||
# Ownership test: line 2 must carry our generator marker.
|
||||
_alias_owned() {
|
||||
[ -f "$1" ] && sed -n '2p' "$1" 2>/dev/null | grep -q 'Managed by pos system alias'
|
||||
}
|
||||
|
||||
# Render one wrapper to stdout (args: name command).
|
||||
_wrapper_render() {
|
||||
local name="$1" command="$2"
|
||||
cat <<WRAPPER_EOF
|
||||
#!/usr/bin/env bash
|
||||
# Managed by pos system alias — regenerated automatically; hand-edits are overwritten.
|
||||
# Alias: ${name} | command: ${command}
|
||||
set -euo pipefail
|
||||
exec bash -c '${command} "\$@"' _ "\$@"
|
||||
WRAPPER_EOF
|
||||
}
|
||||
|
||||
# Atomically install/refresh one wrapper. Skips when content matches.
|
||||
# Pre-commit validation: bash -n on the rendered file; failure keeps previous.
|
||||
_wrapper_install() {
|
||||
local name="$1" command="$2" path tmp
|
||||
path="$(_wrapper_path "$name")"
|
||||
tmp="$(mktemp "${HOME}/.local/bin/.pos-alias.XXXXXX")"
|
||||
_wrapper_render "$name" "$command" >"$tmp"
|
||||
if cmp -s "$tmp" "$path" 2>/dev/null; then
|
||||
rm -f "$tmp"
|
||||
return 0
|
||||
fi
|
||||
if ! bash -n "$tmp" 2>/dev/null; then
|
||||
warn "Wrapper for '$name' failed syntax check — keeping previous version" >&2
|
||||
rm -f "$tmp"
|
||||
return 1
|
||||
fi
|
||||
mv "$tmp" "$path"
|
||||
chmod 755 "$path"
|
||||
}
|
||||
|
||||
# rc 0 iff ~/.local/bin is on PATH.
|
||||
_alias_check_path() {
|
||||
case ":$PATH:" in
|
||||
*":$HOME/.local/bin:"*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Two-way reconciliation on every invocation:
|
||||
# forward: each ENV entry → render-diff-install
|
||||
# reverse: owned wrappers whose name is not in ENV → deleted
|
||||
# plus: PATH guidance when owned wrappers exist but ~/.local/bin is absent
|
||||
_alias_sync() {
|
||||
_alias_load
|
||||
local bin_dir="${HOME}/.local/bin" i name f base match any=0
|
||||
mkdir -p "$bin_dir"
|
||||
for ((i = 0; i < ${#_ALIAS_NAMES[@]}; i++)); do
|
||||
_wrapper_install "${_ALIAS_NAMES[$i]}" "${_ALIAS_COMMANDS[$i]}" || :
|
||||
done
|
||||
for f in "$bin_dir"/*; do
|
||||
[ -f "$f" ] || continue
|
||||
_alias_owned "$f" || continue
|
||||
base="${f##*/}"
|
||||
match=0
|
||||
for name in ${_ALIAS_NAMES[@]+"${_ALIAS_NAMES[@]}"}; do
|
||||
[ "$base" = "$name" ] && { match=1; break; }
|
||||
done
|
||||
[ "$match" -eq 1 ] || rm -f "$f"
|
||||
done
|
||||
if ! _alias_check_path; then
|
||||
for f in "$bin_dir"/*; do
|
||||
[ -f "$f" ] && _alias_owned "$f" && { any=1; break; }
|
||||
done
|
||||
if [ "$any" -eq 1 ]; then
|
||||
warn "~/.local/bin is not on your PATH — alias scripts will not resolve by name."
|
||||
warn " Fix now: export PATH=\"\$HOME/.local/bin:\$PATH\""
|
||||
warn " Persist it: echo 'export PATH=\"\$HOME/.local/bin:\$PATH\"' >> ~/.profile"
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_alias_find() {
|
||||
local name="$1" i
|
||||
for ((i = 0; i < ${#_ALIAS_NAMES[@]}; i++)); do
|
||||
if [ "${_ALIAS_NAMES[$i]}" = "$name" ]; then
|
||||
echo "$i"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo "-1"
|
||||
return 0
|
||||
}
|
||||
|
||||
_alias_name_valid() {
|
||||
[[ "$1" =~ ^[a-zA-Z][a-zA-Z0-9_-]*$ ]]
|
||||
}
|
||||
|
||||
# Truncate a command string for display (inline pipes, redirects).
|
||||
_command_truncate() {
|
||||
local s="$1" max="${2:-42}"
|
||||
s="${s//$'\n'/ }"
|
||||
if [ ${#s} -gt "$max" ]; then
|
||||
printf '%s…' "${s:0:max}"
|
||||
else
|
||||
printf '%s' "$s"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Non-interactive output ─────────────────────────────────────
|
||||
|
||||
_alias_table() {
|
||||
local count=${#_ALIAS_NAMES[@]} i
|
||||
[ "$count" -eq 0 ] && return 0
|
||||
printf ' %-16s %s\n' "Name" "Command"
|
||||
printf ' %-16s %s\n' "----------------" "----------------------------------------"
|
||||
for ((i = 0; i < count; i++)); do
|
||||
printf ' %-16s %s\n' "${_ALIAS_NAMES[$i]}" "$(_command_truncate "${_ALIAS_COMMANDS[$i]}" 60)"
|
||||
done
|
||||
}
|
||||
|
||||
_alias_list() {
|
||||
printf 'Aliases (%d):\n' "${#_ALIAS_NAMES[@]}"
|
||||
_alias_table
|
||||
}
|
||||
|
||||
_alias_show() {
|
||||
local idx
|
||||
idx="$(_alias_find "$1")"
|
||||
[ "$idx" = "-1" ] && err "Alias '$1' not found"
|
||||
local name="${_ALIAS_NAMES[$idx]}" command="${_ALIAS_COMMANDS[$idx]}"
|
||||
printf ' %-12s %s\n' "Alias:" "$name"
|
||||
printf ' %-12s %s\n' "Command:" "$command"
|
||||
if _alias_check_path; then
|
||||
printf ' %-12s %s\n' "Wrapper:" "$(_wrapper_path "$name")"
|
||||
else
|
||||
printf ' %-12s %s\n' "Wrapper:" "(not installed — ~/.local/bin not on PATH)"
|
||||
fi
|
||||
printf ' %-12s %s\n' "Test:" "$name"
|
||||
}
|
||||
|
||||
# ── Interactive: main menu ─────────────────────────────────────
|
||||
|
||||
_alias_menu() {
|
||||
menu_guard || return 1
|
||||
while true; do
|
||||
{
|
||||
_alias_load
|
||||
if [ ${#_ALIAS_NAMES[@]} -eq 0 ]; then
|
||||
echo "${YELLOW}[!] No aliases defined yet — create one with option 1.${RESET}"
|
||||
else
|
||||
_alias_table
|
||||
printf ' %d alias(es)\n' "${#_ALIAS_NAMES[@]}"
|
||||
fi
|
||||
echo >&2
|
||||
} >&2
|
||||
local choice
|
||||
choice="$(menu_run "System Aliases" "Create new alias" "Edit existing alias" \
|
||||
"Remove alias" "List aliases")" || return 0
|
||||
case "$choice" in
|
||||
1) _alias_create ;;
|
||||
2) _alias_edit ;;
|
||||
3) _alias_remove ;;
|
||||
4) : ;; # List aliases — the loop's pre-render IS the current table
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# ── Interactive: create ────────────────────────────────────────
|
||||
|
||||
_alias_create() {
|
||||
local preset_name="${1:-}"
|
||||
section "Create System Alias" >&2
|
||||
|
||||
# Step 1: Alias name
|
||||
local name="$preset_name"
|
||||
while true; do
|
||||
if [ -z "$name" ]; then
|
||||
step 1 2 "Alias Name" >&2
|
||||
name="$(menu_ask_value "Alias name" "")" || return 0
|
||||
fi
|
||||
[ -z "$name" ] && { warn "Alias name cannot be empty" >&2; name=""; continue; }
|
||||
if ! _alias_name_valid "$name"; then
|
||||
warn "Invalid name '$name' — use letters, digits, hyphens, underscores (start with a letter)" >&2
|
||||
name=""; continue
|
||||
fi
|
||||
_alias_load
|
||||
local existing
|
||||
existing="$(_alias_find "$name")"
|
||||
if [ "$existing" != "-1" ]; then
|
||||
warn "Alias '$name' already exists — use 'pos system alias edit $name' instead" >&2
|
||||
[ -n "$preset_name" ] && return 1
|
||||
name=""; continue
|
||||
fi
|
||||
# Collision: wrapper exists without our marker → refuse
|
||||
local wpath
|
||||
wpath="$(_wrapper_path "$name")"
|
||||
if [ -e "$wpath" ]; then
|
||||
_alias_owned "$wpath" || err "File '~/.local/bin/$name' already exists and was not created by pos system alias — pick another name"
|
||||
fi
|
||||
# Collision: name resolves to another binary on PATH → refuse
|
||||
if command -v "$name" >/dev/null 2>&1; then
|
||||
err "'$name' already exists on PATH as $(command -v "$name") — pick another name"
|
||||
fi
|
||||
break
|
||||
done
|
||||
|
||||
# Step 2: Command
|
||||
local command=""
|
||||
while true; do
|
||||
step 2 2 "Command" >&2
|
||||
command="$(menu_ask_value "Command to execute" "")" || return 0
|
||||
[ -z "$command" ] && { warn "Command cannot be empty" >&2; continue; }
|
||||
[[ "$command" == *'|'* ]] || break
|
||||
warn "Command must not contain '|' characters" >&2
|
||||
command=""
|
||||
done
|
||||
|
||||
# Confirmation
|
||||
{
|
||||
echo "────────────────────────────────────────────"
|
||||
printf ' Create alias '\''%s'\''?\n' "$name"
|
||||
printf ' Command: %s\n' "$command"
|
||||
echo "────────────────────────────────────────────"
|
||||
} >&2
|
||||
if ! confirm "Create alias '$name'?" y; then
|
||||
log "Aborted." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
_alias_load
|
||||
_ALIAS_NAMES+=("$name")
|
||||
_ALIAS_COMMANDS+=("$command")
|
||||
_alias_save
|
||||
_alias_sync
|
||||
log "Alias '$name' created." >&2
|
||||
log "Test it: $name" >&2
|
||||
log "Available immediately: $(_wrapper_path "$name")" >&2
|
||||
}
|
||||
|
||||
# ── Interactive: edit ──────────────────────────────────────────
|
||||
|
||||
_alias_edit() {
|
||||
local preset_name="${1:-}"
|
||||
_alias_load
|
||||
if [ ${#_ALIAS_NAMES[@]} -eq 0 ]; then
|
||||
warn "No aliases to edit — create one first" >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
local name="$preset_name"
|
||||
if [ -z "$name" ]; then
|
||||
section "Edit System Alias" >&2
|
||||
local display_items=() i
|
||||
for ((i = 0; i < ${#_ALIAS_NAMES[@]}; i++)); do
|
||||
local c="${_ALIAS_COMMANDS[$i]}"
|
||||
if [ ${#c} -gt 30 ]; then
|
||||
c="${c:0:30}…"
|
||||
fi
|
||||
display_items+=("${_ALIAS_NAMES[$i]} → ${c}")
|
||||
done
|
||||
local picked
|
||||
picked="$(menu_pick "Pick alias to edit" "${display_items[@]}")" || return 0
|
||||
name="${_ALIAS_NAMES[$((picked - 1))]}"
|
||||
fi
|
||||
|
||||
local idx
|
||||
idx="$(_alias_find "$name")"
|
||||
if [ "$idx" = "-1" ]; then
|
||||
err "Alias '$name' not found"
|
||||
fi
|
||||
|
||||
# Show current values
|
||||
{
|
||||
echo " Current values for '$name':"
|
||||
printf ' Command: %s\n' "${_ALIAS_COMMANDS[$idx]}"
|
||||
echo >&2
|
||||
} >&2
|
||||
|
||||
local new_command="${_ALIAS_COMMANDS[$idx]}"
|
||||
local changed=0
|
||||
|
||||
# Edit command
|
||||
step 1 1 "Command" >&2
|
||||
local default_display="${_ALIAS_COMMANDS[$idx]}"
|
||||
[ ${#default_display} -gt 60 ] && default_display="${default_display:0:60}…"
|
||||
local tmp_command
|
||||
tmp_command="$(menu_ask_value "Command to execute" "$default_display")" || return 0
|
||||
if [ -n "$tmp_command" ]; then
|
||||
if [[ "$tmp_command" == *'|'* ]]; then
|
||||
warn "Command must not contain '|' characters" >&2
|
||||
return 0
|
||||
fi
|
||||
if [ "$tmp_command" != "${_ALIAS_COMMANDS[$idx]}" ]; then
|
||||
new_command="$tmp_command"
|
||||
changed=1
|
||||
fi
|
||||
fi
|
||||
|
||||
# No changes?
|
||||
if [ "$changed" -eq 0 ]; then
|
||||
log "No changes — nothing to save." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Show diff summary
|
||||
{
|
||||
echo "────────────────────────────────────────────"
|
||||
printf ' Save changes to '\''%s'\''?\n' "$name"
|
||||
local tag_c
|
||||
[ "$new_command" = "${_ALIAS_COMMANDS[$idx]}" ] && tag_c="(unchanged)" || tag_c="(changed)"
|
||||
printf ' Command: %s %s\n' "$new_command" "$tag_c"
|
||||
echo "────────────────────────────────────────────"
|
||||
} >&2
|
||||
if ! confirm "Save changes to '$name'?" y; then
|
||||
log "Discarded." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
_alias_load
|
||||
_ALIAS_COMMANDS[$idx]="$new_command"
|
||||
_alias_save
|
||||
_alias_sync
|
||||
log "Alias '$name' updated — the change is live on next invocation." >&2
|
||||
}
|
||||
|
||||
# ── Interactive: remove ────────────────────────────────────────
|
||||
|
||||
_alias_remove() {
|
||||
local preset_name="${1:-}"
|
||||
_alias_load
|
||||
if [ ${#_ALIAS_NAMES[@]} -eq 0 ]; then
|
||||
warn "No aliases to remove" >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
local name="$preset_name"
|
||||
if [ -z "$name" ]; then
|
||||
section "Remove System Alias" >&2
|
||||
local display_items=() i
|
||||
for ((i = 0; i < ${#_ALIAS_NAMES[@]}; i++)); do
|
||||
local c="${_ALIAS_COMMANDS[$i]}"
|
||||
if [ ${#c} -gt 30 ]; then
|
||||
c="${c:0:30}…"
|
||||
fi
|
||||
display_items+=("${_ALIAS_NAMES[$i]} → ${c}")
|
||||
done
|
||||
local picked
|
||||
picked="$(menu_pick "Pick alias to remove" "${display_items[@]}")" || return 0
|
||||
name="${_ALIAS_NAMES[$((picked - 1))]}"
|
||||
fi
|
||||
|
||||
local idx
|
||||
idx="$(_alias_find "$name")"
|
||||
if [ "$idx" = "-1" ]; then
|
||||
err "Alias '$name' not found"
|
||||
fi
|
||||
|
||||
# Show alias detail
|
||||
{
|
||||
echo " Alias: $name"
|
||||
printf ' Command: %s\n' "${_ALIAS_COMMANDS[$idx]}"
|
||||
echo >&2
|
||||
} >&2
|
||||
|
||||
if ! confirm "Remove alias '$name'? This cannot be undone." n; then
|
||||
log "Cancelled." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
_alias_load
|
||||
local new_names=() new_commands=() i
|
||||
for ((i = 0; i < ${#_ALIAS_NAMES[@]}; i++)); do
|
||||
if [ "${_ALIAS_NAMES[$i]}" != "$name" ]; then
|
||||
new_names+=("${_ALIAS_NAMES[$i]}")
|
||||
new_commands+=("${_ALIAS_COMMANDS[$i]}")
|
||||
fi
|
||||
done
|
||||
_ALIAS_NAMES=("${new_names[@]+"${new_names[@]}"}")
|
||||
_ALIAS_COMMANDS=("${new_commands[@]+"${new_commands[@]}"}")
|
||||
_alias_save
|
||||
_alias_sync
|
||||
log "Alias '$name' removed — script deleted from $(_wrapper_path "$name")." >&2
|
||||
log "If the name still autocompletes stale in this shell, run: hash -r" >&2
|
||||
}
|
||||
|
||||
# ── Usage ──────────────────────────────────────────────────────
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: pos system alias [subcommand] [args]
|
||||
|
||||
Manage persistent command aliases — create, edit, remove, list, and show
|
||||
named aliases. Each alias maps a name to a shell command, materialized as
|
||||
an executable wrapper script in ~/.local/bin/.
|
||||
|
||||
Subcommands:
|
||||
(no args) Interactive menu
|
||||
create [name] Create a new alias (interactive prompts)
|
||||
edit [name] Edit an existing alias (interactive, Enter = keep)
|
||||
remove [name] Remove an alias (with confirmation)
|
||||
list List all aliases (non-interactive, machine-readable)
|
||||
show <name> Show one alias's details
|
||||
|
||||
Activation: every alias is materialized as an executable script at
|
||||
~/.local/bin/<name>, synced automatically on every invocation. Changes are
|
||||
live on the next invocation.
|
||||
|
||||
Options:
|
||||
-h|--help Show this help.
|
||||
|
||||
Examples:
|
||||
pos system alias # interactive menu
|
||||
pos system alias list # show all aliases
|
||||
pos system alias create # interactive create
|
||||
pos system alias create restart-dns # create 'restart-dns' alias
|
||||
pos system alias edit restart-dns # edit the 'restart-dns' alias
|
||||
pos system alias remove restart-dns # remove 'restart-dns' (with confirm)
|
||||
pos system alias show restart-dns # show alias details
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# ── Main dispatch ──────────────────────────────────────────────
|
||||
# Every subcommand syncs first: artifacts always equal ENV truth before any
|
||||
# subcommand logic runs.
|
||||
|
||||
case "${1:-}" in
|
||||
-h|--help) usage ;;
|
||||
create) shift; _alias_sync; _alias_create "${1:-}" ;;
|
||||
edit) shift; _alias_sync; _alias_edit "${1:-}" ;;
|
||||
remove) shift; _alias_sync; _alias_remove "${1:-}" ;;
|
||||
list) _alias_sync; _alias_list ;;
|
||||
show)
|
||||
[ -n "${2:-}" ] || err "Usage: pos system alias show <name>"
|
||||
_alias_sync
|
||||
_alias_show "$2"
|
||||
;;
|
||||
"") _alias_sync; _alias_menu ;;
|
||||
*) err "Unknown subcommand '$1' (use -h for help)" ;;
|
||||
esac
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
# POS: bank — Persistent command bank for saving and running shell commands
|
||||
# POS: system bank — Persistent command bank for saving and running shell commands
|
||||
# POS_SUBCMDS: list add show run edit remove
|
||||
|
||||
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
|
||||
@@ -9,7 +9,7 @@ source "$(dirname "$0")/../lib/bank-lib.sh" 2>/dev/null || source "$(dirname "$0
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: pos bank [subcommand] [args]
|
||||
Usage: pos system bank [subcommand] [args]
|
||||
|
||||
Persistent command bank for saving and running shell commands.
|
||||
|
||||
@@ -22,12 +22,12 @@ Subcommands:
|
||||
remove <name> Remove a command
|
||||
|
||||
Interactive menu:
|
||||
pos bank (no args on a terminal)
|
||||
pos system bank (no args on a terminal)
|
||||
|
||||
Examples:
|
||||
pos bank add disk-info "Disk usage" "df -h && du -sh /mnt/12T"
|
||||
pos bank run disk-info
|
||||
pos bank run convert-video input=/path/to/video.mp4 quality=23 output=/path/out.mp4
|
||||
pos system bank add disk-info "Disk usage" "df -h && du -sh /mnt/12T"
|
||||
pos system bank run disk-info
|
||||
pos system bank run convert-video input=/path/to/video.mp4 quality=23 output=/path/out.mp4
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
@@ -41,7 +41,7 @@ _pick_command() {
|
||||
bank_load
|
||||
local count="${#BANK_NAMES[@]}"
|
||||
if [ "$count" -eq 0 ]; then
|
||||
warn "Command bank is empty — add one with: pos bank add <name> \"desc\" \"cmd\""
|
||||
warn "Command bank is empty — add one with: pos system bank add <name> \"desc\" \"cmd\""
|
||||
return 1
|
||||
fi
|
||||
local -a items=()
|
||||
@@ -63,7 +63,7 @@ cmd_list() {
|
||||
bank_load
|
||||
local count="${#BANK_NAMES[@]}"
|
||||
if [ "$count" -eq 0 ]; then
|
||||
log "Command bank is empty — add one with: pos bank add <name> \"desc\" \"cmd\""
|
||||
log "Command bank is empty — add one with: pos system bank add <name> \"desc\" \"cmd\""
|
||||
return 0
|
||||
fi
|
||||
echo
|
||||
@@ -103,7 +103,7 @@ cmd_add() {
|
||||
bank_load
|
||||
local i
|
||||
for ((i = 0; i < ${#BANK_NAMES[@]}; i++)); do
|
||||
[[ "${BANK_NAMES[$i]}" == "$name" ]] && err "Command '$name' already exists (use 'pos bank edit' to modify)"
|
||||
[[ "${BANK_NAMES[$i]}" == "$name" ]] && err "Command '$name' already exists (use 'pos system bank edit' to modify)"
|
||||
done
|
||||
bank_add "$name" "$desc" "$cmd"
|
||||
ok "Saved: $name"
|
||||
@@ -111,7 +111,7 @@ cmd_add() {
|
||||
|
||||
# ── cmd_show ─────────────────────────────────────────────────────
|
||||
cmd_show() {
|
||||
[ -n "${1:-}" ] || err "Usage: pos bank show <name>"
|
||||
[ -n "${1:-}" ] || err "Usage: pos system bank show <name>"
|
||||
local name="$1"
|
||||
bank_load
|
||||
bank_find "$name" >/dev/null 2>&1 || err "Command not found: $name"
|
||||
Reference in New Issue
Block a user