history: add optional persistent history
This commit is contained in:
parent
0c1924d40a
commit
2324fbb0bc
|
@ -164,10 +164,15 @@ class Browser:
|
||||||
else:
|
else:
|
||||||
self.capsule_prefs = capsule_prefs
|
self.capsule_prefs = capsule_prefs
|
||||||
|
|
||||||
|
# Load user data files that may not exist (no warning).
|
||||||
|
if self.config["persistent_history"]:
|
||||||
|
if not self.history.load():
|
||||||
|
logging.warning("Could not load history file.")
|
||||||
|
|
||||||
if failed_to_load:
|
if failed_to_load:
|
||||||
error_msg = (
|
error_msg = (
|
||||||
f"Failed to open some local data: {', '.join(failed_to_load)}. "
|
f"Failed to open some local data: {', '.join(failed_to_load)}. "
|
||||||
"Some data may be lost if you continue."
|
"These may be replaced if you continue."
|
||||||
)
|
)
|
||||||
self.set_status_error(error_msg)
|
self.set_status_error(error_msg)
|
||||||
elif start_url:
|
elif start_url:
|
||||||
|
@ -175,12 +180,16 @@ class Browser:
|
||||||
else:
|
else:
|
||||||
self.open_home()
|
self.open_home()
|
||||||
|
|
||||||
|
# Start listening for inputs.
|
||||||
while self.running:
|
while self.running:
|
||||||
try:
|
try:
|
||||||
self.handle_inputs()
|
self.handle_inputs()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
self.set_status("Cancelled.")
|
self.set_status("Cancelled.")
|
||||||
|
|
||||||
|
if self.config["persistent_history"]:
|
||||||
|
self.history.save()
|
||||||
|
|
||||||
def handle_inputs(self):
|
def handle_inputs(self):
|
||||||
char = self.screen.getch()
|
char = self.screen.getch()
|
||||||
if char == ord("?"):
|
if char == ord("?"):
|
||||||
|
|
|
@ -29,6 +29,7 @@ DEFAULT_CONFIG = {
|
||||||
"-subj", "/CN={common_name}",
|
"-subj", "/CN={common_name}",
|
||||||
],
|
],
|
||||||
"scroll_step": 3,
|
"scroll_step": 3,
|
||||||
|
"persistent_history": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
RENDER_MODES = ("fancy", "dumb")
|
RENDER_MODES = ("fancy", "dumb")
|
||||||
|
|
12
bebop/fs.py
12
bebop/fs.py
|
@ -48,23 +48,29 @@ def get_downloads_path() -> Path:
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(None)
|
@lru_cache(None)
|
||||||
def get_identities_list_path():
|
def get_identities_list_path() -> Path:
|
||||||
"""Return the identities JSON file path."""
|
"""Return the identities JSON file path."""
|
||||||
return get_user_data_path() / "identities.json"
|
return get_user_data_path() / "identities.json"
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(None)
|
@lru_cache(None)
|
||||||
def get_identities_path():
|
def get_identities_path() -> Path:
|
||||||
"""Return the directory where identities are stored."""
|
"""Return the directory where identities are stored."""
|
||||||
return get_user_data_path() / "identities"
|
return get_user_data_path() / "identities"
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(None)
|
@lru_cache(None)
|
||||||
def get_capsule_prefs_path():
|
def get_capsule_prefs_path() -> Path:
|
||||||
"""Return the directory where identities are stored."""
|
"""Return the directory where identities are stored."""
|
||||||
return get_user_data_path() / "capsule_prefs.json"
|
return get_user_data_path() / "capsule_prefs.json"
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(None)
|
||||||
|
def get_history_path() -> Path:
|
||||||
|
"""Return the saved history path."""
|
||||||
|
return get_user_data_path() / "history.txt"
|
||||||
|
|
||||||
|
|
||||||
def ensure_bebop_files_exist() -> Optional[str]:
|
def ensure_bebop_files_exist() -> Optional[str]:
|
||||||
"""Ensure various Bebop's files or directories are present.
|
"""Ensure various Bebop's files or directories are present.
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ Here are the available options:
|
||||||
* render_mode (string): default render mode to use ("fancy" or "dumb").
|
* render_mode (string): default render mode to use ("fancy" or "dumb").
|
||||||
* generate_client_cert_command (see note 3): command to generate a client cert.
|
* generate_client_cert_command (see note 3): command to generate a client cert.
|
||||||
* scroll_step (int): number of lines/columns to scroll in one step.
|
* scroll_step (int): number of lines/columns to scroll in one step.
|
||||||
|
* persistent_history (bool): save and reload history.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
"""History management."""
|
"""History management."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from bebop.fs import get_history_path
|
||||||
|
|
||||||
|
|
||||||
class History:
|
class History:
|
||||||
"""Basic browsing history manager.
|
"""Basic browsing history manager."""
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, limit):
|
def __init__(self, limit):
|
||||||
self.urls = []
|
self.urls = []
|
||||||
|
@ -55,3 +57,28 @@ class History:
|
||||||
urls.append(url)
|
urls.append(url)
|
||||||
seen.add(url)
|
seen.add(url)
|
||||||
return "# History\n\n" + "\n".join("=> " + url for url in urls)
|
return "# History\n\n" + "\n".join("=> " + url for url in urls)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
"""Save current history to user data."""
|
||||||
|
history_path = get_history_path()
|
||||||
|
try:
|
||||||
|
with open(history_path, "wt") as history_file:
|
||||||
|
for url in self.urls:
|
||||||
|
history_file.write(url + "\n")
|
||||||
|
except OSError as exc:
|
||||||
|
logging.error(f"Failed to save history {history_path}: {exc}")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
"""Load saved history from user data."""
|
||||||
|
history_path = get_history_path()
|
||||||
|
self.urls = []
|
||||||
|
try:
|
||||||
|
with open(history_path, "rt") as history_file:
|
||||||
|
for url in history_file:
|
||||||
|
self.urls.append(url.rstrip())
|
||||||
|
except OSError as exc:
|
||||||
|
logging.error(f"Failed to load history {history_path}: {exc}")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
Reference in a new issue