请按照以下标准格式生成项目文档:
- 文档标题:# 项目名称
- 结构部分:
标题:## Project Structure / 项目结构
内容:用树形图展示,使用符号 ├── │ └── 表示层级关系
格式:文件名后添加 # 英文描述 / 中文描述 的注释 - 文件内容部分:
每个文件独立章节:## 序号. 文件描述 – (目录/文件名) (重要)
每个章节包含完整的代码块,代码块语言根据文件扩展名自动设置 - 特殊要求:
- 目录以斜杠 / 结尾
- 完整路径包含在括号中
- 整个项目按照这种结构,给出来
Py解析Md生成项目🧡—-deep
import os
import re
import argparse
from pathlib import Path
from collections import defaultdict
def parse_markdown_file(md_file_path):
"""解析Markdown文件,提取项目结构和文件内容"""
try:
with open(md_file_path, 'r', encoding='utf-8') as f:
content = f.read()
except UnicodeDecodeError:
try:
with open(md_file_path, 'r', encoding='gbk') as f:
content = f.read()
except:
with open(md_file_path, 'r', encoding='latin-1') as f:
content = f.read()
# 解析项目结构
project_structure = {'root': '', 'files': [], 'dirs': []}
# 查找项目结构部分
structure_patterns = [
r'## 项目结构\s*```[^\n]*\n([\s\S]*?)```',
r'## 文件结构\s*```[^\n]*\n([\s\S]*?)```',
r'## Project Structure\s*```[^\n]*\n([\s\S]*?)```',
r'#+.*结构[^#]*```[^\n]*\n([\s\S]*?)```',
]
structure_text = None
for pattern in structure_patterns:
structure_match = re.search(pattern, content, re.IGNORECASE)
if structure_match:
structure_text = structure_match.group(1)
break
if structure_text:
lines = structure_text.strip().split('\n')
root_candidates = []
for line in lines:
clean_line = re.sub(r'[├│└──]', '', line).strip()
clean_line = re.sub(r'^\s+', '', clean_line)
if clean_line:
# 移除注释
if '#' in clean_line:
clean_line = clean_line.split('#')[0].strip()
# 移除其他注释格式
clean_line = re.sub(r'//.*$', '', clean_line).strip()
clean_line = re.sub(r'/\*.*\*/', '', clean_line).strip()
if clean_line:
# 检查是否是目录
is_directory = clean_line.endswith('/')
# 保存到结构
if is_directory:
project_structure['dirs'].append(clean_line.rstrip('/'))
else:
project_structure['files'].append(clean_line)
# 提取可能的根目录
if '/' in clean_line:
parts = clean_line.split('/')
if parts[0] and parts[0] not in root_candidates:
root_candidates.append(parts[0])
# 确定根目录
if root_candidates:
from collections import Counter
root_counter = Counter(root_candidates)
project_structure['root'] = root_counter.most_common(1)[0][0]
else:
project_structure['root'] = Path(md_file_path).stem
else:
project_structure['root'] = 'generated-project'
# 解析文件内容
file_contents = {}
# 匹配文件章节
pattern = r'(?:##\s+\d+\.\s+[^(\n]+\(([^)]+)\)|##\s+[^(\n]+\(([^)]+)\)|##+\s+([^\s\.]+\.\w+))\s*[\s\S]*?```(?:\w+)?\n([\s\S]*?)```'
matches = re.findall(pattern, content)
for match in matches:
filename = match[0] or match[1] or match[2]
code_content = match[3]
if filename and code_content:
filename = filename.strip()
code_content = code_content.strip()
# 标准化路径
filename = filename.replace('\\', '/')
# 如果文件名是纯文件名,查找在结构中的完整路径
if '/' not in filename:
for struct_file in project_structure['files']:
if filename in struct_file:
filename = struct_file
break
file_contents[filename] = code_content
return project_structure, file_contents
def analyze_directory_needs(project_structure, file_contents):
"""分析需要创建的目录"""
# 收集所有包含文件的目录
dirs_needed = set()
# 1. 从有内容的文件中提取目录
for file_path in file_contents.keys():
path_obj = Path(file_path)
if len(path_obj.parts) > 1:
# 获取父目录
parent_dir = str(path_obj.parent)
dirs_needed.add(parent_dir)
# 2. 从项目结构中检查目录是否真的需要
final_dirs = set()
for dir_path in project_structure.get('dirs', []):
# 检查这个目录是否包含任何文件
dir_has_files = False
# 检查有内容的文件
for file_path in file_contents.keys():
if file_path.startswith(dir_path + '/'):
dir_has_files = True
break
# 检查项目结构中的文件
if not dir_has_files:
for struct_file in project_structure.get('files', []):
if struct_file.startswith(dir_path + '/'):
dir_has_files = True
break
if dir_has_files:
final_dirs.add(dir_path)
# 添加必要的父目录
all_dirs = set(final_dirs)
for dir_path in final_dirs:
# 添加所有父目录
parts = dir_path.split('/')
for i in range(1, len(parts)):
parent_dir = '/'.join(parts[:i])
if parent_dir:
all_dirs.add(parent_dir)
return sorted(all_dirs)
def create_project_with_report(project_structure, file_contents, output_dir='.'):
"""创建项目并生成详细报告"""
report = {
'summary': {
'total_files_in_structure': 0,
'files_with_content': 0,
'files_created': 0,
'files_skipped': 0,
'dirs_needed': 0,
'dirs_created': 0,
'dirs_skipped': 0
},
'details': {
'files_created': [],
'files_skipped': [],
'files_missing_content': [],
'dirs_created': [],
'dirs_skipped': []
}
}
# 获取项目根目录
root_dir = Path(output_dir) / project_structure['root']
# 分析需要的目录
needed_dirs = analyze_directory_needs(project_structure, file_contents)
report['summary']['dirs_needed'] = len(needed_dirs)
print(f"\n{'='*60}")
print(f"项目创建分析报告")
print(f"{'='*60}")
print(f"项目根目录: {root_dir}")
print(f"\n分析结果:")
# 1. 创建必要的目录
for dir_path in needed_dirs:
full_dir_path = root_dir / dir_path
if full_dir_path.exists():
print(f" ✓ 目录已存在: {dir_path}/")
report['details']['dirs_skipped'].append(str(dir_path))
else:
print(f" + 创建目录: {dir_path}/")
full_dir_path.mkdir(parents=True, exist_ok=True)
report['details']['dirs_created'].append(str(dir_path))
report['summary']['dirs_created'] += 1
# 2. 创建有内容的文件
files_in_structure = project_structure.get('files', [])
report['summary']['total_files_in_structure'] = len(files_in_structure)
report['summary']['files_with_content'] = len(file_contents)
print(f"\n文件处理:")
# 首先创建有内容的文件
for filename, content in file_contents.items():
# 检查文件是否在项目结构中
file_in_structure = any(filename == struct_file or
filename.endswith('/' + struct_file)
for struct_file in files_in_structure)
full_path = root_dir / filename
# 确保父目录存在
full_path.parent.mkdir(parents=True, exist_ok=True)
if file_in_structure:
print(f" ✓ 创建文件: {filename} (有内容)")
with open(full_path, 'w', encoding='utf-8') as f:
f.write(content)
report['details']['files_created'].append(filename)
report['summary']['files_created'] += 1
else:
print(f" ⚠ 跳过文件: {filename} (不在项目结构中)")
report['details']['files_skipped'].append(filename)
report['summary']['files_skipped'] += 1
# 3. 检查项目结构中的其他文件(没有内容的)
missing_files = []
for struct_file in files_in_structure:
# 检查这个文件是否有内容
has_content = False
for content_file in file_contents.keys():
if struct_file == content_file or content_file.endswith('/' + struct_file):
has_content = True
break
if not has_content:
# 检查文件是否已经在其他路径创建
file_exists = False
for created_file in report['details']['files_created']:
if struct_file in created_file:
file_exists = True
break
if not file_exists:
missing_files.append(struct_file)
if missing_files:
print(f"\n⚠ 以下文件在项目结构中但缺少内容:")
for i, filename in enumerate(missing_files, 1):
print(f" {i:2d}. {filename}")
report['details']['files_missing_content'].append(filename)
# 4. 创建空的占位文件(可选)
create_empty = input("\n是否要为缺少内容的文件创建空文件? (y/N): ").lower() == 'y'
if create_empty and missing_files:
print(f"\n创建空文件:")
for filename in missing_files:
full_path = root_dir / filename
full_path.parent.mkdir(parents=True, exist_ok=True)
if not full_path.exists():
print(f" + 创建空文件: {filename}")
with open(full_path, 'w', encoding='utf-8') as f:
f.write(f"# TODO: 需要补充 {filename} 的内容\n")
report['details']['files_created'].append(filename)
report['summary']['files_created'] += 1
# 生成最终报告
print(f"\n{'='*60}")
print(f"创建完成总结")
print(f"{'='*60}")
print(f"\n📁 目录统计:")
print(f" • 需要创建的目录: {report['summary']['dirs_needed']}")
print(f" • 实际创建的目录: {report['summary']['dirs_created']}")
print(f" • 跳过的目录: {len(report['details']['dirs_skipped'])}")
print(f"\n📄 文件统计:")
print(f" • 项目结构中的文件: {report['summary']['total_files_in_structure']}")
print(f" • 有内容的文件: {report['summary']['files_with_content']}")
print(f" • 实际创建的文件: {report['summary']['files_created']}")
print(f" • 跳过的文件: {report['summary']['files_skipped']}")
print(f" • 缺少内容的文件: {len(report['details']['files_missing_content'])}")
# 保存报告到文件
report_file = root_dir / "creation_report.txt"
with open(report_file, 'w', encoding='utf-8') as f:
f.write(f"项目创建报告\n")
f.write(f"=" * 50 + "\n\n")
f.write(f"项目根目录: {root_dir}\n")
f.write(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
f.write("📁 目录创建情况:\n")
f.write("-" * 30 + "\n")
if report['details']['dirs_created']:
f.write("创建的目录:\n")
for dir_path in report['details']['dirs_created']:
f.write(f" ✓ {dir_path}/\n")
else:
f.write("没有创建新目录\n")
if report['details']['dirs_skipped']:
f.write("\n跳过的目录(已存在):\n")
for dir_path in report['details']['dirs_skipped']:
f.write(f" ⚠ {dir_path}/\n")
f.write("\n📄 文件创建情况:\n")
f.write("-" * 30 + "\n")
if report['details']['files_created']:
f.write("创建的文件:\n")
for file_path in report['details']['files_created']:
f.write(f" ✓ {file_path}\n")
else:
f.write("没有创建新文件\n")
if report['details']['files_skipped']:
f.write("\n跳过的文件(不在结构中):\n")
for file_path in report['details']['files_skipped']:
f.write(f" ⚠ {file_path}\n")
if report['details']['files_missing_content']:
f.write("\n⚠ 需要补充内容的文件:\n")
for file_path in report['details']['files_missing_content']:
f.write(f" ! {file_path}\n")
print(f"\n📋 详细报告已保存到: {report_file}")
# 显示建议
if report['details']['files_missing_content']:
print(f"\n💡 建议:")
print(f" 以下文件需要在Markdown中添加内容:")
for i, filename in enumerate(report['details']['files_missing_content'][:5], 1):
print(f" {i}. {filename}")
if len(report['details']['files_missing_content']) > 5:
print(f" ... 还有 {len(report['details']['files_missing_content']) - 5} 个文件")
return str(root_dir), report
def main():
parser = argparse.ArgumentParser(
description='从Markdown文档生成项目文件结构 - 智能版',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
%(prog)s project_doc.md # 基本使用
%(prog)s project_doc.md -o ./output # 指定输出目录
%(prog)s project_doc.md --dry-run # 仅分析不创建
%(prog)s project_doc.md --report-only # 只生成报告
智能特性:
• 只创建有文件的目录
• 生成详细创建报告
• 提示缺少内容的文件
"""
)
parser.add_argument('markdown_file', help='包含项目结构的Markdown文件路径')
parser.add_argument('-o', '--output', default='.', help='输出目录(默认当前目录)')
parser.add_argument('--dry-run', action='store_true', help='模拟运行,只分析不创建')
parser.add_argument('--report-only', action='store_true', help='只生成分析报告,不创建文件')
parser.add_argument('-q', '--quiet', action='store_true', help='安静模式,减少输出')
args = parser.parse_args()
# 检查文件是否存在
if not Path(args.markdown_file).exists():
print(f"❌ 错误: 找不到文件 {args.markdown_file}")
return
try:
# 解析Markdown文件
project_structure, file_contents = parse_markdown_file(args.markdown_file)
if not args.quiet:
print(f"📄 解析文件: {args.markdown_file}")
print(f"📁 项目根目录: {project_structure.get('root', '未指定')}")
print(f"📋 项目结构中的文件: {len(project_structure.get('files', []))}")
print(f"📝 有内容的文件: {len(file_contents)}")
# 分析目录需求
needed_dirs = analyze_directory_needs(project_structure, file_contents)
if args.dry_run or args.report_only:
print(f"\n{'='*60}")
print(f"模拟运行报告")
print(f"{'='*60}")
print(f"项目: {project_structure.get('root')}")
print(f"\n📁 需要创建的目录 ({len(needed_dirs)}个):")
for dir_path in needed_dirs:
print(f" • {dir_path}/")
print(f"\n📄 文件分析:")
print(f" • 项目结构中的文件: {len(project_structure.get('files', []))}")
print(f" • 有内容的文件: {len(file_contents)}")
# 检查缺失内容
missing_files = []
for struct_file in project_structure.get('files', []):
has_content = any(struct_file in content_file or
content_file.endswith('/' + struct_file)
for content_file in file_contents.keys())
if not has_content:
missing_files.append(struct_file)
if missing_files:
print(f"\n⚠ 以下文件缺少内容:")
for filename in missing_files:
print(f" ! {filename}")
if not args.report_only:
print(f"\n💡 运行命令时不加 --dry-run 或 --report-only 来实际创建项目")
else:
# 实际创建项目
root_dir, report = create_project_with_report(
project_structure,
file_contents,
args.output
)
except Exception as e:
print(f"❌ 错误: {str(e)}")
if not args.quiet:
import traceback
traceback.print_exc()
if __name__ == "__main__":
from datetime import datetime
main()
发表评论