TITLE: Qutebrowser setup
DATE: 2018-08-10
AUTHOR: John L. Godlee
====================================================================


Firefox was becoming annoying and bloated, and so I decided to go
back to using [Qutebrowser], a project I’d been following for a
while. It’s a minimalistic web browser, which is massively
extensible and keyboard driven, with default vim-like keybindings.
This is about how I’ve set it up. Qutebrowser is configured using a
python file called config.py which is normally found in
~/.qutebrowser/config.py.

  [Qutebrowser]: https://www.qutebrowser.org/index.html

  {IMAGE}


The tab bar

By default, the tab bar looks like this:

  {IMAGE}


It’s pretty ugly, it doesn’t have much padding around the text and
the text is quite small.

This is how I’ve modified it:

  {IMAGE}


The relevant lines of the config.py are:

    # Open new tabs in the background.
    c.tabs.background = True

    # Show favicons in the tab bar.
    c.tabs.favicons.show = False

    # Position of new tabs opened from another tab.
    c.tabs.new_position.related = 'next'

    # Padding (in pixels) around text for tabs.
    c.tabs.padding = {'bottom': 8, 'left': 5, 'right': 5, 'top': 8}

    # Position of the tab bar.
    c.tabs.position = 'top'

    # Alignment of the text inside of tabs.
    c.tabs.title.alignment = 'center'

    # Format to use for the tab title
    c.tabs.title.format = '{index}: {title} - {host}'

    # Width of tab indicators.
    c.tabs.indicator.width = 3

    # Padding (in pixels) for tab indicators.
    c.tabs.indicator.padding = {'bottom': 0, 'left': 0, 'right': 5, 'top': 0}

    # Background color of the tab bar.
    c.colors.tabs.bar.bg = '#555555'

    # Color gradient start for the tab indicator.
    c.colors.tabs.indicator.start = 'black'

    # Color gradient end for the tab indicator.
    c.colors.tabs.indicator.stop = 'black'

    # Color for the tab indicator on errors.
    c.colors.tabs.indicator.error = 'black'

    # Color gradient interpolation system for the tab indicator.
    c.colors.tabs.indicator.system = 'rgb'

    # Foreground color of unselected odd tabs.
    c.colors.tabs.odd.fg = 'black'

    # Background color of unselected odd tabs.
    c.colors.tabs.odd.bg = 'lightgrey'

    # Foreground color of unselected even tabs.
    c.colors.tabs.even.fg = 'black'

    # Background color of unselected even tabs.
    c.colors.tabs.even.bg = 'lightgrey'

    # Foreground color of selected odd tabs.
    c.colors.tabs.selected.odd.fg = 'black'

    # Background color of selected odd tabs.
    c.colors.tabs.selected.odd.bg = 'darkgrey'

    # Foreground color of selected even tabs.
    c.colors.tabs.selected.even.fg = 'black'

    # Background color of selected even tabs.
    c.colors.tabs.selected.even.bg = 'darkgrey'

Tabs are always at the top of the screen. Tabs are all lightgrey
unless they are selected, then they become darkgrey, regardless of
whether they are odd or even numbered. The foreground text is black
and the tab indicator is black. I didn’t like the gradient that
shows on the tab indicator when a tab is loading, so it just stays
black (c.colors.tabs.indicator.start, c.colors.tabs.indicator.stop).
The text in the tabs is centred and a bit bigger than the default
and each tab lists the number of the tab ({index}), the name of the
webpage ({title}) and the top level domain ({host}).

c.tabs.indicator.padding = {'bottom': 0, 'left': 0, 'right': 5, 'top': 0}
means that the tab indicator is positioned a minimum of 5 pixels
left of any text in the tab.

  {IMAGE}


Status bar

  {IMAGE}


The default status bar and completion bar are super ugly, with a
dark gradient background style which doesn’t really fit with the
colour scheme of the default tab bar. I want it to have a similar
colour style to my custom tab bar. These are the relevant lines from
the config.py:

    # Height (in pixels or as percentage of the window) of the completion.
    c.completion.height = '30%'

    # Padding (in pixels) for the statusbar.
    c.statusbar.padding = {'bottom': 5, 'left': 5, 'right': 5, 'top': 5}

    # Widgets in statusbar
    c.statusbar.widgets = ["keypress", "url", "scroll", "history", "tabs", "progress"]

    # Position of the status bar.
    c.statusbar.position = 'bottom'

    # Text color of the completion widget
    c.colors.completion.fg = 'black'

    # Background color of the completion widget for odd rows.
    c.colors.completion.odd.bg = '#F2F2F2'

    # Background color of the completion widget for even rows.
    c.colors.completion.even.bg = 'lightgrey'

    # Foreground color of completion widget category headers.
    c.colors.completion.category.fg = 'black'

    # Background color of the completion widget category headers.
    c.colors.completion.category.bg = 'lightgrey'

    # Foreground color of the selected completion item.
    c.colors.completion.item.selected.fg = 'black'

    # Background color of the selected completion item.
    c.colors.completion.item.selected.bg = 'darkgrey'

    # Top border color of the completion widget category headers.
    c.colors.completion.item.selected.border.top = 'black'

    # Bottom border color of the selected completion item.
    c.colors.completion.item.selected.border.bottom = 'black'

    # Foreground color of the matched text in the completion.
    c.colors.completion.match.fg = '#ff4444'

    # Color of the scrollbar handle in the completion view.
    c.colors.completion.scrollbar.fg = 'white'

    # Color of the scrollbar in the completion view.
    c.colors.completion.scrollbar.bg = 'darkgrey'

    # Foreground color of the statusbar.
    c.colors.statusbar.normal.fg = 'black'

    # Background color of the statusbar.
    c.colors.statusbar.normal.bg = 'darkgrey'

    # Background color of the statusbar in insert mode.
    c.colors.statusbar.insert.bg = '#039B9A'

    # Foreground color of the statusbar in private browsing mode.
    c.colors.statusbar.private.fg = 'black'

    # Foreground color of the statusbar in command mode.
    c.colors.statusbar.command.fg = 'black'

    # Background color of the statusbar in command mode.
    c.colors.statusbar.command.bg = 'darkgrey'

    # Default foreground color of the URL in the statusbar.
    c.colors.statusbar.url.fg = 'black'

    # Foreground color of the URL in the statusbar on error.
    c.colors.statusbar.url.error.fg = 'orange'

    # Foreground color of the URL in the statusbar for hovered links.
    c.colors.statusbar.url.hover.fg = 'blue'

    # Foreground color of the URL in the statusbar on successful load
    c.colors.statusbar.url.success.http.fg = 'black'

    # Foreground color of the URL in the statusbar on successful load
    c.colors.statusbar.url.success.https.fg = 'black'

    # Foreground color of the URL in the statusbar when there's a warning.
    c.colors.statusbar.url.warn.fg = 'black'

  {IMAGE}


The completion widget needs different colours for odd and even rows,
otherwise it’s difficult to discriminate between rows. So they
alternate between a very light grey for odd rows
(c.colors.completion.odd.bg = '#F2F2F2') and lightgrey for even
rows. The text is always black in the completion bar and the status
bar. Warnings on the status bar take their default colours of amber
and red. The completion bar headers are also light grey and the
selected completion item comes up as dark grey with a black border
on the top and bottom. As text is matched it becomes red. The
scrollbar is visible and follows the same colour pattern as the rest
of the setup.

When open, the completion box takes up 30% of the screen.

When you enter insert mode to enter text into a web page field, the
statusbar turns blue a la vim.

The statusbar has information on the current url (url), how far
through the file you are (scroll), what tab is visible (tabs) and
when a page is loading, the progress bar (progress).

  {IMAGE}


Fonts

The fonts are very simple, basically everything is either
monospace 8pt or monospace 9pt, e.g.

    # Font used in the completion widget.
    c.fonts.completion.entry = '8pt monospace'

Hints

Qutebrowser has this really nice hinting system, you press f and the
screen is filled with all the links you could click, you then type
the corresponding letter code and it follows that link. Normally the
hints look like this:

  {IMAGE}


The relevant bits of the config.py are:

    # CSS border value for hints.
    c.hints.border = '2px solid black'

    # Font color for hints.
    c.colors.hints.fg = 'white'

    # Background color for hints.
    c.colors.hints.bg = 'black'

    # Font color for the matched part of hints.
    c.colors.hints.match.fg = 'lime'

The hints are black with white text. Matched letters become lime
green.

  {IMAGE}


Key-bindings

I have a few keybindings that are different to the default setup,
mainly to make it feel more vim-like:

    # keybindings for normal mode
    config.bind('<backspace>', 'back')
    config.bind('gT', 'tab-prev')
    config.bind('gt', 'tab-next')
    config.bind('q', None)
    config.bind('qq', 'quit')
    config.bind('<Meta-R>', 'reload')
    config.bind('l', 'forward')
    config.bind('h', 'back')

Unbinding q is necessary so it doesn’t match anything when I’m
typing qq to quit.

The reload bind is because Cmd-r is so engrained in me for reloading
a page, from other web browsers, though I’m using it less and less

The full config.py can be found [here]

  [here]: https://johngodlee.github.io/files/qutebrowser/config.py