-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
123 lines (99 loc) · 4.13 KB
/
Copy pathmain.py
File metadata and controls
123 lines (99 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
from __future__ import annotations
import logging
import shutil
from ulauncher.api.client.EventListener import EventListener
from ulauncher.api.client.Extension import Extension
from ulauncher.api.shared.action.RenderResultListAction import RenderResultListAction
from ulauncher.api.shared.event import (
KeywordQueryEvent,
PreferencesEvent,
PreferencesUpdateEvent,
)
from src.enums import MatchMode, SearchType
from src.preferences import (
FindPreferences,
get_preferences,
load_raw_preferences,
validate_preferences,
)
from src.results import generate_message, generate_result_items
from src.search import MIN_QUERY_LENGTH, SearchError, resolve_fd_binary, search
logger = logging.getLogger(__name__)
KEYWORD_SEARCH_TYPE = {
"kw_fz": SearchType.BOTH,
"kw_all": SearchType.BOTH,
"kw_files": SearchType.FILES,
"kw_dirs": SearchType.DIRS,
}
KEYWORD_MATCH_MODE = {
"kw_fz": MatchMode.FUZZY,
"kw_all": MatchMode.EXACT,
"kw_files": MatchMode.EXACT,
"kw_dirs": MatchMode.EXACT,
}
class FindExtension(Extension):
typed_preferences: FindPreferences
def __init__(self) -> None:
super().__init__()
self.subscribe(PreferencesEvent, PreferencesEventListener())
self.subscribe(PreferencesUpdateEvent, PreferencesUpdateEventListener())
self.subscribe(KeywordQueryEvent, KeywordQueryEventListener())
class PreferencesEventListener(EventListener):
def on_event(self, event: PreferencesEvent, extension: FindExtension) -> None:
extension.typed_preferences = get_preferences(event.preferences)
class PreferencesUpdateEventListener(EventListener):
def on_event(
self, event: PreferencesUpdateEvent, extension: FindExtension
) -> None:
preferences = extension.preferences
preferences[event.id] = event.new_value
extension.typed_preferences = get_preferences(preferences)
class KeywordQueryEventListener(EventListener):
def on_event(
self, event: KeywordQueryEvent, extension: FindExtension
) -> RenderResultListAction:
if not resolve_fd_binary():
return generate_message("fd is not installed. Run: sudo dnf install fd-find", "error")
raw_prefs = load_raw_preferences()
try:
prefs = get_preferences(raw_prefs)
except (ValueError, KeyError):
# The prefs file is user-editable, so a non-numeric result limit or
# timeout would otherwise raise here and die unseen in the listener
# thread. Surface it instead of failing silently.
logger.warning("Invalid preference value, check the extension settings", exc_info=True)
return generate_message(
"A preference value is invalid. Check the extension settings.", "error"
)
errors = validate_preferences(prefs)
if errors:
return generate_message(errors[0], "error")
query = event.get_argument()
if not query or len(query) < MIN_QUERY_LENGTH:
noun = "character" if MIN_QUERY_LENGTH == 1 else "characters"
return generate_message(f"Type at least {MIN_QUERY_LENGTH} {noun} to search.")
keyword = event.get_keyword()
search_type = SearchType.BOTH
match_mode = MatchMode.EXACT
for kw_id in KEYWORD_SEARCH_TYPE:
if raw_prefs.get(kw_id) == keyword:
search_type = KEYWORD_SEARCH_TYPE[kw_id]
match_mode = KEYWORD_MATCH_MODE[kw_id]
break
if match_mode == MatchMode.FUZZY and not shutil.which("fzf"):
return generate_message("fzf is not installed. Run: sudo dnf install fzf", "error")
try:
results = search(
preferences=prefs,
query=query,
search_type=search_type,
match_mode=match_mode,
)
except SearchError as exc:
return generate_message(str(exc), "error")
if not results:
return generate_message("No results found.")
items = generate_result_items(prefs, results)
return RenderResultListAction(items)
if __name__ == "__main__":
FindExtension().run()