xtermjs / xterm.js

A terminal for the web
https://xtermjs.org/
MIT License
17.33k stars 1.61k forks source link

Empty `input()` or `input("")` won't ask a thing and duplicate the output #4966

Closed WebReflection closed 6 months ago

WebReflection commented 6 months ago

Details

Steps to reproduce

We are using this (lovely btw) project to fuel PyScript and our users noticed that if an input() has no relevant content to ask for, as a prompt, the terminal duplicates the output and users get no chances to interact.

This Does Not Work

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>PyTerminal Main</title>
        <link rel="stylesheet" href="https://pyscript.net/releases/2024.1.3/core.css">
        <script type="module" src="https://pyscript.net/releases/2024.1.3/core.js"></script>
        <style>.xterm { padding: .5rem; }</style>
    </head>
    <body>
        <script type="py" worker terminal>
          print("Hello")
          a = input()
          print("You entered", a)
        </script>
    </body>
</html>

This Does Work (zero-width space filling)

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>PyTerminal Main</title>
        <link rel="stylesheet" href="https://pyscript.net/releases/2024.1.3/core.css">
        <script type="module" src="https://pyscript.net/releases/2024.1.3/core.js"></script>
        <style>.xterm { padding: .5rem; }</style>
    </head>
    <body>
        <script type="py" worker terminal>
          print("Hello")
          a = input("​")
          print("You entered", a)
        </script>
    </body>
</html>

As we don't really change or dictate any specific behavior, it was weird to me not finding previously opened discussions but if my searching skills are that bad, my apologies.

Proposed Solution

Literally default to zero width space argument/parameter for the input function whenever no argument or an empty string is passed along.

Thank you 🙏

Tyriar commented 6 months ago

It's not clear what input and print do, are they calls in pyscript that forward things to xterm.js? If so do you have their definitions?

WebReflection commented 6 months ago

@Tyriar we use xterm and readline to handle things but we don't provide anything special there ... print is just a console.log though, the issue is with the input() ... where input("anything: ") works but input() or input("") doesn't.

If it helps anyhow, our py-terminal plugin is here.

The bootstrap is here: https://github.com/pyscript/pyscript/blob/main/pyscript.core/src/plugins/py-terminal.js#L121-L126 and its init is here: https://github.com/pyscript/pyscript/blob/main/pyscript.core/src/plugins/py-terminal.js#L144-L148

Happy to explain or answer anything else, thank you!

WebReflection commented 6 months ago

btw, the stdin is handled by pyodide and I am not excluding the issue is in there ... if anyone can confirm that empty input() works out of the box already, I think we can close this and pass the ball to pyodide stdin handling or monkey-patch that ourselves if no input is expected to be handled.

If that's the case, apologies for filing this here but as we can handle empty inputs in other examples, I kinda believed it wasn't pyodide but a combination of readline and pyodide might make the difference.

Tyriar commented 6 months ago

@WebReflection oh, I'm guessing this is a question for xterm-readline then which isn't maintained by us https://www.npmjs.com/package/xterm-readline?activeTab=readme

xterm.js just has a single write(string) call that writes that text and you're not meant to call it with on argument (TS compile error). I'm guessing xterm-readline would call into that somehow so you'd be better off asking that project.