~earboxer/browset

67bccc9e1a39ac2749806a37cb53b23322645083 — Zach DeCook 1 year, 1 month ago 74c1b89
Mimetypes: Handle source code syntax highlighting
3 files changed, 56 insertions(+), 0 deletions(-)

M browset.css
M browset.py
A mime/highlightedcode.py
M browset.css => browset.css +8 -0
@@ 26,3 26,11 @@ Preformatted {
Preformatted > Static {
		width: auto;
}
HighlightedCode {
	overflow: auto;
	max-height: 100%;
}
HighlightedCode > * {
	width: auto;
	height: auto;
}

M browset.py => browset.py +3 -0
@@ 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)

A mime/highlightedcode.py => mime/highlightedcode.py +45 -0
@@ 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)))