07-control-flow / 08-c-operations / 10-imports / README:cif-celif-celse 成套语法与 defined() 谓词改写条件编译章节;值引用注解 &T / &temp T 取代 t.CNeedPtr;assert 自动导入 testcheck 并改译 testcheck.check(cond, None, msg)。MergeWiki.py 仅微调合并快照横幅措辞。
147 lines
5.8 KiB
Python
147 lines
5.8 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""MergeWiki.py - 把 wiki 目录下的 Markdown 快速合并成可发送给 AI 的快照
|
||
|
||
用法(在本目录下执行):
|
||
python MergeWiki.py # → WikiAi0.md(若超块大小则 WikiAi0.md, WikiAi1.md, ...)
|
||
python MergeWiki.py 输出前缀 # 自定义输出前缀
|
||
python MergeWiki.py 输出前缀 200 # 自定义输出前缀 + 每块大小(KB)
|
||
|
||
特点:
|
||
* 递归收集本目录(脚本所在目录)下所有 *.md / *.MD(跳过 .git 与自身产出);
|
||
* 按路径排序合并,结果可复现;
|
||
* 每个文件前后插入 `<!-- ===== BEGIN/END FILE: <相对路径> ===== -->` 边界标记;
|
||
* 每块开头插入文件头,含用途与【弱时效性】声明;
|
||
* 默认每块 199KB(与 Tools/sendaiandsplit.py 口径一致)。
|
||
|
||
【弱时效性声明】
|
||
wiki 会持续修订,本脚本产出的是**生成时刻的快照**。发送给 AI 前请重新生成,
|
||
分析结论请以 wiki 目录下的**实时文件**为准,不要固化。
|
||
"""
|
||
import os
|
||
import sys
|
||
import time
|
||
|
||
DEFAULT_PREFIX = "WikiAi"
|
||
DEFAULT_CHUNK_KB = 199
|
||
|
||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||
|
||
|
||
def CollectMarkdown(Dir: str, Prefix: str):
|
||
"""递归收集 *.md / *.MD(跳过 .git 与以 Prefix 开头的自身产出),返回排序后的路径列表。"""
|
||
Matched = []
|
||
LowPrefix = Prefix.lower()
|
||
for Root, Dirs, Files in os.walk(Dir):
|
||
Dirs[:] = [d for d in Dirs if d != ".git"]
|
||
for F in Files:
|
||
Lower = F.lower()
|
||
if not (Lower.endswith(".md")):
|
||
continue
|
||
if Lower.startswith(LowPrefix):
|
||
continue
|
||
Matched.append(os.path.join(Root, F))
|
||
Matched.sort()
|
||
return Matched
|
||
|
||
|
||
def Banner(Title: str, SrcDir: str, FileCount: int, Total: int,
|
||
ChunkIndex: int, ChunkTotal: int, OutName: str) -> str:
|
||
"""生成面向 AI 分析的文件头(含【弱时效性】声明)。"""
|
||
Stamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
||
return (
|
||
"<!-- ============================================================ -->\n"
|
||
f"<!-- {Title} -->\n"
|
||
"<!-- 用途:把 wiki 全部章节合并为的快照。 -->\n"
|
||
"<!-- 【弱时效性】本文件是生成时刻的快照,wiki 会持续修订;请以目录下实时文件为准, -->\n"
|
||
"<!-- 结论不要固化;需要最新内容请重新运行 MergeWiki.py。 -->\n"
|
||
f"<!-- 生成时间:{Stamp} -->\n"
|
||
f"<!-- 源目录 :{SrcDir} -->\n"
|
||
f"<!-- 文件数 :{FileCount} -->\n"
|
||
f"<!-- 内容字节:{Total} -->\n"
|
||
f"<!-- 分块 :第 {ChunkIndex + 1}/{ChunkTotal} 块 → {OutName} -->\n"
|
||
"<!-- ============================================================ -->\n\n"
|
||
)
|
||
|
||
|
||
def MergeWiki(Dir: str, Prefix: str, ChunkKb: int) -> int:
|
||
"""合并 Dir 下所有 Markdown,带边界标记与【弱时效性】文件头,按 ChunkKb 分块输出。"""
|
||
if not os.path.isdir(Dir):
|
||
print(f"错误: 目录 {Dir} 不存在", file=sys.stderr)
|
||
return 1
|
||
|
||
Matched = CollectMarkdown(Dir, Prefix)
|
||
if not Matched:
|
||
print(f"错误: {Dir} 下没有可合并的 Markdown", file=sys.stderr)
|
||
return 1
|
||
|
||
Parts = []
|
||
Total = 0
|
||
try:
|
||
for Path in Matched:
|
||
Rel = os.path.relpath(Path, Dir).replace("\\", "/")
|
||
with open(Path, "r", encoding="utf-8") as Fh:
|
||
Content = Fh.read()
|
||
Total += len(Content)
|
||
Parts.append(f"<!-- ===== BEGIN FILE: {Rel} ===== -->\n")
|
||
Parts.append(Content)
|
||
if not Content.endswith("\n"):
|
||
Parts.append("\n")
|
||
Parts.append(f"<!-- ===== END FILE: {Rel} ===== -->\n\n")
|
||
except OSError as Exc:
|
||
print(f"错误: 读取源文件失败: {Exc}", file=sys.stderr)
|
||
return 1
|
||
|
||
Body = "".join(Parts)
|
||
ChunkSize = max(1, ChunkKb) * 1024
|
||
ChunkTotal = max(1, (len(Body) + ChunkSize - 1) // ChunkSize)
|
||
Title = "Viper wiki 快照(AI 分析用)"
|
||
|
||
for i in range(ChunkTotal):
|
||
Chunk = Body[i * ChunkSize:(i + 1) * ChunkSize]
|
||
OutName = f"{Prefix}{i}.md"
|
||
OutPath = os.path.join(Dir, OutName)
|
||
try:
|
||
with open(OutPath, "w", encoding="utf-8") as Out:
|
||
Out.write(Banner(Title, Dir, len(Matched), Total, i, ChunkTotal, OutName))
|
||
Out.write(Chunk)
|
||
except OSError as Exc:
|
||
print(f"错误: 写入 {OutName} 失败: {Exc}", file=sys.stderr)
|
||
return 1
|
||
print(f"{OutName}: {len(Chunk)} 字节")
|
||
|
||
print(f"wiki 合并完成: {len(Matched)} 个文件 → {ChunkTotal} 块(前缀 {Prefix},每块 {ChunkKb}KB)")
|
||
print("【弱时效性】以上为生成时刻快照,请以 wiki 目录下实时文件为准。")
|
||
return 0
|
||
|
||
|
||
def PrintUsage() -> None:
|
||
print("用法: python MergeWiki.py [输出前缀] [块大小KB]", file=sys.stderr)
|
||
print(f" 默认: 前缀 {DEFAULT_PREFIX},块大小 {DEFAULT_CHUNK_KB}KB", file=sys.stderr)
|
||
print(" 合并本目录下所有 *.md/*.MD → <前缀>0.md, <前缀>1.md, ...", file=sys.stderr)
|
||
print("【弱时效性】产出为生成时刻快照,分析结论请以实时文件为准。", file=sys.stderr)
|
||
|
||
|
||
def main() -> int:
|
||
Args = sys.argv[1:]
|
||
Prefix = DEFAULT_PREFIX
|
||
ChunkKb = DEFAULT_CHUNK_KB
|
||
|
||
if len(Args) >= 1 and Args[0] not in ("-h", "--help"):
|
||
Prefix = Args[0]
|
||
if len(Args) >= 2:
|
||
try:
|
||
ChunkKb = int(Args[1])
|
||
except ValueError:
|
||
print(f"错误: 块大小 '{Args[1]}' 不是整数", file=sys.stderr)
|
||
PrintUsage()
|
||
return 1
|
||
if len(Args) > 2 or (len(Args) >= 1 and Args[0] in ("-h", "--help")):
|
||
PrintUsage()
|
||
return 1
|
||
|
||
return MergeWiki(HERE, Prefix, ChunkKb)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|