Broken project to implement a cross-protocol browser in textual
Mimetypes: Handle source code syntax highlighting
Zach DeCook 2023-01-14
parent 74c1b89 · commit 67bccc9
-rw-r--r--browset.css8
-rwxr-xr-xbrowset.py3
-rw-r--r--mime/highlightedcode.py45
3 files changed, 56 insertions, 0 deletions
diff --git a/browset.css b/browset.css
index c729e54..f738943 100644
--- a/browset.css
+++ b/browset.css
@@ -26,3 +26,11 @@ Preformatted {
Preformatted > Static {
width: auto;
}
+HighlightedCode {
+ overflow: auto;
+ max-height: 100%;
+}
+HighlightedCode > * {
+ width: auto;
+ height: auto;
+}
diff --git a/browset.py b/browset.py
index 3e65fff..37e04b1 100755
--- a/browset.py
+++ b/browset.py
@@ -6,6 +6,7 @@ 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):
@@ -72,6 +73,8 @@ class Browset(App):
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)
diff --git a/mime/highlightedcode.py b/mime/highlightedcode.py
new file mode 100644
index 0000000..63defef
--- /dev/null
+++ b/mime/highlightedcode.py
@@ -0,0 +1,45 @@
+from textual.widgets import Static
+from textual.containers import Container
+from rich.syntax import Syntax
+
+# mime list from gemini://geminispace.info/statistics
+mimetolexer = {
+ "text/x-diff": "diff",
+ "text/x-csrc": "c",
+ "text/x-python": "python",
+ "text/markdown": "markdown",
+ "text/x-patch": "diff",
+ "text/x-c++src": "cpp",
+ "text/x-pascal": "pascal",
+ "text/x-c++hdr": "cpp",
+ "text/x-go": "go",
+ "text/x-rust": "rust",
+ "text/css": "css",
+ "text/x-php": "php",
+ # Hopefully, future handlers will take care of these mimes first.
+ "application/json": "json",
+ "text/html": "html",
+ "application/xml": "xml",
+ "application/atom+xml": "xml",
+ "text/xml": "xml",
+ "image/svg+xml": "xml",
+}
+
+class HighlightedCode(Static):
+ """Plaintext widget."""
+
+ def __init__(self, fp, id, mime):
+ super().__init__(id=id)
+ self.addblock(fp, mime)
+
+ def addblock(self, fp, mime):
+ code = ""
+ # Read the whole file first, then render it all.
+ # Hopefully not a problem, because source code should have terminal length.
+ for lin in fp:
+ line = lin
+ if type(line) is bytes:
+ line = line.decode("UTF-8")
+ code += line
+ lexer = mimetolexer[mime]
+ self.mount(Static(Syntax(code,lexer=lexer)))