Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows: first character input lost on successive programs #1167

Open
jtackaberry opened this issue Sep 24, 2024 · 8 comments
Open

Windows: first character input lost on successive programs #1167

jtackaberry opened this issue Sep 24, 2024 · 8 comments
Assignees

Comments

@jtackaberry
Copy link

jtackaberry commented Sep 24, 2024

Describe the bug

On Windows, if multiple Tea programs are run successively within the same process, the first program runs fine, but subsequent programs lose the first key pressed. The key is silently eaten, after which point the program appears to operate properly until it terminates. Then rinse/repeat for subsequent Tea programs.

This does not occur on Linux or Mac.

Setup

  • OS: Windows
  • Shell: cmd and Powershell (both affected)
  • Terminal Emulator: Windows Terminal, Windows Powershell Console, Command Prompt
  • Terminal Multiplexer: none

To Reproduce

  1. Build the example in the source code section for windows
  2. Run it
  3. Type some keys for the first input prompt ("Test 0") and note that it works fine
  4. Type a key for the second input prompt ("Test 1") and note that the first key is eaten, and subsequent keys presses are registered

Source Code

package main

import (
	"fmt"

	"github.com/charmbracelet/bubbles/cursor"
	"github.com/charmbracelet/bubbles/textinput"
	tea "github.com/charmbracelet/bubbletea"
)

func Input(prompt, value string) {
	ti := textinput.New()
	ti.Prompt = prompt
	ti.Focus()
	p := tea.NewProgram(inputModel{textInput: ti})
	p.Run()
}

type inputModel struct {
	textInput textinput.Model
	quitting  bool
}

func (m inputModel) Init() tea.Cmd {
	return nil
}

func (m inputModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	var cmd tea.Cmd

	switch msg := msg.(type) {
	case tea.KeyMsg:
		switch msg.Type {
		case tea.KeyEnter:
			m.textInput.Cursor.SetMode(cursor.CursorHide)
			m.quitting = true
			return m, tea.Quit
		}
	}
	m.textInput, cmd = m.textInput.Update(msg)
	return m, cmd
}

func (m inputModel) View() string {
	str := m.textInput.View()
	if m.quitting {
		return str + "\n"
	}
	return str
}

func main() {
	for i := range 2 {
		Input(fmt.Sprintf("Test %d: ", i), "default")
	}
}

Expected behavior

The first key on subsequent Tea programs should not be lost.

Screenshots

image

@Denish3436
Copy link

Denish3436 commented Oct 9, 2024

hi @jtackaberry I would like to work on this, could you assign me

@meowgorithm
Copy link
Member

Go for it, @Denish3436 ✌️

@Denish3436
Copy link

Hii @meowgorithm , can you please review my PR

@meowgorithm
Copy link
Member

Hey @Denish3436! Ayman's reviewed it in #1180. Let's track progress over there.

@aymanbagabas
Copy link
Member

@Denish3436 This should be fixed in v2-exp

@nojaf
Copy link

nojaf commented Nov 27, 2024

Hi @aymanbagabas, I'm still getting that problem with the v2-exp branch on Windows.

Example file:

package main

import (
	"fmt"
	"log"
	"os"

	tea "github.com/charmbracelet/bubbletea/v2"
)

type model struct {
	v string
}

func NewModel() model {
	return model{v: ""}
}

func (m model) Init() (tea.Model, tea.Cmd) {
	return m, nil
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := msg.(type) {

	// Is it a key press?
	case tea.KeyMsg:
		log.Println("key pressed:", msg.String())

		switch msg.String() {
		case "ctrl+c", "enter":
			return m, tea.Quit
		default:
			m.v += msg.String()
		}
	}

	return m, nil
}

func (m model) View() string {
	return "> " + m.v
}

func main() {
	file := "debug.log"

	// Check if the file exists
	if _, err := os.Stat(file); err == nil {
		// File exists, attempt to remove it
		if err := os.Remove(file); err != nil {
			// Handle error during removal
			panic(err)
		}
	} else if !os.IsNotExist(err) {
		// Handle unexpected error during Stat
		panic(err)
	}

	f, err := tea.LogToFile(file, "debug")
	if err != nil {
		fmt.Println("fatal:", err)
		os.Exit(1)
	}
	defer f.Close()

	p := tea.NewProgram(NewModel())
	if _, err := p.Run(); err != nil {
		fmt.Printf("Alas, there's been an error: %v", err)
		os.Exit(1)
	}

	p2 := tea.NewProgram(NewModel())
	if _, err := p2.Run(); err != nil {
		fmt.Printf("Alas, there's been an error 2: %v", err)
		os.Exit(1)
	}
}

A keypress is swallowed for the second program and each key is duplicated in the stdout:

Actual key presses: a,b,c,enter,d,e,f,enter

debug 2024/11/27 16:29:30 key pressed: a
debug 2024/11/27 16:29:30 key pressed: a
debug 2024/11/27 16:29:31 key pressed: b
debug 2024/11/27 16:29:31 key pressed: b
debug 2024/11/27 16:29:31 key pressed: c
debug 2024/11/27 16:29:31 key pressed: c
debug 2024/11/27 16:29:32 key pressed: enter
debug 2024/11/27 16:29:32 key pressed: enter
debug 2024/11/27 16:29:35 key pressed: e
debug 2024/11/27 16:29:35 key pressed: e
debug 2024/11/27 16:29:36 key pressed: f
debug 2024/11/27 16:29:36 key pressed: f
debug 2024/11/27 16:29:36 key pressed: enter
debug 2024/11/27 16:29:36 key pressed: enter

Any pointers?

@aymanbagabas
Copy link
Member

Hi @aymanbagabas, I'm still getting that problem with the v2-exp branch on Windows.

Hi @nojaf. You're getting duplicate keys because you're listening for tea.KeyMsg which accounts for both tea.KeyPressMsg and tea.KeyReleaseMsg.

This should fix that for you:

-	case tea.KeyMsg:
+	case tea.KeyPressMsg:

Now, running your examples with the latest v2-exp branch gives me this output.

PS C:\Users\Ayman\Source\charmbracelet\bubbletea\examples> Get-Content -path .\debug.log -wait
debug 2024/11/27 11:23:29 key pressed: a
debug 2024/11/27 11:23:30 key pressed: b
debug 2024/11/27 11:23:30 key pressed: c
debug 2024/11/27 11:23:33 key pressed: d
debug 2024/11/27 11:23:34 key pressed: enter
debug 2024/11/27 11:23:35 key pressed: e
debug 2024/11/27 11:23:36 key pressed: f
debug 2024/11/27 11:23:39 key pressed: g
debug 2024/11/27 11:23:40 key pressed: h
debug 2024/11/27 11:23:41 key pressed: enter

I'm using Windows Terminal Preview on Windows 11 with the default PowerShell version.

@nojaf
Copy link

nojaf commented Nov 27, 2024

Hey @aymanbagabas, thanks for the quick feedback!

The KeyPressMsg fix does indeed solve the duplicate keys.
As for the missing one, it does still pop up in vscode termninal for me.
Not in the Windows Terminal but the thing vscode uses. (both using latest pwsh)

bubbletea_vscode

debug 2024/11/27 17:42:53 key pressed: a
debug 2024/11/27 17:42:53 key pressed: b
debug 2024/11/27 17:42:54 key pressed: c
debug 2024/11/27 17:42:54 key pressed: enter
debug 2024/11/27 17:42:56 key pressed: e
debug 2024/11/27 17:42:56 key pressed: f
debug 2024/11/27 17:42:56 key pressed: enter

I did press d and it is still missing there.

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

No branches or pull requests

5 participants