Broken project to implement a cross-protocol browser in textual
Mimetypes: Handle source code syntax highlighting
| -rw-r--r-- | browset.css | 8 | ||||
| -rwxr-xr-x | browset.py | 3 | ||||
| -rw-r--r-- | mime/highlightedcode.py | 45 |
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; +} @@ -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))) |