-
Notifications
You must be signed in to change notification settings - Fork 49
Description
I am currently implementing a browser based terminal with a DSL narrowly scoped for interacting with JSON APIs. I implemented command output using scoped containers to avoid race conditions and naturally ran into the problem of accepting input from commands that had already lost the prompt. Here are my thoughts:
Traditionally:
- STDIN is a stream that is open by default
- STDIN can be read by one process at a time
- Synchronous portions of a command block the shell
- Asynchronous portions of a command race for write access to STDOUT
Goals:
- Allow asynchronous commands to release the shell early
- Organize latent output
- Support latent input
When should a command release the shell?
- When it is done reading input
- When it is done performing synchronous tasks
- It should never actually block the shell at all
It would be interesting to allow developers to simply close the STDIN stream to guarantee that their program is done asking for input. That would even allow synchronous programs to free the shell early.
It would be nice to get non-blocking async behavior by default though. If you want to free the shell and continue accepting input without disrupting the active shell, it becomes a matter of user interface design. The command needs a way to ask for input without loosing the context of it's output. If you assume that output is organized in containers that are scoped to commands, then you have to assume that it might be hidden in the scroll history.
How should latent input prompts look?
- A global notification with a link that scrolls to the command container
- Shift the command container to the bottom of the stack so it is visible
- A popup with a copy of the command container
I prefer reordering the command containers to avoid making the user scroll back to the main prompt when they are done. I am not a fan of popups. I am not convinced that allowing multiple active input prompts is a good idea. It might be confusing to the user.
In the end I think I would prefer that users have an intuitive experience and put the burden of optimization on the developer.
- Provide an unopened STDIN stream to the command
- Block the shell while the command is executing synchronously
- Require the command to synchronously open the STDIN stream if it wants read from it at any time
- Block the shell until the STDIN stream is closed or the command exits
- Allow the shell to release the STDIN stream before it is opened which releases the shell before the command is done executing synchronously