From 84221a78164f4df1cbf35ecadeda69528277295e Mon Sep 17 00:00:00 2001 From: dece Date: Mon, 8 Mar 2021 23:40:03 +0100 Subject: [PATCH] browser: handle local file:// URIs --- bebop/__main__.py | 2 -- bebop/browser.py | 22 +++++++++++++++++----- bebop/navigation.py | 5 ++++- bebop/tests/test_navigation.py | 4 ++++ 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/bebop/__main__.py b/bebop/__main__.py index a8b928e..360a45c 100644 --- a/bebop/__main__.py +++ b/bebop/__main__.py @@ -11,8 +11,6 @@ def main(): if args.url: start_url = args.url - if not start_url.startswith("gemini://"): - start_url = "gemini://" + start_url else: start_url = None diff --git a/bebop/browser.py b/bebop/browser.py index be81fd0..5d1bb26 100644 --- a/bebop/browser.py +++ b/bebop/browser.py @@ -65,12 +65,10 @@ class Browser: ) self.command_line = CommandLine(command_line_window) - pending_url = start_url - while self.running: - if pending_url: - self.open_url(pending_url) - pending_url = None + if start_url: + self.open_url(start_url, assume_absolute=True) + while self.running: char = self.screen.getch() if char == ord(":"): self.quick_command("") @@ -191,6 +189,8 @@ class Browser: self.open_gemini_url(sanitize_url(url), redirects) elif parts.scheme.startswith("http"): self.open_web_url(url) + elif parts.scheme == "file": + self.open_file(parts.path) else: self.set_status_error(f"Protocol {parts.scheme} not supported.") @@ -461,3 +461,15 @@ class Browser: """Open a Web URL. Currently relies in Python's webbrowser module.""" self.set_status(f"Opening {url}") open_new_tab(url) + + def open_file(self, filepath): + """Open a file and render it. + + This should be used only on Gemtext files or at least text files. + Anything else will produce garbage and may crash the program. + """ + try: + with open(filepath, "rb") as f: + self.load_page(f.read()) + except (OSError, ValueError) as exc: + self.set_status_error(f"Failed to open file: {exc}") diff --git a/bebop/navigation.py b/bebop/navigation.py index b2b8827..5cb21fa 100644 --- a/bebop/navigation.py +++ b/bebop/navigation.py @@ -17,6 +17,9 @@ def parse_url(url: str, absolute: bool =False): though it technically is not, e.g. "dece.space" is not absolute as it misses either the // delimiter. """ + url = url.strip() + if url.startswith("file://"): + return urllib.parse.urlparse(url) if url.startswith("gemini://"): url = url[7:] parts = urllib.parse.urlparse(url, scheme="gemini") @@ -42,5 +45,5 @@ def set_parameter(url: str, user_input: str): """Return a new URL with the user input escaped (RFC 3986) appended.""" quoted_input = urllib.parse.quote(user_input) if "?" in url: - url = url.rsplit("?", maxsplit=1)[0] + url = url.split("?", maxsplit=1)[0] return url + "?" + quoted_input diff --git a/bebop/tests/test_navigation.py b/bebop/tests/test_navigation.py index 83a9592..88556a1 100644 --- a/bebop/tests/test_navigation.py +++ b/bebop/tests/test_navigation.py @@ -24,6 +24,10 @@ class TestNavigation(unittest.TestCase): self.assertEqual(res.netloc, "dece.space") self.assertEqual(res.path, "/index.html") + res = parse_url("file:///home/dece/gemini/index.gmi") + self.assertEqual(res.scheme, "file") + self.assertEqual(res.path, "/home/dece/gemini/index.gmi") + def test_join_url(self): url = join_url("gemini://dece.space/", "some-file.gmi") self.assertEqual(url, "gemini://dece.space/some-file.gmi")