From d928d8dcabcd4bca0efc22fb661de0cc27c66b21 Mon Sep 17 00:00:00 2001 From: bashbunni <15822994+bashbunni@users.noreply.github.com> Date: Wed, 16 Oct 2024 09:58:27 -0700 Subject: [PATCH 1/7] docs: update contributing guidelines (#1186) * docs(contributing): use org contributing guidelines * fix(docs): fix link to contribution page * docs: use https for links, not http --- CONTRIBUTING.md | 13 ------------- README.md | 10 ++++++++-- 2 files changed, 8 insertions(+), 15 deletions(-) delete mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 19ee18c766..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,13 +0,0 @@ -# Contributing - -Pull requests are welcome for any changes. - -Consider opening an issue for larger changes to get feedback on the idea from the team. - -If your change touches parts of the Bubble Tea renderer or internals, make sure -that all the examples in the `examples/` folder continue to run correctly. - -For commit messages, please use conventional commits[^1] to make it easier to -generate release notes. - -[^1]: https://www.conventionalcommits.org/en/v1.0.0 diff --git a/README.md b/README.md index f994fe35bd..4dbe75eb14 100644 --- a/README.md +++ b/README.md @@ -254,8 +254,8 @@ look at the [Command Tutorial][cmd]. It's pretty simple. There are also several [Bubble Tea examples][examples] available and, of course, there are [Go Docs][docs]. -[cmd]: http://github.com/charmbracelet/bubbletea/tree/master/tutorials/commands/ -[examples]: http://github.com/charmbracelet/bubbletea/tree/master/examples +[cmd]: https://github.com/charmbracelet/bubbletea/tree/master/tutorials/commands/ +[examples]: https://github.com/charmbracelet/bubbletea/tree/master/examples [docs]: https://pkg.go.dev/github.com/charmbracelet/bubbletea?tab=doc ## Debugging @@ -354,6 +354,12 @@ For more applications built with Bubble Tea see [Charm & Friends][community]. Is there something cool you made with Bubble Tea you want to share? [PRs][community] are welcome! +## Contributing + +See [contributing][contribute]. + +[contribute]: https://github.com/charmbracelet/bubbletea/contribute + ## Feedback We’d love to hear your thoughts on this project. Feel free to drop us a note! From cd1e4d34a7e0232ea94afcc168eec107450aa332 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Sun, 20 Oct 2024 21:45:53 -0700 Subject: [PATCH 2/7] fix: exec tests on windows Windows doesn't have true/false binaries --- exec_test.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/exec_test.go b/exec_test.go index b5fbbfa3b0..d49f0cc543 100644 --- a/exec_test.go +++ b/exec_test.go @@ -3,6 +3,7 @@ package tea import ( "bytes" "os/exec" + "runtime" "testing" ) @@ -37,21 +38,12 @@ func (m *testExecModel) View() string { } func TestTeaExec(t *testing.T) { - tests := []struct { + type test struct { name string cmd string expectErr bool - }{ - { - name: "true", - cmd: "true", - expectErr: false, - }, - { - name: "false", - cmd: "false", - expectErr: true, - }, + } + tests := []test{ { name: "invalid command", cmd: "invalid", @@ -59,6 +51,21 @@ func TestTeaExec(t *testing.T) { }, } + if runtime.GOOS != "windows" { + tests = append(tests, []test{ + { + name: "true", + cmd: "true", + expectErr: false, + }, + { + name: "false", + cmd: "false", + expectErr: true, + }, + }...) + } + for _, test := range tests { t.Run(test.name, func(t *testing.T) { var buf bytes.Buffer From 566879aa33ce13f27a6bdab4a274e08be01bac9c Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Sun, 20 Oct 2024 21:51:35 -0700 Subject: [PATCH 3/7] fix(ci): run lint workflow on all platforms --- .github/workflows/lint-soft.yml | 59 +++++++++++++++++---------------- .github/workflows/lint.yml | 59 +++++++++++++++++---------------- 2 files changed, 62 insertions(+), 56 deletions(-) diff --git a/.github/workflows/lint-soft.yml b/.github/workflows/lint-soft.yml index 87d1e1f9b0..50484fb502 100644 --- a/.github/workflows/lint-soft.yml +++ b/.github/workflows/lint-soft.yml @@ -1,28 +1,31 @@ -name: lint-soft -on: - push: - pull_request: - -permissions: - contents: read - # Optional: allow read access to pull request. Use with `only-new-issues` option. - pull-requests: read - -jobs: - golangci: - name: lint-soft - runs-on: ubuntu-latest - steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ^1 - - - uses: actions/checkout@v4 - - name: golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - # Optional: golangci-lint command line arguments. - args: --config .golangci-soft.yml --issues-exit-code=0 - # Optional: show only new issues if it's a pull request. The default value is `false`. - only-new-issues: true +name: lint-soft +on: + push: + pull_request: + +permissions: + contents: read + # Optional: allow read access to pull request. Use with `only-new-issues` option. + pull-requests: read + +jobs: + golangci: + name: lint-soft + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ^1 + + - uses: actions/checkout@v4 + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + # Optional: golangci-lint command line arguments. + args: --config .golangci-soft.yml --issues-exit-code=0 + # Optional: show only new issues if it's a pull request. The default value is `false`. + only-new-issues: true diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f617a5a281..a328399b60 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,28 +1,31 @@ -name: lint -on: - push: - pull_request: - -permissions: - contents: read - # Optional: allow read access to pull request. Use with `only-new-issues` option. - pull-requests: read - -jobs: - golangci: - name: lint - runs-on: ubuntu-latest - steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ^1 - - - uses: actions/checkout@v4 - - name: golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - # Optional: golangci-lint command line arguments. - #args: - # Optional: show only new issues if it's a pull request. The default value is `false`. - only-new-issues: true +name: lint +on: + push: + pull_request: + +permissions: + contents: read + # Optional: allow read access to pull request. Use with `only-new-issues` option. + pull-requests: read + +jobs: + golangci: + name: lint + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: ^1 + + - uses: actions/checkout@v4 + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + # Optional: golangci-lint command line arguments. + #args: + # Optional: show only new issues if it's a pull request. The default value is `false`. + only-new-issues: true From 43b11c30b36eddd75472efc83d8e76fadbf72e7f Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 22 Oct 2024 17:26:16 -0400 Subject: [PATCH 4/7] fix: make grapheme clustering opt-in This commit changes the behavior of grapheme clustering to be opt-in instead of opt-out. This is because some terminals like Apple Terminal don't support DECRQM and DECRPM, which are required for querying and setting the grapheme clustering state. Apple Terminal, instead, replies with a `p` character when querying the grapheme clustering state, which is not a valid response and breaks the program output. --- examples/simple/testdata/TestApp.golden | 2 +- options.go | 6 ++--- screen_test.go | 33 ++++++++++++++----------- tea.go | 4 +-- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/examples/simple/testdata/TestApp.golden b/examples/simple/testdata/TestApp.golden index 2c245f9c58..28dc7991b3 100644 --- a/examples/simple/testdata/TestApp.golden +++ b/examples/simple/testdata/TestApp.golden @@ -1,4 +1,4 @@ -[?25l[?2004h[?2027h[?2027$p Hi. This program will exit in 10 seconds. +[?25l[?2004h Hi. This program will exit in 10 seconds. To quit sooner press ctrl-c, or press ctrl-z to suspend... Hi. This program will exit in 9 seconds. diff --git a/options.go b/options.go index 08fb7403ec..db0810b0e7 100644 --- a/options.go +++ b/options.go @@ -254,7 +254,7 @@ func WithKeyboardEnhancements(enhancements ...KeyboardEnhancement) ProgramOption } } -// WithoutGraphemeClustering disables grapheme clustering. This is useful if you +// WithGraphemeClustering disables grapheme clustering. This is useful if you // want to disable grapheme clustering for your program. // // Grapheme clustering is a character width calculation method that accurately @@ -263,8 +263,8 @@ func WithKeyboardEnhancements(enhancements ...KeyboardEnhancement) ProgramOption // characters. // // See https://mitchellh.com/writing/grapheme-clusters-in-terminals -func WithoutGraphemeClustering() ProgramOption { +func WithGraphemeClustering() ProgramOption { return func(p *Program) { - p.startupOptions |= withoutGraphemeClustering + p.startupOptions |= withGraphemeClustering } } diff --git a/screen_test.go b/screen_test.go index 4e569fd50f..4716bb1d03 100644 --- a/screen_test.go +++ b/screen_test.go @@ -17,62 +17,67 @@ func TestClearMsg(t *testing.T) { { name: "clear_screen", cmds: []Cmd{ClearScreen}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b[2J\x1b[1;1H\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", + expected: "\x1b[?25l\x1b[?2004h\x1b[2J\x1b[1;1H\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", }, { name: "altscreen", cmds: []Cmd{EnterAltScreen, ExitAltScreen}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b[?1049h\x1b[2J\x1b[1;1H\x1b[?25l\x1b[?1049l\x1b[?25l\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", + expected: "\x1b[?25l\x1b[?2004h\x1b[?1049h\x1b[2J\x1b[1;1H\x1b[?25l\x1b[?1049l\x1b[?25l\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", }, { name: "altscreen_autoexit", cmds: []Cmd{EnterAltScreen}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b[?1049h\x1b[2J\x1b[1;1H\x1b[?25l\rsuccess\r\n\x1b[2;0H\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b[?1049l\x1b[?25h", + expected: "\x1b[?25l\x1b[?2004h\x1b[?1049h\x1b[2J\x1b[1;1H\x1b[?25l\rsuccess\r\n\x1b[2;0H\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b[?1049l\x1b[?25h", }, { name: "mouse_cellmotion", cmds: []Cmd{EnableMouseCellMotion}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b[?1002h\x1b[?1006h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b[?1002l\x1b[?1003l\x1b[?1006l", + expected: "\x1b[?25l\x1b[?2004h\x1b[?1002h\x1b[?1006h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b[?1002l\x1b[?1003l\x1b[?1006l", }, { name: "mouse_allmotion", cmds: []Cmd{EnableMouseAllMotion}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b[?1003h\x1b[?1006h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b[?1002l\x1b[?1003l\x1b[?1006l", + expected: "\x1b[?25l\x1b[?2004h\x1b[?1003h\x1b[?1006h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b[?1002l\x1b[?1003l\x1b[?1006l", }, { name: "mouse_disable", cmds: []Cmd{EnableMouseAllMotion, DisableMouse}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b[?1003h\x1b[?1006h\x1b[?1002l\x1b[?1003l\x1b[?1006l\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", + expected: "\x1b[?25l\x1b[?2004h\x1b[?1003h\x1b[?1006h\x1b[?1002l\x1b[?1003l\x1b[?1006l\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", }, { name: "cursor_hide", cmds: []Cmd{HideCursor}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", + expected: "\x1b[?25l\x1b[?2004h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", }, { name: "cursor_hideshow", cmds: []Cmd{HideCursor, ShowCursor}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b[?25h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l", + expected: "\x1b[?25l\x1b[?2004h\x1b[?25h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l", }, { name: "bp_stop_start", cmds: []Cmd{DisableBracketedPaste, EnableBracketedPaste}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b[?2004l\x1b[?2004h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", + expected: "\x1b[?25l\x1b[?2004h\x1b[?2004l\x1b[?2004h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", }, { name: "read_set_clipboard", cmds: []Cmd{ReadClipboard, SetClipboard("success")}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b]52;c;?\a\x1b]52;c;c3VjY2Vzcw==\a\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", + expected: "\x1b[?25l\x1b[?2004h\x1b]52;c;?\a\x1b]52;c;c3VjY2Vzcw==\a\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", }, { name: "bg_fg_cur_color", cmds: []Cmd{ForegroundColor, BackgroundColor, CursorColor}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b]10;?\a\x1b]11;?\a\x1b]12;?\a\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", + expected: "\x1b[?25l\x1b[?2004h\x1b]10;?\a\x1b]11;?\a\x1b]12;?\a\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", }, { name: "bg_set_color", cmds: []Cmd{SetBackgroundColor(color.RGBA{255, 255, 255, 255})}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b]11;#ffffff\a\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b]111\a", + expected: "\x1b[?25l\x1b[?2004h\x1b]11;#ffffff\a\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b]111\a", + }, + { + name: "grapheme_clustering", + cmds: []Cmd{EnableGraphemeClustering}, + expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b[?2027l", }, } @@ -81,13 +86,13 @@ func TestClearMsg(t *testing.T) { tests = append(tests, test{ name: "kitty_start", cmds: []Cmd{DisableKeyboardEnhancements, EnableKeyboardEnhancements(WithKeyReleases)}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", + expected: "\x1b[?25l\x1b[?2004h\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h", }) } else { tests = append(tests, test{ name: "kitty_start", cmds: []Cmd{DisableKeyboardEnhancements, EnableKeyboardEnhancements(WithKeyReleases)}, - expected: "\x1b[?25l\x1b[?2004h\x1b[?2027h\x1b[?2027$p\x1b[>4;1m\x1b[>3u\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b[>4;0m\x1b[>0u", + expected: "\x1b[?25l\x1b[?2004h\x1b[>4;1m\x1b[>3u\rsuccess\r\n\x1b[D\x1b[2K\r\x1b[?2004l\x1b[?25h\x1b[>4;0m\x1b[>0u", }) } diff --git a/tea.go b/tea.go index 22a07bc8db..b0028c2195 100644 --- a/tea.go +++ b/tea.go @@ -103,7 +103,7 @@ const ( withoutBracketedPaste withReportFocus withKeyboardEnhancements - withoutGraphemeClustering + withGraphemeClustering ) // channelHandlers manages the series of channels returned by various processes. @@ -733,7 +733,7 @@ func (p *Program) Run() (Model, error) { p.execute(ansi.EnableBracketedPaste) p.modes[ansi.BracketedPasteMode] = true } - if p.startupOptions&withoutGraphemeClustering == 0 { + if p.startupOptions&withGraphemeClustering != 0 { p.execute(ansi.EnableGraphemeClustering) p.execute(ansi.RequestGraphemeClustering) // We store the state of grapheme clustering after we query it and get From 12b04c5d6001056875bc712f81fa1efd470fa592 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 22 Oct 2024 17:46:08 -0400 Subject: [PATCH 5/7] feat(ci): use meta lint workflow This replaces the existing lint workflow and config with the one from the meta repository. --- .github/workflows/lint.yml | 39 +++++++------------------------- .golangci-soft.yml | 46 -------------------------------------- .golangci.yml | 30 ------------------------- 3 files changed, 8 insertions(+), 107 deletions(-) delete mode 100644 .golangci-soft.yml delete mode 100644 .golangci.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a328399b60..a1d6d0e512 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,31 +1,8 @@ -name: lint -on: - push: - pull_request: - -permissions: - contents: read - # Optional: allow read access to pull request. Use with `only-new-issues` option. - pull-requests: read - -jobs: - golangci: - name: lint - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ^1 - - - uses: actions/checkout@v4 - - name: golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - # Optional: golangci-lint command line arguments. - #args: - # Optional: show only new issues if it's a pull request. The default value is `false`. - only-new-issues: true +name: lint +on: + push: + pull_request: + +jobs: + lint: + uses: charmbracelet/meta/.github/workflows/lint.yml@main diff --git a/.golangci-soft.yml b/.golangci-soft.yml deleted file mode 100644 index 1b6824bb2d..0000000000 --- a/.golangci-soft.yml +++ /dev/null @@ -1,46 +0,0 @@ -run: - tests: false - -issues: - include: - - EXC0001 - - EXC0005 - - EXC0011 - - EXC0012 - - EXC0013 - - max-issues-per-linter: 0 - max-same-issues: 0 - -linters: - enable: - # - dupl - - exhaustive - # - exhaustivestruct - - goconst - - godot - - godox - - gomnd - - gomoddirectives - - goprintffuncname - # - lll - - misspell - - nakedret - - nestif - - noctx - - nolintlint - - prealloc - - wrapcheck - - # disable default linters, they are already enabled in .golangci.yml - disable: - - deadcode - - errcheck - - gosimple - - govet - - ineffassign - - staticcheck - - structcheck - - typecheck - - unused - - varcheck diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 3affce9147..0000000000 --- a/.golangci.yml +++ /dev/null @@ -1,30 +0,0 @@ -run: - tests: false - -issues: - include: - - EXC0001 - - EXC0005 - - EXC0011 - - EXC0012 - - EXC0013 - - max-issues-per-linter: 0 - max-same-issues: 0 - -linters: - enable: - - bodyclose - - exportloopref - - gofumpt - - goimports - - gosec - - nilerr - - predeclared - - revive - - rowserrcheck - - sqlclosecheck - - tparallel - - unconvert - - unparam - - whitespace From 1c01f2b1fc9039df02ac968cefc41808fc05f8b3 Mon Sep 17 00:00:00 2001 From: bashbunni Date: Wed, 23 Oct 2024 08:04:55 -0700 Subject: [PATCH 6/7] chore(lint): remove lint-soft; use meta --- .github/workflows/lint-soft.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .github/workflows/lint-soft.yml diff --git a/.github/workflows/lint-soft.yml b/.github/workflows/lint-soft.yml deleted file mode 100644 index 50484fb502..0000000000 --- a/.github/workflows/lint-soft.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: lint-soft -on: - push: - pull_request: - -permissions: - contents: read - # Optional: allow read access to pull request. Use with `only-new-issues` option. - pull-requests: read - -jobs: - golangci: - name: lint-soft - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: ^1 - - - uses: actions/checkout@v4 - - name: golangci-lint - uses: golangci/golangci-lint-action@v6 - with: - # Optional: golangci-lint command line arguments. - args: --config .golangci-soft.yml --issues-exit-code=0 - # Optional: show only new issues if it's a pull request. The default value is `false`. - only-new-issues: true From b3904a305dcb3c3669aff9bd6dae121a8e837322 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Mon, 21 Oct 2024 12:32:34 -0400 Subject: [PATCH 7/7] fix: windows: ensure the input buffer is empty Before initializing the input reader, we need to ensure that the console input buffer is empty, otherwise, we can get dangling events from previous sessions. --- cancelreader_windows.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cancelreader_windows.go b/cancelreader_windows.go index 4aa5a759e0..e55ca79d31 100644 --- a/cancelreader_windows.go +++ b/cancelreader_windows.go @@ -10,6 +10,7 @@ import ( "sync" "time" + xwindows "github.com/charmbracelet/x/windows" "github.com/muesli/cancelreader" "golang.org/x/sys/windows" ) @@ -47,6 +48,11 @@ func newCancelreader(r io.Reader) (cancelreader.CancelReader, error) { return fallback(r) } + // Discard any pending input events. + if err := xwindows.FlushConsoleInputBuffer(conin); err != nil { + return fallback(r) + } + originalMode, err := prepareConsole(conin, windows.ENABLE_MOUSE_INPUT, windows.ENABLE_WINDOW_INPUT,