[term] x/term: handle transpose

0 views
Skip to first unread message

Josh Bleecher Snyder (Gerrit)

unread,
Dec 16, 2025, 4:59:50 PM (9 hours ago) Dec 16
to goph...@pubsubhelper.golang.org, Josh Bleecher Snyder, golang-co...@googlegroups.com

Josh Bleecher Snyder has uploaded the change for review

Commit message

x/term: handle transpose

The behavior implemented here matches readline and libedit.

Updates golang/go#76826
Change-Id: I893677f9bceaf75aa1dada7d893845728e07057e

Change diff

diff --git a/terminal.go b/terminal.go
index 5fdfff0..6ec537c 100644
--- a/terminal.go
+++ b/terminal.go
@@ -162,6 +162,7 @@
keyDeleteLine
keyDelete
keyClearScreen
+ keyTranspose
keyPasteStart
keyPasteEnd
)
@@ -195,6 +196,8 @@
return keyDeleteLine, b[1:]
case 12: // ^L
return keyClearScreen, b[1:]
+ case 20: // ^T
+ return keyTranspose, b[1:]
case 23: // ^W
return keyDeleteWord, b[1:]
case 14: // ^N
@@ -605,6 +608,24 @@
}
case keyCtrlU:
t.eraseNPreviousChars(t.pos)
+ case keyTranspose:
+ // This transposes the two characters around the cursor and advances the cursor. Best-effort.
+ if len(t.line) < 2 || t.pos < 1 {
+ return
+ }
+ swap := t.pos
+ if swap == len(t.line) {
+ swap-- // special: at end of line, swap previous two chars
+ }
+ t.line[swap-1], t.line[swap] = t.line[swap], t.line[swap-1]
+ if t.pos < len(t.line) {
+ t.pos++
+ }
+ if t.echo {
+ t.moveCursorToPos(swap - 1)
+ t.writeLine(t.line[swap-1:])
+ t.moveCursorToPos(t.pos)
+ }
case keyClearScreen:
// Erases the screen and moves the cursor to the home position.
t.queue([]rune("\x1b[2J\x1b[H"))
diff --git a/terminal_test.go b/terminal_test.go
index 45aeffa..7d0afd8 100644
--- a/terminal_test.go
+++ b/terminal_test.go
@@ -263,6 +263,66 @@
in: "abc\x1b[H\x1b[3~\x1b[3~\r",
line: "c",
},
+ {
+ // Ctrl-T at end of line: transpose last two chars
+ in: "abc\x14\r",
+ line: "acb",
+ },
+ {
+ // Ctrl-T at end then type: cursor stays at end
+ in: "abc\x14N\r",
+ line: "acbN",
+ },
+ {
+ // Ctrl-T in middle: transpose chars before cursor, move cursor forward
+ in: "abc\x1b[D\x14\r",
+ line: "acb",
+ },
+ {
+ // Ctrl-T in middle then type: cursor moved past swapped char
+ in: "abcd\x1b[D\x1b[D\x14N\r",
+ line: "acbNd",
+ },
+ {
+ // Ctrl-T at pos 1 then type: cursor moves to pos 2
+ in: "abc\x1b[H\x1b[C\x14N\r",
+ line: "baNc",
+ },
+ {
+ // Ctrl-T with one char: do nothing
+ in: "a\x14\r",
+ line: "a",
+ },
+ {
+ // Ctrl-T with one char then type: cursor unchanged
+ in: "a\x14N\r",
+ line: "aN",
+ },
+ {
+ // Ctrl-T at beginning: do nothing
+ in: "ab\x1b[H\x14\r",
+ line: "ab",
+ },
+ {
+ // Ctrl-T at beginning then type: cursor unchanged, inserts at start
+ in: "ab\x1b[H\x14N\r",
+ line: "Nab",
+ },
+ {
+ // Ctrl-T on empty line: do nothing
+ in: "\x14\r",
+ line: "",
+ },
+ {
+ // Multiple Ctrl-T at end: keeps swapping last two
+ in: "abc\x14\x14\r",
+ line: "abc",
+ },
+ {
+ // Multiple Ctrl-T in middle: progresses through line
+ in: "abcd\x1b[D\x1b[D\x1b[D\x14\x14\x14\r",
+ line: "bcda",
+ },
}

func TestKeyPresses(t *testing.T) {

Change information

Files:
  • M terminal.go
  • M terminal_test.go
Change size: M
Delta: 2 files changed, 81 insertions(+), 0 deletions(-)
Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement is not satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: newchange
Gerrit-Project: term
Gerrit-Branch: master
Gerrit-Change-Id: I893677f9bceaf75aa1dada7d893845728e07057e
Gerrit-Change-Number: 730441
Gerrit-PatchSet: 1
Gerrit-Owner: Josh Bleecher Snyder <josh...@gmail.com>
unsatisfied_requirement
satisfied_requirement
open
diffy

Ian Lance Taylor (Gerrit)

unread,
Dec 16, 2025, 6:09:00 PM (8 hours ago) Dec 16
to Josh Bleecher Snyder, goph...@pubsubhelper.golang.org, Ian Lance Taylor, Michael Knyszek, golang-co...@googlegroups.com
Attention needed from Josh Bleecher Snyder and Michael Knyszek

Ian Lance Taylor voted and added 1 comment

Votes added by Ian Lance Taylor

Code-Review+2
Commit-Queue+1

1 comment

Patchset-level comments
File-level comment, Patchset 1 (Latest):
Ian Lance Taylor . resolved

Thanks.

Open in Gerrit

Related details

Attention is currently required from:
  • Josh Bleecher Snyder
  • Michael Knyszek
Submit Requirements:
  • requirement satisfiedCode-Review
  • requirement satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
  • requirement is not satisfiedTryBots-Pass
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: term
Gerrit-Branch: master
Gerrit-Change-Id: I893677f9bceaf75aa1dada7d893845728e07057e
Gerrit-Change-Number: 730441
Gerrit-PatchSet: 1
Gerrit-Owner: Josh Bleecher Snyder <josh...@gmail.com>
Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
Gerrit-Reviewer: Michael Knyszek <mkny...@google.com>
Gerrit-Attention: Josh Bleecher Snyder <josh...@gmail.com>
Gerrit-Attention: Michael Knyszek <mkny...@google.com>
Gerrit-Comment-Date: Tue, 16 Dec 2025 23:08:57 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
satisfied_requirement
unsatisfied_requirement
open
diffy

Michael Knyszek (Gerrit)

unread,
Dec 16, 2025, 8:00:16 PM (6 hours ago) Dec 16
to Josh Bleecher Snyder, goph...@pubsubhelper.golang.org, Go LUCI, Ian Lance Taylor, golang-co...@googlegroups.com
Attention needed from Josh Bleecher Snyder

Michael Knyszek voted Code-Review+2

Code-Review+2
Open in Gerrit

Related details

Attention is currently required from:
  • Josh Bleecher Snyder
Submit Requirements:
    • requirement satisfiedCode-Review
    • requirement satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    • requirement satisfiedTryBots-Pass
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: term
    Gerrit-Branch: master
    Gerrit-Change-Id: I893677f9bceaf75aa1dada7d893845728e07057e
    Gerrit-Change-Number: 730441
    Gerrit-PatchSet: 1
    Gerrit-Owner: Josh Bleecher Snyder <josh...@gmail.com>
    Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
    Gerrit-Reviewer: Michael Knyszek <mkny...@google.com>
    Gerrit-Attention: Josh Bleecher Snyder <josh...@gmail.com>
    Gerrit-Comment-Date: Wed, 17 Dec 2025 01:00:11 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    David Chase (Gerrit)

    unread,
    Dec 16, 2025, 8:48:23 PM (5 hours ago) Dec 16
    to Josh Bleecher Snyder, goph...@pubsubhelper.golang.org, Go LUCI, Ian Lance Taylor, golang-co...@googlegroups.com
    Attention needed from Josh Bleecher Snyder

    David Chase voted Code-Review+1

    Code-Review+1
    Open in Gerrit

    Related details

    Attention is currently required from:
    • Josh Bleecher Snyder
    Submit Requirements:
      • requirement satisfiedCode-Review
      • requirement satisfiedNo-Unresolved-Comments
      • requirement satisfiedReview-Enforcement
      • requirement satisfiedTryBots-Pass
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: term
      Gerrit-Branch: master
      Gerrit-Change-Id: I893677f9bceaf75aa1dada7d893845728e07057e
      Gerrit-Change-Number: 730441
      Gerrit-PatchSet: 1
      Gerrit-Owner: Josh Bleecher Snyder <josh...@gmail.com>
      Gerrit-Reviewer: David Chase <drc...@google.com>
      Gerrit-Reviewer: Ian Lance Taylor <ia...@golang.org>
      Gerrit-Reviewer: Michael Knyszek <mkny...@google.com>
      Gerrit-Attention: Josh Bleecher Snyder <josh...@gmail.com>
      Gerrit-Comment-Date: Wed, 17 Dec 2025 01:48:20 +0000
      Gerrit-HasComments: No
      Gerrit-Has-Labels: Yes
      satisfied_requirement
      open
      diffy
      Reply all
      Reply to author
      Forward
      0 new messages