From ddc6c59608c2153236af50c160d3727787a07473 Mon Sep 17 00:00:00 2001 From: Edward Jazzhands Date: Sun, 20 Jul 2025 22:11:21 -0300 Subject: [PATCH 1/2] First draft of explanation of self.app in the command palette section of the guide. --- docs/guide/command_palette.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/guide/command_palette.md b/docs/guide/command_palette.md index 2c2db2ed35..df6dc11848 100644 --- a/docs/guide/command_palette.md +++ b/docs/guide/command_palette.md @@ -86,6 +86,8 @@ The following example will display a blank screen initially, but if you bring up 5. Highlights matching letters in the search. 6. Adds our custom command provider and the default command provider. +The above example uses [`self.app`][textual.command.Provider.app] to call `open_file`, a method we've defined on our app class. You normally won’t need to access the app class directly, since passing data through messages or other patterns keeps components more loosely coupled. However, when you need to call methods defined on the app class—such as `open_file` in our case—or work with shared app-wide state, [`self.app`][textual.message_pump.MessagePump.app] is the normal way to reach the running app instance. It's accessible from any widget, screen, or command provider. + There are four methods you can override in a command provider: [`startup`][textual.command.Provider.startup], [`search`][textual.command.Provider.search], [`discover`][textual.command.Provider.discover] and [`shutdown`][textual.command.Provider.shutdown]. All of these methods should be coroutines (`async def`). Only `search` is required, the other methods are optional. Let's explore those methods in detail. From 3678cb5f16f568ecbbe99c84312590263c65cac1 Mon Sep 17 00:00:00 2001 From: Edward Jazzhands Date: Sun, 20 Jul 2025 22:55:32 -0300 Subject: [PATCH 2/2] First draft of explanation of self.app in the command palette section of the guide. --- docs/guide/command_palette.md | 4 +++- docs/guide/screens.md | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/guide/command_palette.md b/docs/guide/command_palette.md index df6dc11848..1ee2ff0a7f 100644 --- a/docs/guide/command_palette.md +++ b/docs/guide/command_palette.md @@ -86,7 +86,9 @@ The following example will display a blank screen initially, but if you bring up 5. Highlights matching letters in the search. 6. Adds our custom command provider and the default command provider. -The above example uses [`self.app`][textual.command.Provider.app] to call `open_file`, a method we've defined on our app class. You normally won’t need to access the app class directly, since passing data through messages or other patterns keeps components more loosely coupled. However, when you need to call methods defined on the app class—such as `open_file` in our case—or work with shared app-wide state, [`self.app`][textual.message_pump.MessagePump.app] is the normal way to reach the running app instance. It's accessible from any widget, screen, or command provider. +!!! note + + Unlike widgets and screens, command providers aren’t part of Textual’s normal widget hierarchy—they’re plain Python classes. For convenience, Textual still sets a [self.app][textual.command.Provider.app] attribute on them, giving you access to the running app instance. As with widgets and screens, you won’t often need to reach into the app directly, but it’s the right approach when you need to call app-level methods such as `open_file()` in this example. There are four methods you can override in a command provider: [`startup`][textual.command.Provider.startup], [`search`][textual.command.Provider.search], [`discover`][textual.command.Provider.discover] and [`shutdown`][textual.command.Provider.shutdown]. All of these methods should be coroutines (`async def`). Only `search` is required, the other methods are optional. diff --git a/docs/guide/screens.md b/docs/guide/screens.md index f539c10da4..4699f408e1 100644 --- a/docs/guide/screens.md +++ b/docs/guide/screens.md @@ -180,6 +180,8 @@ From the quit screen you can click either Quit to exit the app immediately, or C Note the `request_quit` action in the app which pushes a new instance of `QuitScreen`. This makes the quit screen active. If you click Cancel, the quit screen calls [pop_screen][textual.app.App.pop_screen] to return the default screen. This also removes and deletes the `QuitScreen` object. +This example also shows [`self.app`][textual.message_pump.MessagePump.app], which gives you access to the running app instance from within a screen. You won’t often need to reach into the app directly, since it's usually preferable for widgets or screens to communicate through messages. But when you do need to call app-level methods—such as [`pop_screen()`][textual.app.App.pop_screen] in this example—[`self.app`][textual.message_pump.MessagePump.app] is the normal way to do it. You can access it on any widget or screen that is mounted in the app. + There are two flaws with this modal screen, which we can fix in the same way. The first flaw is that the app adds a new quit screen every time you press ++q++, even when the quit screen is still visible.