#!/bin/sh # Variables assigned here are consumed by the sourcing install.sh/update.sh. # shellcheck disable=SC2034 # Shared helpers for the bundle's POSIX sh scripts. # Source this file; it defines say(), warn(), the Kitty/Zsh resolution # helpers, and the my-pi managed-block machinery used by install.sh and # update.sh. say() { printf '%s\n' "$*" } warn() { printf '警告: %s\n' "$*" >&2 } detect_kitty() { kitty_bin= for candidate in /Applications/kitty.app/Contents/MacOS/kitty "$HOME/.local/kitty.app/bin/kitty"; do if [ -x "$candidate" ]; then kitty_bin=$candidate return 0 fi done if command -v kitty >/dev/null 2>&1; then kitty_bin=$(command -v kitty) return 0 fi return 1 } resolve_kitty_config_dir() { kitty_config_dir=${KITTY_CONFIG_DIRECTORY:-${XDG_CONFIG_HOME:-$HOME/.config}/kitty} } resolve_zsh_paths() { oh_my_zsh_dir=${ZSH:-$HOME/.oh-my-zsh} zsh_custom_dir=${ZSH_CUSTOM:-$oh_my_zsh_dir/custom} zshrc_file=${ZDOTDIR:-$HOME}/.zshrc my_pi_config_dir=${XDG_CONFIG_HOME:-$HOME/.config}/my-pi p10k_managed_config_file=$my_pi_config_dir/p10k.zsh } # Anchor regex shared by every "before the Oh My Zsh loader" managed block. MY_PI_ZSH_LOADER_ANCHOR='^(# >>> my-pi:oh-my-zsh-loader >>>|[[:space:]]*(source|\.)[[:space:]].*oh-my-zsh\.sh)' replace_zsh_managed_block() { managed_id=$1 managed_placement=$2 managed_anchor=$3 shift 3 managed_content=$(mktemp "${TMPDIR:-/tmp}/my-pi-zsh-block.XXXXXX") || return 1 printf '%s\n' "$@" > "$managed_content" my_pi_replace_managed_block "$zshrc_file" "$managed_id" "$managed_content" \ "$managed_placement" "$managed_anchor" managed_status=$? rm -f "$managed_content" return "$managed_status" } MY_PI_MANAGED_BACKUPS=${MY_PI_MANAGED_BACKUPS:-} my_pi_backup_once() { managed_file=$1 case "|$MY_PI_MANAGED_BACKUPS|" in *"|$managed_file|"*) return 0 ;; esac if [ -f "$managed_file" ]; then managed_backup=$(mktemp "$managed_file.my-pi-backup-$(date +%Y%m%d%H%M%S).XXXXXX") || return 1 cp "$managed_file" "$managed_backup" || { rm -f "$managed_backup" return 1 } say "已备份配置到 $managed_backup" fi MY_PI_MANAGED_BACKUPS=${MY_PI_MANAGED_BACKUPS:+$MY_PI_MANAGED_BACKUPS|}$managed_file } my_pi_managed_block_exists() { managed_file=$1 managed_id=$2 managed_begin="# >>> my-pi:$managed_id >>>" managed_end="# <<< my-pi:$managed_id <<<" [ -f "$managed_file" ] || return 1 grep -F -x "$managed_begin" "$managed_file" >/dev/null 2>&1 && grep -F -x "$managed_end" "$managed_file" >/dev/null 2>&1 } my_pi_replace_managed_block() { managed_file=$1 managed_id=$2 managed_content_file=$3 managed_placement=${4:-append} managed_anchor=${5:-} managed_begin="# >>> my-pi:$managed_id >>>" managed_end="# <<< my-pi:$managed_id <<<" managed_dir=${managed_file%/*} [ "$managed_dir" = "$managed_file" ] && managed_dir=. mkdir -p "$managed_dir" || return 1 [ -f "$managed_file" ] || : > "$managed_file" || return 1 managed_counts=$(awk -v begin="$managed_begin" -v end="$managed_end" ' $0 == begin { begins++ if (active) invalid = 1 active = 1 } $0 == end { ends++ if (!active) invalid = 1 active = 0 } END { if (active) invalid = 1 printf "%d %d %d\n", begins, ends, invalid } ' "$managed_file") || return 1 managed_begin_count=${managed_counts%% *} managed_remainder=${managed_counts#* } managed_end_count=${managed_remainder%% *} managed_invalid=${managed_remainder#* } if [ "$managed_begin_count" -ne "$managed_end_count" ] || \ [ "$managed_begin_count" -gt 1 ] || [ "$managed_invalid" -ne 0 ]; then warn "$managed_file 中的 my-pi:$managed_id 受管标记不完整或重复,已拒绝修改。" return 1 fi managed_tmp=$(mktemp "$managed_dir/.my-pi-managed.XXXXXX") || return 1 if ! awk \ -v begin="$managed_begin" \ -v end="$managed_end" \ -v content="$managed_content_file" \ -v placement="$managed_placement" \ -v anchor="$managed_anchor" ' function emit_block( line) { print begin while ((getline line < content) > 0) print line close(content) print end } BEGIN { replacing = 0; emitted = 0 } $0 == begin { emit_block() replacing = 1 emitted = 1 next } replacing && $0 == end { replacing = 0; next } replacing { next } !emitted && placement == "before" && anchor != "" && $0 ~ anchor { emit_block() emitted = 1 } { print } END { if (!emitted) { if (NR > 0) print "" emit_block() } } ' "$managed_file" > "$managed_tmp"; then rm -f "$managed_tmp" return 1 fi if cmp -s "$managed_tmp" "$managed_file"; then rm -f "$managed_tmp" return 0 fi my_pi_backup_once "$managed_file" || { rm -f "$managed_tmp" return 1 } if ! mv "$managed_tmp" "$managed_file"; then rm -f "$managed_tmp" return 1 fi } my_pi_sync_managed_file() { managed_source=$1 managed_target=$2 [ -f "$managed_source" ] || { warn "找不到仓库配置:$managed_source" return 1 } if [ -f "$managed_target" ] && cmp -s "$managed_source" "$managed_target"; then return 0 fi managed_target_dir=${managed_target%/*} [ "$managed_target_dir" = "$managed_target" ] && managed_target_dir=. mkdir -p "$managed_target_dir" || return 1 my_pi_backup_once "$managed_target" || return 1 managed_tmp=$(mktemp "$managed_target_dir/.my-pi-sync.XXXXXX") || return 1 if ! cp "$managed_source" "$managed_tmp" || ! mv "$managed_tmp" "$managed_target"; then rm -f "$managed_tmp" return 1 fi say "已同步受管配置:$managed_target" }