Compare commits

..

7 Commits

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

Change-Id: I91b80d2350746afd3a4a6c03bc55eeb03a42e6ae
Reviewed-on: https://go-review.googlesource.com/c/term/+/710095
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-10-08 08:23:35 -07:00
Gopher Robot
1a11b45a6f go.mod: update golang.org/x dependencies
Update golang.org/x dependencies to their latest tagged versions.

Change-Id: If0cee55db64c734f53dfaa2d5b014c7eba22cd46
Reviewed-on: https://go-review.googlesource.com/c/term/+/701037
Auto-Submit: Gopher Robot <gobot@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2025-09-07 20:32:07 -07:00
Gopher Robot
d862cd548e all: upgrade go directive to at least 1.24.0 [generated]
By now Go 1.25.0 has been released, and Go 1.23 is no longer supported
per the Go Release Policy (see https://go.dev/doc/devel/release#policy).

For golang/go#69095.

[git-generate]
(cd . && go get go@1.24.0 && go mod tidy && go fix ./... && go mod edit -toolchain=none)

Change-Id: I8bf28e20963f73333d83fbe50434bb5abcce36da
Reviewed-on: https://go-review.googlesource.com/c/term/+/695280
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-08-13 07:50:04 -07:00
Gopher Robot
a35244d18d go.mod: update golang.org/x dependencies
Update golang.org/x dependencies to their latest tagged versions.

Change-Id: I99ad2113f2fb7d1f8e22475659335424ff94ffb7
Reviewed-on: https://go-review.googlesource.com/c/term/+/693976
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2025-08-07 07:52:19 -07:00
Laurent Demailly
4f53e0cd39 term: allow multi-line bracketed paste to not create single line with verbatim LFs
Treat "\n" (LF) like "Enter" (CR)

Avoids that when pasting 3 lines
(with a terminal like kitty, ghostty, alacritty that do not change the clipboard
in bracketed paste mode)
it turns into 1 prompt looking like:

Test> line one
..............line.two
......................line.three

Fixes golang/go#74600

Change-Id: I4a86044a4a175eccb3a96dbf7021fee97a5940ce
GitHub-Last-Rev: 0cf26df9ae
GitHub-Pull-Request: golang/term#21
Reviewed-on: https://go-review.googlesource.com/c/term/+/687755
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-07-21 12:13:29 -07:00
Ayman Bagabas
27f29d8328 term: remove duplicate flag and add comment on windows
Both windows.ENABLE_PROCESSED_INPUT and windows.ENABLE_PROCESSED_OUTPUT have
the same value of 0x1. Using makeRaw on a console output screen buffer handle
wouldn't make sense since on Windows the input handle and the output screen
buffer handle are two separate things.

See https://learn.microsoft.com/en-us/windows/console/setconsolemode

Change-Id: I19feadf8da303a1ada8e517399416a4730845900
GitHub-Last-Rev: 832fc7e8af
GitHub-Pull-Request: golang/term#14
Reviewed-on: https://go-review.googlesource.com/c/term/+/562779
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Laurent Demailly <ldemailly@gmail.com>
Reviewed-by: Jorropo <jorropo.pgm@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
2025-07-15 09:43:07 -07:00
Gopher Robot
30da5dd58f go.mod: update golang.org/x dependencies
Update golang.org/x dependencies to their latest tagged versions.

Change-Id: I4d4074eba1258708fcf00744be2607aadb104396
Reviewed-on: https://go-review.googlesource.com/c/term/+/687037
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-07-09 13:10:58 -07:00
5 changed files with 58 additions and 7 deletions

4
go.mod
View File

@@ -1,5 +1,5 @@
module golang.org/x/term
go 1.23.0
go 1.24.0
require golang.org/x/sys v0.33.0
require golang.org/x/sys v0.37.0

4
go.sum
View File

@@ -1,2 +1,2 @@
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=

View File

@@ -20,12 +20,14 @@ func isTerminal(fd int) bool {
return err == nil
}
// This is intended to be used on a console input handle.
// See https://learn.microsoft.com/en-us/windows/console/setconsolemode
func makeRaw(fd int) (*State, error) {
var st uint32
if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil {
return nil, err
}
raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT)
raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT)
raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT
if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil {
return nil, err

View File

@@ -146,6 +146,7 @@ const (
keyCtrlD = 4
keyCtrlU = 21
keyEnter = '\r'
keyLF = '\n'
keyEscape = 27
keyBackspace = 127
keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota
@@ -497,7 +498,7 @@ func (t *Terminal) historyAdd(entry string) {
// handleKey processes the given key and, optionally, returns a line of text
// that the user has entered.
func (t *Terminal) handleKey(key rune) (line string, ok bool) {
if t.pasteActive && key != keyEnter {
if t.pasteActive && key != keyEnter && key != keyLF {
t.addKeyToLine(key)
return
}
@@ -567,7 +568,7 @@ func (t *Terminal) handleKey(key rune) (line string, ok bool) {
t.setLine(runes, len(runes))
}
}
case keyEnter:
case keyEnter, keyLF:
t.moveCursorToPos(len(t.line))
t.queue([]rune("\r\n"))
line = string(t.line)
@@ -812,6 +813,10 @@ func (t *Terminal) readLine() (line string, err error) {
if !t.pasteActive {
lineIsPasted = false
}
// If we have CR, consume LF if present (CRLF sequence) to avoid returning an extra empty line.
if key == keyEnter && len(rest) > 0 && rest[0] == keyLF {
rest = rest[1:]
}
line, lineOk = t.handleKey(key)
}
if len(rest) > 0 {

View File

@@ -6,6 +6,8 @@ package term
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"runtime"
@@ -208,12 +210,24 @@ var keyPressTests = []struct {
line: "efgh",
throwAwayLines: 1,
},
{
// Newline in bracketed paste mode should still work.
in: "abc\x1b[200~d\nefg\x1b[201~h\r",
line: "efgh",
throwAwayLines: 1,
},
{
// Lines consisting entirely of pasted data should be indicated as such.
in: "\x1b[200~a\r",
line: "a",
err: ErrPasteIndicator,
},
{
// Lines consisting entirely of pasted data should be indicated as such (\n paste).
in: "\x1b[200~a\n",
line: "a",
err: ErrPasteIndicator,
},
{
// Ctrl-C terminates readline
in: "\003",
@@ -296,6 +310,36 @@ func TestRender(t *testing.T) {
}
}
func TestCRLF(t *testing.T) {
c := &MockTerminal{
toSend: []byte("line1\rline2\r\nline3\n"),
// bytesPerRead 0 in this test means read all at once
// CR+LF need to be in same read for ReadLine to not produce an extra empty line
// which is what terminals do for reasonably small paste. if way many lines are pasted
// and going over say 1k-16k buffer, readline current implementation will possibly generate 1
// extra empty line, if the CR is in chunk1 and LF in chunk2 (and that's fine).
}
ss := NewTerminal(c, "> ")
for i := range 3 {
line, err := ss.ReadLine()
if err != nil {
t.Fatalf("failed to read line %d: %v", i+1, err)
}
expected := fmt.Sprintf("line%d", i+1)
if line != expected {
t.Fatalf("expected '%s', got '%s'", expected, line)
}
}
line, err := ss.ReadLine()
if !errors.Is(err, io.EOF) {
t.Fatalf("expected EOF after 3 lines, got '%s' with error %v", line, err)
}
if line != "" {
t.Fatalf("expected empty line after EOF, got '%s'", line)
}
}
func TestPasswordNotSaved(t *testing.T) {
c := &MockTerminal{
toSend: []byte("password\r\x1b[A\r"),