# BFG: a multiprotocol "small web" browser in Tcl/Tk

BFG (stands for Back/Forward/Go) is a free (absolutely), open-source, cross-platform, single-script, self-contained GUI client for a number of "small web" protocols like Gopher, Finger, Nex, Spartan and Gemini.

BFG is written in under 1000 SLOC of Tcl 8.6 and depends upon Tcllib, Tk (obviously) and TclTLS.

Note: the TclTLS dependency can be turned off in the configuration file at the expense of losing Gemini and Gopher-over-TLS support. It is generally not recommended to do this unless you have troubles installing TclTLS onto your system.

If you found any bugs, feel free to submit an issue into this repo!


## Supported features

The following features are already (fully or partially) supported in BFG.

### Complete

* [Finger](https://datatracker.ietf.org/doc/html/rfc1288) protocol (`finger://` URLs)
* [Gopher](https://datatracker.ietf.org/doc/html/rfc1436) protocol with optional TLS support (`gopher://` and `gophers://` URLs)
* [Nex](https://nex.nightfall.city/nex/info/specification.txt) protocol (`nex://` URLs)
* [Spartan](https://portal.mozz.us/spartan/spartan.mozz.us/specification.gmi) protocol (`spartan://` URLs) with single-line text query support
* [Gemini](https://geminiprotocol.net/docs/) protocol (`gemini://` URLs) with single-line custom input support
* Gophermap rendering (almost all known entry types)
* Single-line search query support for Gopher type 7 resources
* UTF-8 support for text content
* Basic history support (back/forward actions)
* Page refresh action
* Page/file download action
* Status bar
* Bookmarks
* Opening a URL from the command line
* Opening unknown URL schemes in the outside OS environment
* Opening the links in a new window
* Easy keybindings for fully mouseless navigation (see "Usage" section)
* Dynamic window title based on the current URL
* In-page text search
* Ini-based customization of the current Ttk theme, content fonts and colors
* Non-TLS mode for systems without TclTLS support
* Automatic TLS upgrade support for Gopher and other protocols (configurable in the `bfg.ini` file)
* Opening links in Torified windows (for the systems with torsocks installed)

## Non-supported features

The following features aren't supported by BFG as of now, some of them never will be.
In general, there are two reasons why a feature might not be implemented in BFG:

* it bloats the scope too much (making the codebase over 1000 SLOC with no space for optimization),
* it requires more third-party package dependencies (other than Tk, Tcllib and TclTLS).

### Still pending (might be imlpemented someday)

* Source view toggle (between plaintext and rendered gophermap/Gemtext/etc)
* Local plaintext/Gemtext reader (file:// URL scheme)
* ANSI terminal coloring (basic 16 colors only)
* Image viewer (non-embedded, only PNG/GIF/PPM/PGM types)
* Gemini client certificates (might never be implemented; don't ask for it unless absolutely necessary)

### Unsupported by design

* Tabs (they complicate the architecture a lot; use your WM's tabbing functionality instead)
* Horizontal scrolling (word wrapping is mandatory; expand the window if the content doesn't fit)
* Saved history (unsupported for security reasons; use bookmarks if you want to save a page URL)
* Any other text content encoding except UTF-8
* Context menus
* Any sort of sound or video output
* Any sort of embedded non-text content
* NPS and Titan protocols and other means of content uploading \* 
* Gopher+ protocol extensions
* Scroll protocol (see FAQ)
* Guppy protocol (UDP-based, don't want to introduce another third-party dependency)

(\* probably will be implemented in a separate program)


## Usage

You can run the script with an optional URL to open, e.g.: `wish bfg.tcl gopher://hoi.st`

The following keybindings are currently supported:

* b: bo back in history
* f: go forward in history
* g: focus the address bar and select the current address (to be able to easily overwrite it)
* r or F5: refresh the content
* a: select and highlight the previous link
* s: select and highlight the next link
* d: download the file or page contents under the selected link
* Shift+d: download the file or page contents under the selected link and open it with your default application
* Space / Return (Enter): click on the selected link
* Shift + Space / Shift + Return (Enter): open the selected link in a new window
* Control + Shift + Space / Control + Shift + Return (Enter): open the selected link in a new window in Tor
* h / Arrow Left / PgUp: scroll the content up 10 lines
* j / Arrow Down: scroll the content down 1 line
* k / Arrow Up: scroll the content up 1 line
* l / Arrow Right / PgDn: scroll the content down 10 lines
* / (forward slash) or ctrl+f: enter a term to find in the text (enter nothing to find the next one) 
* Esc: reset all search highlights
* Ctrl+b: open bookmarks menu (you can navigate with arrows after opening)
* Ctrl+q: quit BFG

The following mouse bindings are currently supported:

* Left click: open the link
* Shift + Left click or Middle click: open the link in a new window
* Shift + Middle click or Control + Shift + Left click: open the link in a new window in Tor
* Right click: download the link contents
* Shift + Right click: download the link contents and open it with your default application
* Scroll wheel: scroll the page content
* Mouse button 8 ("Back") if present: go back in history
* Mouse button 9 ("Forward") if present: go forward in history

Note: opening a link in Tor requires Tor to be running and torsocks command to be installed in the system.

You don't need to do any special combinations to open links in Tor once the parent window is already opened via torsocks. You also cannot open new windows in clearnet from the Tor-enabled windows.

## Customization

BFG ships with a `bfg.ini` file that holds your configuration values and bookmarks.
The main configuration sections are:

* `[net]`: network-related configs, currently has "timeout" parameter and an optional "tls" parameter (`auto` by default)
* `[widget]`: general UI widget appearance (ttkTheme, font (button font), entryfont, statusfont)
* `[style.general]`: general content area appearance (textfont, monofont\*, foreground color, background color)
* `[style.link.normal]`: normal link colors (foreground, background)
* `[style.link.focused]`: currently focused link colors (foreground, background)
* `[style.highlight]`: highlighted area colors (foreground, background) - used with search functionality
* `[style.error]`: error message colors (foreground, background)

Feel free to modify the bfg.ini file according to your own preferences, the one shipped is just an example.

\* Note: Gopher, Finger and Nex content is always rendered in the monospace font. 

## FAQ

### Why yet another "small web" client?

I like the idea of browsing without bloatware. I also like Lagrange but it already looks too bloated to me.
I also like the idea of Tcl/Tk as the universal tool for creating lightweight and portable GUI applications.
BFG was created as a great playground to combine those ideas and as the next iteration over Bopher-NG.
Which, as you might have guessed, only supports Gopher.

Contrary to most GUI clients, BFG is:

* keyboard-friendly (everything that can be done with a mouse can be done with a keyboard),
* trackball-friendly (the middle click action can be substituted with Shift + left click),
* not overloaded with menus,
* under 40K bytes in size.

### Why such keybindings?

When using "normal" browsers, we don't fully utilize the keyboard. BFG combines the best practices from Links/Elinks, less, Bopher-NG etc to create the most comfortable UX in case you choose to not use the mouse at all.
In fact, the browser name itself contains the first three keybindings to start using it without a mouse.

### Can you build a binary distribution of BFG?

The main idea of BFG is to be as portable as possible, so no, binaries will not be distributed here.
However, you always can do it yourself. Here's how.

1. Obtain the tclkits for your host and target platforms, e.g. build them [here](https://kitcreator.rkeene.org/kitcreator).
Make sure you're building the target tclkit with Metakit, Tcllib, Tk and TLS packages enabled. 
Optionally you can select "TLS: Statically link to LibSSL" and/or "TLS: Build LibreSSL for this platform".
If the host and target platform are the same, you still need two kit binaries (just make a copy).

2. Download `sdx.kit` from somewhere, e.g. from [here](https://codeberg.org/luxferre/StreamGoose/raw/branch/main/tcldep/sdx.kit)

3. Put the two binaries and `sdx.kit` into the same directory as `bfg.tcl`, then run from this directory:
```
[/path/to/host/tclkit] sdx.kit qwrap bfg.tcl -runtime [/path/to/target/tclkit] 
```
A file just named `bfg` should appear, this is your executable.

4. If building for Windows, rename `bfg` to `bfg.exe`.

### I want this feature X to be implemented! Can you do this?

If the feature doesn't belong to the pending items list above, the answer most probably is no.
The pending list can be updated from time to time, so please check it periodically.
Alternatively, you can do a proposal in the "Issues" section or even create a patch or a pull request.
However, one of the BFG's goals is to stay under 1000 SLOC no matter what.
If you want feature creep, feel free to switch to more suitable clients like Lagrange.

### Why aren't you going to implement the Scroll protocol in BFG?

The [Scroll protocol](gemini://scrollprotocol.us.to/) is essentially advertised as an extended version of Gemini with some features of Spartan, despite being described as merely "inspired by Gemini and Gopher+". It introduces a new document format that essentially is a hybrid between Gemtext and Markdown. Implementing a reasonable amount of support for the inline markup alone will bloat the BFG's codebase beyond the desired limit. On top of that, the protocol imposes passing additional metadata and content classification, which, again, takes some more codebase to implement and doesn't add anything really useful in my opinion. The Scroll protocol just seems to introduce more unnecessary complexity the BFG browser is not designed for.

### Why does a Gopher-over-TLS (`gophers://` URL) resource still show plain `gopher://` links?

Due to a purely technical limitation of the Gopher protocol (or rather the Gophermap format) itself, we cannot determine if a particular Gophermap entry points to a plain Gopher or a Gopher-over-TLS resource. Hence, only the links belonging to the same host/port pair that was already opened with a `gophers://` link are displayed as `gophers://` links.

If the `tls` parameter in the `[net]` section of the `bfg.ini` file is set to `auto`, the client will try opening the TLS connection first regardless of the link type, so you don't have to worry about the URL scheme anymore..

### My system (or Tclkit) doesn't have TclTLS available, can I still use BFG for plaintext protocols?

Sure! Just supply `tls=off` (or `0`, or `none`) in the `[net]` section of the `bfg.ini` file.
You'll lose the ability to browse Gemini and Gopher-over-TLS resources but other protocols will be fully functional.

## Credits

Created by Luxferre in 2024, released into the public domain.
