history: fix going back

Ultimately a simple link list does not do all you want, so now the
history maintains a list of visited links that are useful to display,
but also a backlink list to let the user move to the previous pages.
This commit is contained in:
dece 2021-05-09 00:46:26 +02:00
parent 397a143695
commit f1c5d8dfc9
4 changed files with 60 additions and 28 deletions

View file

@ -31,3 +31,4 @@ handle soft-hyphens on wrapping
bug: combining chars reduce lengths bug: combining chars reduce lengths
non shit command-line non shit command-line
response code 11 (if still there) response code 11 (if still there)
gopher?

View file

@ -56,7 +56,7 @@ class Browser:
self.command_line = None self.command_line = None
self.running = True self.running = True
self.status_data = ("", 0, 0) self.status_data = ("", 0, 0)
self.history = History() self.history = History(self.config["history_limit"])
self.cache = {} self.cache = {}
self.special_pages = self.setup_special_pages() self.special_pages = self.setup_special_pages()
self._current_url = "" self._current_url = ""
@ -203,10 +203,15 @@ class Browser:
elif char == ord("l"): elif char == ord("l"):
self.scroll_page_horizontally(1) self.scroll_page_horizontally(1)
self.screen.nodelay(False) self.screen.nodelay(False)
# else: # elif char == ord("@"):
# unctrled = curses.unctrl(char) # self.current_url = "bebop:debugzone"
# if unctrled == b"^T": # t = "\n".join("* " + u for u in self.history.urls)
# self.set_status("test!") # t += "\n\n" + "\n".join("* " + u for u in self.history.backlist)
# self.load_page(Page.from_text(t))
# # unctrled = curses.unctrl(char)
# # if unctrled == b"^T":
# # self.set_status("test!")
# pass
@property @property
def page_pad_size(self): def page_pad_size(self):
@ -310,7 +315,7 @@ class Browser:
else: else:
parts = parse_url(url) parts = parse_url(url)
if parts["netloc"] is None: if parts["scheme"] is None and parts["netloc"] is None:
base_url = base_url or self.current_url base_url = base_url or self.current_url
if base_url: if base_url:
parts = parse_url(join_url(base_url, url)) parts = parse_url(join_url(base_url, url))
@ -475,7 +480,10 @@ class Browser:
def go_back(self): def go_back(self):
"""Go back in history if possible.""" """Go back in history if possible."""
previous_url = self.history.get_previous() if self.current_url.startswith("bebop:"):
previous_url = self.history.get_previous(actual_previous=True)
else:
previous_url = self.history.get_previous()
if previous_url: if previous_url:
self.open_url(previous_url, history=False) self.open_url(previous_url, history=False)
@ -489,14 +497,19 @@ class Browser:
if self.current_url: if self.current_url:
self.open_url(get_root_url(self.current_url)) self.open_url(get_root_url(self.current_url))
def open_internal_page(self, name, gemtext):
"""Open some content corresponding to a "bebop:" internal URL."""
page = Page.from_gemtext(gemtext, self.config["text_width"])
self.load_page(page)
self.current_url = "bebop:" + name
def open_bookmarks(self): def open_bookmarks(self):
"""Open bookmarks.""" """Open bookmarks."""
content = get_bookmarks_document() content = get_bookmarks_document()
if content is None: if content is None:
self.set_status_error("Failed to open bookmarks.") self.set_status_error("Failed to open bookmarks.")
return return
self.load_page(Page.from_gemtext(content, self.config["text_width"])) self.open_internal_page("bookmarks", content)
self.current_url = "bebop:bookmarks"
def add_bookmark(self): def add_bookmark(self):
"""Add the current URL as bookmark.""" """Add the current URL as bookmark."""
@ -551,8 +564,7 @@ class Browser:
def open_help(self): def open_help(self):
"""Show the help page.""" """Show the help page."""
self.load_page(Page.from_gemtext(HELP_PAGE, self.config["text_width"])) self.open_internal_page("help", HELP_PAGE)
self.current_url = "bebop:help"
def prompt(self, text, keys): def prompt(self, text, keys):
"""Display the text and allow it to type one of the given keys.""" """Display the text and allow it to type one of the given keys."""
@ -561,8 +573,4 @@ class Browser:
def open_history(self): def open_history(self):
"""Show a generated history of visited pages.""" """Show a generated history of visited pages."""
self.load_page(Page.from_gemtext( self.open_internal_page("history", self.history.to_gemtext())
self.history.to_gemtext(),
self.config["text_width"]
))
self.current_url = "bebop:history"

View file

@ -9,6 +9,7 @@ DEFAULT_CONFIG = {
"text_width": 80, "text_width": 80,
"source_editor": ["vi"], "source_editor": ["vi"],
"command_editor": ["vi"], "command_editor": ["vi"],
"history_limit": 1000,
} }

View file

@ -4,32 +4,54 @@
class History: class History:
"""Basic browsing history manager. """Basic browsing history manager.
The history follows the "by last visited" behaviour of Firefox for the lack
of a better idea. Links are pushed as they are visited. If a link is visited
again, it bubbles up to the top of the history.
""" """
def __init__(self): def __init__(self, limit):
self.urls = [] self.urls = []
self.backlist = []
self.limit = limit
def push(self, url): def push(self, url):
"""Add an URL to the history. """Add an URL to the history."""
# Append url to our URLs, bubbling it up if it's already there.
If the URL is already in the list, it is moved to the top.
"""
try: try:
self.urls.remove(url) self.urls.remove(url)
except ValueError: except ValueError:
pass pass
self.urls.append(url) self.urls.append(url)
if len(self.urls) > self.limit:
self.urls.pop(0)
def get_previous(self): # Also simply push it to the backlist.
self.backlist.append(url)
if len(self.backlist) > self.limit:
self.backlist.pop(0)
def get_previous(self, actual_previous=False):
"""Return previous URL, or None if there is only one or zero URL.""" """Return previous URL, or None if there is only one or zero URL."""
try: try:
return self.urls[-2] if actual_previous:
return self.backlist[-1]
# The backlist should be populated with the first link visited and
# never completely emptied afterwards, or we end up in situation
# where you can't get away from internal pages.
if len(self.backlist) > 1:
self.backlist.pop()
return self.backlist[-1]
except IndexError: except IndexError:
return None return None
def to_gemtext(self): def to_gemtext(self):
"""Generate a simple Gemtext page of the current history.""" """Generate a simple Gemtext page of the current history.
return "\n".join("=> " + url for url in self.urls)
Present a page that follows the "by last visited" behaviour of Firefox
for the lack of a better idea, avoiding duplicated entries.
"""
urls = []
seen = set()
for url in reversed(self.urls):
if url in seen:
continue
urls.append(url)
seen.add(url)
return "\n".join("=> " + url for url in urls)