summaryrefslogtreecommitdiff
path: root/doc/help/configuring.asciidoc
blob: ad287b03045b42245f4dd91203f34ef6e37b199c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
Configuring qutebrowser
=======================

IMPORTANT: qutebrowser's configuration system was completely rewritten in
September 2017. This information is not applicable to older releases, and older
information elsewhere might be outdated.

qutebrowser's config files
--------------------------

qutebrowser releases before v1.0.0 had a `qutebrowser.conf` and `keys.conf`
file. Those are not used anymore since v1.0.0.

When using `:set` and `:bind`, changes are saved to an `autoconfig.yml` file
automatically. If you don't want to have a config file which is curated by
hand, you can simply use those - see
<<autoconfig,"Configuring qutebrowser via the user interface">> for details.

For more advanced configuration, you can write a `config.py` file - see
<<configpy,"Configuring qutebrowser via config.py">>. When a `config.py`
exists, the `autoconfig.yml` file **is not read anymore** by default. You need
to <<configpy-autoconfig,load it from `config.py`>> if you want settings changed via
`:set`/`:bind` to persist between restarts.

[[autoconfig]]
Configuring qutebrowser via the user interface
----------------------------------------------

The easy (but less flexible) way to configure qutebrowser is using its user
interface or command line. Changes you make this way are immediately active
(with the exception of a few settings, where this is pointed out in the
documentation) and are persisted in an `autoconfig.yml` file.

The `autoconfig.yml` file is located in the "config" folder listed on the
link:qute://version[] page. On macOS, the "auto config" folder is used, which is
different from where hand-written config files are kept.

However, **do not** edit `autoconfig.yml` by hand. Instead, see the next
section.

If you want to customize many settings, you can open the link:qute://settings[]
page by running `:set` without any arguments, where all settings are listed and
customizable.

Using the link:commands{outfilesuffix}#set[`:set`] command and command completion, you
can quickly set settings interactively, for example `:set tabs.position left`.

Some settings are also customizable for a given
https://developer.chrome.com/apps/match_patterns[URL pattern] by doing e.g.
`:set --pattern=*://example.com/ content.images false`.

To get more help about a setting, use e.g. `:help tabs.position`.

To bind and unbind keys, you can use the link:commands{outfilesuffix}#bind[`:bind`] and
link:commands{outfilesuffix}#unbind[`:unbind`] commands:

- Binding the key chain `,v` to the `:spawn mpv {url}` command:
  `:bind ,v spawn mpv {url}`
- Unbinding the same key chain: `:unbind ,v`

Key chains starting with a comma are ideal for custom bindings, as the comma key
will never be used in a default keybinding.

See the help pages linked above (or `:help :bind`, `:help :unbind`) for more
information.

Other useful commands for config manipulation are
link:commands{outfilesuffix}#config-unset[`:config-unset`] to reset a value to its default,
link:commands{outfilesuffix}#config-clear[`:config-clear`] to reset the entire configuration,
and link:commands{outfilesuffix}#config-cycle[`:config-cycle`] to cycle a setting between
different values.

[[configpy]]
Configuring qutebrowser via config.py
-------------------------------------

For more powerful configuration possibilities, you can create a `config.py`
file. Since it's a Python file, you have much more flexibility for
configuration. Note that qutebrowser will never touch this file - this means
you'll be responsible for updating it when upgrading to a newer qutebrowser
version.

You can run `:config-edit` inside qutebrowser to open the file in your editor,
`:config-source` to reload the file (`:config-edit` does this automatically), or
`:config-write-py --defaults` to write a template file to work with.

The file should be located in the "config" location listed on
link:qute://version[], which is typically `~/.config/qutebrowser/config.py` on
Linux, `~/.qutebrowser/config.py` on macOS, and
`%APPDATA%/qutebrowser/config/config.py` on Windows.

Two global objects are pre-defined when running `config.py`: `c` and `config`.

Changing settings
~~~~~~~~~~~~~~~~~

While you can set settings using the `config.set()` method (which is explained
in the next section), it's easier to use the `c` shorthand object to easily set
settings like this:

.config.py:
[source,python]
----
c.tabs.position = "left"
c.completion.shrink = True
----

Note that qutebrowser does some Python magic so it's able to warn you about
mistyped config settings. As an example, if you do `c.tabs.possition = "left"`,
you'll get an error when starting.

See the link:settings{outfilesuffix}[settings help page] for all available settings. The
accepted values depend on the type of the option. Commonly used are:

- Strings: `c.tabs.position = "left"`
- Booleans: `c.completion.shrink = True`
- Integers: `c.messages.timeout = 5000`
- Dictionaries:
  * `c.content.headers.custom = {'X-Hello': 'World', 'X-Awesome': 'yes'}` to override
    any other values in the dictionary.
  * `c.aliases['foo'] = 'message-info foo'` to add a single value.
- Lists:
  * `c.url.start_pages = ["https://www.qutebrowser.org/"]` to override any
    previous elements.
  * `c.url.start_pages.append("https://www.python.org/")` to add a new value.

Any other config types (e.g. a color) are specified as a string. The only
exception is the `Regex` type, which can take either a string (with an `r`
prefix to preserve backslashes) or a Python regex object:

- `c.hints.next_regexes.append(r'\bvor\b')`
- `c.hints.prev_regexes.append(re.compile(r'\bzurück\b'))`

If you want to read a setting, you can use the `c` object to do so as well:
`c.colors.tabs.even.bg = c.colors.tabs.odd.bg`.

Using strings for setting names
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you want to set settings based on their name as a string, use the
`config.set` method:

.config.py:
[source,python]
----
# Equivalent to:
# c.content.javascript.enabled = False
config.set('content.javascript.enabled', False)
----

To read a setting, use the `config.get` method:

[source,python]
----
# Equivalent to:
# color = c.colors.completion.fg
color = config.get('colors.completion.fg')
----

Per-domain settings
~~~~~~~~~~~~~~~~~~~

Using `config.set`, some settings are also customizable for a given
https://developer.chrome.com/apps/match_patterns[URL pattern]:

[source,python]
----
config.set('content.images', False, '*://example.com/')
----

Alternatively, you can use `with config.pattern(...) as p:` to get a shortcut
similar to `c.` which is scoped to the given domain:

[source,python]
----
with config.pattern('*://example.com/') as p:
    p.content.images = False
----

Binding keys
~~~~~~~~~~~~

While it's possible to change the `bindings.commands` setting to customize the keyboard shortcuts, it's
preferred to use the `config.bind` command. Doing so ensures the commands are
valid and normalizes different expressions which map to the same key.

For details on how to specify keys and the available modes, see the
link:settings{outfilesuffix}#bindings.commands[documentation] for the `bindings.commands`
setting.

To bind a key:

.config.py:
[source,python]
----
config.bind('<Ctrl-v>', 'spawn mpv {url}')
----

To bind a key in a mode other than `'normal'`, add a `mode` argument:

[source,python]
----
config.bind('<Ctrl-y>', 'prompt-yes', mode='prompt')
----

To unbind a key (either a key which has been bound before, or a default binding):

[source,python]
----
config.unbind('<Ctrl-v>', mode='normal')
----

To bind keys without modifiers, specify a key chain to bind as a string. Key
chains starting with a comma are ideal for custom bindings, as the comma key
will never be used in a default keybinding.

[source,python]
----
config.bind(',v', 'spawn mpv {url}')
----

To suppress loading of any default keybindings, you can set
`c.bindings.default = {}`.

[[configpy-autoconfig]]
Loading `autoconfig.yml`
~~~~~~~~~~~~~~~~~~~~~~~~

All customization done via the UI (`:set`, `:bind` and `:unbind`) is
stored in the `autoconfig.yml` file. When a `config.py` file exists, `autoconfig.yml`
is not loaded automatically. To load `autoconfig.yml` automatically, add the
following snippet to `config.py`:

[source,python]
----
config.load_autoconfig()
----

You can configure which file overrides the other by the location of the above code snippet.
Place the snippet at the top to allow `config.py` to override `autoconfig.yml`.
Place the snippet at the bottom for the opposite effect.

Importing other modules
~~~~~~~~~~~~~~~~~~~~~~~

You can import any module from the
https://docs.python.org/3/library/index.html[Python standard library] (e.g.
`import os.path`), as well as any module installed in the environment
qutebrowser is run with.

If you have an `utils.py` file in your qutebrowser config folder, you can import
that via `import utils` as well.

While it's in some cases possible to import code from the qutebrowser
installation, doing so is unsupported and discouraged.

To read config data from a different file with `c` and `config` available, you
can use `config.source('otherfile.py')` in your `config.py`.

Getting the config directory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you need to get the qutebrowser config directory, you can do so by reading
`config.configdir`. Similarly, you can get the qutebrowser data directory via
`config.datadir`.

This gives you a https://docs.python.org/3/library/pathlib.html[`pathlib.Path`
object], on which you can use `/` to add more directory parts, or `str(...)` to
get a string:

.config.py:
[source,python]
----
print(str(config.configdir / 'config.py'))
----

Handling errors
~~~~~~~~~~~~~~~

If there are errors in your `config.py`, qutebrowser will try to apply as much
of it as possible, and show an error dialog before starting.

qutebrowser tries to display errors which are easy to understand even for people
who are not used to writing Python. If you see a config error which you find
confusing or you think qutebrowser could handle better, please
https://github.com/qutebrowser/qutebrowser/issues[open an issue]!

Recipes
~~~~~~~

Reading a YAML file
^^^^^^^^^^^^^^^^^^^

To read a YAML config like this:

.config.yml:
----
tabs.position: left
tabs.show: switching
----

You can use:

.config.py:
[source,python]
----
import yaml

with (config.configdir / 'config.yml').open() as f:
    yaml_data = yaml.safe_load(f)

for k, v in yaml_data.items():
    config.set(k, v)
----

Reading a nested YAML file
^^^^^^^^^^^^^^^^^^^^^^^^^^

To read a YAML file with nested values like this:

.colors.yml:
----
colors:
  statusbar:
    normal:
      bg: lime
      fg: black
    url:
      fg: red
----

You can use:

.config.py:
[source,python]
----
import yaml

with (config.configdir / 'colors.yml').open() as f:
    yaml_data = yaml.safe_load(f)

def dict_attrs(obj, path=''):
    if isinstance(obj, dict):
        for k, v in obj.items():
            yield from dict_attrs(v, '{}.{}'.format(path, k) if path else k)
    else:
        yield path, obj

for k, v in dict_attrs(yaml_data):
    config.set(k, v)
----

Note that this won't work for values which are dictionaries.

Binding chained commands
^^^^^^^^^^^^^^^^^^^^^^^^

If you have a lot of chained commands you want to bind, you can write a helper
to do so:

[source,python]
----
def bind_chained(key, *commands):
    config.bind(key, ' ;; '.join(commands))

bind_chained('<Escape>', 'clear-keychain', 'search')
----

Reading colors from Xresources
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You can use something like this to read colors from an `~/.Xresources` file:

[source,python]
----
import subprocess

def read_xresources(prefix):
    props = {}
    x = subprocess.run(['xrdb', '-query'], stdout=subprocess.PIPE)
    lines = x.stdout.decode().split('\n')
    for line in filter(lambda l : l.startswith(prefix), lines):
        prop, _, value = line.partition(':\t')
        props[prop] = value
    return props

xresources = read_xresources('*')
c.colors.statusbar.normal.bg = xresources['*.background']
----

Pre-built colorschemes
^^^^^^^^^^^^^^^^^^^^^^

- A collection of https://github.com/chriskempson/base16[base16] color-schemes can be found in https://github.com/theova/base16-qutebrowser[base16-qutebrowser] and used with https://github.com/AuditeMarlow/base16-manager[base16-manager].
- https://gitlab.com/jjzmajic/qutewal[Pywal integration]
- https://github.com/arcticicestudio/nord[Nord]: https://github.com/Linuus/nord-qutebrowser[Linuus], https://github.com/KnownAsDon/QuteBrowser-Nord-Theme[KnownAsDon]
- https://github.com/dracula/qutebrowser-dracula-theme[Dracula]
- https://gitlab.com/lovetocode999/selenized-qutebrowser[Selenized]
- https://github.com/morhetz/gruvbox[gruvbox]: https://github.com/The-Compiler/dotfiles/blob/master/qutebrowser/gruvbox.py[The-Compiler], https://gitlab.com/shaneyost/dots-popos-september-2020/-/blob/master/qutebrowser/config.py[Shane Yost]

Avoiding flake8 errors
^^^^^^^^^^^^^^^^^^^^^^

If you use an editor with flake8 and pylint integration, it may have some
complaints about invalid names, undefined variables, or missing docstrings.
You can silence those with:

[source,python]
----
# pylint: disable=C0111
c = c  # noqa: F821 pylint: disable=E0602,C0103
config = config  # noqa: F821 pylint: disable=E0602,C0103
----

For type annotation support (note that those imports aren't guaranteed to be
stable across qutebrowser versions):

[source,python]
----
# pylint: disable=C0111
from qutebrowser.config.configfiles import ConfigAPI  # noqa: F401
from qutebrowser.config.config import ConfigContainer  # noqa: F401
config: ConfigAPI = config  # noqa: F821 pylint: disable=E0602,C0103
c: ConfigContainer = c  # noqa: F821 pylint: disable=E0602,C0103
----

emacs-like config
^^^^^^^^^^^^^^^^^

Various emacs/conkeror-like keybinding configs exist:

- https://gitlab.com/jgkamat/qutemacs/blob/master/qutemacs.py[jgkamat]
- https://gitlab.com/Kaligule/qutebrowser-emacs-config/blob/master/config.py[Kaligule]
- https://me0w.net/pit/1540882719[nm0i]
- https://www.reddit.com/r/qutebrowser/comments/eh10i7/config_share_qute_with_emacs_keybindings/[jasonsun0310]

It's also mostly possible to get rid of modal keybindings by setting
`input.insert_mode.auto_enter` to `false`, and `input.forward_unbound_keys` to
`all`.