diff --git a/src/textual_dev/renderables.py b/src/textual_dev/renderables.py index 8502afc..4f865fa 100644 --- a/src/textual_dev/renderables.py +++ b/src/textual_dev/renderables.py @@ -21,7 +21,15 @@ class DevConsoleHeader: - def __init__(self, verbose: bool = False) -> None: + """Renderable representing the header at the top of the console + + Args: + port: The port the devtools server is running on. + verbose: Whether verbose logging is enabled + """ + + def __init__(self, port: int | None = None, verbose: bool = False) -> None: + self.port = port self.verbose = verbose def __rich_console__( @@ -29,7 +37,7 @@ def __rich_console__( ) -> RenderResult: preamble = Text.from_markup( f"[bold]Textual Development Console [magenta]v{version('textual')}\n" - "[magenta]Run a Textual app with [reverse]textual run --dev my_app.py[/] to connect.\n" + f"[magenta]Run a Textual app with [reverse]{self._run_command()}[/] to connect.\n" "[magenta]Press [reverse]Ctrl+C[/] to quit." ) if self.verbose: @@ -45,6 +53,17 @@ def __rich_console__( yield from line yield new_line + def _run_command(self) -> str: + """Get help text for the user to connect to the console + + Returns: + The command a user can run to connect a Textual app to the dev server + """ + if self.port: + return f"textual run --port {self.port} --dev my_app.py" + else: + return "textual run --dev my_app.py" + class DevConsoleLog: """Renderable representing a single log message diff --git a/src/textual_dev/server.py b/src/textual_dev/server.py index 69a8d2d..44fa483 100644 --- a/src/textual_dev/server.py +++ b/src/textual_dev/server.py @@ -41,7 +41,7 @@ async def _on_startup(app: Application) -> None: def _run_devtools( verbose: bool, exclude: list[str] | None = None, port: int | None = None ) -> None: - app = _make_devtools_aiohttp_app(verbose=verbose, exclude=exclude) + app = _make_devtools_aiohttp_app(port=port, verbose=verbose, exclude=exclude) def noop_print(_: str) -> None: pass @@ -63,6 +63,7 @@ def noop_print(_: str) -> None: def _make_devtools_aiohttp_app( size_change_poll_delay_secs: float = DEFAULT_SIZE_CHANGE_POLL_DELAY_SECONDS, + port: int | None = None, verbose: bool = False, exclude: list[str] | None = None, ) -> Application: @@ -73,7 +74,10 @@ def _make_devtools_aiohttp_app( app["verbose"] = verbose app["service"] = DevtoolsService( - update_frequency=size_change_poll_delay_secs, verbose=verbose, exclude=exclude + update_frequency=size_change_poll_delay_secs, + port=port, + verbose=verbose, + exclude=exclude, ) app.add_routes( diff --git a/src/textual_dev/service.py b/src/textual_dev/service.py index a6d6daa..b20f217 100644 --- a/src/textual_dev/service.py +++ b/src/textual_dev/service.py @@ -29,6 +29,7 @@ class DevtoolsService: def __init__( self, update_frequency: float, + port: int | None = None, verbose: bool = False, exclude: list[str] | None = None, ) -> None: @@ -36,10 +37,12 @@ def __init__( Args: update_frequency: The number of seconds to wait between sending updates of the console size to connected clients. + port: The port the devtools server is running on. verbose: Enable verbose logging on client. exclude: List of log groups to exclude from output. """ self.update_frequency = update_frequency + self.port = port self.verbose = verbose self.exclude = {name.upper() for name in exclude} if exclude else set() self.console = Console() @@ -49,7 +52,7 @@ def __init__( async def start(self) -> None: """Starts devtools tasks""" self.size_poll_task = asyncio.create_task(self._console_size_poller()) - self.console.print(DevConsoleHeader(verbose=self.verbose)) + self.console.print(DevConsoleHeader(port=self.port, verbose=self.verbose)) @property def clients_connected(self) -> bool: