2026-05-31 02:25:28 +00:00
|
|
|
import os
|
|
|
|
|
|
2026-06-04 10:09:45 +00:00
|
|
|
import os
|
|
|
|
|
import argparse
|
|
|
|
|
|
2026-05-31 02:25:28 +00:00
|
|
|
# ==========================================
|
|
|
|
|
# 設定區
|
|
|
|
|
# ==========================================
|
|
|
|
|
# ⚠️ 嚴格排除的資料夾 (完全不掃描這些目錄)
|
|
|
|
|
EXCLUDE_DIRS = {
|
|
|
|
|
"__pycache__",
|
|
|
|
|
".git",
|
|
|
|
|
".vscode", # VS Code 設定檔
|
|
|
|
|
".continue", # Continue.dev 設定檔
|
2026-06-04 10:09:45 +00:00
|
|
|
"cmts_api_env", # 🚨 Python 虛擬環境
|
|
|
|
|
"venv",
|
2026-05-31 02:25:28 +00:00
|
|
|
".venv",
|
|
|
|
|
"node_modules",
|
|
|
|
|
"dist",
|
|
|
|
|
"build"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ⚠️ 排除的檔案副檔名 (不讀取這些格式)
|
|
|
|
|
EXCLUDE_EXTENSIONS = {
|
2026-06-04 10:09:45 +00:00
|
|
|
".png", ".jpg", ".jpeg", ".gif", ".ico", ".svg",
|
|
|
|
|
".pyc", ".pyo", ".pyd",
|
|
|
|
|
".exe", ".dll", ".so", ".dylib",
|
|
|
|
|
".zip", ".tar", ".gz", ".rar",
|
|
|
|
|
".pdf", ".doc", ".docx",
|
|
|
|
|
".sqlite3", ".db"
|
2026-05-31 02:25:28 +00:00
|
|
|
}
|
|
|
|
|
|
2026-06-04 10:09:45 +00:00
|
|
|
# ⚠️ 排除的特定檔案名稱
|
2026-05-31 02:25:28 +00:00
|
|
|
EXCLUDE_FILES = {
|
2026-06-04 10:09:45 +00:00
|
|
|
"merge_code.py", # 排除這支腳本自己
|
|
|
|
|
"all_code.txt", # 排除全域輸出的檔案
|
|
|
|
|
"target_code.txt", # 排除指定輸出的檔案 (新增)
|
|
|
|
|
".DS_Store",
|
|
|
|
|
".clineignore",
|
|
|
|
|
".clinerules",
|
|
|
|
|
".gitignore",
|
|
|
|
|
"requirements.txt"
|
2026-05-31 02:25:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def should_process_file(filename):
|
2026-06-04 10:09:45 +00:00
|
|
|
"""判斷該檔案是否應該被處理 (用於全域掃描)"""
|
2026-05-31 02:25:28 +00:00
|
|
|
if filename in EXCLUDE_FILES:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
ext = os.path.splitext(filename)[1].lower()
|
|
|
|
|
if ext in EXCLUDE_EXTENSIONS:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2026-06-04 10:09:45 +00:00
|
|
|
def merge_all_files():
|
|
|
|
|
"""模式一:全域掃描 (無參數時觸發)"""
|
|
|
|
|
output_file = "all_code.txt"
|
2026-05-31 02:25:28 +00:00
|
|
|
root_dir = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
2026-06-04 10:09:45 +00:00
|
|
|
with open(output_file, "w", encoding="utf-8") as outfile:
|
2026-05-31 02:25:28 +00:00
|
|
|
outfile.write("=" * 80 + "\n")
|
2026-06-04 10:09:45 +00:00
|
|
|
outfile.write("PROJECT SOURCE CODE EXPORT (FULL)\n")
|
2026-05-31 02:25:28 +00:00
|
|
|
outfile.write("=" * 80 + "\n\n")
|
|
|
|
|
|
|
|
|
|
for dirpath, dirnames, filenames in os.walk(root_dir):
|
|
|
|
|
dirnames[:] = [d for d in dirnames if d not in EXCLUDE_DIRS]
|
|
|
|
|
|
|
|
|
|
for filename in filenames:
|
|
|
|
|
if should_process_file(filename):
|
|
|
|
|
file_path = os.path.join(dirpath, filename)
|
|
|
|
|
rel_path = os.path.relpath(file_path, root_dir)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
with open(file_path, "r", encoding="utf-8") as infile:
|
|
|
|
|
content = infile.read()
|
|
|
|
|
outfile.write("\n" + "=" * 80 + "\n")
|
|
|
|
|
outfile.write(f"FILE: {rel_path}\n")
|
|
|
|
|
outfile.write("=" * 80 + "\n")
|
|
|
|
|
outfile.write(content)
|
|
|
|
|
outfile.write("\n")
|
|
|
|
|
print(f"✅ 已合併: {rel_path}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ 讀取失敗 {rel_path}: {e}")
|
|
|
|
|
|
2026-06-04 10:09:45 +00:00
|
|
|
print(f"\n🎉 全域合併完成!所有程式碼已儲存至: {output_file}")
|
|
|
|
|
|
|
|
|
|
def merge_target_files(file_list):
|
|
|
|
|
"""模式二:指定檔案合併 (-t 參數觸發)"""
|
|
|
|
|
output_file = "target_code.txt"
|
|
|
|
|
root_dir = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
|
|
|
|
with open(output_file, "w", encoding="utf-8") as outfile:
|
|
|
|
|
outfile.write("=" * 80 + "\n")
|
|
|
|
|
outfile.write("TARGET SOURCE CODE EXPORT (SPECIFIC)\n")
|
|
|
|
|
outfile.write("=" * 80 + "\n\n")
|
|
|
|
|
|
|
|
|
|
for rel_path in file_list:
|
|
|
|
|
file_path = os.path.join(root_dir, rel_path)
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(file_path):
|
|
|
|
|
print(f"❌ 找不到檔案 (已跳過): {rel_path}")
|
|
|
|
|
continue
|
|
|
|
|
if not os.path.isfile(file_path):
|
|
|
|
|
print(f"❌ 不是有效檔案 (已跳過): {rel_path}")
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
with open(file_path, "r", encoding="utf-8") as infile:
|
|
|
|
|
content = infile.read()
|
|
|
|
|
outfile.write("\n" + "=" * 80 + "\n")
|
|
|
|
|
outfile.write(f"FILE: {rel_path}\n")
|
|
|
|
|
outfile.write("=" * 80 + "\n")
|
|
|
|
|
outfile.write(content)
|
|
|
|
|
outfile.write("\n")
|
|
|
|
|
print(f"✅ 已合併: {rel_path}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"❌ 讀取失敗 {rel_path}: {e}")
|
|
|
|
|
|
|
|
|
|
print(f"\n🎯 指定合併完成!選定的程式碼已儲存至: {output_file}")
|
2026-05-31 02:25:28 +00:00
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2026-06-04 10:09:45 +00:00
|
|
|
# 使用 argparse 來解析終端機指令
|
|
|
|
|
parser = argparse.ArgumentParser(description="合併專案程式碼供 AI 讀取")
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
'-t', '--target',
|
|
|
|
|
nargs='+', # 允許接收一個或多個參數
|
|
|
|
|
help="指定要合併的檔案路徑 (例如: -t main.py routers/api.py)"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
# 根據是否有傳入 -t 參數,決定執行哪一種模式
|
|
|
|
|
if args.target:
|
|
|
|
|
print("🔍 啟動 [指定模式]...")
|
|
|
|
|
merge_target_files(args.target)
|
|
|
|
|
else:
|
|
|
|
|
print("🔍 啟動 [全域模式]...")
|
|
|
|
|
merge_all_files()
|