pi-better-paste-markers
Richer collapsed paste markers for pi: first/last line preview around the canonical paste marker
Package details
Install pi-better-paste-markers from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-better-paste-markers- Package
pi-better-paste-markers- Version
0.3.1- Published
- Oct 21, 2026
- Downloads
- 495/mo · 10/wk
- Author
- acidnik
- License
- MIT
- Types
- extension
- Size
- 25.4 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-better-paste-markers
Richer collapsed paste markers for pi.
Large pastes collapse into a bare [paste #1 1623 chars] marker with no feedback about what was actually pasted — easy to mix up clipboards (Linux primary/secondary). This replaces the marker with a three-line preview block. Pure extension: no core changes. Follow-up to earendil-works/pi#10216.
What it does
Pastes over 10 lines or 1000 chars render as a three-line block:
[first line of the pasted text, truncated...
paste #1 1623 chars / 42 lines
...last line of the pasted text, truncated from the left]
- Small pastes keep the built-in behavior (inserted as-is, no marker).
- The first/last previews show up to 80 characters;
...is added only when the line was actually cut. - The block is ordinary editable buffer lines; the middle line carries the marker.
- On submit the block is replaced with the original pasted content — nothing is lost.
- Everywhere else (drafts, autocomplete, undo) the block collapses back to the standard single-line
[paste #N ...]marker. - The block deletes as one unit: a single Backspace/Delete (or Ctrl+W/U/K) that touches it removes the whole block, like the built-in
[paste #N ...]marker. Text before and after the block on the same line is kept. - Undo restores the whole block and it keeps expanding/submitting correctly.
- Survives
/new,/resumeand fork: pi rebuilds the editor component during a session switch, so blocks are rebuilt from the shared registry (and from paste content captured out of the base editor) instead of degrading to a literal[paste #N ...]marker. - The input is prefixed with a gray
❯prompt (the one pi-powerline-footer draws on the default editor is lost when a custom editor component replaces it). - The block is painted with the theme's
userMessageBgbackground (follows light/dark and theme switches); only the block text is filled, the padding after it stays normal.
Install
pi install git:github.com/acidnik/pi-better-paste-markers
How it works
The extension replaces the main editor on session_start via ctx.ui.setEditorComponent() with a CustomEditor subclass:
handlePaste()— small pastes delegate to the base; large pastes insert the 3-line block and keep the content in an extension-side map.handleInput()— intercepts delete keys (deleteCharBackward/Forward,deleteWordBackward/Forward,deleteToLineStart/End) and removes the whole block when the cursor touches one; every other key goes to the base editor untouched.getText()— collapses blocks back to canonical[paste #N ...]markers (drafts, autocomplete snapshots, undo).expandPasteMarkers()— plain Enter submits through the base editor's privatesubmitValue(), which expands paste markers with this method; shadowing it makes Enter submit the original pasted content instead of the three-line preview.getExpandedText()— used by the follow-up (Alt+Enter), external-editor and extension-API (getEditorText) paths.render()— prefixes the input with a gray❯, keeps the other content lines indented, and paints the paste-block text withctx.ui.theme.bg("userMessageBg", …)(re-applied after the cursor's reset so the highlight survives the cursor).
Paste records are kept after a block is deleted so that undoing the deletion restores a block that still collapses and expands correctly.
The registry is shared across editor instances: during /new, /resume or a fork, pi tears the custom editor down (resetExtensionUI()), rebuilds it, and carries the draft over with setText(editor.getText()) — i.e. collapsed markers. Blocks are therefore rebuilt on setText, from the shared registry or from content captured out of the base editor (whose pastes map pi clears on the same path).