C.W.K.
Stream
Lesson 05 of 05 · published

Restore the Whole Clipboard, Not Just the Text

~11 min · pasteboard, preservation, fidelity, etiquette

Level 0Cold Flint
0 XP0/34 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"The clipboard the user had might be an image, a file, rich text. Borrow all of it, give all of it back."

The Clipboard Is Not a String

The probe borrows the clipboard, so the restore has to return it faithfully — and here's the trap: the clipboard is not just plain text. At any moment it may hold an image, files, rich text, HTML, or a custom type from some app, often several representations of the same thing at once. If your restore only saved and rewrote the plain-text string, then a user who had an image or a set of files on the clipboard gets it silently destroyed by your probe. 'Reversible' has to mean reversible for whatever they actually had, not just for text.

Snapshot Every Item, Every Type

A full capture walks the pasteboard's items — there can be more than one — and for each item records every type it advertises together with that type's data. That map of items-to-types-to-data is the real snapshot. Restoring is the mirror image: clear the pasteboard and write those items back with all their types intact. Do it this way and an image survives as an image, files survive as files, rich text keeps its formatting — the user's clipboard comes back byte-for-byte, not flattened to a string.

NAIVE (loses everything but text):
  save   pb.string(forType: .string)
  ...probe...
  restore pb.setString(saved, forType: .string)   // image/files GONE

FAITHFUL:
  save   every item -> every type -> its data
  ...probe...
  restore rebuild each item with all its types, write them back

When You Can't Fully Capture

Honesty check: some clipboard contents can't be fully snapshotted — promised or lazily-provided data, where the source app hands over the bytes only when a paste actually happens. You cannot always capture those up front. The conservative rule is: if you can't snapshot the entire pasteboard with fidelity, don't run the destructive probe at all — fall back to whatever you could read another way, and leave the clipboard alone. It is better to miss a selection than to eat a user's copied file. Preservation is all-or-nothing: full fidelity, or don't touch it.

Full fidelity or conservative — never half-preserve. When you borrow shared state, restoring 80% of it is worse than not borrowing it, because the user trusts that their clipboard is intact and won't notice the 20% you dropped until it matters. Either capture and restore everything, or decline the operation that would have damaged it. A partial restore is a silent data loss wearing the costume of safety.
The same discipline reappears at insertion. If a macro's result is placed by writing to the clipboard and pasting, that insertion borrows the clipboard too — and owes the same full capture-and-restore. Build the pasteboard snapshot as a reusable piece; both the read probe (this track) and the paste-based insertion (Track 6) lean on it. One careful implementation, two callers.

Code

Capture and restore the whole pasteboard, every item and type·swift
struct PasteboardSnapshot {
    let items: [[NSPasteboard.PasteboardType: Data]]
}

func capturePasteboard(_ pb: NSPasteboard) -> PasteboardSnapshot {
    let items = (pb.pasteboardItems ?? []).map { item in
        var byType: [NSPasteboard.PasteboardType: Data] = [:]
        for type in item.types {
            if let data = item.data(forType: type) { byType[type] = data }
        }
        return byType
    }
    return PasteboardSnapshot(items: items)
}

func restorePasteboard(_ pb: NSPasteboard, from snap: PasteboardSnapshot) {
    pb.clearContents()
    let rebuilt = snap.items.map { byType -> NSPasteboardItem in
        let item = NSPasteboardItem()
        for (type, data) in byType { item.setData(data, forType: type) }
        return item
    }
    if !rebuilt.isEmpty { pb.writeObjects(rebuilt) }
}

External links

Exercise

A user has three files copied to the clipboard. Your macro strikes in an Electron app, so Flint runs the copy probe. Walk exactly what must be captured before the synthetic Cmd+C and restored after, so the three files are still on the clipboard when you're done. Then state the rule for what Flint should do if it discovers the clipboard holds promised data it cannot fully snapshot.
Hint
Capture every pasteboard item and, per item, every advertised type mapped to its data — the file references included — then rebuild those items and write them back after reading the probe result. If the clipboard holds promised/lazy data that can't be captured with fidelity, the rule is all-or-nothing: don't run the destructive probe, because a partial restore would silently drop the user's files.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.