Skip to content

Commit

Permalink
change hotkey
Browse files Browse the repository at this point in the history
  • Loading branch information
willmcgugan committed Sep 14, 2023
1 parent ccc3e7a commit eaa7496
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
2 changes: 1 addition & 1 deletion docs/examples/guide/command_palette/command01.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def read_files(self) -> list[Path]:
"""Get a list of Python files in the current working directory."""
return list(Path("./").glob("*.py"))

async def post_init(self) -> None: # (1)!
async def startup(self) -> None: # (1)!
"""Called once when the command palette is opened, prior to searching."""
worker = self.app.run_worker(self.read_files, thread=True)
self.python_paths = await worker.wait()
Expand Down
13 changes: 9 additions & 4 deletions docs/guide/command_palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ The following example will display a blank screen initially, but if you hit ++ct
5. Highlights matching letters in the search.
6. Adds our custom command source and the default command sources.

There are two methods you will typically override in a command source: [`post_init`][textual.command.Source.post_init] and [`search`][textual.command.Source.search].
Both should be coroutines (`async def`).
There are three methods you can override in a command source: [`startup`][textual.command.Source.startup], [`search`][textual.command.Source.search], and [`shutdown`][textual.command.Source.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.

### post_init method
### startup method

The [`post_init`][textual.command.Source.post_init] method is called when the command palette is opened.
The [`startup`][textual.command.Source.startup] method is called when the command palette is opened.
You can use this method as way of performing work that needs to be done prior to searching.
In the example, we use this method to get the Python (.py) files in the current working directory.

Expand All @@ -99,6 +99,11 @@ In the example above, the callback is a lambda which calls the `open_file` metho
This is a deliberate design decision taken to prevent a single broken `Source` class from making the command palette unusable.
Errors in command sources will be logged to the [console](./devtools.md).

### Shutdown method

The [`shutdown`][textual.command.Source.shutdown] method is called when the command palette is closed.
You can use this as a hook to gracefully close any objects you created in startup.

## Screen commands

You can also associate commands with a screen by adding a `COMMAND_SOURCES` class var to your Screen class.
Expand Down
27 changes: 23 additions & 4 deletions src/textual/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from asyncio import CancelledError, Queue, Task, TimeoutError, wait_for
from asyncio import Queue, Task, wait, wait_for
from dataclasses import dataclass
from functools import total_ordering
from time import monotonic
from typing import TYPE_CHECKING, Any, AsyncGenerator, AsyncIterator, ClassVar
from typing import TYPE_CHECKING, Any, AsyncIterator, ClassVar

import rich.repr
from rich.align import Align
from rich.console import Group, RenderableType
from rich.emoji import Emoji
Expand Down Expand Up @@ -162,7 +163,7 @@ def _post_init(self) -> None:
async def post_init_task() -> None:
"""Wrapper to post init that runs in a task."""
try:
await self.post_init()
await self.startup()
except Exception:
self.app.log.error(Traceback())
else:
Expand All @@ -175,7 +176,7 @@ async def _wait_init(self) -> None:
if self._init_task is not None:
await self._init_task

async def post_init(self) -> None:
async def startup(self) -> None:
"""Called after the Source is initialized, but before any calls to `search`."""

async def _search(self, query: str) -> Hits:
Expand Down Expand Up @@ -205,7 +206,16 @@ async def search(self, query: str) -> Hits:
"""
yield NotImplemented

async def shutdown(self) -> None:
"""Called when the Source is shutdown.
Use this method to perform an cleanup, if required.
"""
print("SHUTDOWN Source ")


@rich.repr.auto
@total_ordering
class Command(Option):
"""Class that holds a command in the [`CommandList`][textual.command.CommandList]."""
Expand Down Expand Up @@ -510,6 +520,15 @@ def on_mount(self, _: Mount) -> None:
for _source in self._sources:
_source._post_init()

async def on_unmount(self) -> None:
try:
await wait(
[create_task(source.shutdown()) for source in self._sources],
)
except Exception:
self.log(Exception)
self._sources.clear()

def _stop_busy_countdown(self) -> None:
"""Stop any busy countdown that's in effect."""
if self._busy_timer is not None:
Expand Down

0 comments on commit eaa7496

Please sign in to comment.