feat(riot): separate command options from riot options

This commit is contained in:
Dict Xiong 2026-08-13 14:55:51 +08:00
parent aa5c2e86b6
commit e3dad6d9cc
No known key found for this signature in database
GPG Key ID: 7B97FAAC15EB0628
3 changed files with 96 additions and 45 deletions

View File

@ -1,7 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# connect to iot services # connect to iot services
THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]:-${(%):-%x}}" )" && pwd ) THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]:-${(%):-%x}}" )" && pwd )
DFS_SKIP_ARG_PARSE=1
source "$THIS_DIR/../tools/common.sh" source "$THIS_DIR/../tools/common.sh"
unset DFS_SKIP_ARG_PARSE
RIOT_TRUST_CLIENT=${RIOT_TRUST_CLIENT:-${DFS_TRUST:-0}} RIOT_TRUST_CLIENT=${RIOT_TRUST_CLIENT:-${DFS_TRUST:-0}}
RIOT_TRUST_SERVER=${RIOT_TRUST_SERVER:-0} RIOT_TRUST_SERVER=${RIOT_TRUST_SERVER:-0}
EXTRA_SSH_OPTIONS=() EXTRA_SSH_OPTIONS=()
@ -13,11 +15,14 @@ RIOT_CONFIG_FILES=(
"$HOME/.config/riot-config.sh" "$HOME/.config/riot-config.sh"
"riot-config.sh" "riot-config.sh"
) )
load_riot_config() {
local file
for file in "${RIOT_CONFIG_FILES[@]}"; do for file in "${RIOT_CONFIG_FILES[@]}"; do
if [[ -f "$file" ]]; then if [[ -f "$file" ]]; then
source "$file" source "$file"
fi fi
done done
}
# check if port number valid # check if port number valid
check_port() { check_port() {
@ -437,12 +442,13 @@ NAME
riot - connect to remote hosts using SSH presets riot - connect to remote hosts using SSH presets
SYNOPSIS SYNOPSIS
${0##*/} [OPTION]... REMOTE [COMMAND] [--] [COMMAND-ARG]... ${0##*/} [OPTION]... REMOTE [OPTION]... [COMMAND [COMMAND-ARG]...]
DESCRIPTION DESCRIPTION
Connect to REMOTE using the matching configuration from riot-config.sh. Connect to REMOTE using the matching configuration from riot-config.sh.
COMMAND defaults to ssh. Separate multiple remotes with commas and jump COMMAND defaults to ssh. Separate multiple remotes with commas and jump
hosts with slashes. hosts with slashes. OPTIONs may appear before COMMAND. Once COMMAND is
found, all remaining arguments are passed to it without further parsing.
OPTIONS OPTIONS
-4 -4
@ -529,8 +535,44 @@ EOF
router() { router() {
local positional=() local positional=()
while [[ $# > 0 ]]; do local arg=""
case "$1" in local option=""
local remaining=""
local option_value=""
while [[ $# > 0 || -n "$arg" ]]; do
if [[ -z "$arg" ]]; then
arg=$1
shift
fi
# Normalize a long option or one item from a short-option group.
remaining=""
case "$arg" in
-- )
positional+=("$@")
break
;;
--* )
option=$arg
arg=""
;;
-?* )
option=${arg:0:2}
remaining=${arg:2}
arg=${remaining:+-$remaining}
;;
* )
positional+=("$arg")
arg=""
if [[ "${#positional[@]}" -ge 2 ]]; then
positional+=("$@")
break
fi
continue
;;
esac
case "$option" in
-h|--help ) -h|--help )
print_help print_help
exit 0 exit 0
@ -547,39 +589,54 @@ router() {
-p|--password ) -p|--password )
EXTRA_SSH_OPTIONS+=("-o" "PasswordAuthentication=yes" "-o" "PubkeyAuthentication=no") EXTRA_SSH_OPTIONS+=("-o" "PasswordAuthentication=yes" "-o" "PubkeyAuthentication=no")
;; ;;
-D|--dry-run )
export DFS_DRY_RUN=1
;;
-d|--dev )
export DFS_DEV=1
set -x
;;
-l|--lite )
export DFS_LITE=1
;;
-q|--quiet )
export DFS_QUIET=1
;;
--color )
export DFS_COLOR=1
setup_color
;;
-4|-6|-v )
EXTRA_SSH_OPTIONS+=("$option")
;;
-o ) -o )
EXTRA_SSH_OPTIONS+=("-o" "$2") if [[ -n "$remaining" ]]; then
option_value=$remaining
arg=""
else
[[ $# -gt 0 ]] || fmt_fatal "option '-o' requires an argument"
option_value=$1
shift shift
;; fi
-4 ) EXTRA_SSH_OPTIONS+=("-o" "$option_value")
EXTRA_SSH_OPTIONS+=("-4")
;;
-6 )
EXTRA_SSH_OPTIONS+=("-6")
;;
-v )
EXTRA_SSH_OPTIONS+=("-v")
;;
-- )
shift
positional+=("$@")
break
;;
-* )
fmt_fatal "unknown option: '$1'. if this option is for the remote command, add '--' before."
;; ;;
* ) * )
positional+=("$1") fmt_fatal "unknown option: '$option'"
;; ;;
esac esac
shift
done done
if [[ "${positional[2]}" == "--" ]]; then
positional=("${positional[@]:0:2}" "${positional[@]:3}")
fi
IFS=',' read -ra remotes <<< "${positional[0]}" IFS=',' read -ra remotes <<< "${positional[0]}"
for i in ${!remotes[@]}; do if [[ -z "${remotes[i]}" ]]; then unset remotes[i]; fi; done for i in ${!remotes[@]}; do if [[ -z "${remotes[i]}" ]]; then unset remotes[i]; fi; done
if [[ "${#positional[@]}" == "0" || "${#remotes[@]}" == "0" ]]; then if [[ "${#positional[@]}" == "0" || "${#remotes[@]}" == "0" ]]; then
print_help print_help
exit 1 exit 1
fi fi
load_riot_config
if [[ "$GPG_FORWARD" == "1" && ( \ if [[ "$GPG_FORWARD" == "1" && ( \
( "${positional[1]}" != "" && "${positional[1]}" != "ssh" && "${positional[1]}" != "tmux" ) \ ( "${positional[1]}" != "" && "${positional[1]}" != "ssh" && "${positional[1]}" != "tmux" ) \
|| "${#positional[@]}" -gt 2 ) ]]; then || "${#positional[@]}" -gt 2 ) ]]; then
@ -659,4 +716,4 @@ router() {
fi fi
} }
router "${GOT_OPTS[@]}" router "$@"

View File

@ -6,9 +6,9 @@ if [[ -f ~/.config/dotfiles/env ]]; then set -a; source ~/.config/dotfiles/env;
if [[ "$DFS_DEV" == "1" ]]; then set -x; fi if [[ "$DFS_DEV" == "1" ]]; then set -x; fi
DFS_CURL_OPTIONS="--retry 2 --max-time 20" DFS_CURL_OPTIONS="--retry 2 --max-time 20"
# parse args and set env, when it is sourced # Parse args and set env when sourced, unless the caller handles its own
# todo: make this skipable # option boundary.
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then if [[ "${BASH_SOURCE[0]}" != "${0}" && "$DFS_SKIP_ARG_PARSE" != "1" ]]; then
ORIGIN_ARGS=("$@") ORIGIN_ARGS=("$@")
ARG="" ARG=""
GOT_OPTS=() GOT_OPTS=()
@ -41,15 +41,9 @@ fi
# Color settings # Color settings
# Source: https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh # Source: https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh
if [[ -t 1 || "$DFS_COLOR" == "1" ]]; then
is_tty() { is_tty() {
true [[ -t 1 || "$DFS_COLOR" == "1" ]]
} }
else
is_tty() {
false
}
fi
supports_truecolor() { supports_truecolor() {
case "$COLORTERM" in case "$COLORTERM" in

View File

@ -41,9 +41,9 @@ test $(echo n | tools/common.sh ask_for_yN "test") = "0"
test $(echo | tools/common.sh ask_for_yN "test") = "0" test $(echo | tools/common.sh ask_for_yN "test") = "0"
test $(echo | tools/common.sh ask_for_Yn "test") = "1" test $(echo | tools/common.sh ask_for_Yn "test") = "1"
test $(DFS_QUIET=1 tools/common.sh ask_for_Yn "test") = "1" test $(DFS_QUIET=1 tools/common.sh ask_for_Yn "test") = "1"
test "$(DFS_TRUST=1 riot time@is.impt:2222/yes@you-r.right/you@are.really.recht./ibd./try@it,another@host scp /tmp/ ./tmp -D 2>/dev/null)" = 'scp -P 12022 -o ServerAliveInterval=60 -o PermitLocalCommand=yes -o ControlMaster=auto -o ControlPersist=5s -o ControlPath=~/.ssh/master-socket/%C -o ProxyJump=time@is.impt:2222,yes@you-r.right:12022,you@are.really.recht:12022,root@ibd:12022 -r try@it.dxng.net:/tmp/ ./tmp test "$(DFS_TRUST=1 riot time@is.impt:2222/yes@you-r.right/you@are.really.recht./ibd./try@it,another@host -D scp /tmp/ ./tmp 2>/dev/null)" = 'scp -P 12022 -o ServerAliveInterval=60 -o PermitLocalCommand=yes -o ControlMaster=auto -o ControlPersist=5s -o ControlPath=~/.ssh/master-socket/%C -o ProxyJump=time@is.impt:2222,yes@you-r.right:12022,you@are.really.recht:12022,root@ibd:12022 -r try@it.dxng.net:/tmp/ ./tmp
scp -P 12022 -o ServerAliveInterval=60 -o PermitLocalCommand=yes -o ControlMaster=auto -o ControlPersist=5s -o ControlPath=~/.ssh/master-socket/%C -o ForwardX11=yes -o ForwardAgent=yes -r another@host.dxng.net:/tmp/ ./tmp' scp -P 12022 -o ServerAliveInterval=60 -o PermitLocalCommand=yes -o ControlMaster=auto -o ControlPersist=5s -o ControlPath=~/.ssh/master-socket/%C -o ForwardX11=yes -o ForwardAgent=yes -r another@host.dxng.net:/tmp/ ./tmp'
test "$(riot you@example.com:55 -tD ssh --password -- ping -c 1 2>/dev/null)" = 'ssh -p 55 -o ServerAliveInterval=60 -o ForwardX11=yes -o ForwardAgent=yes -o PasswordAuthentication=yes -o PubkeyAuthentication=no you@example.com ping -c 1' test "$(riot you@example.com:55 -tD --password ssh ping -c 1 2>/dev/null)" = 'ssh -p 55 -o ServerAliveInterval=60 -o ForwardX11=yes -o ForwardAgent=yes -o PasswordAuthentication=yes -o PubkeyAuthentication=no you@example.com ping -c 1'
# check alias # check alias
alias p114 alias p114