refactor(plugin 命名空間): plugin 更名 jsc-doc、hooks 只註冊自己擁有的 worklog
- 五份 manifest 的 name 由 jsc 改為 jsc-doc - skill 目錄去掉重複的 doc- 前綴共 5 個(doc-funcs → funcs 等),worklog 名稱不變,frontmatter name 同步 - hooks/hooks.json 由合併超集改為只註冊 Stop(worklog):role 的 hook 交還 jsc-generic,避免改名後重複執行 - hook 腳本搜尋路徑與文件內 cache 路徑改指 jsc-doc - 指令引用改為 /jsc-doc: 前綴;跨 plugin 引用指向 /jsc-code:、/jsc-generic: - 保留 .docs/doc-funcs-index.md 等產物檔名不變(非 skill 識別名) - 版號 0.2.6 → 0.2.7 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
---
|
||||
name: docker
|
||||
description: 整理並對齊 docker-compose.yaml 的行內註解與標題區塊。當使用者要對齊 docker-compose 註解、整理 compose 檔註解欄位、更新 compose 標題日期,或提到 docker-compose、dc-tidy、align_comments、註解對齊時使用此 skill。
|
||||
---
|
||||
|
||||
# 對齊 docker-compose 註解
|
||||
|
||||
整理並對齊 `docker-compose.yaml` 的行內註解與標題。請優先使用自動化腳本執行。
|
||||
|
||||
以下範例中的 `skill_dir` 是本 skill 所在目錄,也就是包含此 `SKILL.md` 與 `scripts/` 的資料夾。不要假設目標專案內存在 `plugins/skills/docker/`。
|
||||
|
||||
## 全專案批次處理(未指定檔案時)
|
||||
|
||||
```bash
|
||||
bash "${skill_dir}/scripts/align_comments.sh" --yes
|
||||
```
|
||||
|
||||
## 單一檔案處理(指定檔案時)
|
||||
|
||||
`${file}` 為使用者指定的目標檔案:
|
||||
|
||||
```bash
|
||||
bash "${skill_dir}/scripts/align_comments.sh" "${file}" --yes
|
||||
```
|
||||
|
||||
## 手動執行流程參考
|
||||
|
||||
1. **[步驟 0] 還原空白基準**:移除既有對齊用空白,回到可重新計算的狀態。
|
||||
|
||||
```bash
|
||||
tmp="$(mktemp "${file}.tmp.XXXXXX")" && awk -f "${skill_dir}/scripts/awk/strip_col.awk" "${file}" > "$tmp" && mv -- "$tmp" "${file}"
|
||||
```
|
||||
|
||||
2. **[步驟 1] 校閱註解**:修正註解文字與數值正確性。
|
||||
|
||||
3. **[步驟 2] 計算對齊欄位**:取得對齊欄位。
|
||||
|
||||
```bash
|
||||
awk -f "${skill_dir}/scripts/awk/find_col.awk" "${file}"
|
||||
```
|
||||
|
||||
取得 `TARGET=XX`。
|
||||
|
||||
4. **[步驟 3] 執行對齊**:依 `TARGET` 欄位對齊註解。
|
||||
|
||||
```bash
|
||||
tmp="$(mktemp "${file}.tmp.XXXXXX")" && awk -v TARGET=<TARGET> -f "${skill_dir}/scripts/awk/align_col.awk" "${file}" > "$tmp" && mv -- "$tmp" "${file}"
|
||||
```
|
||||
|
||||
5. **[步驟 4] 驗證對齊**:驗證對齊結果。
|
||||
|
||||
```bash
|
||||
awk -v TARGET=<TARGET> -f "${skill_dir}/scripts/awk/verify_col.awk" "${file}"
|
||||
```
|
||||
|
||||
6. **[步驟 5] 更新日期**:更新標題區塊的 `更新日期` 為今日。
|
||||
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env bash
|
||||
# docker-compose 註解對齊工具
|
||||
# 用法: bash align_comments.sh [file_or_directory] [--yes]
|
||||
#
|
||||
# 功能:
|
||||
# 1. 如果未指定檔案,則搜尋專案中所有 docker-compose.yaml。
|
||||
# 2. 每個檔案獨立計算註解對齊欄位。
|
||||
# 3. 更新標題中的更新日期。
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 參數處理
|
||||
target_path=""
|
||||
auto_confirm=false
|
||||
had_failure=false
|
||||
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == "--yes" ]] || [[ "$arg" == "-y" ]]; then
|
||||
auto_confirm=true
|
||||
else
|
||||
target_path="$arg"
|
||||
fi
|
||||
done
|
||||
|
||||
AWK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/awk"
|
||||
|
||||
write_with_tmp() {
|
||||
local source_file="$1"
|
||||
local awk_file="$2"
|
||||
shift 2
|
||||
|
||||
local tmp_file
|
||||
tmp_file="$(mktemp "${source_file}.tmp.XXXXXX")"
|
||||
if awk "$@" -f "$awk_file" "$source_file" > "$tmp_file"; then
|
||||
mv -- "$tmp_file" "$source_file"
|
||||
else
|
||||
rm -f -- "$tmp_file"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
process_file() {
|
||||
local file="$1"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
echo "Skip: $file is not a file."
|
||||
return
|
||||
fi
|
||||
|
||||
echo ">>> Processing: $file"
|
||||
|
||||
# 步驟 0:還原多餘空白 (Strip)
|
||||
write_with_tmp "$file" "$AWK_DIR/strip_col.awk"
|
||||
echo "[0] Strip done."
|
||||
|
||||
# 步驟 1:人工修正註解內容 (Review)
|
||||
if [[ "$auto_confirm" == "false" ]]; then
|
||||
echo "[1] 請檢查註解內容是否正確 ($file)。"
|
||||
read -r -p "完成後按 Enter 繼續 (或輸入 's' 跳過此檔, 'a' 全部自動完成): " input
|
||||
if [[ "$input" == "s" ]]; then
|
||||
echo "Skipped."
|
||||
return
|
||||
fi
|
||||
if [[ "$input" == "a" ]]; then
|
||||
auto_confirm=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# 步驟 2:找出最大對齊欄位 (Find)
|
||||
local target
|
||||
target=$(awk -f "$AWK_DIR/find_col.awk" "$file" | awk -F= '{print $2}')
|
||||
|
||||
if [[ -z "$target" ]] || [[ "$target" -eq 0 ]]; then
|
||||
echo "[2] No inline comments found. Skipping alignment."
|
||||
else
|
||||
echo "[2] Calculated TARGET column: $target"
|
||||
|
||||
# 步驟 3:對齊 (Align)
|
||||
write_with_tmp "$file" "$AWK_DIR/align_col.awk" -v TARGET="$target"
|
||||
echo "[3] Align done."
|
||||
|
||||
# 步驟 4:驗證 (Verify)
|
||||
local verify
|
||||
verify=$(awk -v TARGET="$target" -f "$AWK_DIR/verify_col.awk" "$file")
|
||||
if [[ -z "$verify" ]]; then
|
||||
echo "[4] Verify OK."
|
||||
else
|
||||
echo "[4] Verify FAILED for $file:"
|
||||
echo "$verify"
|
||||
had_failure=true
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 步驟 5:更新標題日期 (Update)
|
||||
local today
|
||||
today=$(date +%Y-%m-%d)
|
||||
# 支援不同的 sed 版本 (Linux/GNU vs BSD/MacOS)
|
||||
if sed --version >/dev/null 2>&1; then
|
||||
# GNU sed
|
||||
sed -i "s/# 更新日期: [0-9-]*/# 更新日期: $today/" "$file"
|
||||
else
|
||||
# BSD sed (MacOS)
|
||||
sed -i '' "s/# 更新日期: [0-9-]*/# 更新日期: $today/" "$file"
|
||||
fi
|
||||
echo "[5] Updated '更新日期' to $today."
|
||||
echo ""
|
||||
}
|
||||
|
||||
find_compose_files() {
|
||||
local root="$1"
|
||||
|
||||
find "$root" \
|
||||
\( -path '*/node_modules' -o -path '*/.git' -o -path '*/bin' -o -path '*/obj' \) -prune \
|
||||
-o -name 'docker-compose.yaml' -type f -print0
|
||||
}
|
||||
|
||||
process_found_files() {
|
||||
local root="$1"
|
||||
local found=false
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
found=true
|
||||
process_file "$file" || had_failure=true
|
||||
done < <(find_compose_files "$root")
|
||||
|
||||
if [[ "$found" == "false" ]]; then
|
||||
echo "No docker-compose.yaml files found."
|
||||
fi
|
||||
}
|
||||
|
||||
# 執行邏輯
|
||||
if [[ -z "$target_path" ]]; then
|
||||
echo "No target specified. Searching for all docker-compose.yaml files in the project..."
|
||||
process_found_files "."
|
||||
elif [[ -d "$target_path" ]]; then
|
||||
echo "Target is a directory. Searching for docker-compose.yaml files within: $target_path"
|
||||
process_found_files "$target_path"
|
||||
else
|
||||
process_file "$target_path" || had_failure=true
|
||||
fi
|
||||
|
||||
if [[ "$had_failure" == "true" ]]; then
|
||||
echo "Done with failures."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Done!"
|
||||
@@ -0,0 +1,9 @@
|
||||
!/^[[:space:]]*#/ && / #/ {
|
||||
idx = index($0, " #")
|
||||
if (idx > 0 && idx != TARGET) {
|
||||
pad = ""
|
||||
for (i = idx; i < TARGET; i++) pad = pad " "
|
||||
sub(/ #/, pad " #")
|
||||
}
|
||||
}
|
||||
{ print }
|
||||
@@ -0,0 +1,8 @@
|
||||
!/^[[:space:]]*#/ && / #/ {
|
||||
idx = index($0, " #")
|
||||
content = substr($0, 1, idx - 1)
|
||||
gsub(/ +$/, "", content)
|
||||
col = length(content) + 2
|
||||
if (col > max_col) max_col = col
|
||||
}
|
||||
END { print "max_col=" max_col }
|
||||
@@ -0,0 +1,8 @@
|
||||
!/^[[:space:]]*#/ && / #/ {
|
||||
idx = index($0, " #")
|
||||
content = substr($0, 1, idx - 1)
|
||||
gsub(/ +$/, "", content)
|
||||
comment = substr($0, idx)
|
||||
$0 = content comment
|
||||
}
|
||||
{ print }
|
||||
@@ -0,0 +1,4 @@
|
||||
!/^[[:space:]]*#/ && / #/ {
|
||||
idx = index($0, " #")
|
||||
if (idx != TARGET) print NR, "col=" idx, substr($0, 1, 80)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# 自動補全與修正 docker-compose.yaml 行內註解內容
|
||||
# 用法: bash scripts/fix_comments.sh <file>
|
||||
|
||||
set -euo pipefail
|
||||
file="${1:-}"
|
||||
if [ -z "$file" ]; then
|
||||
echo "請指定要處理的檔案"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp_file="$(mktemp "${file}.tmp.XXXXXX")"
|
||||
trap 'rm -f -- "$tmp_file"' EXIT
|
||||
|
||||
awk '
|
||||
/^[[:space:]]*#/ { print; next }
|
||||
/[[:space:]]+#/ {
|
||||
match($0, /[[:space:]]+#/);
|
||||
code=substr($0, 1, RSTART - 1);
|
||||
comment=substr($0, RSTART + RLENGTH);
|
||||
gsub(/^ +| +$/, "", comment);
|
||||
if (length(comment)==0) comment="TODO: 補充說明";
|
||||
print code " # " comment;
|
||||
next;
|
||||
}
|
||||
{ print }
|
||||
' "$file" > "$tmp_file"
|
||||
|
||||
mv -- "$tmp_file" "$file"
|
||||
trap - EXIT
|
||||
Reference in New Issue
Block a user