From ecf92c5ee47ba440ab0f0acbdeb4ab0a7b7fea3e Mon Sep 17 00:00:00 2001 From: yetsing Date: Mon, 23 Feb 2026 00:31:54 +0800 Subject: [PATCH] feat: Add generate_readme.py script --- README.md | 11 +++- README.template.md | 11 ++++ generate_readme.py | 125 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 README.template.md create mode 100644 generate_readme.py diff --git a/README.md b/README.md index 7cbe7b8..d1f2a11 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,12 @@ # toolbox -工具箱 \ No newline at end of file +工具箱 + +# tool list + +> 暂无 Python 脚本或可执行包。 + + +--- +> 自动由 `generate_readme.py` 生成 + diff --git a/README.template.md b/README.template.md new file mode 100644 index 0000000..afb6e94 --- /dev/null +++ b/README.template.md @@ -0,0 +1,11 @@ +# toolbox + +工具箱 + +# tool list + +{content} + +--- +> 自动由 `{script_name}` 生成 + diff --git a/generate_readme.py b/generate_readme.py new file mode 100644 index 0000000..8392eee --- /dev/null +++ b/generate_readme.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +自动生成 README.md:扫描当前目录下的 Python 脚本和可执行包, +提取其 docstring 并更新到 README 中。 +""" + +import os +import ast +import sys +from pathlib import Path + +# 当前脚本所在目录 +SCRIPT_DIR = Path(__file__).parent.resolve() + +# 输出 README 路径 +README_PATH = SCRIPT_DIR / "README.md" + +# 模板路径(可选) +TEMPLATE_PATH = SCRIPT_DIR / "README.template.md" + + +def extract_docstring_from_file(file_path: Path) -> str: + """从 Python 文件中提取模块级 docstring。""" + try: + with open(file_path, "r", encoding="utf-8") as f: + node = ast.parse(f.read()) + return ast.get_docstring(node) or "(无文档说明)" + except Exception as e: + return f"(解析失败: {e})" + + +def collect_items(): + """收集当前目录下所有 .py 文件和含 __main__.py 的子目录。""" + items = [] + + for item in SCRIPT_DIR.iterdir(): + if item.name == Path(__file__).name: + continue # 跳过本脚本 + if item.name.startswith("."): + continue # 跳过隐藏文件/目录 + + if item.is_file() and item.suffix == ".py": + name = item.stem + doc = extract_docstring_from_file(item) + items.append({"type": "script", "name": name, "doc": doc, "path": item.name}) + + elif item.is_dir(): + main_py = item / "__main__.py" + if main_py.exists(): + name = item.name + doc = extract_docstring_from_file(main_py) + items.append({"type": "package", "name": name, "doc": doc, "path": str(item.name) + "/__main__.py"}) + + # 按名称排序 + items.sort(key=lambda x: x["name"].lower()) + return items + + +def load_template() -> str: + """加载模板:优先用 README.template.md,否则用内置模板。""" + if TEMPLATE_PATH.exists(): + with open(TEMPLATE_PATH, "r", encoding="utf-8") as f: + return f.read() + else: + # 内置默认模板 + return """# 工具集 + +本目录包含以下可执行脚本与工具包: + +{content} + +--- +> 自动由 `{script_name}` 生成 +""" + + +def generate_content(items): + """根据 items 生成 Markdown 内容。""" + if not items: + return "> 暂无 Python 脚本或可执行包。\n" + + lines = [] + for item in items: + title = f"`{item['name']}`" + if item["type"] == "package": + title += " (包)" + lines.append(f"## {title}") + lines.append("") + # 渲染 docstring(保留原始换行,但缩进处理) + doc = item["doc"].strip() + if doc: + # 如果 docstring 是多行,用引用块或直接段落 + if "\n" in doc: + lines.append("```text") + lines.append(doc) + lines.append("```") + else: + lines.append(doc) + else: + lines.append("(无文档说明)") + lines.append("") + lines.append(f"> 文件路径: `{item['path']}`") + lines.append("") + return "\n".join(lines) + + +def main(): + items = collect_items() + template = load_template() + content = generate_content(items) + readme_text = template.format( + content=content, + script_name=Path(__file__).name + ) + + with open(README_PATH, "w", encoding="utf-8") as f: + f.write(readme_text) + + print(f"✅ README.md 已更新,共收录 {len(items)} 个项目。") + + +if __name__ == "__main__": + main() +