Compare commits

..

7 Commits

Author SHA1 Message Date
Gopher Robot
9d2dc074d2 go.mod: update golang.org/x dependencies
Update golang.org/x dependencies to their latest tagged versions.

Change-Id: I073699501f2bc25a2e2066199e57fb222c538551
Reviewed-on: https://go-review.googlesource.com/c/term/+/752840
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
2026-03-09 18:43:14 -07:00
Gopher Robot
d954e03213 all: upgrade go directive to at least 1.25.0 [generated]
By now Go 1.26.0 has been released, and Go 1.24 is no longer supported
per the Go Release Policy (see https://go.dev/doc/devel/release#policy).

See go.dev/doc/godebug#go-125 for GODEBUG changes relevant to Go 1.25.

For golang/go#69095.

[git-generate]
(cd . && go get go@1.25.0 && go mod tidy)

Change-Id: I4a118e0eda9ccd419b4287e5e9dfadb0c701b93a
Reviewed-on: https://go-review.googlesource.com/c/term/+/744480
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
2026-02-11 11:15:20 -08:00
Gopher Robot
3aff3041f5 go.mod: update golang.org/x dependencies
Update golang.org/x dependencies to their latest tagged versions.

Change-Id: I5b515b495088db93315c991c1be3932d2b1122d7
Reviewed-on: https://go-review.googlesource.com/c/term/+/743180
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2026-02-09 08:13:12 -08:00
Gopher Robot
a7e5b0437f go.mod: update golang.org/x dependencies
Update golang.org/x dependencies to their latest tagged versions.

Change-Id: I5ffb7b7c88fd3074335b3465a0fb76e839654802
Reviewed-on: https://go-review.googlesource.com/c/term/+/734802
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
2026-01-09 08:09:29 -08:00
Josh Bleecher Snyder
943f25d359 x/term: handle transpose
The behavior implemented here matches readline and libedit.

Updates golang/go#76826

Change-Id: I893677f9bceaf75aa1dada7d893845728e07057e
Reviewed-on: https://go-review.googlesource.com/c/term/+/730441
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: David Chase <drchase@google.com>
2025-12-17 11:04:51 -08:00
Josh Bleecher Snyder
9b991dd831 x/term: handle delete key
Fixes golang/go#76826

Change-Id: I80dc9468c2cc716dab10a8e165ca5f72817ef4b9
Reviewed-on: https://go-review.googlesource.com/c/term/+/730440
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-12-16 13:07:46 -08:00
Gopher Robot
3863673230 go.mod: update golang.org/x dependencies
Update golang.org/x dependencies to their latest tagged versions.

Change-Id: I2b01858489f549d13f8274173247152bd9067849
Reviewed-on: https://go-review.googlesource.com/c/term/+/728003
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-12-08 08:57:31 -08:00
4 changed files with 117 additions and 6 deletions

4
go.mod
View File

@@ -1,5 +1,5 @@
module golang.org/x/term
go 1.24.0
go 1.25.0
require golang.org/x/sys v0.38.0
require golang.org/x/sys v0.42.0

4
go.sum
View File

@@ -1,2 +1,2 @@
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=

View File

@@ -160,7 +160,9 @@ const (
keyEnd
keyDeleteWord
keyDeleteLine
keyDelete
keyClearScreen
keyTranspose
keyPasteStart
keyPasteEnd
)
@@ -194,6 +196,8 @@ func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
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
@@ -228,6 +232,10 @@ func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
}
}
if !pasteActive && len(b) >= 4 && b[0] == keyEscape && b[1] == '[' && b[2] == '3' && b[3] == '~' {
return keyDelete, b[4:]
}
if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
switch b[5] {
case 'C':
@@ -590,7 +598,7 @@ func (t *Terminal) handleKey(key rune) (line string, ok bool) {
}
t.line = t.line[:t.pos]
t.moveCursorToPos(t.pos)
case keyCtrlD:
case keyCtrlD, keyDelete:
// Erase the character under the current position.
// The EOF case when the line is empty is handled in
// readLine().
@@ -600,6 +608,24 @@ func (t *Terminal) handleKey(key rune) (line string, ok bool) {
}
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"))

View File

@@ -238,6 +238,91 @@ var keyPressTests = []struct {
in: "a\003\r",
err: io.EOF,
},
{
// Delete at EOL: nothing
in: "abc\x1b[3~\r",
line: "abc",
},
{
// Delete in empty string: nothing
in: "\x1b[3~\r",
line: "",
},
{
// Move left, delete: delete 'c'
in: "abc\x1b[D\x1b[3~\r",
line: "ab",
},
{
// Home, delete: delete 'a'
in: "abc\x1b[H\x1b[3~\r",
line: "bc",
},
{
// Home, delete twice: delete 'a' and 'b'
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) {
@@ -387,7 +472,7 @@ func TestReadPasswordLineEnd(t *testing.T) {
input string
want string
}
var tests = []testType{
tests := []testType{
{"\r\n", ""},
{"test\r\n", "test"},
{"test\r", "test"},