nushell / nushell/reedline

Proposal: host hooks for paste interception + timing-based paste-burst detection (Warp/ConPTY)

Open
#1,127 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
818
Forks
249
Avg merge
4d 14h
Merged PRs (30d)
30

Description

Summary

Two small, optional host hooks that let an application customize how reedline handles pastes. Both are no-ops when not installed, so existing users see zero behavior change. We've been running an implementation of both in a downstream fork and would be glad to upstream them if there's interest — opening this to gauge appetite and design preferences before sending a PR.

1. Paste interception hook

Today a bare Ctrl+V (EditCommand::PasteSystem, system_clipboard feature) reads the OS clipboard and inserts the text verbatim. Some hosts want to intervene — for example, turn a large paste (or an image) into a compact reference token like [Pasted text #N, +M lines] while stashing the real content elsewhere, then expand it back on submit. This keeps a chat-style / REPL composer readable, which is a common pattern in modern terminal CLIs.

Proposed shape: Reedline::with_paste_interceptor(Arc<dyn PasteInterceptor>). On PasteSystem, if an interceptor is installed, reedline calls interceptor.on_paste() -> PasteAction (InsertText(String) or Noop) instead of the default clipboard-read-and-insert. The interceptor reads the clipboard itself, so it can access image bytes the text-only path never exposes. An optional expand_for_display(&buffer) -> Option<String> lets the host expand placeholders for the submitted-line render.

2. Timing-based paste-burst detection (fallback for terminals without bracketed paste)

use_bracketed_paste handles terminals that emit Event::Paste. But some terminals — notably Warp and Windows ConPTY (crossterm#737) — deliver a paste as a rapid stream of individual key events, indistinguishable from fast typing by content alone. Without arrival timing, the read loop can't tell a paste-embedded newline from a settling Enter, so multi-line pastes submit prematurely.

Proposed shape: Reedline::with_paste_burst(Arc<dyn PasteBurstHook>). Chars keep echoing live (no added latency); the read loop feeds each just-read char to hook.on_char(c) at read time (preserving real inter-char timing), keeps draining while hook.is_burst_active() (using hook.poll_timeout() as the idle-flush window), and reclassifies a bare Enter to an inserted newline when hook.enter_is_newline(). All detector state and thresholds live host-side; reedline only drives the hook from the read loop.

Notes

  • Both traits are deliberately host-agnostic (no app-specific concepts).
  • Both are opt-in and no-op when absent (Send + Sync, held behind an Arc).
  • #1 is small and self-contained. #2 touches the read loop more deeply — happy to discuss whether a host timing hook is the right layer, or whether this is better addressed at the crossterm level (upstream #737).

References

  • Paste-reference UX (found in several chat-style terminal CLIs): a large paste collapses to a [Pasted text #N] placeholder in the composer and expands to the full text on submit.
  • crossterm#737 — Event::Paste is not emitted on Windows / ConPTY, so bracketed-paste-based detection does not fire there.
  • Warp terminal delivers pastes as individual key events rather than a bracketed-paste sequence.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the PasteSystem handling and the read loop described in the issue, including the existing use_bracketed_paste path. Review how Reedline currently reads clipboard content and processes individual characters, then clarify the API and behavior for both opt-in hooks. Done should include agreed host hooks that remain no-ops when absent, with coverage for interception and paste-burst behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.