feat(tools): 新增發現合併與變更註解兩支腳本
- 合併、去重、排序原本寫在兩支技能的步驟文字裡,各寫一份就會各自演化。改由腳本執行,並定下六欄 TSV 的回報格式。格式不對就擋下並指出是第幾列,不猜、不放行、不自行補欄。 - 另一支腳本列出本次改到的註解行,清理範圍不再靠肉眼判讀。 - 註解樣式與非程式碼副檔名清單沿用註解範圍腳本的同一份,不另立第二套判準。markdown 的標題行開頭就是井字號,判準不一致就會把整份文件當成註解。
This commit is contained in:
Executable
+107
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env sh
|
||||
# changed-comments.sh — 列出本次變更裡新增或修改的註解行,供 comment-cleanup 決定清理範圍。
|
||||
#
|
||||
# 用法:
|
||||
# changed-comments.sh 比對工作區與 HEAD(git diff HEAD),即尚未提交的變更
|
||||
# changed-comments.sh <base> 比對基準版本(git diff {base}...HEAD),實作完成時用
|
||||
# 一律在要檢查的存取庫目錄下執行;本腳本不吃路徑參數,也不切換目錄。
|
||||
#
|
||||
# 輸出(TSV,一列一行註解,三欄,欄位之間一個 tab,只走 stdout):
|
||||
# 1 檔案 路徑,相對存取庫根目錄
|
||||
# 2 行號 該註解行在新版檔案裡的行號,正整數
|
||||
# 3 內容 該行原文;行內的 tab 換成一個空白,欄位才不會錯位
|
||||
#
|
||||
# 結束碼:
|
||||
# 0 有結果,至少印出一列
|
||||
# 1 沒有結果,本次變更沒有新增或修改的註解行(呼叫端回報「無發現」)
|
||||
# 2 參數或環境錯誤:參數超過一個、目前目錄不在 git 工作區、基準版本無效、缺 git 或 awk
|
||||
#
|
||||
# 判準的來源:註解行樣式與「不受本規則限制的非程式碼副檔名」兩份判準,都沿用 jsc-hooks 的
|
||||
# hooks/comment-scope.sh(scan_file 裡的那兩份),一字不差地照抄。那支 hook 是規則實作的
|
||||
# 正本,這裡只是把同一份判準搬到 git diff 上;哪天正本改了樣式,這裡要跟著改,不得各自演化。
|
||||
# 跳過非程式碼檔不是可有可無的:markdown 的標題行開頭就是 #,不跳過就會把整份文件當成註解。
|
||||
set -u
|
||||
|
||||
usage() {
|
||||
echo '用法:changed-comments.sh [base](不給基準時比對工作區與 HEAD)' >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
[ "$#" -le 1 ] || usage
|
||||
|
||||
for cmd in git awk; do
|
||||
command -v "$cmd" >/dev/null 2>&1 || {
|
||||
echo "錯誤:環境缺 $cmd,無法列出變更的註解行。" >&2
|
||||
exit 2
|
||||
}
|
||||
done
|
||||
|
||||
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || {
|
||||
echo '錯誤:目前目錄不在 git 工作區內,取不到變更範圍。' >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
# git diff 的失敗一律原樣往上帶:判不出範圍卻回「無發現」,等於把環境問題講成沒有東西要清。
|
||||
if [ "$#" -eq 1 ]; then
|
||||
base=$1
|
||||
case "$base" in
|
||||
-*) usage ;;
|
||||
esac
|
||||
git rev-parse --verify --quiet "$base^{commit}" >/dev/null 2>&1 || {
|
||||
echo "錯誤:基準版本「$base」不是有效的 commit。" >&2
|
||||
exit 2
|
||||
}
|
||||
DIFF=$(git diff --no-color -U0 "$base...HEAD" 2>&1) || {
|
||||
printf '%s\n' "$DIFF" >&2
|
||||
exit 2
|
||||
}
|
||||
else
|
||||
DIFF=$(git diff --no-color -U0 HEAD 2>&1) || {
|
||||
printf '%s\n' "$DIFF" >&2
|
||||
exit 2
|
||||
}
|
||||
fi
|
||||
|
||||
# 樣式走環境變數交給 awk:走 -v 的話 awk 會先解釋字串裡的跳脫序列,樣式中的 \* 會被吃成
|
||||
# 量詞 *,整條 ERE 的意思就變了。ENVIRON 不做這層處理,樣式進到 awk 時與正本一字不差。
|
||||
COMMENT_RE='^[[:space:]]*(//|#|--|\*|/\*|<!--|;|%)|[[:space:]](//|#)[[:space:]]'
|
||||
|
||||
OUT=$(printf '%s\n' "$DIFF" | COMMENT_RE="$COMMENT_RE" awk '
|
||||
BEGIN { OFS = "\t"; re = ENVIRON["COMMENT_RE"]; skip = 1 }
|
||||
|
||||
# 非程式碼檔沒有「程式碼註解」,整檔跳過(副檔名清單同 comment-scope.sh)。
|
||||
function skipped(p) {
|
||||
return (p ~ /\.(md|markdown|txt|rst|json|csv|tsv|svg|lock|log)$/ || p ~ /COMMIT_EDITMSG$/)
|
||||
}
|
||||
|
||||
/^\+\+\+ / {
|
||||
f = substr($0, 5) # 去掉開頭的「+++ 」
|
||||
sub(/^b\//, "", f)
|
||||
skip = (f == "" || f == "/dev/null" || skipped(f))
|
||||
next
|
||||
}
|
||||
|
||||
# 區塊標頭 @@ -a,b +c,d @@:第三欄的 +c 就是這一段在新版檔案裡的起始行號。
|
||||
/^@@ / {
|
||||
t = $3
|
||||
sub(/^\+/, "", t)
|
||||
sub(/,.*$/, "", t)
|
||||
ln = t + 0
|
||||
next
|
||||
}
|
||||
|
||||
/^\+/ {
|
||||
if (skip || ln < 1) next
|
||||
line = substr($0, 2)
|
||||
if (line ~ re) {
|
||||
out = line
|
||||
gsub(/\t/, " ", out)
|
||||
print f, ln, out
|
||||
}
|
||||
ln++ # 只有新增行會佔掉新版檔案的行號,刪除行不會
|
||||
}
|
||||
')
|
||||
|
||||
[ -n "$OUT" ] || exit 1
|
||||
printf '%s\n' "$OUT"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user