bubbletea icon indicating copy to clipboard operation
bubbletea copied to clipboard

WithInput(nil) allows stdin to pass through

Open moneppo opened this issue 2 years ago • 5 comments

Describe the bug When setting WithInput(nil), input gets passed through to the terminal rather than being disabled entirely.

Setup macOS, tested on Terminal and VSCode's internal terminal

To Reproduce

  1. Run the minimal program below
  2. Enter any keyboard input

Source Code


import (
	tea "github.com/charmbracelet/bubbletea"
)

type model int

func main() {
	p := tea.NewProgram(model(0), tea.WithInput(nil))
	p.Run()
}

func (m model) Init() tea.Cmd { return nil }
func (m model) Update(message tea.Msg) (tea.Model, tea.Cmd) { return m, nil }
func (m model) View() string { return "..." }

Expected behavior No input allowed, program hangs after showing ...

Additional context Rather than not showing the output, any keys typed appear in the terminal (overwriting ...) and ctrl+c exits. Somehow stdin is getting routed to stdout.

moneppo avatar Aug 21 '23 05:08 moneppo

I'm seeing something similar when setting WithOutput. If I add tea.WithOutput(os.Stdout) to one of the example listing projects, the program just hangs in my terminal as well and doesn't respond to my keyboard at all.

You can reproduce by replacing this line:

https://github.com/charmbracelet/bubbletea/blob/91dd1200733714c4fb7bc7ffb24af2c35cc2f111/examples/list-simple/main.go#L124

with

if _, err := tea.NewProgram(m, tea.WithOutput(os.Stdout)).Run(); err != nil {

and running the example program.

priyawadhwa avatar Aug 21 '23 14:08 priyawadhwa

@moneppo It seems in the current implementation of bubble tea, ignoring input with WithInput(nil) means that bubble tea does not do any processing to receive user input. For example, the following processes are omitted

  • properly opening the terminal if the standard input is not terminal
  • hiding the cursor
  • putting the console in raw mode and ignore various terminal operations (e.g. ctrl+C to exit)
  • parsing the input.

If you ignore these processes, bubble tea will do nothing, and will behave exactly the same as a program that would not use bubble tea, just like you explained in this report. Stdin is not routed to stdout by bubble tea. it is simply the default behavior of the terminal.

A simpler implementation to ignore all inputs and hang the program is to simply ignore KeyMsg in Update.

wolfmagnate avatar Oct 26 '23 12:10 wolfmagnate

Hi! @wolfmagnate is mostly correct here. When WithInput(nil) is set Bubble Tea will not set the terminal to raw mode and not attach to input. Thus, input will be handled by the terminal emulator as normal. The cursor will still be hidden and Bubble Tea will still manage rendering, however, as both of those reside in the domain of output.

To prevent input from reaching the terminal, as @wolfmagnate recommends, as you would actually let Bubble Tea capture input as normal and simply ignore that input in your Update.

meowgorithm avatar Oct 26 '23 13:10 meowgorithm

I'm seeing something similar when setting WithOutput. If I add tea.WithOutput(os.Stdout) to one of the example listing projects, the program just hangs in my terminal as well and doesn't respond to my keyboard at all.

You can reproduce by replacing this line:

https://github.com/charmbracelet/bubbletea/blob/91dd1200733714c4fb7bc7ffb24af2c35cc2f111/examples/list-simple/main.go#L124

with

if _, err := tea.NewProgram(m, tea.WithOutput(os.Stdout)).Run(); err != nil {

and running the example program.

@priyawadhwa would you mind opening a separate issue for this, given that this is a separate topic?

meowgorithm avatar Oct 26 '23 13:10 meowgorithm

Thanks @meowgorithm, I was trying to implement a terminal emulator bubble, and as it stands, the existing message event system does not capture the entirety of possible input that would need to be routed to a terminal emulator. So I was looking for ways to capture the input directly to forward. It was a while ago that I was figuring this out, but another option I thought of was a "raw input" event that fired on everything received, rather than the curated events implemented in key.go.

moneppo avatar Oct 26 '23 17:10 moneppo