Skip to content

Terminal: one Ctrl+V is one paste, not two - #37

Merged
Maxaubert merged 1 commit into
mainfrom
fix/paste-twice
Sep 22, 2026
Merged

Maxaubert merged 1 commit into
mainfrom
fix/paste-twice

Conversation

@Maxaubert

Copy link
Copy Markdown
Owner

Owner, 2026-09-22: "found a bug in the terminals. when I copy text and paste it pastes twice", with a screenshot of every word arriving doubled (detdet...AuthenticationAuthentication...secondsseconds).

Cause. The core's key handler pasted on Ctrl+V and returned false. Returning false only tells xterm to leave the key alone; it does not cancel the browser's own action for Ctrl+V, which is a native paste event into xterm's hidden textarea, and xterm pastes on that event too. So every paste arrived twice. The code is in the shared core, so both apps had it.

Fix. preventDefault() on Ctrl+V and Ctrl+Shift+V, so the handler's own paste (the one that knows about images and bracketed framing) is the only one.

Proof, reproduced first. The new paste e2e counts what actually reached the shell:

  • before the fix: Ctrl+V -> 2 copies, Ctrl+Shift+V -> 2 copies
  • after: 1 and 1, and the right-click Paste is held to 1 as well.

The owner's clipboard is saved before the scenario and put back after it.

Verified: typecheck, lint, 778 unit tests, the full e2e (23 scenarios) green.

App 0.7.1, core 0.6.1: a fix, so it should merge FIRST. The look PR (#35) then moves to core 0.6.2, and the help PR (#36) stays above both.

🤖 Generated with Claude Code

Owner, 2026-09-22: "found a bug in the terminals. when I copy text and paste
it pastes twice", with every word in the screenshot arriving doubled.

The key handler pasted and returned false. Returning false only tells xterm
to leave the key alone; it does not cancel the browser's own action for
Ctrl+V, which is a native paste event into xterm's textarea, and xterm pastes
on that too. So every paste arrived twice, in both apps (the core is shared).
preventDefault() now cancels the native one for Ctrl+V and Ctrl+Shift+V.

The new `paste` e2e counts what reached the shell: it failed with 2 copies
for both keys before the fix and passes with 1 after, and the right-click
Paste is held to the same. The owner's clipboard is saved and put back.
App 0.7.1, core 0.6.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Maxaubert added a commit that referenced this pull request Sep 22, 2026
The paste fix is a bug fix and should merge first, as core 0.6.1; this look
PR's own core change climbs past it. App stays 0.8.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Maxaubert
Maxaubert merged commit b30ea3b into main Sep 22, 2026
2 checks passed
@Maxaubert
Maxaubert deleted the fix/paste-twice branch September 22, 2026 13:00
github-actions Bot pushed a commit that referenced this pull request Sep 22, 2026
Owner, 2026-09-22: "found a bug in the terminals. when I copy text and paste
it pastes twice", with every word in the screenshot arriving doubled.

The key handler pasted and returned false. Returning false only tells xterm
to leave the key alone; it does not cancel the browser's own action for
Ctrl+V, which is a native paste event into xterm's textarea, and xterm pastes
on that too. So every paste arrived twice, in both apps (the core is shared).
preventDefault() now cancels the native one for Ctrl+V and Ctrl+Shift+V.

The new `paste` e2e counts what reached the shell: it failed with 2 copies
for both keys before the fix and passes with 1 after, and the right-click
Paste is held to the same. The owner's clipboard is saved and put back.
App 0.7.1, core 0.6.1.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Maxaubert added a commit that referenced this pull request Sep 22, 2026
The paste fix is a bug fix and should merge first, as core 0.6.1; this look
PR's own core change climbs past it. App stays 0.8.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Maxaubert added a commit that referenced this pull request Sep 22, 2026
… width (#35)

* feat(icon): the app wears the owner's own mark

Owner, 2026-09-20: "use this for the prism terminal icon", with the artwork.
build/icon.ico is what the app, the installer, the uninstaller and the taskbar
all read, so one file covers every place it appears.

tools/make-icon.py builds it from build/icon-source.png: ten frames from 16 to
256, each RESAMPLED FROM THE FULL-SIZE ARTWORK rather than from the frame above
it, so the 16px one - the size the taskbar and Explorer's details view draw all
day - is as sharp as the source allows instead of a copy of a copy. 0.7.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(icon): the soft orange and charcoal mark (#35)

Owner, 2026-09-21: new artwork, replacing the blue swirl of the day before.
Same builder, same ten frames; the source is their own
'Prism Terminal Icon Concepts 2026-09-21 - Soft Colours/05-orange-charcoal'.

The PNG is used rather than the JPG that arrived in chat: a JPEG carries no
alpha, so its transparency had been flattened onto BLACK and an icon built
from it would wear a black card on every taskbar. make-icon.py refuses such a
source, which is how this was caught rather than shipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(look): Pitch and Cinder wear the icon's orange, and every tab is one width

Owner, 2026-09-21: "two themes that match the app icon colour scheme, one with
orange and black, and one with orange and dark grey" ("change a couple is
better" than adding), and "make tabs in both apps have a fixed size, and not
dynamically adjust based on the content".

Pitch and Cinder are the two originals whose names already fitted; orange
grey #383c44. The public schemes keep their real colours.

A tab is flex 0 1 176px now: one width that shrinks equally only when the strip
is full. tabWidth measures the boxes with names of very different lengths.
App 0.8.0, core 0.6.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(tabs): 106px, the size the Explorer tab had in Prism

Owner, 2026-09-21: "the fixed size needs to be way smaller. around the size
that the explorer tab had in prism. I'd say around 60% of what it is now".
176px -> 106px (60%), min 64px. tabWidth measures 106 / 106 / 106.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(icon): the orange spiral with dark-grey symbols

Owner, 2026-09-21: "new pt icon", from their own concepts
('Orange Spirals/04-dark-grey-symbols'), replacing the cream-symbol version of
this morning. Same builder, ten frames from the full-size PNG.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(tabs): 127px, 20% wider

Owner, 2026-09-21: "make the tabs a bit wider like 20%". 106px -> 127px.
tabWidth measures 127 / 127 / 127.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* build: core 0.6.2, above the paste fix's 0.6.1 (#37)

The paste fix is a bug fix and should merge first, as core 0.6.1; this look
PR's own core change climbs past it. App stays 0.8.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(tabs): 114px, 10% narrower

Owner, 2026-09-22: "make the tabs 10% less wide". 127px -> 114px.
tabWidth measures 114 / 114 / 114.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Sep 22, 2026
… width (#35)

* feat(icon): the app wears the owner's own mark

Owner, 2026-09-20: "use this for the prism terminal icon", with the artwork.
build/icon.ico is what the app, the installer, the uninstaller and the taskbar
all read, so one file covers every place it appears.

tools/make-icon.py builds it from build/icon-source.png: ten frames from 16 to
256, each RESAMPLED FROM THE FULL-SIZE ARTWORK rather than from the frame above
it, so the 16px one - the size the taskbar and Explorer's details view draw all
day - is as sharp as the source allows instead of a copy of a copy. 0.7.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(icon): the soft orange and charcoal mark (#35)

Owner, 2026-09-21: new artwork, replacing the blue swirl of the day before.
Same builder, same ten frames; the source is their own
'Prism Terminal Icon Concepts 2026-09-21 - Soft Colours/05-orange-charcoal'.

The PNG is used rather than the JPG that arrived in chat: a JPEG carries no
alpha, so its transparency had been flattened onto BLACK and an icon built
from it would wear a black card on every taskbar. make-icon.py refuses such a
source, which is how this was caught rather than shipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(look): Pitch and Cinder wear the icon's orange, and every tab is one width

Owner, 2026-09-21: "two themes that match the app icon colour scheme, one with
orange and black, and one with orange and dark grey" ("change a couple is
better" than adding), and "make tabs in both apps have a fixed size, and not
dynamically adjust based on the content".

Pitch and Cinder are the two originals whose names already fitted; orange
grey #383c44. The public schemes keep their real colours.

A tab is flex 0 1 176px now: one width that shrinks equally only when the strip
is full. tabWidth measures the boxes with names of very different lengths.
App 0.8.0, core 0.6.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(tabs): 106px, the size the Explorer tab had in Prism

Owner, 2026-09-21: "the fixed size needs to be way smaller. around the size
that the explorer tab had in prism. I'd say around 60% of what it is now".
176px -> 106px (60%), min 64px. tabWidth measures 106 / 106 / 106.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(icon): the orange spiral with dark-grey symbols

Owner, 2026-09-21: "new pt icon", from their own concepts
('Orange Spirals/04-dark-grey-symbols'), replacing the cream-symbol version of
this morning. Same builder, ten frames from the full-size PNG.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(tabs): 127px, 20% wider

Owner, 2026-09-21: "make the tabs a bit wider like 20%". 106px -> 127px.
tabWidth measures 127 / 127 / 127.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* build: core 0.6.2, above the paste fix's 0.6.1 (#37)

The paste fix is a bug fix and should merge first, as core 0.6.1; this look
PR's own core change climbs past it. App stays 0.8.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(tabs): 114px, 10% narrower

Owner, 2026-09-22: "make the tabs 10% less wide". 127px -> 114px.
tabWidth measures 114 / 114 / 114.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Maxaubert added a commit that referenced this pull request Sep 25, 2026
…2e harness (#71) (#72)

Settings: the colour editor saves the whole setup into Custom and is a theme
pick (#8, #29); ThemeSwitchAsk registers once (#22); a hex field commits only
a changed draft (#26); the dictation key is never a key that types or a chord
the terminal owns, and a press elsewhere ends the capture (#27); the editor
takes the focus, traps Tab and hears Escape, the pencil is its own button
(#28); a finished download reads fresh state before picking the model (#30).

Release and CI: release.yml tags the built commit (#11); core-release runs
from main only (#34), waits for terminal-gate by name and its success (#38),
and opens an issue when a core change cannot be released; core-version also
requires the core version above the base's (#39).

Harness: a time limit per scenario and closeApp (#35), profiles removed after
each scenario (#36), the poll's first verdict awaited instead of 6 s (#37).

Core 0.15.3, app 0.18.3. New reviewSettings e2e and unit tests.


Claude-Session: https://claude.ai/code/session_01LJbePcRzre7AusNzPNS2Bk

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot pushed a commit that referenced this pull request Sep 25, 2026
…2e harness (#71) (#72)

Settings: the colour editor saves the whole setup into Custom and is a theme
pick (#8, #29); ThemeSwitchAsk registers once (#22); a hex field commits only
a changed draft (#26); the dictation key is never a key that types or a chord
the terminal owns, and a press elsewhere ends the capture (#27); the editor
takes the focus, traps Tab and hears Escape, the pencil is its own button
(#28); a finished download reads fresh state before picking the model (#30).

Release and CI: release.yml tags the built commit (#11); core-release runs
from main only (#34), waits for terminal-gate by name and its success (#38),
and opens an issue when a core change cannot be released; core-version also
requires the core version above the base's (#39).

Harness: a time limit per scenario and closeApp (#35), profiles removed after
each scenario (#36), the poll's first verdict awaited instead of 6 s (#37).

Core 0.15.3, app 0.18.3. New reviewSettings e2e and unit tests.


Claude-Session: https://claude.ai/code/session_01LJbePcRzre7AusNzPNS2Bk

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant