Skip to content

Commit 5e43ea7

Browse files
authored
🔀 Merge pull request #90 from davep/search-history
Add the ability to search the history from the palette
2 parents e4eb256 + 5a01cac commit 5e43ea7

File tree

7 files changed

+127
-1
lines changed

7 files changed

+127
-1
lines changed

ChangeLog.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Hike ChangeLog
22

3+
## Unreleased
4+
5+
**Released: WiP**
6+
7+
- Added an application command for searching history.
8+
([#90](https://github.com/davep/hike/pull/90))
9+
310
## v0.10.0
411

512
**Released: 2025-04-03**

src/hike/commands/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Reload,
1515
SaveCopy,
1616
SearchBookmarks,
17+
SearchHistory,
1718
ToggleNavigation,
1819
)
1920
from .navigation import (
@@ -45,6 +46,7 @@
4546
"Reload",
4647
"SaveCopy",
4748
"SearchBookmarks",
49+
"SearchHistory",
4850
"ToggleNavigation",
4951
]
5052

src/hike/commands/main.py

+7
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ class SearchBookmarks(Command):
6363
BINDING_KEY = "f3"
6464

6565

66+
##############################################################################
67+
class SearchHistory(Command):
68+
"""Search the history"""
69+
70+
BINDING_KEY = "shift+f3"
71+
72+
6673
##############################################################################
6774
class CopyLocationToClipboard(Command):
6875
"""Copy the location to the clipboard"""

src/hike/providers/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
##############################################################################
44
# Local imports.
55
from .bookmarks import BookmarkCommands
6+
from .history import HistoryCommands
67
from .main import MainCommands
78

89
##############################################################################
910
# Exports.
1011
__all__ = [
1112
"BookmarkCommands",
13+
"HistoryCommands",
1214
"MainCommands",
1315
]
1416

src/hike/providers/history.py

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""Bookmark search and visit commands for the command palette."""
2+
3+
##############################################################################
4+
# Python imports.
5+
from dataclasses import dataclass
6+
from functools import total_ordering
7+
from typing import Final
8+
9+
##############################################################################
10+
# httpx imports.
11+
from httpx import URL
12+
13+
##############################################################################
14+
# Rich imports.
15+
from rich.emoji import Emoji
16+
17+
##############################################################################
18+
# Textual enhanced imports.
19+
from textual_enhanced.commands import CommandHit, CommandHits, CommandsProvider
20+
21+
##############################################################################
22+
# Local imports.
23+
from ..messages import OpenLocation
24+
from ..types import HikeHistory, HikeLocation
25+
26+
##############################################################################
27+
# Icons.
28+
LOCAL_FILE: Final[str] = Emoji.replace(":page_facing_up:")
29+
"""Icon to use for a local file."""
30+
REMOTE_FILE: Final[str] = Emoji.replace(":globe_with_meridians:")
31+
"""icon to sue for a remote file."""
32+
33+
34+
##############################################################################
35+
@dataclass(frozen=True)
36+
@total_ordering
37+
class Historical:
38+
"""Holds a location from history."""
39+
40+
location: HikeLocation
41+
"""The location."""
42+
43+
@property
44+
def name(self) -> str:
45+
"""A name for the location."""
46+
if isinstance(self.location, URL):
47+
return self.location.path
48+
return str(self.location)
49+
50+
@property
51+
def context(self) -> str:
52+
"""The context for the location."""
53+
if isinstance(self.location, URL):
54+
return f"{REMOTE_FILE} Remote on {self.location.host}"
55+
return f"{LOCAL_FILE} Local file"
56+
57+
def __gt__(self, value: object, /) -> bool:
58+
if isinstance(value, Historical):
59+
return self.name.casefold() > value.name.casefold()
60+
raise NotImplementedError
61+
62+
def __eq__(self, value: object, /) -> bool:
63+
if isinstance(value, Historical):
64+
return self.name == value.name
65+
raise NotImplementedError
66+
67+
def __str__(self) -> str:
68+
return self.name
69+
70+
71+
##############################################################################
72+
class HistoryCommands(CommandsProvider):
73+
"""A command palette provider related to history."""
74+
75+
history: HikeHistory = HikeHistory()
76+
"""The history."""
77+
78+
@classmethod
79+
def prompt(cls) -> str:
80+
"""The prompt for the command provider."""
81+
return "Search history..."
82+
83+
def commands(self) -> CommandHits:
84+
"""Provide the history-based command data for the command palette.
85+
86+
Yields:
87+
The commands for the command palette.
88+
"""
89+
for location in sorted(set(Historical(location) for location in self.history)):
90+
# TODO: Improve what's shown in the palette.
91+
yield CommandHit(
92+
location.name,
93+
location.context,
94+
OpenLocation(location.location),
95+
)
96+
97+
98+
### history.py ends here

src/hike/providers/main.py

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
Reload,
3131
SaveCopy,
3232
SearchBookmarks,
33+
SearchHistory,
3334
ToggleNavigation,
3435
)
3536

@@ -64,6 +65,7 @@ def commands(self) -> CommandHits:
6465
yield from self.maybe(Reload)
6566
yield from self.maybe(SaveCopy)
6667
yield SearchBookmarks()
68+
yield SearchHistory()
6769
yield ToggleNavigation()
6870

6971

src/hike/screens/main.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
Reload,
5151
SaveCopy,
5252
SearchBookmarks,
53+
SearchHistory,
5354
ToggleNavigation,
5455
)
5556
from ..data import (
@@ -74,7 +75,7 @@
7475
RemoveHistoryEntry,
7576
SetLocalViewRoot,
7677
)
77-
from ..providers import BookmarkCommands, MainCommands
78+
from ..providers import BookmarkCommands, HistoryCommands, MainCommands
7879
from ..support import view_in_browser
7980
from ..widgets import CommandLine, Navigation, Viewer
8081

@@ -154,6 +155,7 @@ class Main(EnhancedScreen[None]):
154155
Reload,
155156
SaveCopy,
156157
SearchBookmarks,
158+
SearchHistory,
157159
)
158160

159161
BINDINGS = Command.bindings(*COMMAND_MESSAGES)
@@ -390,6 +392,11 @@ def action_search_bookmarks_command(self) -> None:
390392
"""Search the bookmarks in the command palette."""
391393
self.show_palette(BookmarkCommands)
392394

395+
@on(SearchHistory)
396+
def action_search_history_command(self) -> None:
397+
"""search the history in the command palette."""
398+
self.show_palette(HistoryCommands)
399+
393400
@on(ToggleNavigation)
394401
def action_toggle_navigation_command(self) -> None:
395402
"""Toggle the display of the navigation panel."""
@@ -523,6 +530,7 @@ def _update_history(self, message: Viewer.HistoryUpdated) -> None:
523530
Args:
524531
message: The message to say that history changed.
525532
"""
533+
HistoryCommands.history = message.viewer.history
526534
self.query_one(Navigation).update_history(message.viewer.history)
527535
save_history(message.viewer.history)
528536

0 commit comments

Comments
 (0)