11 Commits

10 changed files with 258 additions and 27 deletions

View File

@@ -1,4 +1,5 @@
set -g prefix ^a set -g prefix ^a
bind ^a send-prefix
set -g mouse on set -g mouse on
set -g set-clipboard on set -g set-clipboard on
set -g default-terminal "xterm-256color" set -g default-terminal "xterm-256color"

27
.zshrc2
View File

@@ -9,6 +9,7 @@ else
fi fi
export DOTFILES=$( cd "$( dirname "${BASH_SOURCE[0]:-${(%):-%x}}" )" && pwd ) export DOTFILES=$( cd "$( dirname "${BASH_SOURCE[0]:-${(%):-%x}}" )" && pwd )
export PATH="$PATH:$DOTFILES/scripts" export PATH="$PATH:$DOTFILES/scripts"
fpath=($DOTFILES/functions $fpath)
export EDITOR='vim' export EDITOR='vim'
# env for apps # env for apps
export PYTHONIOENCODING='UTF-8' export PYTHONIOENCODING='UTF-8'
@@ -130,9 +131,29 @@ alias "jcf"='jc -f'
alias "jcfu"='jc -fu' alias "jcfu"='jc -fu'
alias "sc"='systemctl' alias "sc"='systemctl'
alias "t"='tmux' alias "t"='tmux'
gbes() { git for-each-ref --sort=-committerdate refs/heads refs/remotes --format="%(authordate:format:%y-%m-%d.%a %H:%M %z)|%(color:red)%(objectname:short)|%(color:yellow)%(refname:short)%(color:reset)|%(color:reset)%(authorname): %(color:green)%(subject)" --color=always | column -ts"|" | less -FX } gbes() { git for-each-ref --sort=-committerdate refs/heads refs/remotes --format="%(authordate:format:%y-%m-%d.%a %H:%M %z)|%(color:red)%(objectname:short)|%(color:yellow)%(refname:short)%(color:reset)|%(color:reset)%(authorname): %(color:green)%(subject)" --color=always | column -ts"|" | less -FX ; }
sagt() { eval "$($DOTFILES/tools/sagent.sh $@)" } sagt() { eval "$($DOTFILES/tools/sagent.sh $@)" ; }
use() { nix --experimental-features nix-command --extra-experimental-features flakes shell "${(*)@/#%(#b)([^#]#)/nixpkgs#$match}" } ## nixos
use() { nix --experimental-features nix-command --extra-experimental-features flakes shell "${(*)@/#%(#b)([^#]#)/nixpkgs#$match}" ; }
bnd() {
if [[ -n "$1" && -d "./hosts/$1" ]]; then
nixos-rebuild --flake .#$1 build || return $?
nix-diff /opt/NixOS-Config/results/hosts/$1 ./result --color=always | less
else
echo host $1 does not exist
fi
}
nor() {
test -n "$1" || { echo fatal: no verb given; return 1; }
nixos-rebuild "$1" --flake .${2:+#}$2
}
alias 'nors'='nor switch'
alias 'norbt'='nor boot'
alias 'nort'='nor test'
alias 'norb'='nor build'
alias 'nordb'='nor dry-build'
alias 'norda'='nor dry-activate'
# key bindings # key bindings
bindkey "^b" beginning-of-line # ctrl+b bindkey "^b" beginning-of-line # ctrl+b

99
functions/_beam Normal file
View File

@@ -0,0 +1,99 @@
#compdef beam
# =============================================================================
# Beam-Go Zsh Completion Script
# =============================================================================
_beam() {
local context state state_descr line
typeset -A opt_args
_arguments -C \
'1: :_beam_commands' \
'*:: :->args'
case $state in
(args)
case $line[1] in
(serve) _beam_serve ;;
(add) _beam_add ;;
(list) _beam_list ;;
(del) _beam_del ;;
esac
;;
esac
}
# --- Subcommand Definitions ---
(( $+functions[_beam_commands] )) ||
_beam_commands() {
local -a commands
commands=(
'serve:Start the beam server daemon'
'add:Share a file or directory'
'list:List active shares'
'del:Delete a share by path or code'
)
_describe -t commands 'beam command' commands
}
_beam_serve() {
_arguments \
'(-d --database)'{-d,--database}'=[Database directory (Required)]:directory:_path_files -/' \
'(-p --port)'{-p,--port}'=[Port to listen on (default :8280)]:port:' \
'(-s --socket)'{-s,--socket}'=[Socket path]:socket path:_files' \
'--subpath=[Enable subpath sharing]'
}
_beam_add() {
_arguments \
'(-d --days)'{-d,--days}'=[Expiration days (default 7)]:days:' \
'(-s --socket)'{-s,--socket}'=[Socket path]:socket path:_files' \
'1:file to share:_files'
}
_beam_list() {
_arguments \
'(-s --socket)'{-s,--socket}'=[Socket path]:socket path:_files'
}
_beam_del() {
_arguments \
'(-s --socket)'{-s,--socket}'=[Socket path]:socket path:_files' \
'(-c --code)'{-c,--code}'=[Share code]:share code:_beam_active_codes' \
'1:shared path:_files'
}
# --- Helpers ---
# 动态获取当前的 Share Code
# 它会尝试读取用户当前输入的 -s 参数,去连接正确的 socket
_beam_active_codes() {
local socket_path=""
# 从 Zsh 解析的参数中提取 socket 路径
if [[ -n ${opt_args[-s]} ]]; then
socket_path=${opt_args[-s]}
elif [[ -n ${opt_args[--socket]} ]]; then
socket_path=${opt_args[--socket]}
fi
# 构造查询命令
local cmd_args=()
cmd_args+=("list")
[[ -n $socket_path ]] && cmd_args+=("-s" "$socket_path")
# 调用 beam list,跳过前两行表头,提取 Code($1) 和 Path($3)
# 2>/dev/null 防止服务未启动时报错打印到终端
local -a shares
shares=("${(@f)$(beam "${cmd_args[@]}" 2>/dev/null | awk 'NR>2 {print $1":"$2" "$3" "$4}')}")
if [[ ${#shares} -gt 0 ]]; then
_describe -t shares 'active share' shares
else
_message 'no active shares or server not running'
fi
}
_beam "$@"

35
functions/_beaml Normal file
View File

@@ -0,0 +1,35 @@
#compdef beaml
_beaml() {
local context state line
typeset -A opt_args
_arguments -C \
'1: :->cmds' \
'2: :->args'
case $state in
cmds)
local commands; commands=(
'add:Add a new item'
'del:Delete an item'
'list:List all items'
)
_describe -t commands 'beaml commands' commands
;;
args)
case $line[1] in
add)
_files
;;
del)
local -a items
items=( /pss/lite/*(N:t) )
_describe -t items 'item to delete' items
;;
esac
;;
esac
}
_beaml "$@"

View File

@@ -0,0 +1,3 @@
#compdef bnd nor
compadd -- /root/NixOS-Config/hosts/*(/:t)

3
functions/_sagt Normal file
View File

@@ -0,0 +1,3 @@
#compdef sagt
compadd -- kill ls op piv reset

3
functions/_use Normal file
View File

@@ -0,0 +1,3 @@
#compdef use
compadd -- $(nix eval --impure --expr 'builtins.attrNames ( (import <nixpkgs>) {} )' 2>/dev/null | tr '[]"' ' ')

View File

@@ -25,7 +25,7 @@ nasps.batch() {
# remotes # remotes
nasp.remote() { nasp.remote() {
remote=nasp.fit remote=jump.nasp.fit
RET_PORT=${RET_PORT:-36022} RET_PORT=${RET_PORT:-36022}
RET_USERNAME=${RET_USERNAME:-root} RET_USERNAME=${RET_USERNAME:-root}
RET_TRUST_SERVER=1 RET_TRUST_SERVER=1
@@ -60,7 +60,7 @@ nasp.domain() {
RET_HOSTNAME=$host RET_HOSTNAME=$host
RET_PORT=${RET_PORT:-12022} RET_PORT=${RET_PORT:-12022}
RET_USERNAME=${RET_USERNAME:-root} RET_USERNAME=${RET_USERNAME:-root}
RET_JUMP_SERVER="ssh@nasp.fit:36022" RET_JUMP_SERVER="ssh@jump.nasp.fit:36022"
RET_TRUST_SERVER=1 RET_TRUST_SERVER=1
} }

View File

@@ -20,14 +20,14 @@ done
# check if port number valid # check if port number valid
check_port() { check_port() {
( echo $1 | grep -qxE "[1-9][0-9]{0,4}" ) || return 1 [[ "$1" =~ ^[1-9][0-9]{0,4}$ ]] || return 1
test $1 -lt 65536 -a $1 -gt 0 || return 1 [[ $1 < 65536 && $1 > 0 ]] || return 1
return 0 return 0
} }
# check if username valid # check if username valid
check_username() { check_username() {
( echo $1 | grep -qxE "^[a-z][-a-z0-9_]*\$" ) || return 1 [[ "$1" =~ ^[a-z][-a-z0-9_]*$ ]] || return 1
return 0 return 0
} }
@@ -42,18 +42,28 @@ get_server_meta() {
RET_JUMP_SERVER="" # optional RET_JUMP_SERVER="" # optional
# body # body
local remote="$1" local remote="$1"
# if in the form user@... # extract username from user@...
if [[ "$remote" == *@* ]]; then if [[ "$remote" == *@* ]]; then
RET_USERNAME=${remote%%@*} RET_USERNAME=${remote%%@*}
remote=${remote#*@} remote=${remote#*@}
check_username $RET_USERNAME || fmt_warning \"$RET_USERNAME\" is not a valid unix username check_username $RET_USERNAME || fmt_warning \"$RET_USERNAME\" is not a valid unix username
fi fi
# if in the form ...:22 # extract port from ...:port
if [[ "$remote" == "["*"]":* || ( "$remote" != "["*"]" && "$remote" == *:* ) ]]; then if [[
"$remote" =~ ^[^:]+:[1-9][0-9]*$ # contains only one colon
|| "$remote" =~ ^\[.+\]:[1-9][0-9]*$ # in the form of [host]:port
|| "$remote" =~ :::[1-9][0-9]*$ # in the form of :::port
|| "$remote" =~ ^([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}:[1-9][0-9]*$ # full ipv6 address with port
|| "$remote" =~ ^[0-9a-f:]+%.+:[1-9][0-9]*$ # ipv6 address with scope and port
]]; then
RET_PORT=${remote##*:} RET_PORT=${remote##*:}
remote=${remote%:*} remote=${remote%:*}
check_port $RET_PORT || fmt_fatal invalid port number \"$RET_PORT\" check_port $RET_PORT || fmt_fatal invalid port number \"$RET_PORT\"
fi fi
# remove square brackets
if [[ "$remote" =~ ^\[.*\]$ ]]; then
remote=${remote:1:-1}
fi
# presets -- match remote # presets -- match remote
local remote_func="$remote.remote" local remote_func="$remote.remote"
if is_function "$remote_func"; then if is_function "$remote_func"; then
@@ -63,8 +73,8 @@ get_server_meta() {
RET_HOSTNAME=${remote} RET_HOSTNAME=${remote}
local domain=${remote##*.} local domain=${remote##*.}
local host=${remote%.*} local host=${remote%.*}
# if there's no dot # if it contains no dot and is not ipv6
if [[ "$host" == "$domain" && "$host" != "["*"]" ]]; then if [[ "$remote" != *.* && "$remote" != *:* ]]; then
domain="default" domain="default"
fi fi
local domain_func="$domain.domain" local domain_func="$domain.domain"
@@ -83,7 +93,10 @@ parse_remote() {
TRUST_SERVER=1 TRUST_SERVER=1
PORT="" # optional PORT="" # optional
USERNAME="" # optional USERNAME="" # optional
SSH_OPTIONS=("-o" "RequestTTY=yes") SSH_OPTIONS=("-o" "ServerAliveInterval=60")
if [[ -t 1 ]]; then
SSH_OPTIONS+=("-o" "RequestTTY=yes")
fi
if [[ "$RIOT_TRUST_CLIENT" == "1" ]]; then if [[ "$RIOT_TRUST_CLIENT" == "1" ]]; then
SSH_OPTIONS+=("-o" "PermitLocalCommand=yes") SSH_OPTIONS+=("-o" "PermitLocalCommand=yes")
if [[ "$(get_os_type)" != "msys" ]]; then if [[ "$(get_os_type)" != "msys" ]]; then
@@ -125,7 +138,7 @@ parse_remote() {
print_cmd() { print_cmd() {
local output="" local output=""
for s in "${CMD[@]}"; do for s in "${CMD[@]}"; do
if [[ "$s" =~ [\ \\\'\"] ]]; then if [[ "$s" =~ [\ \\\'\"] ]]; then # needs to be escaped
s="${s@Q}" s="${s@Q}"
fi fi
output+="$s " output+="$s "
@@ -185,19 +198,50 @@ run_ssh()
# sshl # sshl
run_sshl() run_sshl()
{ {
local arg="$1" local arg left right localsock access
if [[ "$arg" != *":"* ]]; then local res="${1//[^:]}"
# treat as a port number local lorr="-L"
arg=localhost:$arg if [[ "${FUNCNAME[1]}" == "run_sshr" ]]; then
lorr="-R"
fi fi
local port=$(get_free_port) if [[ ${#res} -eq 2 ]]; then
SSH_OPTIONS+=("-NC" "-L" "$port:$arg") arg="$1"
elif [[ ${#res} -eq 0 ]]; then
if [[ "$lorr" == "-R" ]]; then
arg="$1"
else
arg="$(get_free_port):localhost:$1"
fi
else
left=${1%%:*}
right=${1##*:}
if check_port "$left"; then
arg="$1"
elif check_port "$right"; then
arg="$(get_free_port):$1"
else
arg="$1"
localsock=1
fi
fi
if [[ "$localsock" == "1" ]]; then
access="unix://${arg%%:*}"
else
access="localhost:${arg%%:*}"
fi
SSH_OPTIONS+=("-NC" "$lorr" "$arg")
prepare_ssh_cmd ssh prepare_ssh_cmd ssh
print_cmd print_cmd
fmt_note " > please access localhost:$port" fmt_note " > please access $access"
eval_or_echo eval_or_echo
} }
# sshr
run_sshr()
{
run_sshl "$1"
}
# sshd # sshd
run_sshd() run_sshd()
{ {
@@ -259,11 +303,12 @@ remove_hostkey() {
# main # main
print_help() print_help()
{ {
fmt_info "usage: $0 [-Ddhlqt] [--dry-run] [--dev] [--help] [--lite] [--quite] [--trust] [--tmux] [--password] [[-o ssh-option]...] remote [command] [--] [ssh-command-args]" fmt_info "usage: $0 [-Ddhlqt] [--dry-run] [--dev] [--help] [--lite] [--quite] [--trust] [--tmux] [--password] [[-o ssh-option]...] remote [command] [--] [command-args]"
cat <<EOF cat <<EOF
available commands: available commands:
- ssh [ssh-command-args] (default) - ssh [ssh-command-args] (default)
- tmux [ssh-command-args] (run ssh in multiple tmux windows) - tmux [ssh-command-args] (run ssh in multiple tmux windows)
- git [git-command-args] (run git on remote machine)
- sshl [local-port:remote-host:]remote-port (ssh -L) - sshl [local-port:remote-host:]remote-port (ssh -L)
- sshd [local-port] (ssh -D) - sshd [local-port] (ssh -D)
- zssh [ssh-command-args] - zssh [ssh-command-args]
@@ -295,13 +340,22 @@ router() {
EXTRA_SSH_OPTIONS+=("-o" "$2") EXTRA_SSH_OPTIONS+=("-o" "$2")
shift shift
;; ;;
-4 )
EXTRA_SSH_OPTIONS+=("-4")
;;
-6 )
EXTRA_SSH_OPTIONS+=("-6")
;;
-v )
EXTRA_SSH_OPTIONS+=("-v")
;;
-- ) -- )
shift shift
positional+=("$@") positional+=("$@")
break break
;; ;;
-* ) -* )
fmt_fatal "unknown option: $1" fmt_fatal "unknown option: '$1'. if this option is for the remote command, add '--' before."
;; ;;
* ) * )
positional+=("$1") positional+=("$1")
@@ -328,6 +382,13 @@ router() {
[[ "${positional[1]}" == tmux ]] && USE_TMUX=1 [[ "${positional[1]}" == tmux ]] && USE_TMUX=1
run_ssh ssh "${positional[@]:2}" run_ssh ssh "${positional[@]:2}"
;; ;;
git )
if printf '%s\0' "${positional[@]:2}" | grep -Fxqz -- '-C'; then
run_ssh ssh git "${positional[@]:2}"
else
run_ssh ssh git -C "$(pwd)" "${positional[@]:2}"
fi
;;
ping|ping4|ping6 ) ping|ping4|ping6 )
test "${#positional[@]}" -eq 2 || fmt_fatal "ping requires no arguments" test "${#positional[@]}" -eq 2 || fmt_fatal "ping requires no arguments"
run_ping "${positional[1]}" run_ping "${positional[1]}"
@@ -343,6 +404,11 @@ router() {
test "${#positional[@]}" -eq 3 || fmt_fatal "sshl requires exactly one argument" test "${#positional[@]}" -eq 3 || fmt_fatal "sshl requires exactly one argument"
run_sshl "${positional[2]}" run_sshl "${positional[2]}"
;; ;;
sshr )
test -n "${positional[2]}" || fmt_fatal "no target address provided"
test "${#positional[@]}" -eq 3 || fmt_fatal "sshr requires exactly one argument"
run_sshr "${positional[2]}"
;;
sshd ) sshd )
test "${#positional[@]}" -le 3 || fmt_fatal "sshd requires one or no arguments" test "${#positional[@]}" -le 3 || fmt_fatal "sshd requires one or no arguments"
if [[ "${#positional[@]}" -eq 3 ]]; then if [[ "${#positional[@]}" -eq 3 ]]; then

View File

@@ -40,9 +40,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 RequestTTY=yes -o PermitLocalCommand=yes -o ControlMaster=auto -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 scp /tmp/ ./tmp -D 2>/dev/null)" = 'scp -P 12022 -o ServerAliveInterval=60 -o PermitLocalCommand=yes -o ControlMaster=auto -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 RequestTTY=yes -o PermitLocalCommand=yes -o ControlMaster=auto -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 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 RequestTTY=yes -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 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'
# check alias # check alias
alias p114 alias p114