screen: handle input request (code 10)
This commit is contained in:
parent
5ef9a0430a
commit
b23e4a8d6a
|
@ -1,7 +1,7 @@
|
|||
import urllib.parse
|
||||
|
||||
|
||||
def parse_url(url, absolute=False):
|
||||
def parse_url(url: str, absolute: bool =False):
|
||||
"""Return URL parts from this URL.
|
||||
|
||||
This uses urllib.parse.urlparse to not reinvent the wheel, with a few
|
||||
|
@ -25,14 +25,22 @@ def parse_url(url, absolute=False):
|
|||
return parts
|
||||
|
||||
|
||||
def sanitize_url(url):
|
||||
def sanitize_url(url: str):
|
||||
"""Parse and unparse an URL to ensure it has been properly formatted."""
|
||||
return urllib.parse.urlunparse(parse_url(url))
|
||||
|
||||
|
||||
def join_url(base_url, url):
|
||||
def join_url(base_url: str, url: str):
|
||||
"""Join a base URL with a relative url."""
|
||||
if base_url.startswith("gemini://"):
|
||||
base_url = base_url[7:]
|
||||
parts = parse_url(urllib.parse.urljoin(base_url, url))
|
||||
return urllib.parse.urlunparse(parts)
|
||||
|
||||
|
||||
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]
|
||||
return url + "?" + quoted_input
|
||||
|
|
|
@ -7,7 +7,7 @@ from bebop.colors import ColorPair, init_colors
|
|||
from bebop.command_line import (CommandLine, EscapeCommandInterrupt,
|
||||
TerminateCommandInterrupt)
|
||||
from bebop.mouse import ButtonState
|
||||
from bebop.navigation import join_url, parse_url, sanitize_url
|
||||
from bebop.navigation import join_url, parse_url, sanitize_url, set_parameter
|
||||
from bebop.page import Page
|
||||
from bebop.protocol import Request, Response
|
||||
|
||||
|
@ -71,7 +71,7 @@ class Screen:
|
|||
if char == ord("q"):
|
||||
running = False
|
||||
elif char == ord(":"):
|
||||
command = self.input_common_command()
|
||||
command = self.take_user_input()
|
||||
self.set_status(f"Command: {command}")
|
||||
elif char == ord("s"):
|
||||
self.set_status(f"h {self.h} w {self.w}")
|
||||
|
@ -203,6 +203,8 @@ class Screen:
|
|||
elif response.generic_code in (40, 50):
|
||||
error = f"Server error: {response.meta or Response.code.name}."
|
||||
self.set_status_error(error)
|
||||
elif response.generic_code == 10:
|
||||
self.handle_input_request(url, response)
|
||||
|
||||
def load_page(self, gemtext: bytes):
|
||||
"""Load Gemtext data as the current page."""
|
||||
|
@ -215,9 +217,9 @@ class Screen:
|
|||
else:
|
||||
self.refresh_page()
|
||||
|
||||
def input_common_command(self):
|
||||
"""Focus command line to type a regular command. Currently useless."""
|
||||
return self.command_line.focus(":", self.validate_common_char)
|
||||
def take_user_input(self, type_char: str =":"):
|
||||
"""Focus command line to let the user type something"""
|
||||
return self.command_line.focus(type_char, self.validate_common_char)
|
||||
|
||||
def validate_common_char(self, ch: int):
|
||||
"""Generic input validator, handles a few more cases than default.
|
||||
|
@ -321,6 +323,16 @@ class Screen:
|
|||
return
|
||||
self.open_url(links[link_id])
|
||||
|
||||
def handle_input_request(self, from_url: str, response: Response):
|
||||
if response.meta:
|
||||
self.set_status(f"Input needed: {response.meta}")
|
||||
else:
|
||||
self.set_status("Input needed:")
|
||||
user_input = self.take_user_input("?")
|
||||
if user_input:
|
||||
url = set_parameter(from_url, user_input)
|
||||
self.open_gemini_url(url)
|
||||
|
||||
def handle_mouse(self, mouse_id: int, x: int, y: int, z: int, bstate: int):
|
||||
"""Handle mouse events.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import unittest
|
||||
|
||||
from ..navigation import join_url, parse_url
|
||||
from ..navigation import join_url, parse_url, set_parameter
|
||||
|
||||
|
||||
class TestNavigation(unittest.TestCase):
|
||||
|
@ -28,3 +28,9 @@ class TestNavigation(unittest.TestCase):
|
|||
self.assertEqual(url, "gemini://dece.space/dir1/other-file.gmi")
|
||||
url = join_url("gemini://dece.space/dir1/file.gmi", "../top-level.gmi")
|
||||
self.assertEqual(url, "gemini://dece.space/top-level.gmi")
|
||||
|
||||
def test_set_parameter(self):
|
||||
url = set_parameter("gemini://gus.guru/search", "my search")
|
||||
self.assertEqual(url, "gemini://gus.guru/search?my%20search")
|
||||
url = set_parameter("gemini://gus.guru/search?old%20search", "new")
|
||||
self.assertEqual(url, "gemini://gus.guru/search?new")
|
||||
|
|
Reference in a new issue