Compare commits

..

No commits in common. "84764644df64aee8d7d107c87b9f89df8bbf8b42" and "62619f29fb2175cb258480c218e42cdf6d3af696" have entirely different histories.

4 changed files with 7 additions and 68 deletions

View file

@ -1,45 +0,0 @@
Bebop
=====
Bebop is a [Gemini][gemini] browser for the terminal, focusing on practicality
and speed. It is a personal project to learn how to use ncurses and try new
ways to explore the Geminispace. It borrows some ideas from [Amfora][amfora],
another great terminal browser, Vim for interactivity and tries to support mouse
usage decently.
[gemini]: https://gemini.circumlunar.space/
[amfora]: https://github.com/makeworld-the-better-one/amfora
If you are interested in Gemini and looking for a client, I recommend trying a
graphical one like the excellent [Lagrange][lagrange] or [Kristall][kristall],
or Amfora if you're feeling more at home in the terminal. Bebop won't attempt
to support every feature other clients might have.
[lagrange]: https://git.skyjake.fi/skyjake/lagrange
[kristall]: https://kristall.random-projects.net/
It passes the Conman's client test but not Egsam's for now.
Features
--------
### What works
- Basic browsing: scrolling, follow links, redirections, Web links.
### What is planned
- Handle more content types.
- Great config options.
- Identity management with temporary and managed certificates.
- Buffers (or tabs if you prefer).
- Home page.
- Bookmarks.
### What is not planned for now
- 256-colors mode and themes.
- Subscriptions. I have no need for them as I prefer to use a browser-agnostic
aggregator at the moment.

View file

@ -222,11 +222,7 @@ class Browser:
else:
pass # TODO
data = req.proceed()
if not data:
self.set_status_error(f"Server did not respond in time ({url}).")
return
response = Response.parse(data)
response = Response.parse(req.proceed())
if not response:
self.set_status_error(f"Server response parsing failed ({url}).")
return

View file

@ -81,7 +81,7 @@ class Request:
self.payload += LINE_TERM
try:
sock = socket.create_connection((hostname, port), timeout=10)
sock = socket.create_connection((hostname, port))
except OSError as exc:
self.state = Request.STATE_CONNECTION_FAILED
self.error = exc.strerror
@ -124,10 +124,7 @@ class Request:
self.ssock.sendall(self.payload)
response = b""
while True:
try:
buf = self.ssock.recv(4096)
except socket.timeout:
buf = None
if not buf:
return response
response += buf
@ -175,7 +172,6 @@ class Response:
content: bytes = b""
HEADER_RE = re.compile(r"(\d{2}) (.*)")
MAX_META_LEN = 1024
@property
def generic_code(self):
@ -193,8 +189,6 @@ class Response:
if not match:
return None
code, meta = match.groups()
if len(meta) > Response.MAX_META_LEN:
return None
response = Response(StatusCode(int(code)), meta=meta)
if response.generic_code == StatusCode.SUCCESS:
content_offset = response_header_len + len(LINE_TERM)

View file

@ -215,13 +215,10 @@ def render_lines(metalines, window, max_width):
- max_width: line length limit for the pad.
Return:
The tuple of integers (error, height, width), error being a non-zero value
if an error occured during rendering, and height and width being the new
dimensions of the resized window.
The tuple (height, width) of the resized window.
"""
num_lines = len(metalines)
new_dimensions = num_lines, max_width
window.resize(*new_dimensions)
window.resize(num_lines, max_width)
for line_index, metaline in enumerate(metalines):
meta, line = metaline
line = line[:max_width - 1]
@ -240,10 +237,7 @@ def render_lines(metalines, window, max_width):
attr = curses.color_pair(ColorPair.BLOCKQUOTE) | curses.A_ITALIC
else: # includes LineType.PARAGRAPH
attr = curses.color_pair(ColorPair.NORMAL)
try:
window.addstr(line, attr)
except ValueError:
return new_dimensions
if line_index < num_lines - 1:
window.addstr("\n")
return new_dimensions
return num_lines, max_width