Broken project to implement a cross-protocol browser in textual
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
from textual.widgets import Static
from textual.containers import Container
from rich.syntax import Syntax
from pygments.lexers import get_lexer_for_mimetype
from pygments.util import ClassNotFound

# 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",
    # Less popular mimes will call out to get_lexer_for_mimetype
}

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] if mime in mimetolexer else get_lexer_for_mimetype(mime)
        self.mount(Static(Syntax(code,lexer=lexer,background_color="default")))

    def can_handle_mime(mime):
      if mime in mimetolexer:
        return True
      try:
        get_lexer_for_mimetype(mime)
        return True
      except ClassNotFound:
        pass
      return False