~sotirisp/qute-gemini

4ae25c005eab6aefbecb5ddd2003f9c4f3f7a6f0 — Sotiris Papatheodorou 9 months ago c58e136
Improve documentation and style
1 files changed, 47 insertions(+), 47 deletions(-)

M qute-gemini
M qute-gemini => qute-gemini +47 -47
@@ 11,34 11,31 @@ import cgi
import os
import socket
import ssl
import subprocess
import sys
import tempfile
import urllib.parse

from typing import Tuple


def script_dir() -> str:
    """The directory this script is located in"""
    """The directory this script is located in."""
    return os.path.dirname(os.path.realpath(__file__))



def qute_url() -> str:
    """Get the URL passed to the script by qutebrowser"""
    """Get the URL passed to the script by qutebrowser."""
    return os.environ["QUTE_URL"]



def qute_fifo() -> str:
    """Get the FIFO or file to write qutebrowser commands to"""
    """Get the FIFO or file to write qutebrowser commands to."""
    return os.environ["QUTE_FIFO"]


def gemini_absolutise_url(base: str, relative: str) -> str:
    """Absolutise relative gemini URLs.

def gemini_absolutise_url(base, relative):
    """
    Absolutise relative gemini URLs. All URLs are strings.
    Adapted from gcat: https://github.com/aaronjanse/gcat
    """
    if "://" not in relative:


@@ 49,13 46,14 @@ def gemini_absolutise_url(base, relative):
    return relative


def gemini_fetch_url(url: str) -> Tuple[str, str]:
    """Fetch a Gemini URL and return the content as a string.

    url: URL with gemini:// or no scheme.
    Returns 2 strings:
      On success returns the content and an empty error message.
      On failure returns an empty content and an error message.

def gemini_fetch_url(url):
    """
    url: str   URL to the article with gemini:// or no scheme
    Retruns 2 strings.
    On success returns the content and an empty error message.
    On failure returns an empty content and an error message.
    Adapted from gcat: https://github.com/aaronjanse/gcat
    """
    parsed_url = urllib.parse.urlparse(url)


@@ 84,10 82,11 @@ def gemini_fetch_url(url):
        if status.startswith("3"):
            url = gemini_absolutise_url(url, mime)
            parsed_url = urllib.parse.urlparse(url)
        # Otherwise, we're done
        # Otherwise we're done
        else:
            break
    # Fail if transaction was not successful
    # Fail if transaction was not successful, user input or a certificate was
    # required
    if status.startswith("2"):
        if mime == "text/gemini":
            # Decode according to declared charset


@@ 96,31 95,33 @@ def gemini_fetch_url(url):
            body = body.decode(mime_opts.get("charset", "UTF-8"))
            return body, ""
        else:
            return "", "Received non-gemini content: " + mime
            return "", "Received non-gemtext content: " + mime
    else:
        return "", "Received gemini status " + status
 
        return "", "Received Gemini status " + status


def gemtext_to_html(gemtext, title, url):
    """
    Convert gemtext with the supplied title, downloaded from the supplied
    url to HTML.
def gemtext_to_html(gemtext: str, title: str, url: str) -> str:
    """Convert gemtext to HTML.

    title: Used as the document title.
    url:   The URL the gemtext was received from. Used to resolve relative URLs
           in the gemtext content.
    Returns the HTML representation as a string.
    """
    in_pre = False
    in_list = False
    # Accumulate converted gemtext lines
    lines = ['<?xml version="1.0" encoding="UTF-8"?>',
            '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">',
            "  <head>",
            "    <title>" + title + "</title>",
            "  </head>",
            "  <body>"]
            "\t<head>",
            "\t\t<title>" + title + "</title>",
            "\t</head>",
            "\t<body>"]
    in_pre = False
    in_list = False
    # Add an extra newline to ensure list tags are closed properly
    for line in (gemtext + "\n").splitlines():
        # Add the list closing tag
        if not line.startswith("*") and in_list:
            lines.append("    </ul>")
            lines.append("\t\t</ul>")
            in_list = False
        # Blank line
        if not line:


@@ 134,44 135,44 @@ def gemtext_to_html(gemtext, title, url):
                l.append(l[0])
            # Resolve relative URLs
            l[0] = gemini_absolutise_url(url, l[0])
            lines.append("".join(['    <p><a href="', l[0], '">', l[1], "</a></p>"]))
            lines.append("".join(['\t\t<p><a href="', l[0], '">', l[1], "</a></p>"]))
        # Preformated toggle
        elif line.startswith("```"):
            if in_pre:
                lines.append("    </pre>")
                lines.append("\t\t</pre>")
            else:
                lines.append("    <pre>")
                lines.append("\t\t<pre>")
            in_pre = not in_pre
        # Preformated
        elif in_pre:
            lines.append(line)
        # Header
        elif line.startswith("###"):
            lines.append("    <h3>" + line[3:].strip() + "</h3>")
            lines.append("\t\t<h3>" + line[3:].strip() + "</h3>")
        elif line.startswith("##"):
            lines.append("    <h2>" + line[2:].strip() + "</h2>")
            lines.append("\t\t<h2>" + line[2:].strip() + "</h2>")
        elif line.startswith("#"):
            lines.append("    <h1>" + line[1:].strip() + "</h1>")
            lines.append("\t\t<h1>" + line[1:].strip() + "</h1>")
        # List
        elif line.startswith("*"):
            if not in_list:
                lines.append("    <ul>")
                lines.append("\t\t<ul>")
            in_list = True
            lines.append("      <li>" + line[1:].strip() + "</li>")
            lines.append("\t\t\t<li>" + line[1:].strip() + "</li>")
        # Quote
        elif line.startswith(">"):
            lines.append("    <blockquote>\n      <p>" + line[1:].strip() + "</p>\n    </blockquote>")
            lines.append("\t\t<blockquote>\n\t\t\t<p>" + line[1:].strip() + "</p>\n\t\t</blockquote>")
        # Normal text
        else:
            lines.append("    <p>" + line.strip() + "</p>")
            lines.append("\t\t<p>" + line.strip() + "</p>")
    lines.append("")
    lines.append("  </body>\n")
    lines.append("\t</body>\n")
    lines.append("</html>")
    return "\n".join(lines)



def open_gemini(url: str, open_args: str):
def open_gemini(url: str, open_args: str) -> None:
    """Open Gemini URL in qutebrowser."""
    # Get the Gemini content
    content, error_msg = gemini_fetch_url(url)
    if error_msg:


@@ 190,13 191,12 @@ def open_gemini(url: str, open_args: str):
        qfifo.write("open " + open_args + " file://" + tmp_filename)



def open_other(url: str, open_args: str):
def open_other(url: str, open_args: str) -> None:
    """Open non-Gemini URL in qutebrowser."""
    with open(qute_fifo(), "w") as qfifo:
        qfifo.write("open " + open_args + " " + url)



if __name__ == "__main__":
    # Open in the current or a new tab depending on the script name
    if sys.argv[0].endswith("-tab"):