Show a file write as a syntax-highlighted panel. Memory-conscious: caps preview at 40 lines, diff at 60 lines. Caller should `del old_content` immediately after this returns.
(path, content, old_content=None)
| 24 | ) |
| 25 | |
| 26 | def show_file_write(path, content, old_content=None): |
| 27 | """Show a file write as a syntax-highlighted panel. |
| 28 | |
| 29 | Memory-conscious: caps preview at 40 lines, diff at 60 lines. |
| 30 | Caller should `del old_content` immediately after this returns. |
| 31 | """ |
| 32 | fname = Path(path).name |
| 33 | ext = Path(path).suffix.lstrip('.') |
| 34 | lang_map = { |
| 35 | 'py': 'python', 'js': 'javascript', 'ts': 'typescript', |
| 36 | 'sh': 'bash', 'json': 'json', 'md': 'markdown', |
| 37 | 'yaml': 'yaml', 'yml': 'yaml', 'toml': 'toml', |
| 38 | } |
| 39 | lang = lang_map.get(ext, 'text') |
| 40 | lines_count = content.count('\n') + 1 |
| 41 | if old_content: |
| 42 | # Show as diff — cap inputs to avoid huge difflib allocations |
| 43 | _MAX_DIFF_LINES = 200 |
| 44 | old_lines = old_content.splitlines(keepends=True)[:_MAX_DIFF_LINES] |
| 45 | new_lines = content.splitlines(keepends=True)[:_MAX_DIFF_LINES] |
| 46 | diff = list(difflib.unified_diff(old_lines, new_lines, lineterm='')) |
| 47 | if diff: |
| 48 | diff_text = Text() |
| 49 | shown = 0 |
| 50 | for line in diff[2:]: # skip --- +++ headers |
| 51 | if shown >= 60: |
| 52 | diff_text.append(f'... ({len(diff) - 2 - shown} more diff lines)\n', style='dim') |
| 53 | break |
| 54 | if line.startswith('+'): |
| 55 | diff_text.append(line + '\n', style='green') |
| 56 | elif line.startswith('-'): |
| 57 | diff_text.append(line + '\n', style='red') |
| 58 | elif line.startswith('@@'): |
| 59 | diff_text.append(line + '\n', style='cyan') |
| 60 | else: |
| 61 | diff_text.append(line + '\n', style='dim') |
| 62 | shown += 1 |
| 63 | console.print(Panel(diff_text, title=f'Editing {fname}', |
| 64 | border_style='yellow', box=box.ROUNDED)) |
| 65 | return |
| 66 | # New file — cap preview before passing to Syntax to avoid Pygments bloat |
| 67 | if lines_count <= 40: |
| 68 | preview = content |
| 69 | else: |
| 70 | preview = '\n'.join(content.splitlines()[:40]) + f'\n... ({lines_count - 40} more lines)' |
| 71 | syntax = Syntax(preview, lang, theme='monokai', line_numbers=True) |
| 72 | console.print(Panel(syntax, title=f'Creating {fname}', |
| 73 | border_style='green', box=box.ROUNDED)) |
| 74 | |
| 75 | def show_patch(path, old_str, new_str): |
| 76 | """Show a patch operation as a mini diff.""" |
no test coverage detected