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
|
#!/usr/bin/env python3
from textual.app import App, ComposeResult
from textual.widgets import Input, Button, Static, Footer
from textual.containers import Container
from rich.markdown import Markdown
from textual.binding import Binding
from mime.gemtext import Gemtext
from mime.plaintext import Plaintext
from mime.highlightedcode import HighlightedCode,mimetolexer
from protocol.gemini import GeminiProtocol
class Browset(App):
url = ""
CSS_PATH = "browset.css"
BINDINGS = [
Binding("ctrl+q,ctrl+c", "app.quit", "Quit", show=True),
Binding("ctrl+left", "back()", "Back", show=False),
Binding("ctrl+right", "soon()", "Soon", show=False),
]
history = []
fistory = [] # forward history
content = ["#h1", "## hey [b]Is this unformatted?[/b]", "```startpre","in preformatted text this hsould have a scrollbar if it is too wide oh yeah tonight is gonna be great.", "``` (ended pre)", "afterward"]
def compose(self) -> ComposeResult:
yield Footer()
yield Container(
Button("🔙", variant='primary', name='back'), # ⏪
Button("🔝", name='../'), # ⏫
Button("🔜", variant='primary', name='soon'), # ⏩
Button("🔄", variant='primary', name='refresh'), # 🔁
Input(placeholder="Enter URI", id="url"),
id="toolbar"
)
yield Gemtext(fp=self.content, id="content")
async def on_input_submitted(self, message: Input.Submitted) -> None:
self._do_url(message.value, setbar=False)
async def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.variant == 'primary':
if event.button.name == 'refresh':
self._do_url(self.url)
elif event.button.name == 'back':
self.action_back()
elif event.button.name == 'soon':
self.action_soon()
else:
url = event.button.name
if not ":" in url:
url = GeminiProtocol.relativeURL(url, self.url)
self._do_url(url)
def action_back(self):
if len(self.history):
self.fistory.append(self.url)
url = self.history.pop()
self._do_url(url, histore=False, clearF=False)
def action_soon(self):
if len(self.fistory):
url = self.fistory.pop()
self._do_url(url, clearF=False)
def _do_url(self, url, histore=True, setbar=True, clearF=True):
if clearF:
self.fistory = []
if setbar:
input = self.query_one("#url")
input.value = url
if histore:
self.history.append(self.url)
self.url = url
(mime, fp) = GeminiProtocol.get(url)
self.query_one("#content").remove()
if "text/gemini" in mime:
content = Gemtext(fp=fp, id="content")
elif mime in mimetolexer:
content = HighlightedCode(fp=fp, id="content", mime=mime)
else:
content = Plaintext(fp=fp, id="content")
self.mount(content)
if __name__ == "__main__":
app = Browset()
app.run()
|