#!/usr/bin/env sh # model-config.sh — 解析 SDLC 各階段的指定模型鏈(角色式路由)。 # 設定格式(一行一階段):stage=model[,fallback1[,fallback2...]] # 「#」開頭為註解,空白行忽略。階段限定:plan、analyze、implement、maintain。 # 解析順序: # 1. 目前工作目錄的 ./.jsc/models(專案覆寫) # 2. $JSC_HOME/models.conf(JSC_HOME 預設 ~/.jsc) # 專案檔有設定的階段完全覆寫全域設定;其餘階段仍讀全域檔。 # 用法: # model-config.sh get {stage} 印出該階段解析後的模型鏈(逗號分隔);未設定不印。兩種情況都 exit 0。 # model-config.sh list 每階段一行:stagechainsource(project 或 global);未設定的 chain 與 source 印「-」。 set -u JSC_HOME="${JSC_HOME:-$HOME/.jsc}" PROJECT_FILE=./.jsc/models GLOBAL_FILE="$JSC_HOME/models.conf" STAGES="plan analyze implement maintain" # 取出單一設定檔裡某階段的模型鏈。 # 同階段出現多行時取最後一行,結果才有確定性。 read_chain() { # $1=設定檔 $2=階段 [ -f "$1" ] || return 0 awk -F= -v stage="$2" ' { sub(/\r$/, "") } # 去掉 CR /^[ \t]*#/ { next } # 註解行 /^[ \t]*$/ { next } # 空白行 index($0, "=") == 0 { next } { key = $1 gsub(/[ \t]/, "", key) if (key != stage) next val = substr($0, index($0, "=") + 1) gsub(/[ \t]/, "", val) if (val != "") chain = val } END { if (chain != "") print chain } ' "$1" } # 解析單一階段:專案檔優先,該階段沒設定才退回全域檔。 # 輸出:chainsource;兩檔都沒設定時不輸出。 resolve() { # $1=階段 chain=$(read_chain "$PROJECT_FILE" "$1") if [ -n "$chain" ]; then printf '%s\tproject\n' "$chain" return 0 fi chain=$(read_chain "$GLOBAL_FILE" "$1") if [ -n "$chain" ]; then printf '%s\tglobal\n' "$chain" fi return 0 } usage() { echo "用法:model-config.sh get {plan|analyze|implement|maintain} | list" >&2 exit 1 } case "${1:-}" in get) stage="${2:-}" case " $STAGES " in *" $stage "*) ;; *) usage ;; esac resolve "$stage" | cut -f1 exit 0 ;; list) for stage in $STAGES; do line=$(resolve "$stage") if [ -n "$line" ]; then printf '%s\t%s\n' "$stage" "$line" else printf '%s\t-\t-\n' "$stage" fi done exit 0 ;; *) usage ;; esac