# Dunlin - a extensible Fennel-based web browser > The dunlin (Calidris alpina) is a small wader. It is a circumpolar > breeder in Arctic or subarctic regions. Birds that breed in northern > Europe and Asia are long-distance migrants, wintering south to Africa, > southeast Asia and the Middle East. Birds that breed in Alaska and the > Canadian Arctic migrate short distances to the Pacific and Atlantic > coasts of North America, although those nesting in northern Alaska > overwinter in Asia. Dunlin is a GTK-based Webkit browser which can be extended in (indeed, is mostly written in) [Fennel](https://www.fennel-lang.org). ## Why does the world need another half-assed Webkit browser? It doesn't, really. But me, personally, I think I do. I want a browser that lets me easily change keybindings/add commands to do things like: * find the open Fediverse tab and post a message * watch a local html file and reload when it changes * search the {Lua reference, Ruby docs, GTK docs} for term instead of wading through the the SEO cesspool that is the internet in 2022 * search in previously "liked" pages for the thing I found three weeks ago, instead of ... ditto * find the tab that's playing music and pause the player (instead of muting it) * more stuff I haven't thought of Full disclosure: Dunlin today can do none of these things, but if I borrow enough design decisions from Emacs, I hope some day it will ## Installation and getting started If you're using Nix, you can run `nix-shell` to pull all the dependencies. Otherwise .. Luarocks? Refer to `default.nix` and `shell.nix` and obtain: * All Lua packages listed in any `lua5_3.withPackages` stanza * All system packages listed in any `buildInputs` or `nativeBuildInputs` stanzas. To run the browser, ```sh $ fennel dunlin.fnl ``` Dunlin will open a socket in `$XDG_RUNTIME_DIR` to allow communication with a Fennel REPL. You can run the `repl.sh` script to connect to it with [socat](http://www.dest-unreach.org/socat/). ### Running tests Tests are in `test/*.fnl`. The test coverage is not 100% nor will it ever be, probably: tests exist only for the bits that were hard to write (algorithmically complex) and easy to test (not full of UI). `make watch` will watch the filesystem in this directory and run the tests whenever something changes. ### Running everything There's a `Procfile` that starts the test runner and a Fennel repl and probably in time some other useful things. I use it with [Overmind](https://github.com/DarthSim/overmind#readme) - `overmind start -D; overmind connect` to create a tmux session. ## Customizing _This is all quite fluid right now and I reserve the right to change things_. In particular, I anticipate the need to bind to non-key events (mouse events, on-screen buttons, touch gestures) (Among) the concepts you need to know here are "commands" and "bindings". * A "command" is a chunk of code that may be invoked interactively, plus a descrition of the parameters it needs and their default values. For example, `visit-location` needs a `url` parameter for the location and a `buffer` parameter that says which tab should visit it. * A "binding" is a sequence of keystrokes which map to a command: it may supply zero or more parameter values to the command. For example, (as of git commit cde0b8cd56d; YMMV if you're reading this significantly before or after 2022-12-23) the `g` binding invokes `visit-location` with the `buffer` parameter set to `main`, and the `url` parameter unset. When a command is invoked without all parameter values, Dunlin will prompt for each missing parameter in the "commander" text entry widget. A command with no binding may be invoked by pressing `M-x` (hold down the "meta" or "alt" key and press `x`) and then typing the command name. To see how commands are implemented, read the code in `command.fnl`. There is a simple keymap in `dunlin.fnl`, and you can see the details of how keymaps work in `keymap.fnl`