Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest known commands if there is no history #29

Merged
merged 2 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
([#24](https://github.com/davep/hike/pull/24))
- Added `help` as a command that the command line understands.
([#24](https://github.com/davep/hike/pull/24))
- Changed command line completion so that if history is empty, known
commands are suggested. ([#29](https://github.com/davep/hike/pull/29))

## v0.2.0

Expand Down
31 changes: 23 additions & 8 deletions src/hike/widgets/command_line/base_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,23 +54,38 @@ def split_command(text: str) -> tuple[str, str]:
return command.strip(), tail.strip()

@classmethod
def is_command(cls, command: str) -> bool:
"""Does the given command appear to be a match?

Args:
command: The command to test.
def suggestions(cls) -> tuple[str, ...]:
"""The suggested command matches for this command.

Returns:
`True` if the given command seems to be a match, `False` if not.
A tuple of suggestions for the command.

Notes:
Any commands that look like value placeholders will be filtered
out.
"""
# Build up all the possible matches. These are built from the main
# command and also the aliases. By convention the code will often
# use `code` fences for commands, and the aliases will be a comma
# list, so we clean that up as we go...
return command.strip().lower() in (
candidate.strip().lower().removeprefix("`").removesuffix("`")
return tuple(
candidate.strip().removeprefix("`").removesuffix("`")
for candidate in (cls.COMMAND, *cls.ALIASES.split(","))
# Note that we filter out anything that looks like `<this>`.
if not candidate.startswith("`<")
)

@classmethod
def is_command(cls, command: str) -> bool:
"""Does the given command appear to be a match?

Args:
command: The command to test.

Returns:
`True` if the given command seems to be a match, `False` if not.
"""
return command.strip().lower() in cls.suggestions()


### base_command.py ends here
13 changes: 11 additions & 2 deletions src/hike/widgets/command_line/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
##############################################################################
# Python imports.
from dataclasses import dataclass
from itertools import chain
from typing import Final

##############################################################################
Expand Down Expand Up @@ -149,8 +150,16 @@ class CommandLine(Vertical):

@property
def _history_suggester(self) -> SuggestFromList:
"""A suggester for the history of input."""
return SuggestFromList(reversed(list(self.history)))
"""A suggester for the history of input.

If there us no history yet then a list of commands and aliases will
be used.
"""
return SuggestFromList(
reversed(list(self.history))
if self.history
else chain(*(command.suggestions() for command in COMMANDS))
)

def compose(self) -> ComposeResult:
"""Compose the content of the widget."""
Expand Down
Loading