-
-
Notifications
You must be signed in to change notification settings - Fork 844
Add Xterm
element
#4520
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
base: main
Are you sure you want to change the base?
Add Xterm
element
#4520
Conversation
Xterm.js is quite a well-used project at this point. I have seen it used in Proxmox, as well as various third-party router plugins which provide SSH. So, I can stand behind including it for NiceGUI. If I understand correctly, now we need to do Check out npm.json and npm.py to see how other elements officially in NiceGUI currently fetches the dependencies from NPM (though that's up for change later, but should stick until rest of 2.X) |
@evnchn Thanks for your comment. This PR just adds an example, very similar to the one here: https://github.com/zauberzeug/nicegui/tree/main/examples/signature_pad |
I think xterm.js would be a wonderful (and very powerful) NiceGUI element. But let me discuss it with @falkoschindler first. Might be at the end of the week. |
Thanks for the pull request, @paco-sevilla! @rodja and I agreed that it would be great to integrate Xterm.js in NiceGUI. For such a useful UI element, it only adds ~300KB of minified JS and a few lines of CSS. (I haven't checked the addons though.) Instead of So we'd appreciate it very much if you could convert the example into an integrated UI element, either on this PR or a new one. As @evnchn pointed out, we currently manage our dependencies with npm.json and npm.py, which might be a bit tricky to use. Let us know if you need help with anything! |
+1 |
@falkoschindler If you are working on Notably, the files this PR needs:
|
Add this to "xterm": {
"package": "@xterm/xterm",
"destination": "nicegui/elements/lib",
"keep": [
"package/lib/xterm.js",
"package/css/xterm.css"
],
"rename": {
"package/lib/": "",
"package/css/": ""
},
"version": "5.5.0"
} Shift things into |
…4733) This PR lets npm.py run on Windows as well. It also allows it to be ran repeatedly without throwing errors Core changes: - Use `tempfile.TemporaryDirectory()` - `unlink` before `rename` so that the old file is overwritten - Try-except the failing line `if not any(destination.iterdir()):` `destination.rmdir()` --- Admittedly, this is a minor concern, because by all means you should be on Linux or using a Dev Container, according to the [contributing guide](https://github.com/zauberzeug/nicegui/blob/42d24d40129785038d6fce9c2aafe24c62482478/CONTRIBUTING.md). But, both has failed me so far, and so I'm still on Windows. And, I need `npm.py` to work, so as to help out in #4656 and #4520. I personally believe that making `npm.py` runnable on cross-platform may speed up development of new elements, as we lower the barrier to custom element development. --- It is best to answer the following before we proceed: - [ ] What's the purpose of the `if not any(destination.iterdir()):` `destination.rmdir()`? - It seems to always fail on Windows, so I add a try-except - But I don't want to just carelessly do that and call it a day - [x] Is the output on Linux still working? - You may want to grab the `npm.json` with pinned version in #4632, and test. - It's the same on my side, minus Tailwind, which they changed stuff upstream and so we'll never get the exact same copy.
This PR addresses the most basic demand highlighted in #2508, that is to color individual lines in `ui.log`. #### Implementation details Note that, the user may have already styled the `ui.label` via `default_classes`, `default_style` and/or `default_props`. Since: - It would be way too much parameters if we allow 3 (add/remove/replace) * 3 (classes/style/props) = 9 parameters to skip into `log.push` - Users are not supposed to receive the `ui.label` instances and style it themselves since - Function returns None, and, - They will be deleted automatically via `self.remove(0)` I have elected to make the `classes`, `style`, and `props`, should they be passed in, **replace existing one and be final**. #### Test script ```py from nicegui import ui ui.label.default_classes('text-gray-500') ui.label.default_style('font-size: 2rem') ui.label.default_props('my_label_props') ui.add_css(''' *[my_label_props] { font-style: italic; } *[my_log_props] { font-weight: bold; } ''') ui.label('This is how a normal label looks like') ui.log().push('This is how a log label looks like', classes='text-red-500', style='font-size: 1rem', props='my_log_props') ui.run() ``` <img width="380" alt="{3B0DEA0A-E006-4A54-950E-58F06FBD5E3D}" src="https://github.com/user-attachments/assets/f54a8b7e-2ead-4976-8977-9593fc51aee4" /> <img width="514" alt="{F0E4BAC4-A13B-494A-A350-7D0F8560B501}" src="https://github.com/user-attachments/assets/652e594c-b72d-481b-b6b5-ce174ee77401" /> #### What this PR doesn't do - Let you style individual characters in each line - Let you put custom HTML in `ui.log` - Accept ANSI escape sequences and display as colors appropriately - Be a replacement to `Xterm.js` in #4520 #### To-do - [x] Pytest? - [x] Documentation? - [x] Drafted documentation text #### Questions left on the table, which is best if we can answer them - [x] Why no `replace` for `props`, and I had to do `label.props.clear()`? - Considered a missing future feature for NiceGUI --------- Co-authored-by: Falko Schindler <falko@zauberzeug.com>
0433835
to
787ba92
Compare
Sorry that I've been offline for so long... I finally found some time to work on this. I'll add some documentation/demos to the website in the next few days. |
.devcontainer/Dockerfile
Outdated
# Install packages | ||
RUN apt-get update && apt-get install --no-install-recommends -y \ | ||
sudo git build-essential chromium chromium-driver \ | ||
sudo git build-essential chromium chromium-driver chromium-sandbox \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now required to run tests in the devcontainer.
poetry.lock
Outdated
@@ -1,12 +1,11 @@ | |||
# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. | |||
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Poetry only supports Python 3.8 up to version 1.6.1
.
A lock file generated with a newer version produces warnings (e.g. in the devcontainer).
However, I'm happy to revert this change, if preferred.
Xterm.js
connected to BashXterm
element
This PR is so old it witnessed 2 changes of our JS dependency management 😮 |
Oh I should finally start reviewing it! Dependency management should be even easier now. |
Ok, I reviewed most of the code and migrated the dependency management to use a separate package.json and the new Now I'm pondering about the purpose of process = await asyncio.create_subprocess_exec(...)
ui.xterm().connect(process) Or: pty_pid, pty_fd = pty.fork()
ui.xterm().connect(pty_pid, pty_fd) Or could Maybe that's something for a later PR if it doesn't require breaking the API again. But I'd like to hear your thoughts. 🙂 |
I like the idea of connecting Would propose the creation of binding functions which take 2+ arguments, first being the |
I'm still able to download the audio (https://www.soundjay.com/buttons/beep-07a.mp3). It's just a short beeping sound (7kB).
Yeah, I sort of see your point... What makes Xterm special is actually the parsing of ANSI escape codes (which is not trivial). Caveats for subprocesses:We could add a method like The problem is that most commands detect that Therefore, you actually want to use a PTY in most cases. But... Caveats for pty:The Even worse, all of the above only work on Unix systems. If you're on Windows, you'll need to use a different package: pywinpty. To my knowledge, there is no cross-platform solution out there (see also python/cpython#85829). Final thoughtsThis comment is already quite long 🙈 My proposal is:
In any case, I think the work should happen in a separate PR. The current API shouldn't be affected. |
Ok, thanks a lot for the detailed explanation, @paco-sevilla! |
This PR integrates Xterm.js as a new element
Xterm
. See discussion (#1846).Use-cases for Xterm in nicegui:
subprocess
containing ANSI escape codes (this is what I'm mostly interested in)Example
The example connects the new
Xterm
element to/bin/bash
running in apty.fork()
process. This allows using Bash from your browser.Warning
Exposing a terminal through a server is not secure. Use this example with care.
The page looks as follows:
