WithInput(nil) allows stdin to pass through
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
- Run the minimal program below
- 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.
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.
@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.
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.
I'm seeing something similar when setting
WithOutput. If I addtea.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?
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.