From 75a5e45b2b85a17e2c4b5f1e8d86f0552dff6abe Mon Sep 17 00:00:00 2001 From: traxys Date: Sun, 16 Apr 2023 13:08:07 +0200 Subject: [PATCH] plugin/which-key: init + tests (#337) --- plugins/default.nix | 1 + plugins/utils/which-key.nix | 201 ++++++++++++++++++ .../test-sources/plugins/utils/which-key.nix | 90 ++++++++ 3 files changed, 292 insertions(+) create mode 100644 plugins/utils/which-key.nix create mode 100644 tests/test-sources/plugins/utils/which-key.nix diff --git a/plugins/default.nix b/plugins/default.nix index 1903a3d5..7a78ef03 100644 --- a/plugins/default.nix +++ b/plugins/default.nix @@ -98,5 +98,6 @@ ./utils/dashboard.nix ./utils/emmet.nix ./utils/magma-nvim.nix + ./utils/which-key.nix ]; } diff --git a/plugins/utils/which-key.nix b/plugins/utils/which-key.nix new file mode 100644 index 00000000..52f10b5b --- /dev/null +++ b/plugins/utils/which-key.nix @@ -0,0 +1,201 @@ +{ + pkgs, + config, + lib, + ... +} @ args: +with lib; let + helpers = import ../helpers.nix args; +in { + options.plugins.which-key = { + enable = + mkEnableOption + "which-key.nvim, a plugin that popup with possible key bindings of the command you started typing"; + + package = helpers.mkPackageOption "whick-key-nvim" pkgs.vimPlugins.which-key-nvim; + + plugins = { + marks = helpers.defaultNullOpts.mkBool true "shows a list of your marks on ' and `"; + + registers = + helpers.defaultNullOpts.mkBool true + ''shows your registers on " in NORMAL or in INSERT mode''; + + spelling = { + enabled = + helpers.defaultNullOpts.mkBool true + "enabling this will show WhichKey when pressing z= to select spelling suggestions"; + suggestions = + helpers.defaultNullOpts.mkInt 20 + "how many suggestions should be shown in the list?"; + }; + + presets = { + operators = helpers.defaultNullOpts.mkBool true "adds help for operators like d, y, ..."; + motions = helpers.defaultNullOpts.mkBool true "adds help for motions"; + textObjects = + helpers.defaultNullOpts.mkBool true + "help for text objects triggered after entering an operator"; + windows = helpers.defaultNullOpts.mkBool true "default bindings on "; + nav = helpers.defaultNullOpts.mkBool true "misc bindings to work with windows"; + z = + helpers.defaultNullOpts.mkBool true + "bindings for folds, spelling and others prefixed with z"; + g = helpers.defaultNullOpts.mkBool true "bindings for prefixed with g"; + }; + }; + + operators = helpers.defaultNullOpts.mkNullable (types.attrsOf types.str) ''{gc = "Comments";}'' '' + add operators that will trigger motion and text object completion + to enable all native operators, set the preset / operators plugin above + ''; + + keyLabels = helpers.defaultNullOpts.mkNullable (types.attrsOf types.str) ''{}'' '' + override the label used to display some keys. It doesn't effect WK in any other way. + ''; + + motions = { + count = helpers.defaultNullOpts.mkBool true ""; + }; + + icons = { + breadcrumb = + helpers.defaultNullOpts.mkStr "»" + "symbol used in the command line area that shows your active key combo"; + separator = helpers.defaultNullOpts.mkStr "➜" "symbol used between a key and it's label"; + group = helpers.defaultNullOpts.mkStr "+" "symbol prepended to a group"; + }; + + popupMappings = { + scrollDown = helpers.defaultNullOpts.mkStr "" "binding to scroll down inside the popup"; + scrollUp = helpers.defaultNullOpts.mkStr "" "binding to scroll up inside the popup"; + }; + + window = let + spacingOptions = types.submodule { + options = { + top = mkOption {type = types.int;}; + right = mkOption {type = types.int;}; + bottom = mkOption {type = types.int;}; + left = mkOption {type = types.int;}; + }; + }; + in { + border = helpers.defaultNullOpts.mkEnumFirstDefault ["none" "single" "double" "shadow"] ""; + position = helpers.defaultNullOpts.mkEnumFirstDefault ["bottom" "top"] ""; + margin = + helpers.defaultNullOpts.mkNullable spacingOptions + ''{top = 1; right = 0; bottom = 1; left = 0;}'' "extra window margin"; + padding = + helpers.defaultNullOpts.mkNullable spacingOptions + ''{top = 1; right = 2; bottom = 1; left = 2;}'' "extra window padding"; + winblend = + helpers.defaultNullOpts.mkNullable (types.ints.between 0 100) "0" + "0 for fully opaque and 100 for fully transparent"; + }; + + layout = let + rangeOption = types.submodule { + options = { + min = mkOption {type = types.int;}; + max = mkOption {type = types.int;}; + }; + }; + in { + height = + helpers.defaultNullOpts.mkNullable rangeOption "{min = 4; max = 25;}" + "min and max height of the columns"; + width = + helpers.defaultNullOpts.mkNullable rangeOption "{min = 20; max = 50;}" + "min and max width of the columns"; + spacing = helpers.defaultNullOpts.mkInt 3 "spacing between columns"; + align = helpers.defaultNullOpts.mkEnumFirstDefault ["left" "center" "right"] ""; + }; + + ignoreMissing = + helpers.defaultNullOpts.mkBool false + "enable this to hide mappings for which you didn't specify a label"; + + hidden = helpers.defaultNullOpts.mkNullable (types.listOf types.str) '' + ["" "" "" "" "^:" "^ " "^call " "^lua "] + '' "hide mapping boilerplate"; + + showHelp = + helpers.defaultNullOpts.mkBool true + "show a help message in the command line for using WhichKey"; + + showKeys = + helpers.defaultNullOpts.mkBool true + "show the currently pressed key and its label as a message in the command line"; + + triggers = + helpers.defaultNullOpts.mkNullable + (types.either (types.enum ["auto"]) (types.listOf types.str)) + ''"auto"'' "automatically setup triggers, or specifiy a list manually"; + + triggersNoWait = + helpers.defaultNullOpts.mkNullable (types.listOf types.str) + ''["`" "'" "g`" "g'" "\"" "" "z="]'' '' + list of triggers, where WhichKey should not wait for timeoutlen and show immediately + ''; + + triggersBlackList = + helpers.defaultNullOpts.mkNullable (types.attrsOf (types.listOf types.str)) + ''{ i = ["j" "k"]; v = ["j" "k"]}}'' '' + list of mode / prefixes that should never be hooked by WhichKey + this is mostly relevant for keymaps that start with a native binding + ''; + + disable = { + buftypes = + helpers.defaultNullOpts.mkNullable (types.listOf types.str) "[]" + "Disabled by default for Telescope"; + filetypes = helpers.defaultNullOpts.mkNullable (types.listOf types.str) "[]" ""; + }; + }; + + config = let + cfg = config.plugins.which-key; + setupOptions = { + plugins = { + inherit (cfg.plugins) marks registers spelling; + presets = { + inherit (cfg.plugins.presets) operators motions; + text_objects = cfg.plugins.presets.textObjects; + inherit (cfg.plugins.presets) windows nav z g; + }; + }; + inherit (cfg) operators; + key_labels = cfg.keyLabels; + inherit (cfg) motions icons; + popup_mappings = { + scroll_down = cfg.popupMappings.scrollDown; + scroll_up = cfg.popupMappings.scrollUp; + }; + window = let + mkSpacing = opt: helpers.ifNonNull' opt [opt.top opt.right opt.bottom opt.top]; + in { + inherit (cfg.window) border position; + margin = mkSpacing cfg.window.margin; + padding = mkSpacing cfg.window.padding; + inherit (cfg.window) winblend; + }; + inherit (cfg) layout; + ignore_missing = cfg.ignoreMissing; + inherit (cfg) hidden; + show_help = cfg.showHelp; + show_keys = cfg.showKeys; + inherit (cfg) triggers; + triggers_nowait = cfg.triggersNoWait; + triggers_blacklist = cfg.triggersBlackList; + inherit (cfg) disable; + }; + in + mkIf cfg.enable { + extraPlugins = [cfg.package]; + + extraConfigLua = '' + require("which-key").setup(${helpers.toLuaObject setupOptions}) + ''; + }; +} diff --git a/tests/test-sources/plugins/utils/which-key.nix b/tests/test-sources/plugins/utils/which-key.nix new file mode 100644 index 00000000..4039daaf --- /dev/null +++ b/tests/test-sources/plugins/utils/which-key.nix @@ -0,0 +1,90 @@ +{ + empty = { + plugins.which-key.enable = true; + }; + + defaults = { + plugins.which-key = { + enable = true; + plugins = { + marks = true; + registers = true; + spelling = { + enabled = true; + suggestions = 20; + }; + presets = { + operators = true; + motions = true; + textObjects = true; + windows = true; + nav = true; + z = true; + g = true; + }; + }; + + operators = {gc = "Comments";}; + keyLabels = {}; + + motions = { + count = true; + }; + + icons = { + breadcrumb = "»"; + separator = "➜"; + group = "+"; + }; + + popupMappings = { + scrollDown = ""; + scrollUp = ""; + }; + + window = { + border = "none"; + position = "bottom"; + margin = { + top = 1; + right = 0; + bottom = 1; + left = 0; + }; + padding = { + top = 1; + right = 2; + bottom = 1; + left = 2; + }; + winblend = 0; + }; + layout = { + height = { + min = 4; + max = 25; + }; + width = { + min = 20; + max = 50; + }; + spacing = 3; + align = "left"; + }; + ignoreMissing = false; + hidden = ["" "" "" "" "^:" "^ " "^call " "^lua "]; + showHelp = true; + showKeys = true; + triggers = "auto"; + triggersNoWait = ["`" "'" "g`" "g'" ''"'' "" "z="]; + triggersBlackList = { + i = ["j" "k"]; + v = ["j" "k"]; + }; + disable = { + buftypes = []; + filetypes = []; + }; + }; + }; +}