-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
167 lines (124 loc) · 5.34 KB
/
main.py
File metadata and controls
167 lines (124 loc) · 5.34 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
from modules.project_scanner import grab_projects, init_projects_config
from textual.app import App, ComposeResult
from textual.containers import Horizontal
from textual.message import Message
from textual.reactive import reactive
from textual.widgets import Footer, Input, Label, ListItem, ListView, Markdown
PROJECT_ROOT_DIRECTORY = "/home/joachims/repos"
class ProjectSearchbar(Input):
"""Input field with logic to unblur and clear itself"""
BINDINGS = [
("ctrl+q", "quit", "quit the app"),
("ctrl+s", "blur_and_move_focus", "Move to list"),
("enter", "blur_and_move_focus", " Search"),
("ctrl+d", "clear_search", "Clear searchbar"),
]
def __init__(self) -> None:
super().__init__()
self.value = ""
class BlurRequested(Message):
def __init__(self, sender: "ProjectSearchbar") -> None:
super().__init__()
self.sender = sender
def update_value(self) -> None:
self.value = ""
def action_blur_and_move_focus(self) -> None:
"""Sends blur message to App class"""
self.post_message(self.BlurRequested(self))
def action_clear_search(self) -> None:
"""Clears searchbar"""
self.value = ""
class ProjectLauncher(App):
"""Main app class"""
CSS_PATH = "styles.tcss"
THEME = "Tokyo Night"
BINDINGS = [
("q", "quit", "quit the app"),
("s", "focus_searchbar", "search"),
("k", "move_up", "move up"),
("j", "move_down", "move down"),
("ctrl+d", "clear_search", "Clear searchbar"),
("enter", "choose_project", "Open project"),
]
selected_index = reactive(0)
def __init__(self):
super().__init__()
self.filtered_projects = []
def compose(self) -> ComposeResult:
yield ProjectSearchbar()
yield Horizontal(
ListView(id="ProjectList"), Markdown("Loading...", id="MarkdownViewer")
)
yield Footer()
async def on_mount(self) -> None:
init_projects_config(PROJECT_ROOT_DIRECTORY, 'config.yaml')
self.PROJECTS = grab_projects('config.yaml')
self.searchbar = self.query_one(ProjectSearchbar)
self.list = self.query_one("#ProjectList", ListView)
self.list.border_title = f"Projects - {PROJECT_ROOT_DIRECTORY}"
self.markdown = self.query_one("#MarkdownViewer", Markdown)
self.markdown.border_title = f"README.md - {self.PROJECTS['Projects'][0]['readme_path']}"
for project in self.PROJECTS['Projects']:
await self.list.append(ListItem(Label(project['name'])))
self.markdown.update(self.grab_readme_markdown(self.PROJECTS['Projects'][0]['readme_path']))
self.list.index = 0
self.set_focus(self.list)
def action_move_down(self) -> None:
"""Moves cursor 1 item down"""
self.selected_index = (
self.selected_index + 1
if self.selected_index < len(self.list.children) - 1
else self.selected_index
)
def action_move_up(self) -> None:
"""Moves cursor 1 item up"""
self.selected_index = (
self.selected_index - 1 if self.selected_index != 0 else self.selected_index
)
def action_focus_searchbar(self) -> None:
"""Focuses searchbar"""
self.set_focus(self.searchbar)
def action_clear_search(self) -> None:
"""Clears searchbar"""
self.searchbar.update_value()
async def on_input_changed(self, event: Input.Changed) -> None:
filter = event.value
self.list.clear()
self.markdown.update("searching...")
self.filtered_projects = self.project_filter(self.PROJECTS, filter)
for project in self.filtered_projects:
await self.list.append(ListItem(Label(project['name'])))
try:
self.markdown.update(self.grab_readme_markdown(self.filtered_projects[0]['readme_path']))
except IndexError:
self.markdown.update(f"No project found matching string {filter}!")
def on_project_searchbar_blur_requested(
self, event: ProjectSearchbar.BlurRequested
) -> None:
self.set_focus(self.list)
self.selected_index = 0
self.list.index = 0
def watch_selected_index(self, value: int) -> None:
self.list.index = value
if not self.filtered_projects:
self.markdown.update(self.grab_readme_markdown(self.PROJECTS['Projects'][value]['readme_path']))
self.markdown.border_title = f"README.md - {self.PROJECTS['Projects'][value]['readme_path']}"
else:
self.markdown.update(self.grab_readme_markdown(self.filtered_projects[value]['readme_path']))
self.markdown.border_title = (
f"README.md - {self.filtered_projects[value]['readme_path']}"
)
def project_filter(self, projects: dict, filter_string: str) -> list:
filtered_list = []
for entry in projects['Projects']:
if filter_string.lower() in entry['name'].lower():
filtered_list.append(entry)
return filtered_list
def grab_readme_markdown(self, path: str) -> str:
path = f'{path}'
with open(file=path, mode="r", encoding="utf-8") as md_file:
markdown_content = md_file.read()
return markdown_content
if __name__ == "__main__":
app = ProjectLauncher()
app.run()