Merge branch 'config-write-py'
This commit is contained in:
commit
618586f8b0
@ -67,6 +67,7 @@ Added
|
|||||||
- `:config-clear` to remove all configured options
|
- `:config-clear` to remove all configured options
|
||||||
- `:config-source` to (re-)read a `config.py` file
|
- `:config-source` to (re-)read a `config.py` file
|
||||||
- `:config-edit` to open the `config.py` file in an editor
|
- `:config-edit` to open the `config.py` file in an editor
|
||||||
|
- `:config-write-py` to write a `config.py` template file
|
||||||
- New `:version` command which opens `qute://version`.
|
- New `:version` command which opens `qute://version`.
|
||||||
|
|
||||||
Changed
|
Changed
|
||||||
|
@ -36,6 +36,7 @@ It is possible to run or bind multiple commands by separating them with `;;`.
|
|||||||
|<<config-edit,config-edit>>|Open the config.py file in the editor.
|
|<<config-edit,config-edit>>|Open the config.py file in the editor.
|
||||||
|<<config-source,config-source>>|Read a config.py file.
|
|<<config-source,config-source>>|Read a config.py file.
|
||||||
|<<config-unset,config-unset>>|Unset an option.
|
|<<config-unset,config-unset>>|Unset an option.
|
||||||
|
|<<config-write-py,config-write-py>>|Write the current configuration to a config.py file.
|
||||||
|<<download,download>>|Download a given URL, or current page if no URL given.
|
|<<download,download>>|Download a given URL, or current page if no URL given.
|
||||||
|<<download-cancel,download-cancel>>|Cancel the last/[count]th download.
|
|<<download-cancel,download-cancel>>|Cancel the last/[count]th download.
|
||||||
|<<download-clear,download-clear>>|Remove all finished downloads from the list.
|
|<<download-clear,download-clear>>|Remove all finished downloads from the list.
|
||||||
@ -266,6 +267,19 @@ This sets an option back to its default and removes it from autoconfig.yml.
|
|||||||
==== optional arguments
|
==== optional arguments
|
||||||
* +*-t*+, +*--temp*+: Don't touch autoconfig.yml.
|
* +*-t*+, +*--temp*+: Don't touch autoconfig.yml.
|
||||||
|
|
||||||
|
[[config-write-py]]
|
||||||
|
=== config-write-py
|
||||||
|
Syntax: +:config-write-py [*--force*] [*--defaults*] ['filename']+
|
||||||
|
|
||||||
|
Write the current configuration to a config.py file.
|
||||||
|
|
||||||
|
==== positional arguments
|
||||||
|
* +'filename'+: The file to write to, or not given for the default config.py.
|
||||||
|
|
||||||
|
==== optional arguments
|
||||||
|
* +*-f*+, +*--force*+: Force overwriting existing files.
|
||||||
|
* +*-d*+, +*--defaults*+: Write the defaults instead of values configured via :set.
|
||||||
|
|
||||||
[[download]]
|
[[download]]
|
||||||
=== download
|
=== download
|
||||||
Syntax: +:download [*--mhtml*] [*--dest* 'dest'] ['url'] ['dest-old']+
|
Syntax: +:download [*--mhtml*] [*--dest* 'dest'] ['url'] ['dest-old']+
|
||||||
|
@ -68,6 +68,12 @@ will never be used in a default keybinding.
|
|||||||
See the help pages linked above (or `:help :bind`, `:help :unbind`) for more
|
See the help pages linked above (or `:help :bind`, `:help :unbind`) for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
|
Other useful commands for config manipulation are
|
||||||
|
link:commands.html#config-unset[`:config-unset`] to reset a value to its default,
|
||||||
|
link:commands.html#config-clear[`:config-clear`] to reset the entire configuration,
|
||||||
|
and link:commands.html#config-cycle[`:config-cycle`] to cycle a setting between
|
||||||
|
different values.
|
||||||
|
|
||||||
Configuring qutebrowser via config.py
|
Configuring qutebrowser via config.py
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
@ -77,6 +83,10 @@ configuration. Note that qutebrowser will never touch this file - this means
|
|||||||
you'll be responsible for updating it when upgrading to a newer qutebrowser
|
you'll be responsible for updating it when upgrading to a newer qutebrowser
|
||||||
version.
|
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
|
The file should be located in the "config" location listed on
|
||||||
link:qute://version[], which is typically `~/.config/qutebrowser/config.py` on
|
link:qute://version[], which is typically `~/.config/qutebrowser/config.py` on
|
||||||
Linux, `~/.qutebrowser/config.py` on macOS, and
|
Linux, `~/.qutebrowser/config.py` on macOS, and
|
||||||
|
@ -280,11 +280,6 @@ Always restore open sites when qutebrowser is reopened.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[backend]]
|
[[backend]]
|
||||||
@ -1304,11 +1299,6 @@ Move on to the next part when there's only one possible completion left.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[completion.scrollbar.padding]]
|
[[completion.scrollbar.padding]]
|
||||||
@ -1347,11 +1337,6 @@ Shrink the completion to be smaller than the configured size if there are no scr
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[completion.timestamp_format]]
|
[[completion.timestamp_format]]
|
||||||
@ -1395,11 +1380,6 @@ An application cache acts like an HTTP cache in some sense. For documents that u
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
This setting is only available with the QtWebKit backend.
|
This setting is only available with the QtWebKit backend.
|
||||||
@ -1448,11 +1428,6 @@ Note this option needs a restart with QtWebEngine on Qt < 5.9.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.default_encoding]]
|
[[content.default_encoding]]
|
||||||
@ -1471,11 +1446,6 @@ This needs to be enabled for `:inspector` to work and also adds an _Inspect_ ent
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
This setting is only available with the QtWebKit backend.
|
This setting is only available with the QtWebKit backend.
|
||||||
@ -1486,11 +1456,6 @@ Try to pre-fetch DNS entries to speed up browsing.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
This setting is only available with the QtWebKit backend.
|
This setting is only available with the QtWebKit backend.
|
||||||
@ -1502,11 +1467,6 @@ This will flatten all the frames to become one scrollable page.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
This setting is only available with the QtWebKit backend.
|
This setting is only available with the QtWebKit backend.
|
||||||
@ -1548,11 +1508,6 @@ When this is set to true, qutebrowser asks websites to not track your identity.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.headers.referer]]
|
[[content.headers.referer]]
|
||||||
@ -1586,11 +1541,6 @@ Whether host blocking is enabled.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.host_blocking.lists]]
|
[[content.host_blocking.lists]]
|
||||||
@ -1633,11 +1583,6 @@ Enable or disable hyperlink auditing (`<a ping>`).
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[content.images]]
|
[[content.images]]
|
||||||
@ -1646,11 +1591,6 @@ Whether images are automatically loaded in web pages.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.javascript.alert]]
|
[[content.javascript.alert]]
|
||||||
@ -1659,11 +1599,6 @@ Show javascript alerts.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.javascript.can_access_clipboard]]
|
[[content.javascript.can_access_clipboard]]
|
||||||
@ -1673,11 +1608,6 @@ With QtWebEngine, writing the clipboard as response to a user interaction is alw
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[content.javascript.can_close_tabs]]
|
[[content.javascript.can_close_tabs]]
|
||||||
@ -1686,11 +1616,6 @@ Whether JavaScript can close tabs.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
This setting is only available with the QtWebKit backend.
|
This setting is only available with the QtWebKit backend.
|
||||||
@ -1701,11 +1626,6 @@ Whether JavaScript can open new tabs without user interaction.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[content.javascript.enabled]]
|
[[content.javascript.enabled]]
|
||||||
@ -1714,11 +1634,6 @@ Enables or disables JavaScript.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.javascript.log]]
|
[[content.javascript.log]]
|
||||||
@ -1742,11 +1657,6 @@ Use the standard JavaScript modal dialog for `alert()` and `confirm()`
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[content.javascript.prompt]]
|
[[content.javascript.prompt]]
|
||||||
@ -1755,11 +1665,6 @@ Show javascript prompts.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.local_content_can_access_file_urls]]
|
[[content.local_content_can_access_file_urls]]
|
||||||
@ -1768,11 +1673,6 @@ Whether locally loaded documents are allowed to access other local urls.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.local_content_can_access_remote_urls]]
|
[[content.local_content_can_access_remote_urls]]
|
||||||
@ -1781,11 +1681,6 @@ Whether locally loaded documents are allowed to access remote urls.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[content.local_storage]]
|
[[content.local_storage]]
|
||||||
@ -1794,11 +1689,6 @@ Whether support for HTML 5 local storage and Web SQL is enabled.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.media_capture]]
|
[[content.media_capture]]
|
||||||
@ -1847,11 +1737,6 @@ Note that the files can still be downloaded by clicking the download button in t
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
This setting is only available with the QtWebKit backend.
|
This setting is only available with the QtWebKit backend.
|
||||||
@ -1862,11 +1747,6 @@ Enables or disables plugins in Web pages.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[content.print_element_backgrounds]]
|
[[content.print_element_backgrounds]]
|
||||||
@ -1875,11 +1755,6 @@ Whether the background color and images are also drawn when the page is printed.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
On QtWebEngine, this setting requires Qt 5.8 or newer.
|
On QtWebEngine, this setting requires Qt 5.8 or newer.
|
||||||
@ -1890,11 +1765,6 @@ Open new windows in private browsing mode which does not record visited pages.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[content.proxy]]
|
[[content.proxy]]
|
||||||
@ -1917,11 +1787,6 @@ Send DNS requests over the configured proxy.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
This setting is only available with the QtWebKit backend.
|
This setting is only available with the QtWebKit backend.
|
||||||
@ -1954,11 +1819,6 @@ Enables or disables WebGL.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[content.xss_auditing]]
|
[[content.xss_auditing]]
|
||||||
@ -1968,11 +1828,6 @@ Suspicious scripts will be blocked and reported in the inspector's JavaScript co
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[downloads.location.directory]]
|
[[downloads.location.directory]]
|
||||||
@ -1991,11 +1846,6 @@ If set to false, `downloads.location.directory` will be used.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[downloads.location.remember]]
|
[[downloads.location.remember]]
|
||||||
@ -2004,11 +1854,6 @@ Remember the last used download directory.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[downloads.location.suggestion]]
|
[[downloads.location.suggestion]]
|
||||||
@ -2270,11 +2115,6 @@ This is needed for QtWebEngine to work with Nouveau drivers. This setting requir
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
This setting is only available with the QtWebEngine backend.
|
This setting is only available with the QtWebEngine backend.
|
||||||
@ -2347,11 +2187,6 @@ Hide unmatched hints in rapid mode.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[hints.min_chars]]
|
[[hints.min_chars]]
|
||||||
@ -2412,11 +2247,6 @@ Ignored for number hints.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[hints.uppercase]]
|
[[hints.uppercase]]
|
||||||
@ -2425,11 +2255,6 @@ Make chars in hint strings uppercase.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[history_gap_interval]]
|
[[history_gap_interval]]
|
||||||
@ -2475,11 +2300,6 @@ Leave insert mode if a non-editable element is clicked.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[input.insert_mode.auto_load]]
|
[[input.insert_mode.auto_load]]
|
||||||
@ -2488,11 +2308,6 @@ Automatically enter insert mode if an editable element is focused after loading
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[input.insert_mode.plugins]]
|
[[input.insert_mode.plugins]]
|
||||||
@ -2501,11 +2316,6 @@ Switch to insert mode when clicking flash and other plugins.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[input.links_included_in_focus_chain]]
|
[[input.links_included_in_focus_chain]]
|
||||||
@ -2514,11 +2324,6 @@ Include hyperlinks in the keyboard focus chain when tabbing.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[input.partial_timeout]]
|
[[input.partial_timeout]]
|
||||||
@ -2537,11 +2342,6 @@ This disables the context menu.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[input.spatial_navigation]]
|
[[input.spatial_navigation]]
|
||||||
@ -2551,11 +2351,6 @@ Spatial navigation consists in the ability to navigate between focusable element
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[keyhint.blacklist]]
|
[[keyhint.blacklist]]
|
||||||
@ -2590,11 +2385,6 @@ Show messages in unfocused windows.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[new_instance_open_target]]
|
[[new_instance_open_target]]
|
||||||
@ -2637,11 +2427,6 @@ Show a filebrowser in upload/download prompts.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[prompt.radius]]
|
[[prompt.radius]]
|
||||||
@ -2668,11 +2453,6 @@ Show a scrollbar.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[scrolling.smooth]]
|
[[scrolling.smooth]]
|
||||||
@ -2682,11 +2462,6 @@ Note smooth scrolling does not work with the `:scroll-px` command.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[session_default_name]]
|
[[session_default_name]]
|
||||||
@ -2704,11 +2479,6 @@ Hide the statusbar unless a message is shown.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[statusbar.padding]]
|
[[statusbar.padding]]
|
||||||
@ -2743,11 +2513,6 @@ Open new tabs (middleclick/ctrl+click) in the background.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[tabs.close_mouse_button]]
|
[[tabs.close_mouse_button]]
|
||||||
@ -2779,11 +2544,6 @@ Show favicons in the tab bar.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[tabs.indicator_padding]]
|
[[tabs.indicator_padding]]
|
||||||
@ -2821,11 +2581,6 @@ Switch between tabs using the mouse wheel.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[tabs.new_position.related]]
|
[[tabs.new_position.related]]
|
||||||
@ -2929,11 +2684,6 @@ Open a new window for every tab.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[tabs.title.alignment]]
|
[[tabs.title.alignment]]
|
||||||
@ -3001,11 +2751,6 @@ Whether to wrap when changing tabs.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[true]+
|
Default: +pass:[true]+
|
||||||
|
|
||||||
[[url.auto_search]]
|
[[url.auto_search]]
|
||||||
@ -3090,11 +2835,6 @@ Hide the window decoration when using wayland (requires restart)
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
[[window.title_format]]
|
[[window.title_format]]
|
||||||
@ -3164,11 +2904,6 @@ Whether the zoom factor on a frame applies only to the text or to all content.
|
|||||||
|
|
||||||
Type: <<types,Bool>>
|
Type: <<types,Bool>>
|
||||||
|
|
||||||
Valid values:
|
|
||||||
|
|
||||||
* +true+
|
|
||||||
* +false+
|
|
||||||
|
|
||||||
Default: +pass:[false]+
|
Default: +pass:[false]+
|
||||||
|
|
||||||
This setting is only available with the QtWebKit backend.
|
This setting is only available with the QtWebKit backend.
|
||||||
|
@ -223,6 +223,11 @@ class Config(QObject):
|
|||||||
self._mutables = {}
|
self._mutables = {}
|
||||||
self._yaml = yaml_config
|
self._yaml = yaml_config
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
"""Iterate over Option, value tuples."""
|
||||||
|
for name, value in sorted(self._values.items()):
|
||||||
|
yield (self.get_opt(name), value)
|
||||||
|
|
||||||
def init_save_manager(self, save_manager):
|
def init_save_manager(self, save_manager):
|
||||||
"""Make sure the config gets saved properly.
|
"""Make sure the config gets saved properly.
|
||||||
|
|
||||||
@ -365,10 +370,9 @@ class Config(QObject):
|
|||||||
The changed config part as string.
|
The changed config part as string.
|
||||||
"""
|
"""
|
||||||
lines = []
|
lines = []
|
||||||
for optname, value in sorted(self._values.items()):
|
for opt, value in self:
|
||||||
opt = self.get_opt(optname)
|
|
||||||
str_value = opt.typ.to_str(value)
|
str_value = opt.typ.to_str(value)
|
||||||
lines.append('{} = {}'.format(optname, str_value))
|
lines.append('{} = {}'.format(opt.name, str_value))
|
||||||
if not lines:
|
if not lines:
|
||||||
lines = ['<Default configuration>']
|
lines = ['<Default configuration>']
|
||||||
return '\n'.join(lines)
|
return '\n'.join(lines)
|
||||||
|
@ -27,7 +27,7 @@ from PyQt5.QtCore import QUrl
|
|||||||
from qutebrowser.commands import cmdexc, cmdutils
|
from qutebrowser.commands import cmdexc, cmdutils
|
||||||
from qutebrowser.completion.models import configmodel
|
from qutebrowser.completion.models import configmodel
|
||||||
from qutebrowser.utils import objreg, utils, message, standarddir
|
from qutebrowser.utils import objreg, utils, message, standarddir
|
||||||
from qutebrowser.config import configtypes, configexc, configfiles
|
from qutebrowser.config import configtypes, configexc, configfiles, configdata
|
||||||
from qutebrowser.misc import editor
|
from qutebrowser.misc import editor
|
||||||
|
|
||||||
|
|
||||||
@ -246,3 +246,35 @@ class ConfigCommands:
|
|||||||
|
|
||||||
filename = os.path.join(standarddir.config(), 'config.py')
|
filename = os.path.join(standarddir.config(), 'config.py')
|
||||||
ed.edit_file(filename)
|
ed.edit_file(filename)
|
||||||
|
|
||||||
|
@cmdutils.register(instance='config-commands')
|
||||||
|
def config_write_py(self, filename=None, force=False, defaults=False):
|
||||||
|
"""Write the current configuration to a config.py file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename: The file to write to, or None for the default config.py.
|
||||||
|
force: Force overwriting existing files.
|
||||||
|
defaults: Write the defaults instead of values configured via :set.
|
||||||
|
"""
|
||||||
|
if filename is None:
|
||||||
|
filename = os.path.join(standarddir.config(), 'config.py')
|
||||||
|
else:
|
||||||
|
filename = os.path.expanduser(filename)
|
||||||
|
|
||||||
|
if os.path.exists(filename) and not force:
|
||||||
|
raise cmdexc.CommandError("{} already exists - use --force to "
|
||||||
|
"overwrite!".format(filename))
|
||||||
|
|
||||||
|
if defaults:
|
||||||
|
options = [(opt, opt.default)
|
||||||
|
for _name, opt in sorted(configdata.DATA.items())]
|
||||||
|
bindings = dict(configdata.DATA['bindings.default'].default)
|
||||||
|
commented = True
|
||||||
|
else:
|
||||||
|
options = list(self._config)
|
||||||
|
bindings = dict(self._config.get_obj('bindings.commands'))
|
||||||
|
commented = False
|
||||||
|
|
||||||
|
writer = configfiles.ConfigPyWriter(options, bindings,
|
||||||
|
commented=commented)
|
||||||
|
writer.write(filename)
|
||||||
|
@ -245,6 +245,101 @@ class ConfigAPI:
|
|||||||
self._keyconfig.unbind(key, mode=mode)
|
self._keyconfig.unbind(key, mode=mode)
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigPyWriter:
|
||||||
|
|
||||||
|
"""Writer for config.py files from given settings."""
|
||||||
|
|
||||||
|
def __init__(self, options, bindings, *, commented):
|
||||||
|
self._options = options
|
||||||
|
self._bindings = bindings
|
||||||
|
self._commented = commented
|
||||||
|
|
||||||
|
def write(self, filename):
|
||||||
|
"""Write the config to the given file."""
|
||||||
|
with open(filename, 'w', encoding='utf-8') as f:
|
||||||
|
f.write('\n'.join(self._gen_lines()))
|
||||||
|
|
||||||
|
def _line(self, line):
|
||||||
|
"""Get an (optionally commented) line."""
|
||||||
|
if self._commented:
|
||||||
|
if line.startswith('#'):
|
||||||
|
return '#' + line
|
||||||
|
else:
|
||||||
|
return '# ' + line
|
||||||
|
else:
|
||||||
|
return line
|
||||||
|
|
||||||
|
def _gen_lines(self):
|
||||||
|
"""Generate a config.py with the given settings/bindings.
|
||||||
|
|
||||||
|
Yields individual lines.
|
||||||
|
"""
|
||||||
|
yield from self._gen_header()
|
||||||
|
yield from self._gen_options()
|
||||||
|
yield from self._gen_bindings()
|
||||||
|
|
||||||
|
def _gen_header(self):
|
||||||
|
"""Generate the initial header of the config."""
|
||||||
|
yield self._line("# Autogenerated config.py")
|
||||||
|
yield self._line("# Documentation:")
|
||||||
|
yield self._line("# qute://help/configuring.html")
|
||||||
|
yield self._line("# qute://help/settings.html")
|
||||||
|
yield ''
|
||||||
|
if self._commented:
|
||||||
|
# When generated from an autoconfig.yml with commented=False,
|
||||||
|
# we don't want to load that autoconfig.yml anymore.
|
||||||
|
yield self._line("# This is here so configs done via the GUI are "
|
||||||
|
"still loaded.")
|
||||||
|
yield self._line("# Remove it to not load settings done via the "
|
||||||
|
"GUI.")
|
||||||
|
yield self._line("config.load_autoconfig()")
|
||||||
|
yield ''
|
||||||
|
else:
|
||||||
|
yield self._line("# Uncomment this to still load settings "
|
||||||
|
"configured via autoconfig.yml")
|
||||||
|
yield self._line("# config.load_autoconfig()")
|
||||||
|
yield ''
|
||||||
|
|
||||||
|
def _gen_options(self):
|
||||||
|
"""Generate the options part of the config."""
|
||||||
|
for opt, value in self._options:
|
||||||
|
if opt.name in ['bindings.commands', 'bindings.default']:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for line in textwrap.wrap(opt.description):
|
||||||
|
yield self._line("# {}".format(line))
|
||||||
|
|
||||||
|
yield self._line("# Type: {}".format(opt.typ.get_name()))
|
||||||
|
|
||||||
|
valid_values = opt.typ.get_valid_values()
|
||||||
|
if valid_values is not None and valid_values.generate_docs:
|
||||||
|
yield self._line("# Valid values:")
|
||||||
|
for val in valid_values:
|
||||||
|
try:
|
||||||
|
desc = valid_values.descriptions[val]
|
||||||
|
yield self._line("# - {}: {}".format(val, desc))
|
||||||
|
except KeyError:
|
||||||
|
yield self._line("# - {}".format(val))
|
||||||
|
|
||||||
|
yield self._line('c.{} = {!r}'.format(opt.name, value))
|
||||||
|
yield ''
|
||||||
|
|
||||||
|
def _gen_bindings(self):
|
||||||
|
"""Generate the bindings part of the config."""
|
||||||
|
normal_bindings = self._bindings.pop('normal', {})
|
||||||
|
if normal_bindings:
|
||||||
|
yield self._line('# Bindings for normal mode')
|
||||||
|
for key, command in sorted(normal_bindings.items()):
|
||||||
|
yield self._line('config.bind({!r}, {!r})'.format(key, command))
|
||||||
|
|
||||||
|
for mode, mode_bindings in sorted(self._bindings.items()):
|
||||||
|
yield ''
|
||||||
|
yield self._line('# Bindings for {} mode'.format(mode))
|
||||||
|
for key, command in sorted(mode_bindings.items()):
|
||||||
|
yield self._line('config.bind({!r}, {!r}, mode={!r})'.format(
|
||||||
|
key, command, mode))
|
||||||
|
|
||||||
|
|
||||||
def read_config_py(filename, raising=False):
|
def read_config_py(filename, raising=False):
|
||||||
"""Read a config.py file.
|
"""Read a config.py file.
|
||||||
|
|
||||||
@ -253,6 +348,9 @@ def read_config_py(filename, raising=False):
|
|||||||
raising: Raise exceptions happening in config.py.
|
raising: Raise exceptions happening in config.py.
|
||||||
This is needed during tests to use pytest's inspection.
|
This is needed during tests to use pytest's inspection.
|
||||||
"""
|
"""
|
||||||
|
assert config.instance is not None
|
||||||
|
assert config.key_instance is not None
|
||||||
|
|
||||||
api = ConfigAPI(config.instance, config.key_instance)
|
api = ConfigAPI(config.instance, config.key_instance)
|
||||||
container = config.ConfigContainer(config.instance, configapi=api)
|
container = config.ConfigContainer(config.instance, configapi=api)
|
||||||
basename = os.path.basename(filename)
|
basename = os.path.basename(filename)
|
||||||
|
@ -78,13 +78,15 @@ class ValidValues:
|
|||||||
Attributes:
|
Attributes:
|
||||||
values: A list with the allowed untransformed values.
|
values: A list with the allowed untransformed values.
|
||||||
descriptions: A dict with value/desc mappings.
|
descriptions: A dict with value/desc mappings.
|
||||||
|
generate_docs: Whether to show the values in the docs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *values):
|
def __init__(self, *values, generate_docs=True):
|
||||||
if not values:
|
if not values:
|
||||||
raise ValueError("ValidValues with no values makes no sense!")
|
raise ValueError("ValidValues with no values makes no sense!")
|
||||||
self.descriptions = {}
|
self.descriptions = {}
|
||||||
self.values = []
|
self.values = []
|
||||||
|
self.generate_docs = generate_docs
|
||||||
for value in values:
|
for value in values:
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
# Value without description
|
# Value without description
|
||||||
@ -608,7 +610,7 @@ class Bool(BaseType):
|
|||||||
|
|
||||||
def __init__(self, none_ok=False):
|
def __init__(self, none_ok=False):
|
||||||
super().__init__(none_ok)
|
super().__init__(none_ok)
|
||||||
self.valid_values = ValidValues('true', 'false')
|
self.valid_values = ValidValues('true', 'false', generate_docs=False)
|
||||||
|
|
||||||
def to_py(self, value):
|
def to_py(self, value):
|
||||||
self._basic_py_validation(value, bool)
|
self._basic_py_validation(value, bool)
|
||||||
|
@ -421,7 +421,7 @@ def _generate_setting_option(f, opt):
|
|||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
valid_values = opt.typ.get_valid_values()
|
valid_values = opt.typ.get_valid_values()
|
||||||
if valid_values is not None:
|
if valid_values is not None and valid_values.generate_docs:
|
||||||
f.write("Valid values:\n")
|
f.write("Valid values:\n")
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
for val in valid_values:
|
for val in valid_values:
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
|
||||||
# Copyright 2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
|
||||||
|
|
||||||
# This file is part of qutebrowser.
|
|
||||||
#
|
|
||||||
# qutebrowser is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# qutebrowser is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
"""Fixtures needed in various config test files."""
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from qutebrowser.config import config
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def keyconf(config_stub):
|
|
||||||
config_stub.val.aliases = {}
|
|
||||||
return config.KeyConfig(config_stub)
|
|
@ -93,11 +93,6 @@ class TestChangeFilter:
|
|||||||
|
|
||||||
class TestKeyConfig:
|
class TestKeyConfig:
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def keyconf(self, config_stub):
|
|
||||||
config_stub.val.aliases = {}
|
|
||||||
return config.KeyConfig(config_stub)
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def no_bindings(self):
|
def no_bindings(self):
|
||||||
"""Get a dict with no bindings."""
|
"""Get a dict with no bindings."""
|
||||||
@ -107,14 +102,14 @@ class TestKeyConfig:
|
|||||||
('A', 'A'),
|
('A', 'A'),
|
||||||
('<Ctrl-X>', '<ctrl+x>'),
|
('<Ctrl-X>', '<ctrl+x>'),
|
||||||
])
|
])
|
||||||
def test_prepare_valid(self, keyconf, key, expected):
|
def test_prepare_valid(self, key_config_stub, key, expected):
|
||||||
"""Make sure prepare normalizes the key."""
|
"""Make sure prepare normalizes the key."""
|
||||||
assert keyconf._prepare(key, 'normal') == expected
|
assert key_config_stub._prepare(key, 'normal') == expected
|
||||||
|
|
||||||
def test_prepare_invalid(self, keyconf):
|
def test_prepare_invalid(self, key_config_stub):
|
||||||
"""Make sure prepare checks the mode."""
|
"""Make sure prepare checks the mode."""
|
||||||
with pytest.raises(configexc.KeybindingError):
|
with pytest.raises(configexc.KeybindingError):
|
||||||
assert keyconf._prepare('x', 'abnormal')
|
assert key_config_stub._prepare('x', 'abnormal')
|
||||||
|
|
||||||
@pytest.mark.parametrize('commands, expected', [
|
@pytest.mark.parametrize('commands, expected', [
|
||||||
# Unbinding default key
|
# Unbinding default key
|
||||||
@ -126,7 +121,8 @@ class TestKeyConfig:
|
|||||||
# Unbinding unknown key
|
# Unbinding unknown key
|
||||||
({'x': None}, {'a': 'message-info foo', 'b': 'message-info bar'}),
|
({'x': None}, {'a': 'message-info foo', 'b': 'message-info bar'}),
|
||||||
])
|
])
|
||||||
def test_get_bindings_for_and_get_command(self, keyconf, config_stub,
|
def test_get_bindings_for_and_get_command(self, key_config_stub,
|
||||||
|
config_stub,
|
||||||
commands, expected):
|
commands, expected):
|
||||||
orig_default_bindings = {'normal': {'a': 'message-info foo',
|
orig_default_bindings = {'normal': {'a': 'message-info foo',
|
||||||
'b': 'message-info bar'},
|
'b': 'message-info bar'},
|
||||||
@ -139,18 +135,19 @@ class TestKeyConfig:
|
|||||||
'register': {}}
|
'register': {}}
|
||||||
config_stub.val.bindings.default = copy.deepcopy(orig_default_bindings)
|
config_stub.val.bindings.default = copy.deepcopy(orig_default_bindings)
|
||||||
config_stub.val.bindings.commands = {'normal': commands}
|
config_stub.val.bindings.commands = {'normal': commands}
|
||||||
bindings = keyconf.get_bindings_for('normal')
|
bindings = key_config_stub.get_bindings_for('normal')
|
||||||
|
|
||||||
# Make sure the code creates a copy and doesn't modify the setting
|
# Make sure the code creates a copy and doesn't modify the setting
|
||||||
assert config_stub.val.bindings.default == orig_default_bindings
|
assert config_stub.val.bindings.default == orig_default_bindings
|
||||||
assert bindings == expected
|
assert bindings == expected
|
||||||
for key, command in expected.items():
|
for key, command in expected.items():
|
||||||
assert keyconf.get_command(key, 'normal') == command
|
assert key_config_stub.get_command(key, 'normal') == command
|
||||||
|
|
||||||
def test_get_command_unbound(self, keyconf, config_stub, no_bindings):
|
def test_get_command_unbound(self, key_config_stub, config_stub,
|
||||||
|
no_bindings):
|
||||||
config_stub.val.bindings.default = no_bindings
|
config_stub.val.bindings.default = no_bindings
|
||||||
config_stub.val.bindings.commands = no_bindings
|
config_stub.val.bindings.commands = no_bindings
|
||||||
assert keyconf.get_command('foobar', 'normal') is None
|
assert key_config_stub.get_command('foobar', 'normal') is None
|
||||||
|
|
||||||
@pytest.mark.parametrize('bindings, expected', [
|
@pytest.mark.parametrize('bindings, expected', [
|
||||||
# Simple
|
# Simple
|
||||||
@ -166,46 +163,47 @@ class TestKeyConfig:
|
|||||||
({'a': 'message-info foo ;; message-info bar'},
|
({'a': 'message-info foo ;; message-info bar'},
|
||||||
{'message-info foo': ['a'], 'message-info bar': ['a']}),
|
{'message-info foo': ['a'], 'message-info bar': ['a']}),
|
||||||
])
|
])
|
||||||
def test_get_reverse_bindings_for(self, keyconf, config_stub, no_bindings,
|
def test_get_reverse_bindings_for(self, key_config_stub, config_stub,
|
||||||
bindings, expected):
|
no_bindings, bindings, expected):
|
||||||
config_stub.val.bindings.default = no_bindings
|
config_stub.val.bindings.default = no_bindings
|
||||||
config_stub.val.bindings.commands = {'normal': bindings}
|
config_stub.val.bindings.commands = {'normal': bindings}
|
||||||
assert keyconf.get_reverse_bindings_for('normal') == expected
|
assert key_config_stub.get_reverse_bindings_for('normal') == expected
|
||||||
|
|
||||||
@pytest.mark.parametrize('key', ['a', '<Ctrl-X>', 'b'])
|
@pytest.mark.parametrize('key', ['a', '<Ctrl-X>', 'b'])
|
||||||
def test_bind_duplicate(self, keyconf, config_stub, key):
|
def test_bind_duplicate(self, key_config_stub, config_stub, key):
|
||||||
config_stub.val.bindings.default = {'normal': {'a': 'nop',
|
config_stub.val.bindings.default = {'normal': {'a': 'nop',
|
||||||
'<Ctrl+x>': 'nop'}}
|
'<Ctrl+x>': 'nop'}}
|
||||||
config_stub.val.bindings.commands = {'normal': {'b': 'nop'}}
|
config_stub.val.bindings.commands = {'normal': {'b': 'nop'}}
|
||||||
keyconf.bind(key, 'message-info foo', mode='normal')
|
key_config_stub.bind(key, 'message-info foo', mode='normal')
|
||||||
assert keyconf.get_command(key, 'normal') == 'message-info foo'
|
assert key_config_stub.get_command(key, 'normal') == 'message-info foo'
|
||||||
|
|
||||||
@pytest.mark.parametrize('mode', ['normal', 'caret'])
|
@pytest.mark.parametrize('mode', ['normal', 'caret'])
|
||||||
@pytest.mark.parametrize('command', [
|
@pytest.mark.parametrize('command', [
|
||||||
'message-info foo',
|
'message-info foo',
|
||||||
'nop ;; wq', # https://github.com/qutebrowser/qutebrowser/issues/3002
|
'nop ;; wq', # https://github.com/qutebrowser/qutebrowser/issues/3002
|
||||||
])
|
])
|
||||||
def test_bind(self, keyconf, config_stub, qtbot, no_bindings,
|
def test_bind(self, key_config_stub, config_stub, qtbot, no_bindings,
|
||||||
mode, command):
|
mode, command):
|
||||||
config_stub.val.bindings.default = no_bindings
|
config_stub.val.bindings.default = no_bindings
|
||||||
config_stub.val.bindings.commands = no_bindings
|
config_stub.val.bindings.commands = no_bindings
|
||||||
|
|
||||||
with qtbot.wait_signal(config_stub.changed):
|
with qtbot.wait_signal(config_stub.changed):
|
||||||
keyconf.bind('a', command, mode=mode)
|
key_config_stub.bind('a', command, mode=mode)
|
||||||
|
|
||||||
assert config_stub.val.bindings.commands[mode]['a'] == command
|
assert config_stub.val.bindings.commands[mode]['a'] == command
|
||||||
assert keyconf.get_bindings_for(mode)['a'] == command
|
assert key_config_stub.get_bindings_for(mode)['a'] == command
|
||||||
assert keyconf.get_command('a', mode) == command
|
assert key_config_stub.get_command('a', mode) == command
|
||||||
|
|
||||||
def test_bind_mode_changing(self, keyconf, config_stub, no_bindings):
|
def test_bind_mode_changing(self, key_config_stub, config_stub,
|
||||||
|
no_bindings):
|
||||||
"""Make sure we can bind to a command which changes the mode.
|
"""Make sure we can bind to a command which changes the mode.
|
||||||
|
|
||||||
https://github.com/qutebrowser/qutebrowser/issues/2989
|
https://github.com/qutebrowser/qutebrowser/issues/2989
|
||||||
"""
|
"""
|
||||||
config_stub.val.bindings.default = no_bindings
|
config_stub.val.bindings.default = no_bindings
|
||||||
config_stub.val.bindings.commands = no_bindings
|
config_stub.val.bindings.commands = no_bindings
|
||||||
keyconf.bind('a', 'set-cmd-text :nop ;; rl-beginning-of-line',
|
key_config_stub.bind('a', 'set-cmd-text :nop ;; rl-beginning-of-line',
|
||||||
mode='normal')
|
mode='normal')
|
||||||
|
|
||||||
@pytest.mark.parametrize('key, normalized', [
|
@pytest.mark.parametrize('key, normalized', [
|
||||||
('a', 'a'), # default bindings
|
('a', 'a'), # default bindings
|
||||||
@ -213,7 +211,8 @@ class TestKeyConfig:
|
|||||||
('<Ctrl-X>', '<ctrl+x>')
|
('<Ctrl-X>', '<ctrl+x>')
|
||||||
])
|
])
|
||||||
@pytest.mark.parametrize('mode', ['normal', 'caret', 'prompt'])
|
@pytest.mark.parametrize('mode', ['normal', 'caret', 'prompt'])
|
||||||
def test_unbind(self, keyconf, config_stub, qtbot, key, normalized, mode):
|
def test_unbind(self, key_config_stub, config_stub, qtbot,
|
||||||
|
key, normalized, mode):
|
||||||
default_bindings = {
|
default_bindings = {
|
||||||
'normal': {'a': 'nop', '<ctrl+x>': 'nop'},
|
'normal': {'a': 'nop', '<ctrl+x>': 'nop'},
|
||||||
'caret': {'a': 'nop', '<ctrl+x>': 'nop'},
|
'caret': {'a': 'nop', '<ctrl+x>': 'nop'},
|
||||||
@ -228,9 +227,9 @@ class TestKeyConfig:
|
|||||||
}
|
}
|
||||||
|
|
||||||
with qtbot.wait_signal(config_stub.changed):
|
with qtbot.wait_signal(config_stub.changed):
|
||||||
keyconf.unbind(key, mode=mode)
|
key_config_stub.unbind(key, mode=mode)
|
||||||
|
|
||||||
assert keyconf.get_command(key, mode) is None
|
assert key_config_stub.get_command(key, mode) is None
|
||||||
|
|
||||||
mode_bindings = config_stub.val.bindings.commands[mode]
|
mode_bindings = config_stub.val.bindings.commands[mode]
|
||||||
if key == 'b' and mode != 'prompt':
|
if key == 'b' and mode != 'prompt':
|
||||||
@ -241,13 +240,13 @@ class TestKeyConfig:
|
|||||||
assert default_bindings[mode] == old_default_bindings[mode]
|
assert default_bindings[mode] == old_default_bindings[mode]
|
||||||
assert mode_bindings[normalized] is None
|
assert mode_bindings[normalized] is None
|
||||||
|
|
||||||
def test_unbind_unbound(self, keyconf, config_stub, no_bindings):
|
def test_unbind_unbound(self, key_config_stub, config_stub, no_bindings):
|
||||||
"""Try unbinding a key which is not bound."""
|
"""Try unbinding a key which is not bound."""
|
||||||
config_stub.val.bindings.default = no_bindings
|
config_stub.val.bindings.default = no_bindings
|
||||||
config_stub.val.bindings.commands = no_bindings
|
config_stub.val.bindings.commands = no_bindings
|
||||||
with pytest.raises(configexc.KeybindingError,
|
with pytest.raises(configexc.KeybindingError,
|
||||||
match="Can't find binding 'foobar' in normal mode"):
|
match="Can't find binding 'foobar' in normal mode"):
|
||||||
keyconf.unbind('foobar', mode='normal')
|
key_config_stub.unbind('foobar', mode='normal')
|
||||||
|
|
||||||
|
|
||||||
class TestConfig:
|
class TestConfig:
|
||||||
|
@ -31,8 +31,8 @@ from qutebrowser.misc import objects
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def commands(config_stub, keyconf):
|
def commands(config_stub, key_config_stub):
|
||||||
return configcommands.ConfigCommands(config_stub, keyconf)
|
return configcommands.ConfigCommands(config_stub, key_config_stub)
|
||||||
|
|
||||||
|
|
||||||
class TestSet:
|
class TestSet:
|
||||||
@ -263,7 +263,8 @@ class TestSource:
|
|||||||
|
|
||||||
"""Test :config-source."""
|
"""Test :config-source."""
|
||||||
|
|
||||||
pytestmark = pytest.mark.usefixtures('config_tmpdir', 'data_tmpdir')
|
pytestmark = pytest.mark.usefixtures('config_tmpdir', 'data_tmpdir',
|
||||||
|
'config_stub', 'key_config_stub')
|
||||||
|
|
||||||
@pytest.mark.parametrize('use_default_dir', [True, False])
|
@pytest.mark.parametrize('use_default_dir', [True, False])
|
||||||
@pytest.mark.parametrize('clear', [True, False])
|
@pytest.mark.parametrize('clear', [True, False])
|
||||||
@ -302,14 +303,17 @@ class TestEdit:
|
|||||||
|
|
||||||
"""Tests for :config-edit."""
|
"""Tests for :config-edit."""
|
||||||
|
|
||||||
def test_no_source(self, commands, mocker, config_tmpdir):
|
pytestmark = pytest.mark.usefixtures('config_tmpdir', 'data_tmpdir',
|
||||||
|
'config_stub', 'key_config_stub')
|
||||||
|
|
||||||
|
def test_no_source(self, commands, mocker):
|
||||||
mock = mocker.patch('qutebrowser.config.configcommands.editor.'
|
mock = mocker.patch('qutebrowser.config.configcommands.editor.'
|
||||||
'ExternalEditor._start_editor', autospec=True)
|
'ExternalEditor._start_editor', autospec=True)
|
||||||
commands.config_edit(no_source=True)
|
commands.config_edit(no_source=True)
|
||||||
mock.assert_called_once_with(unittest.mock.ANY)
|
mock.assert_called_once_with(unittest.mock.ANY)
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def patch_editor(self, mocker, config_tmpdir, data_tmpdir):
|
def patch_editor(self, mocker):
|
||||||
"""Write a config.py file."""
|
"""Write a config.py file."""
|
||||||
def do_patch(text):
|
def do_patch(text):
|
||||||
def _write_file(editor_self):
|
def _write_file(editor_self):
|
||||||
@ -345,6 +349,55 @@ class TestEdit:
|
|||||||
assert msg.text == expected
|
assert msg.text == expected
|
||||||
|
|
||||||
|
|
||||||
|
class TestWritePy:
|
||||||
|
|
||||||
|
"""Tests for :config-write-py."""
|
||||||
|
|
||||||
|
def test_custom(self, commands, config_stub, key_config_stub, tmpdir):
|
||||||
|
confpy = tmpdir / 'config.py'
|
||||||
|
config_stub.val.content.javascript.enabled = True
|
||||||
|
key_config_stub.bind(',x', 'message-info foo', mode='normal')
|
||||||
|
|
||||||
|
commands.config_write_py(str(confpy))
|
||||||
|
|
||||||
|
lines = confpy.read_text('utf-8').splitlines()
|
||||||
|
assert "c.content.javascript.enabled = True" in lines
|
||||||
|
assert "config.bind(',x', 'message-info foo')" in lines
|
||||||
|
|
||||||
|
def test_defaults(self, commands, tmpdir):
|
||||||
|
confpy = tmpdir / 'config.py'
|
||||||
|
commands.config_write_py(str(confpy), defaults=True)
|
||||||
|
|
||||||
|
lines = confpy.read_text('utf-8').splitlines()
|
||||||
|
assert "# c.content.javascript.enabled = True" in lines
|
||||||
|
assert "# config.bind('H', 'back')" in lines
|
||||||
|
|
||||||
|
def test_default_location(self, commands, config_tmpdir):
|
||||||
|
confpy = config_tmpdir / 'config.py'
|
||||||
|
commands.config_write_py()
|
||||||
|
lines = confpy.read_text('utf-8').splitlines()
|
||||||
|
assert '# Autogenerated config.py' in lines
|
||||||
|
|
||||||
|
def test_existing_file(self, commands, tmpdir):
|
||||||
|
confpy = tmpdir / 'config.py'
|
||||||
|
confpy.ensure()
|
||||||
|
|
||||||
|
with pytest.raises(cmdexc.CommandError) as excinfo:
|
||||||
|
commands.config_write_py(str(confpy))
|
||||||
|
|
||||||
|
expected = " already exists - use --force to overwrite!"
|
||||||
|
assert str(excinfo.value).endswith(expected)
|
||||||
|
|
||||||
|
def test_existing_file_force(self, commands, tmpdir):
|
||||||
|
confpy = tmpdir / 'config.py'
|
||||||
|
confpy.ensure()
|
||||||
|
|
||||||
|
commands.config_write_py(str(confpy), force=True)
|
||||||
|
|
||||||
|
lines = confpy.read_text('utf-8').splitlines()
|
||||||
|
assert '# Autogenerated config.py' in lines
|
||||||
|
|
||||||
|
|
||||||
class TestBind:
|
class TestBind:
|
||||||
|
|
||||||
"""Tests for :bind and :unbind."""
|
"""Tests for :bind and :unbind."""
|
||||||
@ -355,14 +408,15 @@ class TestBind:
|
|||||||
return {'normal': {}}
|
return {'normal': {}}
|
||||||
|
|
||||||
@pytest.mark.parametrize('command', ['nop', 'nope'])
|
@pytest.mark.parametrize('command', ['nop', 'nope'])
|
||||||
def test_bind(self, commands, config_stub, no_bindings, keyconf, command):
|
def test_bind(self, commands, config_stub, no_bindings, key_config_stub,
|
||||||
|
command):
|
||||||
"""Simple :bind test (and aliases)."""
|
"""Simple :bind test (and aliases)."""
|
||||||
config_stub.val.aliases = {'nope': 'nop'}
|
config_stub.val.aliases = {'nope': 'nop'}
|
||||||
config_stub.val.bindings.default = no_bindings
|
config_stub.val.bindings.default = no_bindings
|
||||||
config_stub.val.bindings.commands = no_bindings
|
config_stub.val.bindings.commands = no_bindings
|
||||||
|
|
||||||
commands.bind('a', command)
|
commands.bind('a', command)
|
||||||
assert keyconf.get_command('a', 'normal') == command
|
assert key_config_stub.get_command('a', 'normal') == command
|
||||||
yaml_bindings = config_stub._yaml['bindings.commands']['normal']
|
yaml_bindings = config_stub._yaml['bindings.commands']['normal']
|
||||||
assert yaml_bindings['a'] == command
|
assert yaml_bindings['a'] == command
|
||||||
|
|
||||||
@ -413,7 +467,7 @@ class TestBind:
|
|||||||
commands.bind('a', 'nop', mode='wrongmode')
|
commands.bind('a', 'nop', mode='wrongmode')
|
||||||
|
|
||||||
@pytest.mark.parametrize('key', ['a', 'b', '<Ctrl-X>'])
|
@pytest.mark.parametrize('key', ['a', 'b', '<Ctrl-X>'])
|
||||||
def test_bind_duplicate(self, commands, config_stub, keyconf, key):
|
def test_bind_duplicate(self, commands, config_stub, key_config_stub, key):
|
||||||
"""Run ':bind' with a key which already has been bound.'.
|
"""Run ':bind' with a key which already has been bound.'.
|
||||||
|
|
||||||
Also tests for https://github.com/qutebrowser/qutebrowser/issues/1544
|
Also tests for https://github.com/qutebrowser/qutebrowser/issues/1544
|
||||||
@ -426,7 +480,7 @@ class TestBind:
|
|||||||
}
|
}
|
||||||
|
|
||||||
commands.bind(key, 'message-info foo', mode='normal')
|
commands.bind(key, 'message-info foo', mode='normal')
|
||||||
assert keyconf.get_command(key, 'normal') == 'message-info foo'
|
assert key_config_stub.get_command(key, 'normal') == 'message-info foo'
|
||||||
|
|
||||||
def test_bind_none(self, commands, config_stub):
|
def test_bind_none(self, commands, config_stub):
|
||||||
config_stub.val.bindings.commands = None
|
config_stub.val.bindings.commands = None
|
||||||
@ -442,7 +496,8 @@ class TestBind:
|
|||||||
('c', 'c'), # :bind then :unbind
|
('c', 'c'), # :bind then :unbind
|
||||||
('<Ctrl-X>', '<ctrl+x>') # normalized special binding
|
('<Ctrl-X>', '<ctrl+x>') # normalized special binding
|
||||||
])
|
])
|
||||||
def test_unbind(self, commands, keyconf, config_stub, key, normalized):
|
def test_unbind(self, commands, key_config_stub, config_stub,
|
||||||
|
key, normalized):
|
||||||
config_stub.val.bindings.default = {
|
config_stub.val.bindings.default = {
|
||||||
'normal': {'a': 'nop', '<ctrl+x>': 'nop'},
|
'normal': {'a': 'nop', '<ctrl+x>': 'nop'},
|
||||||
'caret': {'a': 'nop', '<ctrl+x>': 'nop'},
|
'caret': {'a': 'nop', '<ctrl+x>': 'nop'},
|
||||||
@ -456,7 +511,7 @@ class TestBind:
|
|||||||
commands.bind(key, 'nop')
|
commands.bind(key, 'nop')
|
||||||
|
|
||||||
commands.unbind(key)
|
commands.unbind(key)
|
||||||
assert keyconf.get_command(key, 'normal') is None
|
assert key_config_stub.get_command(key, 'normal') is None
|
||||||
|
|
||||||
yaml_bindings = config_stub._yaml['bindings.commands']['normal']
|
yaml_bindings = config_stub._yaml['bindings.commands']['normal']
|
||||||
if key in 'bc':
|
if key in 'bc':
|
||||||
|
@ -21,11 +21,13 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import unittest.mock
|
import unittest.mock
|
||||||
|
import textwrap
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from qutebrowser.config import config, configfiles, configexc, configdata
|
from qutebrowser.config import (config, configfiles, configexc, configdata,
|
||||||
from qutebrowser.utils import utils
|
configtypes)
|
||||||
|
from qutebrowser.utils import utils, usertypes
|
||||||
|
|
||||||
from PyQt5.QtCore import QSettings
|
from PyQt5.QtCore import QSettings
|
||||||
|
|
||||||
@ -271,14 +273,15 @@ class ConfPy:
|
|||||||
'qbmodule.run(config)')
|
'qbmodule.run(config)')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def confpy(tmpdir, config_tmpdir, data_tmpdir, config_stub, key_config_stub):
|
||||||
|
return ConfPy(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
class TestConfigPyModules:
|
class TestConfigPyModules:
|
||||||
|
|
||||||
pytestmark = pytest.mark.usefixtures('config_stub', 'key_config_stub')
|
pytestmark = pytest.mark.usefixtures('config_stub', 'key_config_stub')
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def confpy(self, tmpdir, config_tmpdir, data_tmpdir):
|
|
||||||
return ConfPy(tmpdir)
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def qbmodulepy(self, tmpdir):
|
def qbmodulepy(self, tmpdir):
|
||||||
return ConfPy(tmpdir, filename="qbmodule.py")
|
return ConfPy(tmpdir, filename="qbmodule.py")
|
||||||
@ -340,10 +343,6 @@ class TestConfigPy:
|
|||||||
|
|
||||||
pytestmark = pytest.mark.usefixtures('config_stub', 'key_config_stub')
|
pytestmark = pytest.mark.usefixtures('config_stub', 'key_config_stub')
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def confpy(self, tmpdir, config_tmpdir, data_tmpdir):
|
|
||||||
return ConfPy(tmpdir)
|
|
||||||
|
|
||||||
def test_assertions(self, confpy):
|
def test_assertions(self, confpy):
|
||||||
"""Make sure assertions in config.py work for these tests."""
|
"""Make sure assertions in config.py work for these tests."""
|
||||||
confpy.write('assert False')
|
confpy.write('assert False')
|
||||||
@ -527,6 +526,153 @@ class TestConfigPy:
|
|||||||
assert error.traceback is not None
|
assert error.traceback is not None
|
||||||
|
|
||||||
|
|
||||||
|
class TestConfigPyWriter:
|
||||||
|
|
||||||
|
def test_output(self):
|
||||||
|
desc = ("This is an option description.\n\n"
|
||||||
|
"Nullam eu ante vel est convallis dignissim. Fusce suscipit, "
|
||||||
|
"wisi nec facilisis facilisis, est dui fermentum leo, quis "
|
||||||
|
"tempor ligula erat quis odio.")
|
||||||
|
opt = configdata.Option(
|
||||||
|
name='opt', typ=configtypes.Int(), default='def',
|
||||||
|
backends=[usertypes.Backend.QtWebEngine], raw_backends=None,
|
||||||
|
description=desc)
|
||||||
|
options = [(opt, 'val')]
|
||||||
|
bindings = {'normal': {',x': 'message-info normal'},
|
||||||
|
'caret': {',y': 'message-info caret'}}
|
||||||
|
|
||||||
|
writer = configfiles.ConfigPyWriter(options, bindings, commented=False)
|
||||||
|
text = '\n'.join(writer._gen_lines())
|
||||||
|
|
||||||
|
assert text == textwrap.dedent("""
|
||||||
|
# Autogenerated config.py
|
||||||
|
# Documentation:
|
||||||
|
# qute://help/configuring.html
|
||||||
|
# qute://help/settings.html
|
||||||
|
|
||||||
|
# Uncomment this to still load settings configured via autoconfig.yml
|
||||||
|
# config.load_autoconfig()
|
||||||
|
|
||||||
|
# This is an option description. Nullam eu ante vel est convallis
|
||||||
|
# dignissim. Fusce suscipit, wisi nec facilisis facilisis, est dui
|
||||||
|
# fermentum leo, quis tempor ligula erat quis odio.
|
||||||
|
# Type: Int
|
||||||
|
c.opt = 'val'
|
||||||
|
|
||||||
|
# Bindings for normal mode
|
||||||
|
config.bind(',x', 'message-info normal')
|
||||||
|
|
||||||
|
# Bindings for caret mode
|
||||||
|
config.bind(',y', 'message-info caret', mode='caret')
|
||||||
|
""").strip()
|
||||||
|
|
||||||
|
def test_binding_options_hidden(self):
|
||||||
|
opt1 = configdata.DATA['bindings.default']
|
||||||
|
opt2 = configdata.DATA['bindings.commands']
|
||||||
|
options = [(opt1, {'normal': {'x': 'message-info x'}}),
|
||||||
|
(opt2, {})]
|
||||||
|
writer = configfiles.ConfigPyWriter(options, bindings={},
|
||||||
|
commented=False)
|
||||||
|
text = '\n'.join(writer._gen_lines())
|
||||||
|
assert 'bindings.default' not in text
|
||||||
|
assert 'bindings.commands' not in text
|
||||||
|
|
||||||
|
def test_commented(self):
|
||||||
|
opt = configdata.Option(
|
||||||
|
name='opt', typ=configtypes.Int(), default='def',
|
||||||
|
backends=[usertypes.Backend.QtWebEngine], raw_backends=None,
|
||||||
|
description='Hello World')
|
||||||
|
options = [(opt, 'val')]
|
||||||
|
bindings = {'normal': {',x': 'message-info normal'},
|
||||||
|
'caret': {',y': 'message-info caret'}}
|
||||||
|
|
||||||
|
writer = configfiles.ConfigPyWriter(options, bindings, commented=True)
|
||||||
|
lines = list(writer._gen_lines())
|
||||||
|
|
||||||
|
assert "## Autogenerated config.py" in lines
|
||||||
|
assert "# config.load_autoconfig()" in lines
|
||||||
|
assert "# c.opt = 'val'" in lines
|
||||||
|
assert "## Bindings for normal mode" in lines
|
||||||
|
assert "# config.bind(',x', 'message-info normal')" in lines
|
||||||
|
caret_bind = ("# config.bind(',y', 'message-info caret', "
|
||||||
|
"mode='caret')")
|
||||||
|
assert caret_bind in lines
|
||||||
|
|
||||||
|
def test_valid_values(self):
|
||||||
|
opt1 = configdata.Option(
|
||||||
|
name='opt1', typ=configtypes.BoolAsk(), default='ask',
|
||||||
|
backends=[usertypes.Backend.QtWebEngine], raw_backends=None,
|
||||||
|
description='Hello World')
|
||||||
|
opt2 = configdata.Option(
|
||||||
|
name='opt2', typ=configtypes.ColorSystem(), default='rgb',
|
||||||
|
backends=[usertypes.Backend.QtWebEngine], raw_backends=None,
|
||||||
|
description='All colors are beautiful!')
|
||||||
|
|
||||||
|
options = [(opt1, 'ask'), (opt2, 'rgb')]
|
||||||
|
|
||||||
|
writer = configfiles.ConfigPyWriter(options, bindings={},
|
||||||
|
commented=False)
|
||||||
|
text = '\n'.join(writer._gen_lines())
|
||||||
|
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
# Hello World
|
||||||
|
# Type: BoolAsk
|
||||||
|
# Valid values:
|
||||||
|
# - true
|
||||||
|
# - false
|
||||||
|
# - ask
|
||||||
|
c.opt1 = 'ask'
|
||||||
|
|
||||||
|
# All colors are beautiful!
|
||||||
|
# Type: ColorSystem
|
||||||
|
# Valid values:
|
||||||
|
# - rgb: Interpolate in the RGB color system.
|
||||||
|
# - hsv: Interpolate in the HSV color system.
|
||||||
|
# - hsl: Interpolate in the HSL color system.
|
||||||
|
# - none: Don't show a gradient.
|
||||||
|
c.opt2 = 'rgb'
|
||||||
|
""")
|
||||||
|
assert expected in text
|
||||||
|
|
||||||
|
def test_empty(self):
|
||||||
|
writer = configfiles.ConfigPyWriter(options=[], bindings={},
|
||||||
|
commented=False)
|
||||||
|
text = '\n'.join(writer._gen_lines())
|
||||||
|
expected = textwrap.dedent("""
|
||||||
|
# Autogenerated config.py
|
||||||
|
# Documentation:
|
||||||
|
# qute://help/configuring.html
|
||||||
|
# qute://help/settings.html
|
||||||
|
|
||||||
|
# Uncomment this to still load settings configured via autoconfig.yml
|
||||||
|
# config.load_autoconfig()
|
||||||
|
""").lstrip()
|
||||||
|
assert text == expected
|
||||||
|
|
||||||
|
def test_write(self, tmpdir):
|
||||||
|
pyfile = tmpdir / 'config.py'
|
||||||
|
writer = configfiles.ConfigPyWriter(options=[], bindings={},
|
||||||
|
commented=False)
|
||||||
|
writer.write(str(pyfile))
|
||||||
|
lines = pyfile.read_text('utf-8').splitlines()
|
||||||
|
assert '# Autogenerated config.py' in lines
|
||||||
|
|
||||||
|
def test_defaults_work(self, confpy):
|
||||||
|
"""Get a config.py with default values and run it."""
|
||||||
|
options = [(opt, opt.default)
|
||||||
|
for _name, opt in sorted(configdata.DATA.items())]
|
||||||
|
bindings = dict(configdata.DATA['bindings.default'].default)
|
||||||
|
writer = configfiles.ConfigPyWriter(options, bindings, commented=False)
|
||||||
|
writer.write(confpy.filename)
|
||||||
|
|
||||||
|
try:
|
||||||
|
configfiles.read_config_py(confpy.filename)
|
||||||
|
except configexc.ConfigFileErrors as exc:
|
||||||
|
# Make sure no other errors happened
|
||||||
|
for error in exc.errors:
|
||||||
|
assert isinstance(error.exception, configexc.BackendError)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def init_patch(qapp, fake_save_manager, config_tmpdir, data_tmpdir,
|
def init_patch(qapp, fake_save_manager, config_tmpdir, data_tmpdir,
|
||||||
config_stub, monkeypatch):
|
config_stub, monkeypatch):
|
||||||
|
Loading…
Reference in New Issue
Block a user