Skip to content

Commit

Permalink
Merge pull request #4994 from Textualize/cmd-palette-sort-fix
Browse files Browse the repository at this point in the history
Fix sorting in command palette search hits
  • Loading branch information
willmcgugan authored Sep 16, 2024
2 parents 5279624 + 3788803 commit 8e6de4c
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 71 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fixed `RichLog` writing at wrong width when `write` occurs before width is known (e.g. in `compose` or `on_mount`) https://github.com/Textualize/textual/pull/4978
- Fixed `RichLog.write` incorrectly shrinking width to `RichLog.min_width` when `shrink=True` (now shrinks to fit content area instead) https://github.com/Textualize/textual/pull/4978
- Fixed flicker when setting `dark` reactive on startup https://github.com/Textualize/textual/pull/4989
- Fixed command palette not sorting search results by their match score https://github.com/Textualize/textual/pull/4994
- Fixed `DataTable` cached height issue on re-populating the table when using auto-height rows https://github.com/Textualize/textual/pull/4992

## [0.79.1] - 2024-08-31
Expand Down
36 changes: 26 additions & 10 deletions src/textual/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ def prompt(self) -> RenderableType:
"""The prompt to use when displaying the discovery hit in the command palette."""
return self.display

@property
def score(self) -> float:
"""A discovery hit always has a score of 0.
The order in which discovery hits are displayed is determined by the order
in which they are yielded by the Provider. It's up to the developer to yield
DiscoveryHits in the .
"""
return 0.0

def __lt__(self, other: object) -> bool:
if isinstance(other, DiscoveryHit):
assert self.text is not None
Expand Down Expand Up @@ -312,35 +322,35 @@ async def shutdown(self) -> None:
@rich.repr.auto
@total_ordering
class Command(Option):
"""Class that holds a command in the [`CommandList`][textual.command.CommandList]."""
"""Class that holds a hit in the [`CommandList`][textual.command.CommandList]."""

def __init__(
self,
prompt: RenderableType,
command: DiscoveryHit | Hit,
hit: DiscoveryHit | Hit,
id: str | None = None,
disabled: bool = False,
) -> None:
"""Initialise the option.
Args:
prompt: The prompt for the option.
command: The details of the command associated with the option.
hit: The details of the hit associated with the option.
id: The optional ID for the option.
disabled: The initial enabled/disabled state. Enabled by default.
"""
super().__init__(prompt, id, disabled)
self.command = command
"""The details of the command associated with the option."""
self.hit = hit
"""The details of the hit associated with the option."""

def __lt__(self, other: object) -> bool:
if isinstance(other, Command):
return self.command < other.command
return self.hit < other.hit
return NotImplemented

def __eq__(self, other: object) -> bool:
if isinstance(other, Command):
return self.command == other.command
return self.hit == other.hit
return NotImplemented


Expand Down Expand Up @@ -891,7 +901,12 @@ def _refresh_command_list(
if command_list.highlighted is not None and not clear_current
else None
)
command_list.clear_options().add_options(commands)

def sort_key(command: Command) -> float:
return -command.hit.score

sorted_commands = sorted(commands, key=sort_key)
command_list.clear_options().add_options(sorted_commands)
if highlighted is not None and highlighted.id:
command_list.highlighted = command_list.get_option_index(highlighted.id)

Expand Down Expand Up @@ -1061,8 +1076,9 @@ def _select_command(self, event: OptionList.OptionSelected) -> None:
input = self.query_one(CommandInput)
with self.prevent(Input.Changed):
assert isinstance(event.option, Command)
input.value = str(event.option.command.text)
self._selected_command = event.option.command
hit = event.option.hit
input.value = str(hit.text)
self._selected_command = hit
input.action_end()
self._list_visible = False
self.query_one(CommandList).clear_options()
Expand Down
Loading

0 comments on commit 8e6de4c

Please sign in to comment.