Skip to content

Copy sometimes does nothing, and never says so #210

Description

@jamescrosswell

Opportunity

Copy can do nothing at all, and look exactly like it worked.

You select text, press Cmd+C, switch to another window, paste — and get whatever was on the
clipboard before. The editor gives no sign: no message, no error, the selection still highlighted.
The maintainer hit this in iTerm2 selecting a whole file with Ctrl+A; a smaller selection of the
same file copied fine (the Original idea below).

The cost isn't the one lost copy. It's that after this happens once you stop trusting copy and
start checking every paste — in the editor the vision wants to be a daily driver.

Evidence — TuiCode never looks at whether the copy landed:

  • Both copy paths end in the same fire-and-forget call: TuiCode's multi-caret copy
    (EditorTextView.Carets.cs:254)
    and, at a single caret, Terminal.Gui's own TextView.Copy, both do
    App?.Clipboard?.SetClipboardData(text). It returns void, the ?. swallows a missing
    clipboard entirely, and nothing checks afterwards that the text arrived.
  • Terminal.Gui offers IClipboard.IsSupported and TrySetClipboardData for exactly this. TuiCode
    uses neither.
  • IsSupported is not trustworthy anyway. MacOSXClipboard decides by shelling out to
    which pbcopy; under dotnet test on the maintainer's Mac it reported False while
    /usr/bin/pbcopy was sitting right there — and writing through that same "unsupported"
    clipboard worked. So the check we'd naturally reach for would have disabled copy here.
  • The size theory doesn't hold. Driving NSPasteboard through the same Objective-C calls
    Terminal.Gui makes, an 86 KB buffer round-trips byte-for-byte, as does CONTRIBUTING.md (5.8 KB).
    Through TG's own MacOSXClipboard: 86,889 characters in, 86,889 out, identical. Whatever ate
    that copy, it was not macOS refusing the text — so there is no cap to raise, and no reproduction
    to work from until copy starts reporting failure.
  • Copy over SSH is a separate hole (there is no local clipboard at all): that's Make native OS shortcuts (Cmd+C/V/X etc.) work across different terminal emulators #40's, and this
    pitch stays local.

Options considered

  1. Document it and move on. Cheapest. But there is nothing to document — no reproducible
    limit, and no workaround to offer beyond "copy less at a time". Leaves the maintainer checking
    every paste.
  2. Hunt the size cap. Bisect buffer size until copy fails, raise whatever bites. Targeted and
    satisfying if it exists — but the measurements above say the OS clipboard takes 86 KB happily,
    so this is most likely chasing a ghost, and it leaves every other silent-failure mode (no
    clipboard, a clipboard that throws, a remote session) exactly as it is.
  3. Make copy prove itself, and say what happened. (Proposed.) Write, read back, compare, and
    tell the user in the status bar — Copied 141 lines • 5,835 selected, or a one-line error naming what
    failed. Where the read-back doesn't match, fall back to the platform's own tool (pbcopy,
    xclip/wl-copy, clip.exe) and check again. Fixes the class rather than the instance, and
    turns this bug from a mystery into a message the maintainer can act on.
  4. Take the clipboard over completely. Drop App.Clipboard, write TuiCode's own per-platform
    clipboard plus OSC 52 for SSH. The most complete answer — and most of Make native OS shortcuts (Cmd+C/V/X etc.) work across different terminal emulators #40 as well, which is a
    lot to sign off on the back of one bug report. Option 3 is its first slice if we go there.

Proposal

Copy never fails silently.

Copy and cut — one caret or many, editor or diff — go through one clipboard service:

  1. Write, then verify. After setting the clipboard, read it back and compare with what we sent.
    Read-back is the check, not IsSupported, which lies.
  2. Fall back once. If the read-back doesn't match, retry through the platform's own tool
    (pbcopy / wl-copy / xclip / clip.exe) and verify again.
  3. Say what happened, in the status bar. On success, what was copied. On failure, one line
    naming which clipboard refused it — the first line of the tool's stderr, never an exception type
    (style guide: outside a
    dialog, errors go to the status bar).

Mockup

StatusBarPart message area. The separator is • (StatusBarPart.DefaultMessage and its
string.Join), and the right-hand readout is StatusBarPart.ShowPosition's own
Ln R, Col C (N selected) — not invented here.

After a successful copy — replaces the file path, reverting to it after a few seconds
(ClearMessage, as Save already does):

 Copied 141 lines  •  5,835 characters              Ln 1, Col 1 (5,835 selected)

After a copy that didn't land — Error scheme, stays until the next message:

 Copy failed: the clipboard didn't take the text (pbcopy)   Ln 1, Col 1 (5,835 selected)

No new controls, no dialog: a copy the user didn't ask to be told about must not open a modal.

Scope

In

  • One clipboard service used by every copy and cut path, including the single-caret one that
    currently falls through to TextView.Copy.
  • Write-then-read-back verification, and the fallback to the platform tool.
  • Status bar messages for both outcomes.

Out

Rough breakdown

  1. Copy tells you what it copied, and tells you when it didn't. One clipboard service behind
    both copy paths; write, read back, compare; status bar message either way. After this merges,
    this bug either stops happening or produces a reportable error instead of silence.
  2. Copy falls back to the platform's own clipboard tool. When the read-back doesn't match,
    retry through pbcopy / wl-copy / xclip / clip.exe. A copy that used to vanish now lands.
  3. (Only if 1 and 2 leave large copies failing) Own the clipboard — option 4: TuiCode's own
    per-platform clipboard in place of App.Clipboard, with OSC 52 from Make native OS shortcuts (Cmd+C/V/X etc.) work across different terminal emulators #40 folded in. Copying a
    whole large file has to work; if the messages from 1 and 2 show the stock clipboard can't do it
    reliably, this is the fix rather than patching whatever the message names.

Decided

  1. Announce every successful copy — reviewer agreed. The message reverts to the file path.
  2. Read back on every copy — reviewer agreed. Measure on a large buffer; revisit only if
    noticeable.
  3. If large copies still fail after slices 1–2, go to option 4 — reviewer: copying big
    portions of text has to work, so owning the clipboard (with Make native OS shortcuts (Cmd+C/V/X etc.) work across different terminal emulators #40's OSC 52) is on the table.
    It's slice 3, gated on what slices 1–2 report.

Original idea

In iTerm2, if I open a reasonably large file like the CONTRIBUTING.md file in this repository and press Ctrl + A and then Ctrl + C to copy everything... nothing gets copied to the system clipboard.

If I copy a smaller subsection of the document, it copies successfully.

Is this specific to iTerm? Is it a bug or a configuration setting? Is there any way around this?

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpitchAn a-team pitch: Lead shapes it, reviewer approves it

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions