Add safety features for file writing and enhance split command with options
This commit is contained in:
parent
dd73f3d71c
commit
75b750b662
|
|
@ -6,7 +6,7 @@ Next:
|
|||
|
||||
# Stack Language Specification
|
||||
|
||||
**Version**: 0.8
|
||||
**Version**: 0.8.1
|
||||
**Status**: Draft Specification
|
||||
**Changes**:
|
||||
- 0.5 (AI)
|
||||
|
|
@ -75,5 +75,7 @@ Next:
|
|||
6. **Tutorial content** - Added beginner tutorials to Appendix G
|
||||
7. **Trait reference** - Consolidated all trait definitions in Appendix B
|
||||
8. **Grammar simplification** - Referenced Implementable trait instead of repeating
|
||||
- 0.8.1 (Human)
|
||||
1. Added links
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import re
|
|||
import sys
|
||||
import json
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
|
||||
filenames = [
|
||||
"docs/changes.md",
|
||||
|
|
@ -72,7 +73,37 @@ def combine_markdown(file_inputs, output_combined, output_meta_json):
|
|||
print(f"Combined file saved as: {output_combined}")
|
||||
print(f"Metadata JSON saved as: {output_meta_json}")
|
||||
|
||||
def split_with_front_matter(input_combined, output_dir, metadata_file):
|
||||
def write_with_safety(path, content, force=False, backup=False):
|
||||
"""Write a file safely with force/backup options and diff-aware prompt."""
|
||||
if path.exists():
|
||||
current = path.read_text(encoding='utf-8')
|
||||
if current == content:
|
||||
print(f"No changes for: {path}")
|
||||
return
|
||||
|
||||
if backup and not force:
|
||||
backup_path = path.with_suffix(path.suffix + ".bak")
|
||||
shutil.copy2(path, backup_path)
|
||||
print(f"Backup created: {backup_path}")
|
||||
elif not force:
|
||||
while True:
|
||||
choice = input(f"{path} has changed. [y] overwrite, [b] backup+overwrite, [n] skip? ").strip().lower()
|
||||
if choice in ("y", "yes"):
|
||||
break
|
||||
elif choice in ("b", "backup"):
|
||||
backup_path = path.with_suffix(path.suffix + ".bak")
|
||||
shutil.copy2(path, backup_path)
|
||||
print(f"Backup created: {backup_path}")
|
||||
break
|
||||
elif choice in ("n", "no", ""):
|
||||
print(f"Skipped: {path}")
|
||||
return
|
||||
else:
|
||||
print("Please choose [y], [b], or [n].")
|
||||
path.write_text(content, encoding='utf-8')
|
||||
print(f"Wrote: {path}")
|
||||
|
||||
def split_with_front_matter(input_combined, output_dir, metadata_file, force=False, backup=False):
|
||||
"""Split a combined markdown file back into original files, restoring front matter."""
|
||||
content = Path(input_combined).read_text(encoding='utf-8')
|
||||
|
||||
|
|
@ -81,13 +112,15 @@ def split_with_front_matter(input_combined, output_dir, metadata_file):
|
|||
sys.exit(1)
|
||||
|
||||
meta_info = json.loads(Path(metadata_file).read_text(encoding='utf-8'))
|
||||
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# Find all sections between <!-- START filename.md --> and <!-- END filename.md -->
|
||||
pattern = r'<!-- START (.*?) -->\n(.*?)\n<!-- END \1 -->'
|
||||
matches = re.findall(pattern, content, flags=re.DOTALL)
|
||||
|
||||
total_written = 0
|
||||
total_skipped = 0
|
||||
total_backups = 0
|
||||
|
||||
for filename, body in matches:
|
||||
body = body.strip()
|
||||
output_path = Path(output_dir, filename)
|
||||
|
|
@ -99,26 +132,35 @@ def split_with_front_matter(input_combined, output_dir, metadata_file):
|
|||
else:
|
||||
restored = body + "\n"
|
||||
|
||||
output_path.write_text(restored, encoding='utf-8')
|
||||
print(f"Restored: {output_path}")
|
||||
before = output_path.exists()
|
||||
write_with_safety(output_path, restored, force=force, backup=backup)
|
||||
|
||||
print("Split complete.")
|
||||
if backup and before:
|
||||
total_backups += 1
|
||||
if output_path.exists():
|
||||
total_written += 1
|
||||
else:
|
||||
total_skipped += 1
|
||||
|
||||
print(f"Split complete. {total_written} files written, {total_skipped} skipped, {total_backups} backups made.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage:")
|
||||
print(" Combine files: python manage_docs.py combine")
|
||||
print(" Split files: python manage_docs.py split")
|
||||
print(" Combine: python manage_docs.py combine")
|
||||
print(" Split: python manage_docs.py split [--force|--backup]")
|
||||
sys.exit(1)
|
||||
|
||||
command = sys.argv[1].lower()
|
||||
force = "--force" in sys.argv
|
||||
backup = "--backup" in sys.argv
|
||||
|
||||
if command == "combine":
|
||||
combine_markdown(filenames, "stack_lang_spec.md", "metadata.json")
|
||||
|
||||
elif command == "split":
|
||||
split_with_front_matter("stack_lang_spec.md", "docs", "metadata.json")
|
||||
split_with_front_matter("stack_lang_spec.md", "docs", "metadata.json",
|
||||
force=force, backup=backup)
|
||||
|
||||
else:
|
||||
print("Unknown command. Use 'combine' or 'split'.")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<!-- START changes.md -->
|
||||
# Stack Language Specification
|
||||
|
||||
**Version**: 0.8
|
||||
**Version**: 0.8.1
|
||||
**Status**: Draft Specification
|
||||
**Changes**:
|
||||
- 0.5 (AI)
|
||||
|
|
@ -70,6 +70,8 @@
|
|||
6. **Tutorial content** - Added beginner tutorials to Appendix G
|
||||
7. **Trait reference** - Consolidated all trait definitions in Appendix B
|
||||
8. **Grammar simplification** - Referenced Implementable trait instead of repeating
|
||||
- 0.8.1 (Human)
|
||||
1. Added links
|
||||
|
||||
---
|
||||
<!-- END changes.md -->
|
||||
|
|
|
|||
Loading…
Reference in New Issue