From 21b12675e92fe23cbf3018b4622d8da4292836a7 Mon Sep 17 00:00:00 2001 From: laily Date: Sat, 30 May 2026 13:42:51 +0800 Subject: [PATCH] fix: dirsize --- fish/completions/ff.fish | 22 ++++- fish/functions/ff-ssh.fish | 181 +++++++++++++++++++++++++++++++++++++ fish/functions/ff.fish | 6 ++ 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 fish/functions/ff-ssh.fish diff --git a/fish/completions/ff.fish b/fish/completions/ff.fish index baf16d4..1befd7d 100644 --- a/fish/completions/ff.fish +++ b/fish/completions/ff.fish @@ -1,6 +1,6 @@ # Completions for ff command complete -c ff -f -set -l ff_subcommands reload edit fish dotfile pon poff pst make script s update help region region +set -l ff_subcommands reload edit fish dotfile pon poff pst make script s update help region ssh init copy help region complete -c ff -n "not __fish_seen_subcommand_from $ff_subcommands" -a "reload" -d "Reload fish configuration" complete -c ff -n "not __fish_seen_subcommand_from $ff_subcommands" -a "edit" -d "Edit custom fish configuration" complete -c ff -n "not __fish_seen_subcommand_from $ff_subcommands" -a "fish" -d "Change to fish config directory" @@ -13,6 +13,26 @@ complete -c ff -n "not __fish_seen_subcommand_from $ff_subcommands" -a "script" complete -c ff -n "not __fish_seen_subcommand_from $ff_subcommands" -a "help" -d "Show this help message" complete -c ff -n "not __fish_seen_subcommand_from $ff_subcommands" -a "region" -d "Toggle or set CN_REGION (mirror/proxy region)" +complete -c ff -n "not __fish_seen_subcommand_from $ff_subcommands" -a "ssh" -d "SSH init (keys + config.d) or copy config to remote" + +complete -c ff -n "__fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from init copy help" -a init -d "Ensure SSH key and config.d Include" +complete -c ff -n "__fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from init copy help" -a copy -d "Copy specified SSH config file(s) to remote" +complete -c ff -n "__fish_seen_subcommand_from ssh; and not __fish_seen_subcommand_from init copy help" -a help -d "Show ssh subcommand help" + +function __ff_ssh_config_d_files + for d in $HOME/.ssh/config.d $HOME/.dotfile/ssh/config.d + if test -d $d + for f in $d/* + if test -f $f + basename $f + end + end + end + end +end + +complete -c ff -n "__fish_seen_subcommand_from ssh copy; and test (count (commandline -opc)) -eq 2" -a "(__fish_ssh_hosts 2>/dev/null; or __fish_print_hostnames)" -d "SSH host" +complete -c ff -n "__fish_seen_subcommand_from ssh copy; and test (count (commandline -opc)) -ge 3" -a "(__ff_ssh_config_d_files)" -d "Config file" # # make 子命令的补全 - 直接使用脚本文件名 # complete -c ff -n "__fish_seen_subcommand_from make" -a "help" -d "Show all make targets" diff --git a/fish/functions/ff-ssh.fish b/fish/functions/ff-ssh.fish new file mode 100644 index 0000000..3c237fa --- /dev/null +++ b/fish/functions/ff-ssh.fish @@ -0,0 +1,181 @@ +# ff ssh: local init (keys + config.d) and copy config to remote + +function __ff_ssh_has_key + for f in $HOME/.ssh/id_* + if test -f $f; and not string match -q '*.pub' -- $f + return 0 + end + end + return 1 +end + +function __ff_ssh_ensure_keys + if __ff_ssh_has_key + echo "SSH key exists, skip generation" + return 0 + end + + set -l key_path "$HOME/.ssh/id_ed25519" + set -l comment "$USER@"(hostname -s 2>/dev/null; or echo localhost) + mkdir -p "$HOME/.ssh" + chmod 700 "$HOME/.ssh" + + echo "No SSH key found, generating ed25519: $key_path" + if test -t 0 + ssh-keygen -t ed25519 -f $key_path -C $comment + else + ssh-keygen -t ed25519 -f $key_path -C $comment -N "" + echo "Non-interactive mode: created with empty passphrase" + end +end + +function __ff_ssh_ensure_config_d + set -l ssh_config "$HOME/.ssh/config" + set -l include_line "Include ~/.ssh/config.d/*" + mkdir -p "$HOME/.ssh/config.d" + chmod 700 "$HOME/.ssh" + + if not test -f $ssh_config + printf '%s\n' $include_line > $ssh_config + chmod 600 $ssh_config + echo "Created $ssh_config with $include_line" + else if grep -qE 'Include[[:space:]]+.*config\.d' $ssh_config + echo "config.d Include already in $ssh_config" + else + printf '\n# config.d\n%s\n' $include_line >> $ssh_config + echo "Appended to $ssh_config: $include_line" + end +end + +function __ff_ssh_resolve_path --argument path + if test -L $path + set path (readlink $path) + if not string match -q '/*' -- $path + set path "$HOME/.ssh/$path" + end + end + echo $path +end + +function __ff_ssh_remote_has_include --argument host + ssh -q $host 'test -f ~/.ssh/config && grep -qE "Include[[:space:]]+.*config\.d" ~/.ssh/config' +end + +function __ff_ssh_remote_ensure_include --argument host + ssh $host 'mkdir -p ~/.ssh/config.d && chmod 700 ~/.ssh + if [ -f ~/.ssh/config ] && grep -qE "Include[[:space:]]+.*config\.d" ~/.ssh/config; then + echo "Remote config.d Include already exists" + elif [ -f ~/.ssh/config ]; then + printf "\n# config.d\nInclude ~/.ssh/config.d/*\n" >> ~/.ssh/config + chmod 600 ~/.ssh/config + echo "Appended config.d Include on remote" + else + printf "%s\n" "Include ~/.ssh/config.d/*" > ~/.ssh/config + chmod 600 ~/.ssh/config + echo "Created remote config with config.d Include" + fi' +end + +function __ff_ssh_resolve_copy_src --argument file + set -l src $file + if test -f $src + echo $src + return 0 + end + set -l in_config_d "$HOME/.ssh/config.d/$file" + if test -f $in_config_d + echo $in_config_d + return 0 + end + set -l dotfile_src "$HOME/.dotfile/ssh/config.d/$file" + if test -f $dotfile_src + echo $dotfile_src + return 0 + end + return 1 +end + +function __ff_ssh_copy_remote --argument-names argv + set -l host $argv[1] + set -l files $argv[2..-1] + set -l ssh_dir "$HOME/.ssh" + set -l main_config "$ssh_dir/config" + + if test -z "$host" + echo "Usage: ff ssh copy ..." + echo " host: SSH alias or user@hostname" + echo " file: path, or name under ~/.ssh/config.d/" + return 1 + end + + if test (count $files) -eq 0 + echo "Usage: ff ssh copy ..." + echo "" + echo "Examples:" + echo " ff ssh copy mynas 30-hanxi.conf" + echo " ff ssh copy mynas ~/.dotfile/ssh/config.d/20-personal.conf" + if test -d "$ssh_dir/config.d" + echo "" + echo "Available in ~/.ssh/config.d/:" + ls -1 "$ssh_dir/config.d/" + end + return 1 + end + + echo "Checking remote Include on $host ..." + ssh -q $host "mkdir -p ~/.ssh/config.d && chmod 700 ~/.ssh" + + if __ff_ssh_remote_has_include $host + echo "Remote config.d Include: OK" + else + echo "Remote missing config.d Include, adding ..." + __ff_ssh_remote_ensure_include $host + end + + for f in $files + set -l src (__ff_ssh_resolve_copy_src $f 2>/dev/null) + if test $status -ne 0 -o -z "$src" + echo "Error: file not found: $f" + return 1 + end + + set -l resolved_main (__ff_ssh_resolve_path $main_config) + set -l name (basename $src) + + if test "$src" = "$resolved_main"; or test "$name" = config + set -l ts (date +%Y%m%d%H%M%S) + ssh -q $host "test -f ~/.ssh/config && cp ~/.ssh/config ~/.ssh/config.bak.$ts || true" + scp -q $src "$host:.ssh/config" + ssh -q $host "chmod 600 ~/.ssh/config" + echo "Copied $src -> $host:~/.ssh/config" + else + scp -q $src "$host:.ssh/config.d/$name" + ssh -q $host "chmod 600 ~/.ssh/config.d/$name" + echo "Copied $src -> $host:~/.ssh/config.d/$name" + end + end + + echo "Done." +end + +function ff_ssh --argument-names argv + set -l sub (test (count $argv) -ge 1; and echo $argv[1]; or echo init) + + switch $sub + case init '' + __ff_ssh_ensure_keys + __ff_ssh_ensure_config_d + case copy + __ff_ssh_copy_remote $argv[2..-1] + case help -h + echo "Usage: ff ssh [init|copy ...|help]" + echo "" + echo " init Ensure SSH key and config.d Include (default)" + echo " copy Check remote Include, then scp specified config file(s)" + echo " help Show this help" + case '*' + echo "Unknown subcommand: $sub" + echo "Run 'ff ssh help' for usage" + return 1 + end +end diff --git a/fish/functions/ff.fish b/fish/functions/ff.fish index 59dc33c..a6b5353 100644 --- a/fish/functions/ff.fish +++ b/fish/functions/ff.fish @@ -13,6 +13,7 @@ function ff "script|Run script from script directory" \ "update|Update dotfile" \ "region|Toggle or set CN_REGION (mirror/proxy region)" \ + "ssh|SSH init (keys + config.d) or copy config to remote" \ "help|Show this help message" # 确保 execute-script 可用(在 fish 自动加载前手动引入一次) @@ -83,6 +84,11 @@ function ff cd ~/.dotfile git pull origin main cd - + case ssh + if not functions -q ff_ssh + source ~/.dotfile/fish/functions/ff-ssh.fish + end + ff_ssh $argv[2..-1] case region set -l sub toggle if test (count $argv) -ge 2