diff --git a/docs/examples/getting_started/console.py b/docs/examples/getting_started/console.py new file mode 100644 index 000000000..051632d9f --- /dev/null +++ b/docs/examples/getting_started/console.py @@ -0,0 +1,18 @@ +""" +Simulates a screenshot of the Textual devtools + +""" + +from textual.app import App + +from textual.devtools.renderables import DevConsoleHeader +from textual.widgets import Static + + +class ConsoleApp(App): + def compose(self): + self.dark = True + yield Static(DevConsoleHeader()) + + +app = ConsoleApp() diff --git a/docs/getting_started.md b/docs/getting_started.md index 299d9d9c0..de59399d5 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -18,9 +18,6 @@ pip install textual If you installed the dev dependencies, you have have access to the `textual` CLI command. There are a number of sub-commands which will aid you in building Textual apps. See the help for more details: -```python +```bash textual --help ``` - -### Textual Console - diff --git a/docs/guide/devtools.md b/docs/guide/devtools.md index efb3a52c9..54237af87 100644 --- a/docs/guide/devtools.md +++ b/docs/guide/devtools.md @@ -28,20 +28,24 @@ textual run my_app.py:alternative_app ## Console -When running any terminal application, you can no longer use `print` when debugging (or log to the console). This is because anything you write to standard output would typically overwrite application content, which generally makes an unreadable mess. Fortunately Textual supplies a debug console of it's own which has some super helpful features. +When running any terminal application, you can no longer use `print` when debugging (or log to the console). This is because anything you write to standard output would overwrite application content, making it unreadable. Fortunately Textual supplies a debug console of it's own which has some super helpful features. -To use the console, open up 2 console emulators. In the first one, run the following: +To use the console, open up 2 terminal emulators. In the first one, run the following: ```bash textual console ``` +This should look something like the following: + +```{.textual title="textual console" path="docs/examples/getting_started/console.py", press="_,_"} +``` + In the other console, run your application using `textual run` and the `--dev` switch: ```bash textual run my_app.py --dev ``` -You should notice that the console will display information regarding the running application, such as events which are sent. - Anything you `print` from your application will be displayed in the console window. You can also call the `log()` method on App and Widget objects for advanced formatting. Try it with `self.log(self.tree)`. + diff --git a/docs/introduction.md b/docs/introduction.md index db7a5fb32..48065ab7e 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -15,7 +15,7 @@ By the end of this page you should have a good idea of the steps involved in cre ## Stopwatch Application -We're going to build a stopwatch app. This app will display the elapsed time since the user hit a "Start" button. The user will be able to stop, resume, and reset each stopwatch in addition to adding or removing them. +We're going to build a stopwatch application. It should show a list of stopwatches with a time display the user can start, stop, and reset. We also want the user to be able to add and remove stopwatches as required. This will be a simple yet **fully featured** app — you could distribute this app if you wanted to! diff --git a/src/textual/_compositor.py b/src/textual/_compositor.py index 0c6015c0f..3fab34aeb 100644 --- a/src/textual/_compositor.py +++ b/src/textual/_compositor.py @@ -463,7 +463,6 @@ class Compositor: except KeyError: raise errors.NoWidget("Widget is not in layout") - @timer("get_widget_at") def get_widget_at(self, x: int, y: int) -> tuple[Widget, Region]: """Get the widget under the given point or None.""" # TODO: Optimize with some line based lookup diff --git a/src/textual/cli/cli.py b/src/textual/cli/cli.py index 61393fff7..9626d005a 100644 --- a/src/textual/cli/cli.py +++ b/src/textual/cli/cli.py @@ -20,7 +20,15 @@ def run(): @run.command(help="Run the Textual Devtools console.") def console(): - _run_devtools() + from rich.console import Console + + console = Console() + console.clear() + console.show_cursor(False) + try: + _run_devtools() + finally: + console.show_cursor(True) class AppFail(Exception): diff --git a/src/textual/devtools/renderables.py b/src/textual/devtools/renderables.py index 1cf0b6320..de0c30929 100644 --- a/src/textual/devtools/renderables.py +++ b/src/textual/devtools/renderables.py @@ -6,22 +6,22 @@ from pathlib import Path from typing import Iterable from importlib_metadata import version -from rich.containers import Renderables -from rich.style import Style -from rich.text import Text if sys.version_info >= (3, 8): from typing import Literal else: from typing_extensions import Literal -from rich.console import Console from rich.align import Align -from rich.console import ConsoleOptions, RenderResult +from rich.console import Console, ConsoleOptions, RenderResult from rich.markup import escape from rich.rule import Rule from rich.segment import Segment, Segments +from rich.style import Style from rich.table import Table +from rich.text import Text + +from textual._border import Border DevConsoleMessageLevel = Literal["info", "warning", "error"] @@ -30,17 +30,17 @@ class DevConsoleHeader: def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: - lines = Renderables( - [ - f"[bold]Textual Development Console [magenta]v{version('textual')}", - "[magenta]Run a Textual app with the environment variable [b]TEXTUAL=devtools[/] to connect.", - "[magenta]Press [b]Ctrl+C[/] to quit.", - ] + 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" + "[magenta]Press [reverse]Ctrl+C[/] to quit." ) render_options = options.update(width=options.max_width - 4) - lines = console.render_lines(lines, render_options) - new_line = Segment("\n") + lines = console.render_lines(preamble, render_options) + + new_line = Segment.line() padding = Segment("▌", Style.parse("bright_magenta")) + for line in lines: yield padding yield from line