Skip to content

Commit fc73b0d

Browse files
committed
fixes #84
1 parent 31de4b8 commit fc73b0d

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

.components.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,12 @@ components:
118118
GPXViewer is a component for visualizing GPX (GPS Exchange Format) files using OpenStreetMap and Leaflet.
119119
It can display GPS tracks, routes and waypoints from URLs, with configurable zoom levels
120120
and map centering.
121+
- name: Shell
122+
source: /ngwidgets/shell.py
123+
issue: 84
124+
demo_url: http://ngdemo.bitplan.com/shell
125+
demo_image_url: https://github.com/WolfgangFahl/nicegui_widgets/assets/1336221/b39f7652-1cc6-4b59-8c3d-ef327aa5db4a
126+
description: >
127+
Shell provides structured subprocess execution with live output capturing (teeing) of
128+
stdout and stderr. It includes StreamTee, SysTee, and StdTee classes to integrate
129+
with NiceGUI ui output elements such as ui.html or ui.code.

ngwidgets/widgets_demo.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,44 @@ def show():
543543

544544
await self.setup_content_div(show)
545545

546+
async def show_shell_demo(self):
547+
"""
548+
Demonstrate Shell execution with tee and capture using safe predefined commands.
549+
"""
550+
# predefined safe shell commands
551+
commands = {
552+
"Echo greeting": "echo Hello from shell",
553+
"List files": "ls -l | head -5",
554+
"Trigger error": "ls non_existent_file",
555+
"Combined": "echo Hello from shell && ls -l | head -5 && ls non_existent_file",
556+
}
557+
558+
# display a labeled preformatted text block
559+
def labeled_pre(label: str, value: str, color: str = "black"):
560+
ui.label(f"{label}:").style("font-weight: bold")
561+
ui.html(f"<pre>{value}</pre>").style(f"color: {color}")
562+
563+
# run the selected command and display output
564+
def run_cmd(cmd_select):
565+
from ngwidgets.shell import Shell
566+
shell = Shell()
567+
cmd = commands[cmd_select.value]
568+
result = shell.run(cmd, tee=True)
569+
labeled_pre("CMD", cmd)
570+
labeled_pre("STDOUT", result.stdout)
571+
if result.stderr.strip():
572+
labeled_pre("STDERR", result.stderr, color="red")
573+
574+
# setup the shell demo UI
575+
async def show():
576+
cmd_select = ui.select(list(commands.keys()),
577+
label="Choose command",
578+
value="Combined").classes("w-full")
579+
ui.button("Run", on_click=lambda: run_cmd(cmd_select))
580+
581+
await self.setup_content_div(show)
582+
583+
546584
async def show_tristate_demo(self):
547585
"""
548586
Demonstrate the Tristate project.
@@ -869,6 +907,7 @@ def setup_home():
869907
"Tristate Demo": "/tristate",
870908
"pdfviewer": "/pdfviewer",
871909
"Progressbar": "/progress",
910+
"Shell Demo": "/shell"
872911
}
873912

874913
# Generate the HTML using the dictionary
@@ -938,6 +977,10 @@ async def show_components(solution_id: str, client: Client):
938977
async def show_progress(client: Client):
939978
return await self.page(client, NiceGuiWidgetsDemo.show_progress)
940979

980+
@ui.page("/shell")
981+
async def show_shell_demo(client: Client):
982+
return await self.page(client, NiceGuiWidgetsDemo.show_shell_demo)
983+
941984
@ui.page("/gpxviewer")
942985
async def show_gpxviewer(client: Client):
943986
return await self.page(client, NiceGuiWidgetsDemo.show_gpxviewer)

0 commit comments

Comments
 (0)