diff --git a/modules/programs/qutebrowser.nix b/modules/programs/qutebrowser.nix
index 3483530f..6738515b 100644
--- a/modules/programs/qutebrowser.nix
+++ b/modules/programs/qutebrowser.nix
@@ -24,10 +24,52 @@ let
else
"${o}${n} = ${formatValue v}";
+ formatDictLine = o: n: v: ''${o}['${n}'] = "${v}"'';
+
+ formatKeyBindings = m: b:
+ let
+ formatKeyBinding = m: k: c:
+ ''config.bind("${k}", "${escape [ ''"'' ] c}", mode="${m}")'';
+ in concatStringsSep "\n" (mapAttrsToList (formatKeyBinding m) b);
+
in {
options.programs.qutebrowser = {
enable = mkEnableOption "qutebrowser";
+ aliases = mkOption {
+ type = types.attrsOf types.str;
+ default = { };
+ description = ''
+ Aliases for commands.
+ '';
+ };
+
+ searchEngines = mkOption {
+ type = types.attrsOf types.str;
+ default = { };
+ description = ''
+ Search engines that can be used via the address bar. Maps a search
+ engine name (such as DEFAULT, or
+ ddg) to a URL with a {}
+ placeholder. The placeholder will be replaced by the search term, use
+ {{ and }} for literal
+ {/} signs. The search engine named
+ DEFAULT is used when
+ url.auto_search is turned on and something else than
+ a URL was entered to be opened. Other search engines can be used by
+ prepending the search engine name to the search term, for example
+ :open google qutebrowser.
+ '';
+ example = literalExample ''
+ {
+ w = "https://en.wikipedia.org/wiki/Special:Search?search={}&go=Go&ns0=1";
+ aw = "https://wiki.archlinux.org/?search={}";
+ nw = "https://nixos.wiki/index.php?search={}";
+ g = "https://www.google.com/search?hl=en&q={}";
+ }
+ '';
+ };
+
settings = mkOption {
type = types.attrs;
default = { };
@@ -50,6 +92,150 @@ in {
'';
};
+ keyMappings = mkOption {
+ type = types.attrsOf types.str;
+ default = { };
+ description = ''
+ This setting can be used to map keys to other keys. When the key used
+ as dictionary-key is pressed, the binding for the key used as
+ dictionary-value is invoked instead. This is useful for global
+ remappings of keys, for example to map Ctrl-[ to Escape. Note that when
+ a key is bound (via bindings.default or
+ bindings.commands), the mapping is ignored.
+ '';
+ };
+
+ enableDefaultBindings = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Disable to prevent loading default key bindings.
+ '';
+ };
+
+ keyBindings = mkOption {
+ type = types.attrsOf (types.attrsOf types.str);
+ default = { };
+ description = ''
+ Key bindings mapping keys to commands in different modes. This setting
+ is a dictionary containing mode names and dictionaries mapping keys to
+ commands: {mode: {key: command}} If you want to map
+ a key to another key, check the keyMappings setting
+ instead. For modifiers, you can use either - or
+ + as delimiters, and these names:
+
+
+
+ Control: Control, Ctrl
+
+
+ Meta: Meta, Windows,
+ Mod4
+
+
+ Alt: Alt, Mod1
+
+
+ Shift: Shift
+
+
+
+ For simple keys (no <>-signs), a capital
+ letter means the key is pressed with Shift. For special keys (with
+ <>-signs), you need to explicitly add
+ Shift- to match a key pressed with shift. If you
+ want a binding to do nothing, bind it to the nop
+ command. If you want a default binding to be passed through to the
+ website, bind it to null. Note that some commands which are only useful
+ for bindings (but not used interactively) are hidden from the command
+ completion. See :help for a full list of available
+ commands. The following modes are available:
+
+
+
+ normal
+
+ Default mode, where most commands are invoked.
+
+
+
+ insert
+
+ Entered when an input field is focused on a website, or by
+ pressing i in normal mode. Passes through almost all keypresses
+ to the website, but has some bindings like
+ <Ctrl-e> to open an external editor.
+ Note that single keys can’t be bound in this mode.
+
+
+
+ hint
+
+ Entered when f is pressed to select links with the keyboard. Note
+ that single keys can’t be bound in this mode.
+
+
+
+ passthrough
+
+ Similar to insert mode, but passes through all keypresses except
+ <Escape> to leave the mode. It might be
+ useful to bind <Escape> to some other
+ key in this mode if you want to be able to send an Escape key to
+ the website as well. Note that single keys can’t be bound in this
+ mode.
+
+
+
+ command
+
+ Entered when pressing the : key in order to enter a command. Note
+ that single keys can’t be bound in this mode.
+
+
+
+ prompt
+
+ Entered when there’s a prompt to display, like for download
+ locations or when invoked from JavaScript.
+
+
+
+ yesno
+
+ Entered when there’s a yes/no prompt displayed.
+
+
+
+ caret
+
+ Entered when pressing the v mode, used to select text using the
+ keyboard.
+
+
+
+ register
+
+ Entered when qutebrowser is waiting for a register name/key for
+ commands like :set-mark.
+
+
+
+ '';
+ example = literalExample ''
+ {
+ normal = {
+ "" = "spawn mpv {url}";
+ ",p" = "spawn --userscript qute-pass";
+ ",l" = '''config-cycle spellcheck.languages ["en-GB"] ["en-US"]''';
+ };
+ prompt = {
+ "" = "prompt-yes";
+ };
+ }
+ '';
+ };
+
extraConfig = mkOption {
type = types.lines;
default = "";
@@ -64,6 +250,12 @@ in {
xdg.configFile."qutebrowser/config.py".text = concatStringsSep "\n" ([ ]
++ mapAttrsToList (formatLine "c.") cfg.settings
+ ++ mapAttrsToList (formatDictLine "c.aliases") cfg.aliases
+ ++ mapAttrsToList (formatDictLine "c.url.searchengines") cfg.searchEngines
+ ++ mapAttrsToList (formatDictLine "c.bindings.key_mappings")
+ cfg.keyMappings
+ ++ optional (!cfg.enableDefaultBindings) [ "c.bindings.default = {}" ]
+ ++ mapAttrsToList formatKeyBindings cfg.keyBindings
++ optional (cfg.extraConfig != "") cfg.extraConfig);
};
}
diff --git a/tests/modules/programs/qutebrowser/default.nix b/tests/modules/programs/qutebrowser/default.nix
index 38dcfeff..581b4a58 100644
--- a/tests/modules/programs/qutebrowser/default.nix
+++ b/tests/modules/programs/qutebrowser/default.nix
@@ -1 +1,4 @@
-{ qutebrowser-settings = ./settings.nix; }
+{
+ qutebrowser-settings = ./settings.nix;
+ qutebrowser-keybindings = ./keybindings.nix;
+}
diff --git a/tests/modules/programs/qutebrowser/keybindings.nix b/tests/modules/programs/qutebrowser/keybindings.nix
new file mode 100644
index 00000000..dc5c4dc1
--- /dev/null
+++ b/tests/modules/programs/qutebrowser/keybindings.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ config = {
+ programs.qutebrowser = {
+ enable = true;
+
+ keyBindings = {
+ normal = {
+ "" = "spawn mpv {url}";
+ ",l" = ''config-cycle spellcheck.languages ["en-GB"] ["en-US"]'';
+ };
+ prompt = { "" = "prompt-yes"; };
+ };
+ };
+
+ nixpkgs.overlays = [
+ (self: super: {
+ qutebrowser = pkgs.writeScriptBin "dummy-qutebrowser" "";
+ })
+ ];
+
+ nmt.script = ''
+ assertFileContent \
+ home-files/.config/qutebrowser/config.py \
+ ${
+ pkgs.writeText "qutebrowser-expected-config.py" ''
+ config.bind(",l", "config-cycle spellcheck.languages [\"en-GB\"] [\"en-US\"]", mode="normal")
+ config.bind("", "spawn mpv {url}", mode="normal")
+ config.bind("", "prompt-yes", mode="prompt")''
+ }
+ '';
+ };
+}