Compare commits

..

No commits in common. "b2fdabea715fd91c9cf1f5b8e256dd50b7c0f0ae" and "f3a3a3603996b6569dc3a9e50ed4e0ccf12ddab9" have entirely different histories.

7 changed files with 22 additions and 86 deletions

View file

@ -4,6 +4,7 @@ import curses
import curses.ascii
import curses.textpad
import os
import subprocess
import tempfile
from math import inf
@ -12,7 +13,6 @@ from bebop.bookmarks import (
)
from bebop.colors import ColorPair, init_colors
from bebop.command_line import CommandLine
from bebop.external import open_external_program
from bebop.history import History
from bebop.links import Links
from bebop.mouse import ButtonState
@ -102,7 +102,7 @@ class Browser:
elif char == ord("h"):
self.scroll_page_horizontally(-3)
elif char == ord("H"):
self.scroll_whole_page_left()
pass # TODO h-scroll whole page left
elif char == ord("j"):
self.scroll_page_vertically(3)
elif char == ord("J"):
@ -114,9 +114,9 @@ class Browser:
elif char == ord("l"):
self.scroll_page_horizontally(3)
elif char == ord("L"):
self.scroll_whole_page_right()
pass # TODO h-scroll whole page right
elif char == ord("^"):
self.scroll_page_horizontally(-inf)
pass # TODO reset horizontal scrolling
elif char == ord("g"):
char = self.screen.getch()
if char == ord("g"):
@ -382,27 +382,10 @@ class Browser:
self.scroll_page_vertically(-self.page_pad_size[0])
def scroll_page_horizontally(self, by_columns):
"""Scroll page horizontally.
If `by_lines` is an integer (positive or negative), scroll the page by
this amount of columns. If `by_lines` is -inf, scroll back to the first
column. Scrolling to the right-most column is not supported.
"""
if by_columns == -inf:
require_refresh = self.page_pad.go_to_first_column()
else:
require_refresh = self.page_pad.scroll_h(by_columns, self.w)
if require_refresh:
"""Scroll page horizontally."""
if self.page_pad.scroll_h(by_columns, self.w):
self.refresh_page()
def scroll_whole_page_left(self):
"""Scroll left by a whole page."""
self.scroll_page_horizontally(-self.page_pad_size[1])
def scroll_whole_page_right(self):
"""Scroll right by a whole page."""
self.scroll_page_horizontally(self.page_pad_size[1])
def reload_page(self):
"""Reload the page, if one has been previously loaded."""
if self.current_url:
@ -445,6 +428,15 @@ class Browser:
save_bookmark(self.current_url, title)
self.reset_status()
def open_external_program(self, command):
"""Pauses the curses modes to open an external program."""
curses.nocbreak()
curses.echo()
subprocess.run(command)
curses.noecho()
curses.cbreak()
self.refresh_windows()
def edit_page(self):
"""Open a text editor to edit the page source.
@ -471,7 +463,6 @@ class Browser:
delete_source_after = True
command.append(source_filename)
open_external_program(command)
self.open_external_program(command)
if delete_source_after:
os.unlink(source_filename)
self.refresh_windows()

View file

@ -3,21 +3,12 @@
import curses
import curses.ascii
import curses.textpad
import os
import tempfile
from bebop.external import open_external_program
from bebop.links import Links
class CommandLine:
"""Basic and flaky command-line à la Vim, using curses module's Textbox.
I don't understand how to get proper pad-like behaviour, e.g. to scroll past
the window's right border when writing more content than the width allows.
Therefore I just added the M-e keybind to call an external editor and use
its content as result.
"""
"""Basic and flaky command-line à la Vim, using curses module's Textbox."""
def __init__(self, window):
self.window = window
@ -87,9 +78,6 @@ class CommandLine:
ch = self.window.getch()
if ch == -1:
raise EscapeCommandInterrupt()
else: # ALT keybinds.
if ch == ord("e"):
self.open_editor(self.gather())
self.window.nodelay(False)
return ch
@ -163,27 +151,6 @@ class CommandLine:
# Everything else could be a control character and should be processed.
return ch
def open_editor(self, existing_content=None):
"""Open an external editor and raise termination interrupt."""
try:
with tempfile.NamedTemporaryFile("w+t", delete=False) as temp_file:
if existing_content:
temp_file.write(existing_content)
temp_filepath = temp_file.name
except OSError:
return
command = ["vi", temp_filepath]
open_external_program(command)
try:
with open(temp_filepath, "rt") as temp_file:
content = temp_file.read()
os.unlink(temp_filepath)
except OSError:
return
raise TerminateCommandInterrupt(content)
class EscapeCommandInterrupt(Exception):
"""Signal that ESC has been pressed during command line."""

View file

@ -1,17 +0,0 @@
"""Call external commands."""
import curses
import subprocess
def open_external_program(command):
"""Call command as a subprocess, suspending curses rendering.
The caller has to refresh whatever windows it manages after calling this
method or garbage may be left on the screen.
"""
curses.nocbreak()
curses.echo()
subprocess.run(command)
curses.noecho()
curses.cbreak()

View file

@ -1,5 +1,7 @@
"""Links manager."""
from typing import List
class Links(dict):

View file

@ -53,11 +53,11 @@ def set_parameter(url: str, user_input: str):
def get_parent_url(url: str) -> str:
"""Return the parent URL (one level up)."""
scheme, netloc, path, _, _, _ = parse_url(url)
scheme, netloc, path, params, query, frag = parse_url(url)
last_slash = path.rstrip("/").rfind("/")
if last_slash > -1:
path = path[:last_slash + 1]
return urllib.parse.urlunparse((scheme, netloc, path, "", "", ""))
return urllib.parse.urlunparse((scheme, netloc, path, params, query, frag))
def get_root_url(url: str) -> str:

View file

@ -1,6 +1,6 @@
from dataclasses import dataclass, field
from bebop.gemtext import parse_gemtext
from bebop.gemtext import parse_gemtext, Title
from bebop.metalines import generate_dumb_metalines, generate_metalines
from bebop.links import Links

View file

@ -98,10 +98,3 @@ class PagePad:
self.current_line = max_line
return True
return False
def go_to_first_column(self):
"""Move to the first column; return True if a refresh is needed."""
if self.current_column:
self.current_column = 0
return True
return False