From 5452c8f77c9c56363d1eb331e0689a0b410b72aa Mon Sep 17 00:00:00 2001 From: jh-block Date: Wed, 4 Feb 2026 17:52:52 +0100 Subject: [PATCH] Allow copying long strings to the clipboard in the diagnostics viewer --- scripts/diagnostics-viewer.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/diagnostics-viewer.py b/scripts/diagnostics-viewer.py index 95aec894a100..049685a64bc5 100755 --- a/scripts/diagnostics-viewer.py +++ b/scripts/diagnostics-viewer.py @@ -1,6 +1,6 @@ #!/usr/bin/env -S uv run --quiet --script # /// script -# dependencies = ["textual>=0.87.0"] +# dependencies = ["textual>=0.87.0", "pyperclip"] # /// """ WARNING: entirely vibe coded. use as a throwaway tool @@ -17,6 +17,8 @@ from pathlib import Path from typing import Optional, Any +import pyperclip + from textual.app import App, ComposeResult from textual.widgets import Header, Footer, Static, Tree, ListView, ListItem, Label, Input from textual.containers import Horizontal, Vertical, VerticalScroll, Container @@ -145,6 +147,7 @@ class TextViewerModal(ModalScreen): BINDINGS = [ Binding("escape,q,enter", "dismiss", "Close", show=True), + Binding("c", "copy", "Copy", show=True), ] def __init__(self, title: str, text: str): @@ -158,12 +161,17 @@ def compose(self) -> ComposeResult: yield Static(f"[bold]{self.title}[/bold]", id="modal-title") with VerticalScroll(id="modal-scroll"): yield Static(self.text, id="modal-text") - yield Static("[dim]Press Escape, Q, or Enter to close[/dim]", id="modal-footer") + yield Static("[dim]Press C to copy, Escape/Q/Enter to close[/dim]", id="modal-footer") def action_dismiss(self): """Dismiss the modal.""" self.app.pop_screen() + def action_copy(self): + """Copy the text to clipboard.""" + pyperclip.copy(self.text) + self.notify("Copied to clipboard") + class SearchOverlay(Container): """Search overlay widget."""