help: clean up a lot and fix smol issues
Moved a lot of stuff from the readme to the help page so the program is more self-contained.
This commit is contained in:
parent
2bfed8533e
commit
8de79a6e5a
|
@ -47,3 +47,5 @@ opt. maintain history between sessions
|
||||||
history (forward) (useful?)
|
history (forward) (useful?)
|
||||||
search in page (ugh)
|
search in page (ugh)
|
||||||
get/set config using command-line
|
get/set config using command-line
|
||||||
|
bug: xterm is borked
|
||||||
|
more UT
|
||||||
|
|
110
README.md
110
README.md
|
@ -2,7 +2,7 @@ Bebop
|
||||||
=====
|
=====
|
||||||
|
|
||||||
Bebop is a [Gemini][gemini] browser for the terminal, focusing on practicality
|
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
|
and laziness. 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],
|
ways to explore the Geminispace. It borrows some ideas from [Amfora][amfora],
|
||||||
another great terminal browser, Vim for interactivity and tries to support mouse
|
another great terminal browser, Vim for interactivity and tries to support mouse
|
||||||
usage decently.
|
usage decently.
|
||||||
|
@ -13,13 +13,12 @@ usage decently.
|
||||||
If you are interested in Gemini and looking for a desktop/laptop client, I
|
If you are interested in Gemini and looking for a desktop/laptop client, I
|
||||||
recommend trying a graphical one like the excellent [Lagrange][lagrange] or
|
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.
|
[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.
|
Bebop won't attempt to support every feature other clients might have, but if
|
||||||
|
you want to try something a bit different, keep reading…
|
||||||
|
|
||||||
[lagrange]: https://git.skyjake.fi/skyjake/lagrange
|
[lagrange]: https://git.skyjake.fi/skyjake/lagrange
|
||||||
[kristall]: https://kristall.random-projects.net/
|
[kristall]: https://kristall.random-projects.net/
|
||||||
|
|
||||||
It passes the Conman's client test but not Egsam's for now.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
|
@ -27,95 +26,36 @@ Features
|
||||||
|
|
||||||
Why use Bebop instead of something else?
|
Why use Bebop instead of something else?
|
||||||
|
|
||||||
### Lightweight
|
- Lightweight, no external Python dependencies.
|
||||||
|
- Nice keybinds are defined, and Vim users should get quickly familiar with
|
||||||
|
them.
|
||||||
|
- Fun! Link navigation is done by entering the link ID with automatic
|
||||||
|
validation: if there are less than 10 links on a page, pressing the link ID
|
||||||
|
will take you to the page directly. If there are 30 links, pressing "1" will
|
||||||
|
wait for another digit. If there are 1000 links but you wish to visit link
|
||||||
|
5, pressing 5 and enter will do. Of course this is based on my own
|
||||||
|
perception of what exactly makes a client "fun" to use, but give it a shot!
|
||||||
|
- History, cache, client certificates, bookmarks (it's just a text file with
|
||||||
|
bindings), downloads and more!
|
||||||
|
|
||||||
It does not use any external dependencies. Everything including NCurses or TLS
|
You can check out the Bebop page on Gemini at gemini://dece.space/dev/bebop.gmi,
|
||||||
is done using Python's standard library.
|
or [this board](BOARD.txt) for what's done and what might be cooking.
|
||||||
|
|
||||||
### Nice keybinds
|
|
||||||
|
|
||||||
A lot of keybinds are defined, and Vim users should get quickly familiar with
|
|
||||||
them. Find them in the help page by pressing `?`.
|
|
||||||
|
|
||||||
### Fun
|
|
||||||
|
|
||||||
Link navigation is done by entering the link ID with automatic validation: if
|
|
||||||
there are less than 10 links on a page, pressing the link ID will take you to
|
|
||||||
the page directly. If there are 30 links, pressing "1" will wait for another
|
|
||||||
digit. If there are 1000 links but you wish to visit link #5, pressing 5 and
|
|
||||||
enter will do!
|
|
||||||
|
|
||||||
Of course this is based on my own perception of what exactly makes a client
|
|
||||||
"fun" to use, but give it a shot!
|
|
||||||
|
|
||||||
### And more!
|
|
||||||
|
|
||||||
It does not try to do many things. Common basic browsing features work: go to
|
|
||||||
URL, scrolling, follow links, redirections, page encodings, etc.
|
|
||||||
|
|
||||||
It also provide these features:
|
|
||||||
|
|
||||||
- History
|
|
||||||
- Caching
|
|
||||||
- Bookmarks (it's just a text file with bindings)
|
|
||||||
- Downloads
|
|
||||||
|
|
||||||
Check out [this board](BOARD.txt) for what's done and coming next.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
Install
|
||||||
-------------
|
-------
|
||||||
|
|
||||||
Bebop uses a JSON file (usually in `~/.config`). It is created with default
|
TODO
|
||||||
values on first start. It is never written to afterwards: you can edit it when
|
|
||||||
you want, just restart Bebop to take changes into account.
|
|
||||||
|
|
||||||
Here are the available options:
|
|
||||||
|
|
||||||
| Key | Type | Default | Description |
|
|
||||||
|----------------------------|--------------|----------------|---------------------------------------|
|
|
||||||
| `connect_timeout` | int | 10 | Seconds before connection times out. |
|
|
||||||
| `text_width` | int | 80 | Rendered line length. |
|
|
||||||
| `download_path` | string | | Download path. |
|
|
||||||
| `source_editor` | string list | `["vi"]` | Command to use for editing sources. |
|
|
||||||
| `command_editor` | string list | `["vi"]` | Command to use for editing CLI input. |
|
|
||||||
| `history_limit` | int | 1000 | Maximum entries in history. |
|
|
||||||
| `external_commands` | (see note 2) | {} | Commands to open various files. |
|
|
||||||
| `external_command_default` | string list | `["xdg-open"]` | Default command to open files. |
|
|
||||||
|
|
||||||
Note: for the "command" parameters such as `source_editor` and `command_editor`,
|
|
||||||
a string list is used to separate the different program arguments, e.g. if you
|
|
||||||
wish to use `vim -c 'startinsert'`, you should write the list `["vim", "-c",
|
|
||||||
"startinsert"]`. In both case, a temporary or regular file name will be appended
|
|
||||||
to this command when run.
|
|
||||||
|
|
||||||
2: the `external_commands` dict maps MIME types to commands just as above. For
|
|
||||||
example, if you want to open video files with VLC and audio files in Clementine,
|
|
||||||
you can use the following dict: `{"audio": ["clementine"], "video", ["vlc"]}`.
|
|
||||||
For now only "main" MIME types are supported, i.e. you cannot specify precise
|
|
||||||
types like "audio/flac", just "audio".
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FAQ
|
Usage
|
||||||
---
|
-----
|
||||||
|
|
||||||
### Can I change the colors?
|
Just run `bebop`, optionally following by an URL.
|
||||||
|
|
||||||
I do not plan to allow modifying the colors or elements style for now. Configure
|
Documentation about the keybinds, config values and commands are embed into the
|
||||||
a nice palette for your terminal so that Bebop fits nicely in there!
|
software itself: press "?" to display the help page.
|
||||||
|
|
||||||
### Will Bebop implement subscriptions?
|
Happy browsing!
|
||||||
|
|
||||||
I have no need for them as I prefer to use a browser-agnostic aggregator at the
|
|
||||||
moment, so no.
|
|
||||||
|
|
||||||
### WTF is wrong with the command line?
|
|
||||||
|
|
||||||
I don't understand how you're supposed to create a fine input field in pure
|
|
||||||
curses without the form extension library, which is not available from Python.
|
|
||||||
Or, I think I understand but it's way too hard for the limited time I have to
|
|
||||||
work on Bebop. So the command line is based on the very limited Textbox class;
|
|
||||||
it's fine for entering a simple URL or a bookmark title but if you need to type
|
|
||||||
more than the window's width, press `M-e` (ALT + e) to open an editor.
|
|
||||||
|
|
|
@ -347,10 +347,15 @@ class Browser:
|
||||||
self.set_status_error(f"Too many redirections ({url}).")
|
self.set_status_error(f"Too many redirections ({url}).")
|
||||||
return
|
return
|
||||||
|
|
||||||
current_scheme = self.current_scheme or "gemini"
|
# Take the current scheme as the default scheme to use if the URL does
|
||||||
|
# not specify it. If it's the bebop scheme, discard it. If there is no
|
||||||
|
# current scheme available, default to the gemini scheme.
|
||||||
|
current_scheme = self.current_scheme
|
||||||
|
if not current_scheme or current_scheme == "bebop":
|
||||||
|
current_scheme = "gemini"
|
||||||
parts = parse_url(url, default_scheme=current_scheme)
|
parts = parse_url(url, default_scheme=current_scheme)
|
||||||
|
|
||||||
# If there is a no netloc part, try to join the URL.
|
# If there is no netloc part, try to join the URL.
|
||||||
if (
|
if (
|
||||||
parts["netloc"] is None
|
parts["netloc"] is None
|
||||||
and parts["scheme"] == current_scheme
|
and parts["scheme"] == current_scheme
|
||||||
|
@ -365,7 +370,7 @@ class Browser:
|
||||||
url_is_usable = True
|
url_is_usable = True
|
||||||
elif parts["scheme"] and parts["path"]:
|
elif parts["scheme"] and parts["path"]:
|
||||||
guessed_url = parts["scheme"] + "://" + parts["path"]
|
guessed_url = parts["scheme"] + "://" + parts["path"]
|
||||||
if self.prompt(f"Did you mean '{guessed_url}'?", "yn") == "y":
|
if self.prompt(f"Do you mean '{guessed_url}'?") == "y":
|
||||||
parts = parse_url(guessed_url)
|
parts = parse_url(guessed_url)
|
||||||
url_is_usable = True
|
url_is_usable = True
|
||||||
# If nothing could be done, just give up.
|
# If nothing could be done, just give up.
|
||||||
|
@ -614,7 +619,7 @@ class Browser:
|
||||||
"""Show the help page."""
|
"""Show the help page."""
|
||||||
self.open_internal_page("help", get_help(self.config))
|
self.open_internal_page("help", get_help(self.config))
|
||||||
|
|
||||||
def prompt(self, text, keys):
|
def prompt(self, text: str, keys: str ="yn"):
|
||||||
"""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."""
|
||||||
choice = "/".join(keys)
|
choice = "/".join(keys)
|
||||||
self.set_status(f"{text} [{choice}]")
|
self.set_status(f"{text} [{choice}]")
|
||||||
|
|
|
@ -330,7 +330,7 @@ def create_identity(browser: Browser, url: str):
|
||||||
Returns:
|
Returns:
|
||||||
The created identity on success (already registered in identities
|
The created identity on success (already registered in identities
|
||||||
"""
|
"""
|
||||||
key = browser.prompt("Create client certificate?", "yn")
|
key = browser.prompt("Create client certificate?")
|
||||||
if key != "y":
|
if key != "y":
|
||||||
browser.reset_status()
|
browser.reset_status()
|
||||||
return None
|
return None
|
||||||
|
@ -357,7 +357,7 @@ def create_identity(browser: Browser, url: str):
|
||||||
|
|
||||||
def forget_certificate(browser: Browser, hostname: str):
|
def forget_certificate(browser: Browser, hostname: str):
|
||||||
"""Remove the fingerprint associated to this hostname for the cert stash."""
|
"""Remove the fingerprint associated to this hostname for the cert stash."""
|
||||||
key = browser.prompt(f"Remove fingerprint for {hostname}?", "yn")
|
key = browser.prompt(f"Remove fingerprint for {hostname}?")
|
||||||
if key != "y":
|
if key != "y":
|
||||||
browser.reset_status()
|
browser.reset_status()
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
"""Help page. Currently only keybinds are shown as help."""
|
"""Help page. Currently only keybinds are shown as help."""
|
||||||
|
|
||||||
|
from bebop.config import DEFAULT_CONFIG
|
||||||
|
|
||||||
HELP_PAGE = """\
|
HELP_PAGE = """\
|
||||||
# Help
|
# Help
|
||||||
|
|
||||||
## Keybinds
|
## Keybinds
|
||||||
|
|
||||||
Keybinds using the SHIFT key are written uppercase. Keybinds using the ALT (or \
|
Keybinds using the SHIFT key are written uppercase. Keybinds using the ALT (or META) key are written using the "M-" prefix. Keybinds using the CTRL key are written using the "C-" prefix. Symbol keys are written as their name, not the symbol itself.
|
||||||
META) key are written using the "M-" prefix. Symbol keys are written as their \
|
|
||||||
name, not the symbol itself.
|
|
||||||
|
|
||||||
* colon: focus the command-line
|
* colon: focus the command-line
|
||||||
* r: reload page
|
* r: reload page
|
||||||
|
@ -37,27 +37,47 @@ name, not the symbol itself.
|
||||||
* y: open history
|
* y: open history
|
||||||
* digits: go to the corresponding link ID
|
* digits: go to the corresponding link ID
|
||||||
* escape: reset status line text
|
* escape: reset status line text
|
||||||
|
* C-c: cancel current operation
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
Commands are mostly for actions requiring user input. You can type a command \
|
Commands are mostly for actions requiring user input. You can type a command with arguments by pressing the corresponding keybind above.
|
||||||
with arguments by pressing the corresponding keybind above.
|
|
||||||
|
|
||||||
* o/open <url>: open this URL
|
* o/open <url>: open this URL
|
||||||
* forget_certificate <hostname>: remove saved fingerprint for the hostname
|
|
||||||
* q/quit: well, quit
|
* q/quit: well, quit
|
||||||
|
* h/home: open your home page
|
||||||
|
* forget_certificate <hostname>: remove saved fingerprint for this hostname
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
The current configuration is:
|
Bebop uses a JSON file (usually in ~/.config). It is created with default values on first start. It is never written to afterwards: you can edit it when you want, just restart Bebop to take changes into account.
|
||||||
|
|
||||||
|
Here are the available options:
|
||||||
|
|
||||||
|
* connect_timeout (int): seconds before connection times out.
|
||||||
|
* text_width (int): rendered line length.
|
||||||
|
* download_path (string): download path.
|
||||||
|
* source_editor (see note 1): command to use for editing sources.
|
||||||
|
* command_editor (see note 1): command to use for editing cli input.
|
||||||
|
* history_limit (int): maximum entries in history.
|
||||||
|
* external_commands (see note 2): commands to open various files.
|
||||||
|
* external_command_default (see note 1): default command to open files.
|
||||||
|
* home (string): home page.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
1: for the "command" parameters such as source_editor and command_editor, a string list is used to separate the different program arguments, e.g. if you wish to use `vim -c 'startinsert'`, you should write the list `["vim", "-c", "startinsert"]`. In both case, a temporary or regular file name will be appended to this command when run.
|
||||||
|
|
||||||
|
2: the external_commands dict maps MIME types to commands just as above. For example, if you want to open video files with VLC and audio files in Clementine, you can use the following dict: `{"audio": ["clementine"], "video": ["vlc"]}`. For now only "main" MIME types are supported, i.e. you cannot specify precise types like "audio/flac", just "audio".
|
||||||
|
|
||||||
|
Your current configuration is:
|
||||||
|
|
||||||
{config_list}
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def get_help(config):
|
def get_help(config):
|
||||||
config_list = "\n".join(
|
config_list = "\n".join(
|
||||||
f"* {key} = {value}"
|
f'* {key} = {value} (default "{DEFAULT_CONFIG[key]}")'
|
||||||
for key, value in config.items()
|
for key, value in config.items()
|
||||||
)
|
)
|
||||||
return HELP_PAGE.format(config_list=config_list)
|
return HELP_PAGE + config_list
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
WELCOME_PAGE = """\
|
WELCOME_PAGE = """\
|
||||||
# Bebop
|
# Bebop
|
||||||
|
|
||||||
Hi! Welcome to the Bebop browser.
|
Hi! Welcome to the Bebop browser! 🚀🎶
|
||||||
|
|
||||||
Press "?" to see the keybinds, commands and more, or click the link below by \
|
Press "?" to see the keybinds, commands and more, or visit the link below by \
|
||||||
pressing its link ID (1).
|
pressing its link ID (1). To start browsing right away, press "o", type an URL \
|
||||||
|
and press Enter.
|
||||||
|
|
||||||
=> bebop:help Help
|
=> bebop:help Help
|
||||||
=> gemini://dece.space/dev/bebop.gmi Bebop @ dece.space
|
=> gemini://dece.space/dev/bebop.gmi Online documentation
|
||||||
"""
|
"""
|
||||||
|
|
Reference in a new issue