Skip to content

Instantly share code, notes, and snippets.

@Mockapapella
Created November 18, 2024 20:09
Show Gist options
  • Save Mockapapella/b752d6ea4db5d05b1ae797a3d781c41c to your computer and use it in GitHub Desktop.
Save Mockapapella/b752d6ea4db5d05b1ae797a3d781c41c to your computer and use it in GitHub Desktop.
# Writing Code and Documentation
## ⚠️ CRITICAL: ALL CODE MUST BE IN ARTIFACTS ⚠️
The single most important rule: NEVER write code directly in the conversation. ALL code MUST be provided as a unified diff file within an artifact. No exceptions.
## Before You Start
1. Read the user's request
2. Plan your response
3. Create a SINGLE unified diff file containing ALL code changes
4. Place this diff file in an artifact
## Unified Diff File Format
Every code response MUST follow this exact format:
```
diff --git a/[filename] b/[filename]
--- a/[filename]
+++ b/[filename]
@@ 1,1 +1,1 @@
[changes with + and - markers]
```
## Multiple Files
If you need to provide multiple files:
- DO NOT create multiple artifacts
- DO NOT paste code into the conversation
- DO combine all changes into a single unified diff file
- DO use proper diff headers to separate files
Example of multiple files in one diff:
```
diff --git a/src/main.py b/src/main.py
[changes for main.py]
diff --git a/src/utils.py b/src/utils.py
[changes for utils.py]
```
## Code Standards
For Python:
- Use type hints
- Add docstrings
- Keep code stateless when possible
- Use clear names over comments
For Documentation:
- Write at middle-school level
- Keep it simple
- Break down complex concepts
## Required Process
1. Plan your work in <thought_process> tags:
- User requirements
- Code/doc types needed
- Component breakdown
- Design choices
- Potential issues
- Solutions
2. Create artifact with unified diff:
- ALL code goes in the diff
- ONE diff file per response
- Proper diff formatting
- NO code in conversation
3. Explain in <explanation> tags:
- Changes made
- Design rationale
- Usage notes
## Example Structure
```
<thought_process>
[Your detailed plan]
</thought_process>
[Artifact containing unified diff file]
<explanation>
[Your explanation]
</explanation>
```
## Common Mistakes to Avoid
❌ Writing code in the conversation
❌ Creating multiple artifacts for different files
❌ Using code blocks instead of diff format
❌ Skipping the artifact creation
❌ Providing incomplete diffs
✅ DO put ALL code in ONE unified diff file
✅ DO put the diff file in an artifact
✅ DO use proper diff formatting
✅ DO combine multiple files into one diff
✅ DO follow this process for EVERY code request
quinten@quinten-desktop-ubuntu:~/Documents/Software_Development/blitz (dev)$ python patch_validator.py -f ai.patch --fix --backup
Validation failed
Errors:
- Hunk header corrected from: @@ -25,13 +25,22 @@ class Migration(migrations.Migration):
to: @@ -25,12 +25,22 @@
Backup created: ai.patch.bak
Patch file has been fixed!
quinten@quinten-desktop-ubuntu:~/Documents/Software_Development/blitz (dev)$ git apply ai.patch
quinten@quinten-desktop-ubuntu:~/Documents/Software_Development/blitz (dev)$ python patch_validator.py --help
usage: patch_validator.py [-h] --file FILE [--quiet] [--fix] [--backup]
Validate and fix a patch file format
options:
-h, --help show this help message and exit
--file FILE, -f FILE Path to the patch file to validate
--quiet, -q Only output errors
--fix Fix the patch file and save changes
--backup Create a backup before fixing
#!/usr/bin/env python3
import argparse
import re
import sys
from dataclasses import dataclass
from typing import List, Optional, Tuple
from pathlib import Path
@dataclass
class ValidationResults:
is_valid: bool
errors: List[str]
warnings: List[str]
fixed_content: Optional[str] = None
@dataclass
class DiffSection:
header: str
old_file: str
new_file: str
hunks: List[Tuple[str, List[str]]] # (hunk header, hunk content)
class PatchValidator:
def __init__(self):
self.hunk_header_regex = re.compile(r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@")
self.diff_header_regex = re.compile(r"^diff --git (a/.+) (b/.+)$")
def count_hunk_lines(self, content_lines: List[str]) -> Tuple[int, int]:
"""Count the number of old and new lines in a hunk."""
old_lines = 0
new_lines = 0
for line in content_lines:
if line.startswith("-"):
old_lines += 1
elif line.startswith("+"):
new_lines += 1
elif line.startswith(" "):
old_lines += 1
new_lines += 1
return old_lines, new_lines
def parse_patch(self, content: str) -> List[DiffSection]:
"""Parse patch content into sections."""
lines = content.splitlines(keepends=True)
sections = []
current_section = None
current_hunk_header = None
current_hunk_lines = []
line_number = 0
while line_number < len(lines):
line = lines[line_number]
# Start of a new diff section
if line.startswith("diff --git"):
if current_section is not None:
if current_hunk_lines:
current_section.hunks.append((current_hunk_header, current_hunk_lines))
sections.append(current_section)
match = self.diff_header_regex.match(line)
if not match:
raise ValueError(
f"Invalid diff header at line {line_number + 1}: {line.strip()}"
)
old_path, new_path = match.groups()
# Look ahead for file headers
old_file = None
new_file = None
next_line = line_number + 1
while next_line < len(lines):
next_line_content = lines[next_line].strip()
if next_line_content.startswith("---"):
old_file = lines[next_line]
next_line += 1
elif next_line_content.startswith("+++"):
new_file = lines[next_line]
next_line += 1
elif next_line_content.startswith("@@ "):
break
elif next_line_content.startswith("diff --git"):
break
else:
next_line += 1
# Generate correct file headers if missing or incorrect
if old_path == "/dev/null":
expected_old_file = "--- /dev/null\n"
else:
expected_old_file = f"--- {old_path}\n"
if new_path == "/dev/null":
expected_new_file = "+++ /dev/null\n"
else:
expected_new_file = f"+++ {new_path}\n"
current_section = DiffSection(
header=line, old_file=expected_old_file, new_file=expected_new_file, hunks=[]
)
current_hunk_header = None
current_hunk_lines = []
# Skip past the file headers we just processed
line_number = next_line - 1
elif line.strip() and self.hunk_header_regex.match(line.strip()):
if current_hunk_lines:
current_section.hunks.append((current_hunk_header, current_hunk_lines))
current_hunk_lines = []
current_hunk_header = line
elif current_section is not None and current_hunk_header is not None:
current_hunk_lines.append(line)
line_number += 1
# Add the last section and hunk
if current_section is not None:
if current_hunk_lines:
current_section.hunks.append((current_hunk_header, current_hunk_lines))
sections.append(current_section)
return sections
def validate_and_fix_patch(self, content: str) -> ValidationResults:
results = ValidationResults(is_valid=True, errors=[], warnings=[], fixed_content=None)
if not content.strip():
results.errors.append("Patch file is empty")
results.is_valid = False
return results
try:
# Parse the patch into sections
sections = self.parse_patch(content)
if not sections:
results.errors.append("No valid diff sections found")
results.is_valid = False
return results
# Process sections and build fixed content
fixed_lines = []
for i, section in enumerate(sections):
# Add blank line between sections if needed
if i > 0:
fixed_lines.append("\n")
# Add diff header
fixed_lines.append(section.header)
# Add file headers
fixed_lines.append(section.old_file)
fixed_lines.append(section.new_file)
# Process hunks
for hunk_header, hunk_lines in section.hunks:
old_count, new_count = self.count_hunk_lines(hunk_lines)
old_start, _, new_start, _ = self.parse_hunk_header(hunk_header)
correct_header = f"@@ -{old_start},{old_count} +{new_start},{new_count} @@\n"
if correct_header.strip() != hunk_header.strip():
results.errors.append(
f"Hunk header corrected from: {hunk_header.strip()}\n"
f"to: {correct_header.strip()}"
)
fixed_lines.append(correct_header)
else:
fixed_lines.append(hunk_header)
fixed_lines.extend(hunk_lines)
# Ensure proper line endings
results.fixed_content = "".join(fixed_lines)
if not results.fixed_content.endswith("\n"):
results.fixed_content += "\n"
except ValueError as e:
results.errors.append(str(e))
results.is_valid = False
return results
results.is_valid = not results.errors
return results
def parse_hunk_header(self, header: str) -> Tuple[int, int, int, int]:
"""Parse a hunk header into its components."""
match = self.hunk_header_regex.match(header.strip())
if not match:
return 1, 1, 1, 1
old_start, old_count, new_start, new_count = match.groups()
return (int(old_start), int(old_count or "1"), int(new_start), int(new_count or "1"))
def main():
parser = argparse.ArgumentParser(description="Validate and fix a patch file format")
parser.add_argument("--file", "-f", required=True, help="Path to the patch file to validate")
parser.add_argument("--quiet", "-q", action="store_true", help="Only output errors")
parser.add_argument("--fix", action="store_true", help="Fix the patch file and save changes")
parser.add_argument("--backup", action="store_true", help="Create a backup before fixing")
args = parser.parse_args()
try:
with open(args.file, "r", encoding="utf-8") as f:
content = f.read()
except Exception as e:
print(f"Error reading file: {e}", file=sys.stderr)
sys.exit(1)
validator = PatchValidator()
results = validator.validate_and_fix_patch(content)
if not args.quiet:
print(f"Validation {'succeeded' if results.is_valid else 'failed'}")
if results.errors:
print("\nErrors:", file=sys.stderr)
for error in results.errors:
print(f" - {error}", file=sys.stderr)
if not args.quiet and results.warnings:
print("\nWarnings:")
for warning in results.warnings:
print(f" - {warning}")
if args.fix and results.fixed_content is not None:
try:
if args.backup:
backup_path = Path(args.file).with_suffix(".patch.bak")
with open(backup_path, "w", encoding="utf-8") as f:
f.write(content)
if not args.quiet:
print(f"\nBackup created: {backup_path}")
with open(args.file, "w", encoding="utf-8") as f:
f.write(results.fixed_content)
if not args.quiet:
print("\nPatch file has been fixed!")
except Exception as e:
print(f"Error fixing file: {e}", file=sys.stderr)
sys.exit(1)
sys.exit(0 if results.is_valid else 1)
if __name__ == "__main__":
main()
@janwilmake
Copy link

pbpaste > new.diff && python3 patch_validator.py -f new.diff --fix --backup; git apply new.diff

to do it straight from Claude :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment