feat: copy the output panel to the system clipboard (#11)
New app-level `copy` / `copy all` / `copy last` command (ADR-0041). Delivery is OSC 52 *and* a best-effort native write (arboard), always both — OSC 52 acceptance is undetectable, so a true fallback can't be built. Payload is the panel's plain text exactly as rendered (tags, ✓/✗, box-drawing), drift-locked to render_output_line. arboard added --no-default-features (X11-only; OSC 52 covers Wayland). Amends ADR-0003's command registry; requirements V6.
This commit is contained in:
@@ -376,6 +376,12 @@ async fn run_loop(
|
||||
// no wake-ups. See `IndicatorDebounce` for the decision
|
||||
// logic; `app.input_indicator` mirrors it for the renderer.
|
||||
let mut debounce = IndicatorDebounce::default();
|
||||
// Long-lived native clipboard for the `copy` command (ADR-0041).
|
||||
// Created lazily on first copy (so an OSC-52-only session never
|
||||
// opens an X11 connection) and kept alive for the session — the
|
||||
// X11 backend serves the selection from a thread owned by this
|
||||
// handle, so it must outlive each write.
|
||||
let mut native_clipboard = crate::clipboard::SystemClipboard::new();
|
||||
loop {
|
||||
let event = if debounce.is_armed() {
|
||||
match tokio::time::timeout(INDICATOR_DEBOUNCE, event_rx.recv()).await {
|
||||
@@ -557,6 +563,20 @@ async fn run_loop(
|
||||
tracing::warn!(error = %e, "could not persist input mode");
|
||||
}
|
||||
}
|
||||
Action::CopyToClipboard(text) => {
|
||||
// OSC 52 to the terminal + a best-effort native
|
||||
// write (ADR-0041). Both always fire; an OSC 52
|
||||
// write error is logged but never fatal.
|
||||
let mut out = std::io::stdout();
|
||||
if let Err(e) = crate::clipboard::deliver(
|
||||
&mut out,
|
||||
&mut native_clipboard,
|
||||
&text,
|
||||
crate::clipboard::in_tmux(),
|
||||
) {
|
||||
tracing::warn!(error = %e, "could not emit clipboard OSC 52 escape");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// A keystroke hides the indicator and re-arms the
|
||||
|
||||
Reference in New Issue
Block a user