From ef8032b300c68815000ab51062c9705e0d3d1890 Mon Sep 17 00:00:00 2001 From: landon Date: Sat, 19 Sep 2026 10:39:41 -0500 Subject: [PATCH] Remove orphaned template folders and the dead create_scene.py script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 07-Revisions/08-Final/09-Covers/10-Archive were leftovers from before the stage renumbering to 06-Revisions/07-Final/08-Covers/09-Archive — identical content under a second set of numbers that every new project was scaffolding twice. scripts/create_scene.py (and its README) hasn't been runnable since project_template.rs stopped executing template hooks — the native "+ New Scene" button replaced it — and its docs already pointed at folder names (05-Plot, 06-First Draft) that predate the current layout. Dropping it removes a Python-interpreter dependency the app itself never used. Co-Authored-By: Claude Sonnet 5 --- .../07-Revisions/line_edits/.gitkeep | 0 .../07-Revisions/proofreading/.gitkeep | 0 .../07-Revisions/structural_edits/notes.md | 0 .../08-Final/final_manuscript.md | 0 .../08-Final/metadata/.gitkeep | 0 .../08-Final/submission_materials/.gitkeep | 0 ...ookiecutter.project_name}} - Full Text.odm | Bin 2568 -> 0 bytes .../09-Covers/.gitkeep | 0 .../10-Archive/.gitkeep | 0 .../scripts/README.md | 314 -------------- .../scripts/create_scene.py | 395 ------------------ 11 files changed, 709 deletions(-) delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/07-Revisions/line_edits/.gitkeep delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/07-Revisions/proofreading/.gitkeep delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/07-Revisions/structural_edits/notes.md delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/08-Final/final_manuscript.md delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/08-Final/metadata/.gitkeep delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/08-Final/submission_materials/.gitkeep delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/08-Final/{{cookiecutter.project_name}} - Full Text.odm delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/09-Covers/.gitkeep delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/10-Archive/.gitkeep delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/scripts/README.md delete mode 100644 templates/snowflake/{{ cookiecutter.project_name }}/scripts/create_scene.py diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/07-Revisions/line_edits/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/07-Revisions/line_edits/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/07-Revisions/proofreading/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/07-Revisions/proofreading/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/07-Revisions/structural_edits/notes.md b/templates/snowflake/{{ cookiecutter.project_name }}/07-Revisions/structural_edits/notes.md deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/08-Final/final_manuscript.md b/templates/snowflake/{{ cookiecutter.project_name }}/08-Final/final_manuscript.md deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/08-Final/metadata/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/08-Final/metadata/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/08-Final/submission_materials/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/08-Final/submission_materials/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/08-Final/{{cookiecutter.project_name}} - Full Text.odm b/templates/snowflake/{{ cookiecutter.project_name }}/08-Final/{{cookiecutter.project_name}} - Full Text.odm deleted file mode 100644 index 00477bf199ec6a63eb15c35d76a2bb9fdf6eca0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2568 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 SKLEhVd|a3z-1%7xz<&W=@K);p diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/09-Covers/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/09-Covers/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/10-Archive/.gitkeep b/templates/snowflake/{{ cookiecutter.project_name }}/10-Archive/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/scripts/README.md b/templates/snowflake/{{ cookiecutter.project_name }}/scripts/README.md deleted file mode 100644 index 7344cdd..0000000 --- a/templates/snowflake/{{ cookiecutter.project_name }}/scripts/README.md +++ /dev/null @@ -1,314 +0,0 @@ -# Scene Management Scripts - -Automate the creation and linking of planning and draft files. - ---- - -## Scripts Available - -### `create_scene.py` - -Creates linked planning and draft files for new scenes. - ---- - -## Quick Start - -### 1. Create a New Scene Pair - -```bash -# Navigate to your project root -cd /path/to/your/project - -# Create a new scene (act 1, chapter 1, scene 2) -python scripts/create_scene.py --act 1 --chapter 1 --scene 2 --title "Chapter Two: The Journey" -``` - -This creates: -- `05-Plot/act_1/scene_02.md` (planning template) -- `06-First Draft/Act 1/scene02.md` (draft file) -- Both files are automatically linked to each other - -### 2. Create Draft from Existing Planning - -```bash -# If you have an existing planning file but no draft -python scripts/create_scene.py --from-planning 05-Plot/act_1/scene_01.md -``` - -This creates the corresponding draft file and links it. - -### 3. Create Planning from Existing Draft - -```bash -# If you have an existing draft file but no planning -python scripts/create_scene.py --from-draft "06-First Draft/Act 1/scene01.md" -``` - -This creates the corresponding planning file and links it. - ---- - -## Usage Examples - -### Minimal (auto-generates title) -```bash -python scripts/create_scene.py --scene 3 -``` -Creates scene 3 in act 1, chapter 1 with title "Chapter 1: Scene 3" - -### Full specification -```bash -python scripts/create_scene.py \ - --act 2 \ - --chapter 3 \ - --scene 5 \ - --title "Chapter Three: The Revelation" \ - --type chapter -``` - -### Batch create multiple scenes -```bash -for scene in {2..10}; do - python scripts/create_scene.py --chapter 1 --scene $scene -Done -``` - ---- - -## File Structure - -### Planning Files (`05-Plot/`) -``` -05-Plot/ -├── _template.md # Template for new planning files -├── act_1/ -│ ├── scene_01.md # Planning for act 1, scene 1 -│ ├── scene_02.md # Planning for act 1, scene 2 -│ └── ... -├── act_2/ -│ ├── scene_01.md -│ └── ... -└── act_3/ - └── ... -``` - -Each planning file contains: -- YAML frontmatter with metadata (act, chapter, scene, word count targets, etc.) -- `draft_file` field pointing to the corresponding draft file -- Scene planning sections (setup, reveal, notes) - -### Draft Files (`06-First Draft/`) -``` -06-First Draft/ -├── _template.md # Template for new draft files -├── Act 1/ -│ ├── scene01.md # Draft for act 1, scene 1 -│ ├── scene02.md # Draft for act 1, scene 2 -│ └── ... -├── Act 2/ -│ ├── scene01.md -│ └── ... -└── Act 3/ - └── ... -``` - -Each draft file contains: -- YAML frontmatter with metadata -- `planning_template` field pointing to the corresponding planning file -- Word count tracking (current, session, target from planning) -- Actual scene content - ---- - -## Linking System - -The two files are linked via relative paths in their frontmatter: - -**Planning file (`05-Plot/act_1/scene_01.md`):** -```yaml ---- -draft_file: "../../06-First Draft/Act 1/scene01.md" ---- -``` - -**Draft file (`06-First Draft/Act 1/scene01.md`):** -```yaml ---- -planning_template: "../../05-Plot/act_1/scene_01.md" ---- -``` - -This bidirectional linking allows: -- Navigating from planning to draft and vice versa -- Sharing metadata between files -- Tracking progress across both - ---- - -## Metadata Reference - -### Planning File Fields - -| Field | Type | Description | -|-------|------|-------------| -| `id` | string | Unique identifier (e.g., `scene_01_01_01`) | -| `title` | string | Scene/chapter title | -| `slug` | string | URL-friendly identifier | -| `act` | int | Act number | -| `chapter` | int | Chapter number | -| `scene` | int | Scene number | -| `type` | string | `scene` \| `chapter` \| `interlude` | -| `status` | string | `planning` \| `ready` \| `blocked` | -| `word_count_target` | int | Target word count | -| `word_count_min` | int | Minimum acceptable words | -| `word_count_max` | int | Maximum acceptable words | -| `pov` | string | Point of view character | -| `characters` | list | Characters in this scene | -| `setting` | string | Primary location | -| `date` | string | Date in story timeline | -| `time` | string | Time of day | -| `conflict` | string | Central conflict | -| `theme` | string | Thematic focus | -| `tone` | string | Emotional tone | -| `draft_file` | string | Path to linked draft file | -| `order` | int | Sort order | - -### Draft File Fields - -| Field | Type | Description | -|-------|------|-------------| -| `id` | string | Unique identifier (e.g., `draft_scene_01_01_01`) | -| `title` | string | Scene/chapter title | -| `slug` | string | URL-friendly identifier | -| `act` | int | Act number | -| `chapter` | int | Chapter number | -| `scene` | int | Scene number | -| `type` | string | `draft` | -| `status` | string | `not_started` \| `in_progress` \| `completed` \| `needs_revision` | -| `word_count` | int | Current word count | -| `word_count_updated` | string | Last word count update date | -| `session_word_count` | int | Words written in current session | -| `last_session` | string | Date of last writing session | -| `total_sessions` | int | Number of writing sessions | -| `pov` | string | Point of view character | -| `version` | int | Draft version | -| `planning_template` | string | Path to linked planning file | - ---- - -## Integration with Your Workflow - -### With Drag-and-Drop Reordering - -If your editor supports drag-and-drop chapter reordering, the `order` field in the frontmatter is available for sorting. Update this field when reordering scenes. - -### With File Watchers - -To automatically create corresponding files when a new file is created: - -1. **Option A: Use the script manually** (recommended) - ```bash - # After creating a planning file manually, run: - python scripts/create_scene.py --from-planning 05-Plot/act_1/scene_05.md - ``` - -2. **Option B: Set up a file watcher** - Create a watcher script that triggers `create_scene.py` when new files are detected. - -3. **Option C: Editor integration** - If your editor supports custom commands, add a command that calls: - ```bash - python scripts/create_scene.py --from-draft "${file}" - ``` - ---- - -## Tips - -1. **Naming Convention** - - Planning: `scene_{number:02d}.md` (e.g., `scene_01.md`, `scene_02.md`) - - Draft: `scene{number:02d}.md` (e.g., `scene01.md`, `scene02.md`) - - Note the slight difference (underscore vs. no underscore) - -2. **Folder Structure** - - Planning: `05-Plot/act_{N}/` - - Draft: `06-First Draft/Act N/` - - Note the difference in folder naming (act_1 vs. Act 1) - -3. **ID Generation** - - Planning IDs: `scene_{act:02d}_{chapter:02d}_{scene:02d}` - - Draft IDs: `draft_scene_{act:02d}_{chapter:02d}_{scene:02d}` - -4. **Word Count Targets** - - Set in planning file - - Displayed in draft file - - Not automatically synced (manual update or via script) - ---- - -## Troubleshooting - -### "Module not found: yaml" -```bash -pip install pyyaml -``` - -### File paths not working -- Ensure you're running the script from the project root -- Check that the `scripts/` directory is in your project -- Verify relative paths are correct for your folder structure - -### Frontmatter not parsing -- Ensure your files start with `---` on the first line -- Ensure there's a closing `---` after the frontmatter -- YAML is sensitive to indentation (use spaces, not tabs) - ---- - -## Advanced Usage - -### Custom Metadata - -Add any additional fields to the frontmatter: - -```bash -python scripts/create_scene.py --scene 1 --custom_field "value" -``` - -### Bulk Operations - -Create multiple scenes at once: - -```bash -# Create scenes 1-10 for chapter 1 -for i in {1..10}; do - python scripts/create_scene.py --chapter 1 --scene $i -done -``` - -### Sync Existing Files - -If you have existing files without links, you can manually add the frontmatter: - -**Planning file:** -```yaml ---- -draft_file: "../../06-First Draft/Act 1/scene01.md" ---- -``` - -**Draft file:** -```yaml ---- -planning_template: "../../05-Plot/act_1/scene_01.md" ---- -``` - ---- - -## Related Files - -- `05-Plot/_template.md` - Planning file template -- `06-First Draft/_template.md` - Draft file template -- `03-Story-Bible/` - Story Bible for character/location/lore tracking diff --git a/templates/snowflake/{{ cookiecutter.project_name }}/scripts/create_scene.py b/templates/snowflake/{{ cookiecutter.project_name }}/scripts/create_scene.py deleted file mode 100644 index 95c2b34..0000000 --- a/templates/snowflake/{{ cookiecutter.project_name }}/scripts/create_scene.py +++ /dev/null @@ -1,395 +0,0 @@ -#!/usr/bin/env python3 -""" -Scene Creation Script - -Creates linked planning and draft files for a new scene. - -Usage: - python create_scene.py --act 1 --chapter 1 --scene 2 --title "Chapter Two: The Journey" - - Or with minimal args (auto-generates title): - python create_scene.py --act 1 --chapter 1 --scene 2 - - Or create from existing planning file: - python create_scene.py --from-planning 05-Plot/act_1/scene_01.md - - Or create from existing draft file: - python create_scene.py --from-draft "06-First Draft/Act 1/scene01.md" -""" - -import argparse -import os -import re -import sys -from pathlib import Path -from datetime import datetime - -# Get the project root (parent of scripts directory) -SCRIPTS_DIR = Path(__file__).parent -PROJECT_ROOT = SCRIPTS_DIR.parent - -# Template paths -PLANNING_TEMPLATE = PROJECT_ROOT / "05-Plot" / "_template.md" -DRAFT_TEMPLATE = PROJECT_ROOT / "06-First Draft" / "_template.md" - - -def slugify(text): - """Convert text to URL-friendly slug.""" - if not text: - return "" - # Convert to lowercase - text = text.lower() - # Remove special characters - text = re.sub(r'[^\w\s-]', '', text) - # Replace spaces with hyphens - text = re.sub(r'[\s_]+', '-', text) - # Remove leading/trailing hyphens - text = text.strip('-') - return text - - -def generate_title(act, chapter, scene): - """Generate a default title based on act/chapter/scene.""" - return f"Chapter {chapter}: Scene {scene}" - - -def parse_yaml_frontmatter(content): - """Parse YAML frontmatter from markdown file.""" - import yaml - - if not content.startswith('---'): - return {} - - # Find the frontmatter - lines = content.split('\n') - if lines[0].strip() == '---': - frontmatter_lines = [] - for line in lines[1:]: - if line.strip() == '---': - break - frontmatter_lines.append(line) - - try: - return yaml.safe_load('\n'.join(frontmatter_lines)) or {} - except yaml.YAMLError: - return {} - return {} - - -def update_frontmatter(content, updates): - """Update YAML frontmatter in markdown content.""" - lines = content.split('\n') - - if not lines[0].strip() == '---': - # No frontmatter, add it - yaml_content = "\n".join(f"{k}: {v}" for k, v in updates.items()) - return f"---\n{yaml_content}\n---\n\n" + content - - # Find and replace frontmatter - in_frontmatter = False - frontmatter_start = 0 - frontmatter_end = 0 - - for i, line in enumerate(lines): - if line.strip() == '---': - if not in_frontmatter: - frontmatter_start = i - in_frontmatter = True - else: - frontmatter_end = i - break - - if frontmatter_end == 0: - return content - - # Parse existing frontmatter - existing = parse_yaml_frontmatter(content) - existing.update(updates) - - # Generate new frontmatter - yaml_lines = ["---"] - for key, value in existing.items(): - if isinstance(value, str): - yaml_lines.append(f"{key}: \"{value}\"") - elif isinstance(value, list): - yaml_lines.append(f"{key}: {value}") - else: - yaml_lines.append(f"{key}: {value}") - yaml_lines.append("---") - - # Reconstruct content - new_content = "\n".join(yaml_lines) + "\n\n" + "\n".join(lines[frontmatter_end + 1:]) - return new_content - - -def create_planning_file(act, chapter, scene, title, slug=None, **kwargs): - """Create a new planning file.""" - if slug is None: - slug = slugify(title) - - # Create path - act_dir = PROJECT_ROOT / "05-Plot" / f"act_{act}" - act_dir.mkdir(parents=True, exist_ok=True) - - filename = act_dir / f"scene_{scene:02d}.md" - - # Read template - with open(PLANNING_TEMPLATE, 'r') as f: - template_content = f.read() - - # Generate ID - scene_id = f"scene_{act:02d}_{chapter:02d}_{scene:02d}" - - # Prepare frontmatter updates - frontmatter = { - 'id': scene_id, - 'title': title, - 'slug': slug, - 'act': act, - 'chapter': chapter, - 'scene': scene, - 'order': scene, - 'created': datetime.now().strftime("%Y-%m-%d"), - 'updated': datetime.now().strftime("%Y-%m-%d"), - } - - # Update with any additional kwargs - frontmatter.update(kwargs) - - # Update draft_file path if not provided - if 'draft_file' not in frontmatter: - draft_path = f"../../06-First Draft/Act {act}/scene{scene:02d}.md" - frontmatter['draft_file'] = draft_path - - # Update content - content = update_frontmatter(template_content, frontmatter) - - # Write file - with open(filename, 'w') as f: - f.write(content) - - return filename - - -def create_draft_file(act, chapter, scene, title, slug=None, planning_path=None, **kwargs): - """Create a new draft file.""" - if slug is None: - slug = slugify(title) - - # Create path - act_dir = PROJECT_ROOT / "06-First Draft" / f"Act {act}" - act_dir.mkdir(parents=True, exist_ok=True) - - filename = act_dir / f"scene{scene:02d}.md" - - # Read template - with open(DRAFT_TEMPLATE, 'r') as f: - template_content = f.read() - - # Generate ID - scene_id = f"draft_scene_{act:02d}_{chapter:02d}_{scene:02d}" - - # Prepare frontmatter updates - frontmatter = { - 'id': scene_id, - 'title': title, - 'slug': slug, - 'act': act, - 'chapter': chapter, - 'scene': scene, - 'created': datetime.now().strftime("%Y-%m-%d"), - 'updated': datetime.now().strftime("%Y-%m-%d"), - } - - # Update with any additional kwargs - frontmatter.update(kwargs) - - # Set planning_template path if not provided - if 'planning_template' not in frontmatter: - if planning_path: - # Use the provided planning path - relative_path = os.path.relpath(planning_path, act_dir) - frontmatter['planning_template'] = relative_path - else: - # Generate default path - planning_path = f"../../05-Plot/act_{act}/scene_{scene:02d}.md" - frontmatter['planning_template'] = planning_path - - # Update content - content = update_frontmatter(template_content, frontmatter) - - # Write file - with open(filename, 'w') as f: - f.write(content) - - return filename - - -def link_files(planning_path, draft_path): - """Ensure both files are linked to each other.""" - # Update planning file with draft path - with open(planning_path, 'r') as f: - planning_content = f.read() - - relative_draft = os.path.relpath(draft_path, Path(planning_path).parent) - planning_content = update_frontmatter(planning_content, { - 'draft_file': relative_draft - }) - - with open(planning_path, 'w') as f: - f.write(planning_content) - - # Update draft file with planning path - with open(draft_path, 'r') as f: - draft_content = f.read() - - relative_planning = os.path.relpath(planning_path, Path(draft_path).parent) - draft_content = update_frontmatter(draft_content, { - 'planning_template': relative_planning - }) - - with open(draft_path, 'w') as f: - f.write(draft_content) - - -def create_scene_pair(act, chapter, scene, title=None, **kwargs): - """Create both planning and draft files.""" - if title is None: - title = generate_title(act, chapter, scene) - - slug = slugify(title) - - # Create planning file - planning_path = create_planning_file( - act, chapter, scene, title, slug, **kwargs - ) - - # Create draft file (without planning_path initially) - draft_path = create_draft_file( - act, chapter, scene, title, slug, **kwargs - ) - - # Link them together - link_files(planning_path, draft_path) - - print(f"✓ Created planning file: {planning_path.relative_to(PROJECT_ROOT)}") - print(f"✓ Created draft file: {draft_path.relative_to(PROJECT_ROOT)}") - print(f"✓ Linked files together") - - return planning_path, draft_path - - -def create_from_planning(planning_path_str): - """Create a draft file from an existing planning file.""" - planning_path = Path(planning_path_str) - - if not planning_path.exists(): - print(f"Error: Planning file not found: {planning_path}") - sys.exit(1) - - # Parse planning file - with open(planning_path, 'r') as f: - planning_content = f.read() - - frontmatter = parse_yaml_frontmatter(planning_content) - - if not frontmatter: - print(f"Error: No valid frontmatter in {planning_path}") - sys.exit(1) - - act = frontmatter.get('act', 1) - chapter = frontmatter.get('chapter', 1) - scene = frontmatter.get('scene', 1) - title = frontmatter.get('title', generate_title(act, chapter, scene)) - - # Create draft file - draft_path = create_draft_file( - act, chapter, scene, title, - planning_path=planning_path - ) - - # Link files - link_files(planning_path, draft_path) - - print(f"✓ Created draft file: {draft_path.relative_to(PROJECT_ROOT)}") - print(f"✓ Linked to planning file: {planning_path.relative_to(PROJECT_ROOT)}") - - return draft_path - - -def create_from_draft(draft_path_str): - """Create a planning file from an existing draft file.""" - draft_path = Path(draft_path_str) - - if not draft_path.exists(): - print(f"Error: Draft file not found: {draft_path}") - sys.exit(1) - - # Parse draft file - with open(draft_path, 'r') as f: - draft_content = f.read() - - frontmatter = parse_yaml_frontmatter(draft_content) - - if not frontmatter: - print(f"Error: No valid frontmatter in {draft_path}") - sys.exit(1) - - act = frontmatter.get('act', 1) - chapter = frontmatter.get('chapter', 1) - scene = frontmatter.get('scene', 1) - title = frontmatter.get('title', generate_title(act, chapter, scene)) - - # Create planning file - planning_path = create_planning_file( - act, chapter, scene, title, - draft_file=draft_path - ) - - # Link files - link_files(planning_path, draft_path) - - print(f"✓ Created planning file: {planning_path.relative_to(PROJECT_ROOT)}") - print(f"✓ Linked to draft file: {draft_path.relative_to(PROJECT_ROOT)}") - - return planning_path - - -def main(): - parser = argparse.ArgumentParser( - description='Create linked planning and draft files for scenes.' - ) - - # For creating new scene pair - parser.add_argument('--act', type=int, default=1, help='Act number') - parser.add_argument('--chapter', type=int, default=1, help='Chapter number') - parser.add_argument('--scene', type=int, required=True, help='Scene number') - parser.add_argument('--title', type=str, default=None, help='Scene title') - parser.add_argument('--type', type=str, default='scene', - choices=['scene', 'chapter', 'interlude'], - help='Scene type') - - # For creating from existing files - parser.add_argument('--from-planning', type=str, default=None, - help='Create draft from existing planning file') - parser.add_argument('--from-draft', type=str, default=None, - help='Create planning from existing draft file') - - args = parser.parse_args() - - if args.from_planning: - create_from_planning(args.from_planning) - elif args.from_draft: - create_from_draft(args.from_draft) - else: - create_scene_pair( - act=args.act, - chapter=args.chapter, - scene=args.scene, - title=args.title, - type=args.type - ) - - -if __name__ == '__main__': - main()