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")'' + } + ''; + }; +}