|
3 | 3 | ############################################################################## |
4 | 4 | # Python imports. |
5 | 5 | from functools import partial |
| 6 | +from typing import Callable, Iterator |
6 | 7 |
|
7 | 8 | ############################################################################## |
8 | 9 | # Textual imports. |
9 | | -from textual.command import Hit, Hits, Provider |
| 10 | +from textual.color import Color |
| 11 | +from textual.command import DiscoveryHit, Hit, Hits, Provider |
10 | 12 |
|
11 | 13 | ############################################################################## |
12 | 14 | # Local imports. |
|
18 | 20 | class MandelbrotCommands(Provider): |
19 | 21 | """A source of command palette commands for the Mandelbrot widget.""" |
20 | 22 |
|
21 | | - async def search(self, query: str) -> Hits: |
22 | | - """Handle a request to search for system commands that match the query. |
23 | | -
|
24 | | - Args: |
25 | | - user_input: The user input to be matched. |
26 | | -
|
27 | | - Yields: |
28 | | - Command hits for use in the command palette. |
29 | | - """ |
30 | | - |
31 | | - # Nothing in here makes sense if the user isn't current on a |
32 | | - # Mandelbrot set. |
33 | | - if not isinstance(self.focused, Mandelbrot): |
34 | | - return |
35 | | - |
36 | | - # Get a fuzzy matcher for looking for hits. |
37 | | - matcher = self.matcher(query) |
| 23 | + PREFIX = "Mandelbrot: " |
| 24 | + """Prefix that is common to all the commands.""" |
38 | 25 |
|
39 | | - # Give all commands a common prefix. |
40 | | - prefix = "Mandelbrot: " |
41 | | - |
42 | | - # Spin out some commands for setting the colours. |
| 26 | + @classmethod |
| 27 | + def _colour_commands(cls) -> Iterator[tuple[str, Callable[[int, int], Color], str]]: |
| 28 | + """The colour commands.""" |
43 | 29 | for colour, source in ( |
44 | 30 | ("default", default_map), |
45 | 31 | ("blue/brown", blue_brown_map), |
46 | 32 | ("green", shades_of_green), |
47 | 33 | ): |
48 | | - colour = f"{prefix}Set the colour map to {colour} " |
49 | | - match = matcher.match(colour) |
50 | | - if match: |
51 | | - yield Hit( |
52 | | - match, |
53 | | - matcher.highlight(colour), |
54 | | - partial(self.focused.set_colour_source, source), |
55 | | - help=f"Set the Mandelbrot colour palette to {colour}", |
56 | | - ) |
| 34 | + yield ( |
| 35 | + f"{cls.PREFIX}Set the colour map to {colour} ", |
| 36 | + source, |
| 37 | + f"Set the Mandelbrot colour palette to {colour}", |
| 38 | + ) |
57 | 39 |
|
| 40 | + @classmethod |
| 41 | + def _action_commands(cls) -> Iterator[tuple[str, str, str]]: |
58 | 42 | # Spin out some commands based around available actions. |
59 | 43 | for command, action, help_text in ( |
60 | 44 | ( |
@@ -92,7 +76,69 @@ async def search(self, query: str) -> Hits: |
92 | 76 | "Remove detail from the Mandelbrot set (will run faster)", |
93 | 77 | ), |
94 | 78 | ): |
95 | | - command = f"{prefix}{command}" |
| 79 | + yield (f"{cls.PREFIX}{command}", action, help_text) |
| 80 | + |
| 81 | + async def discover(self) -> Hits: |
| 82 | + """Handle a request to discover commands. |
| 83 | +
|
| 84 | + Yields: |
| 85 | + Command discovery hits for the command palette. |
| 86 | + """ |
| 87 | + |
| 88 | + # Nothing in here makes sense if the user isn't current on a |
| 89 | + # Mandelbrot set. |
| 90 | + if not isinstance(self.focused, Mandelbrot): |
| 91 | + return |
| 92 | + |
| 93 | + # Spin out some commands for setting the colours. |
| 94 | + for command, source, help_text in self._colour_commands(): |
| 95 | + yield DiscoveryHit( |
| 96 | + command, |
| 97 | + partial(self.focused.set_colour_source, source), |
| 98 | + command, |
| 99 | + help_text, |
| 100 | + ) |
| 101 | + |
| 102 | + # Spin out the action commands. |
| 103 | + for command, action, help_text in self._action_commands(): |
| 104 | + yield DiscoveryHit( |
| 105 | + command, |
| 106 | + partial(self.focused.run_action, action), |
| 107 | + command, |
| 108 | + help_text, |
| 109 | + ) |
| 110 | + |
| 111 | + async def search(self, query: str) -> Hits: |
| 112 | + """Handle a request to search for system commands that match the query. |
| 113 | +
|
| 114 | + Args: |
| 115 | + user_input: The user input to be matched. |
| 116 | +
|
| 117 | + Yields: |
| 118 | + Command hits for use in the command palette. |
| 119 | + """ |
| 120 | + |
| 121 | + # Nothing in here makes sense if the user isn't current on a |
| 122 | + # Mandelbrot set. |
| 123 | + if not isinstance(self.focused, Mandelbrot): |
| 124 | + return |
| 125 | + |
| 126 | + # Get a fuzzy matcher for looking for hits. |
| 127 | + matcher = self.matcher(query) |
| 128 | + |
| 129 | + # Spin out some commands for setting the colours. |
| 130 | + for command, source, help_text in self._colour_commands(): |
| 131 | + match = matcher.match(command) |
| 132 | + if match: |
| 133 | + yield Hit( |
| 134 | + match, |
| 135 | + matcher.highlight(command), |
| 136 | + partial(self.focused.set_colour_source, source), |
| 137 | + help=help_text, |
| 138 | + ) |
| 139 | + |
| 140 | + # Spin out the action commands. |
| 141 | + for command, action, help_text in self._action_commands(): |
96 | 142 | match = matcher.match(command) |
97 | 143 | if match: |
98 | 144 | yield Hit( |
|
0 commit comments