diff --git a/docs/manual/hacking/keybinds.md b/docs/manual/hacking/keybinds.md index 63a05d64..f4a51499 100644 --- a/docs/manual/hacking/keybinds.md +++ b/docs/manual/hacking/keybinds.md @@ -7,26 +7,37 @@ section contains a general overview to how you may utilize said functions. ## Custom Key Mappings Support for a Plugin {#sec-custom-key-mappings} -To set a mapping, you should define it in `vim.keymaps`. +To set a mapping, you should define it in `vim.maps.<>`. +The available modes are: + +- normal +- insert +- select +- visual +- terminal +- normalVisualOp +- visualOnly +- operator +- insertCommand +- lang +- command An example, simple keybinding, can look like this: ```nix { - vim.keymaps = [ - { - key = "wq"; - mode = ["n"]; + vim.maps.normal = { + "wq" = { action = ":wq"; silent = true; desc = "Save file and quit"; - } - ]; + }; + }; } ``` There are many settings available in the options. Please refer to the -[documentation](https://notashelf.github.io/nvf/options.html#opt-vim.keymaps) +[documentation](https://notashelf.github.io/nvf/options.html#opt-vim.maps.command._name_.action) to see a list of them. **nvf** provides a list of helper commands, so that you don't have to write the diff --git a/docs/release-notes/rl-0.7.md b/docs/release-notes/rl-0.7.md index bb9f3d36..060efbab 100644 --- a/docs/release-notes/rl-0.7.md +++ b/docs/release-notes/rl-0.7.md @@ -28,10 +28,10 @@ configuration formats. ### `vim.maps` rewrite {#sec-vim-maps-rewrite} -Instead of specifying map modes using submodules (eg.: `vim.maps.normal`), a new `vim.keymaps` -submodule with support for a `mode` option has been introduced. It can be either a string, or a -list of strings, where a string represents the short-name of the map mode(s), that the mapping -should be set for. See `:help map-modes` for more information. +Instead of specifying map modes using submodules (eg.: `vim.maps.normal`), a new +`mode` option has mode has been introduced. It can be either a string, or a list +of strings, where a string represents the short-name of the map mode(s), that +the mapping should be set for. See `:help map-modes` for more information. For example: @@ -42,13 +42,10 @@ vim.maps.normal."m" = { ... }; has to be replaced by ```nix -vim.keymaps = [ - { - key = "m"; - mode = "n"; - } +vim.maps."m" = { + mode = "n"; ... -]; +}; ``` ### `vim.lsp.nvimCodeActionMenu` removed in favor of `vim.ui.fastaction` {#sec-nvim-code-action-menu-deprecation} @@ -150,8 +147,6 @@ everyone. - Replace `vim.lsp.nvimCodeActionMenu` with `vim.ui.fastaction`, see the breaking changes section above for more details -- Add a `setupOpts` option to nvim-surround, which allows modifying options that aren't defined in nvf. Move the alternate nvim-surround keybinds to use `setupOpts`. - [Neovim documentation on `vim.cmd`]: https://neovim.io/doc/user/lua.html#vim.cmd() - Make Neovim's configuration file entirely Lua based. This comes with a few diff --git a/modules/neovim/mappings/config.nix b/modules/neovim/mappings/config.nix index 4d7f2417..365e1242 100644 --- a/modules/neovim/mappings/config.nix +++ b/modules/neovim/mappings/config.nix @@ -3,75 +3,32 @@ lib, ... }: let - inherit (lib.modules) mkIf mkMerge; - inherit (lib.trivial) pipe; - inherit (lib.attrsets) mapAttrsToList; - inherit (lib.lists) flatten; - - legacyMapModes = { - normal = ["n"]; - insert = ["i"]; - select = ["s"]; - visual = ["v"]; - terminal = ["t"]; - normalVisualOp = ["n" "v" "o"]; - visualOnly = ["n" "x"]; - operator = ["o"]; - insertCommand = ["i" "c"]; - lang = ["l"]; - command = ["c"]; - }; + inherit (lib.modules) mkIf; cfg = config.vim; in { config = { - vim.keymaps = mkMerge [ - ( - mkIf cfg.disableArrows [ - { - key = ""; - mode = ["n" "i"]; - action = ""; - noremap = false; - } - { - key = ""; - mode = ["n" "i"]; - action = ""; - noremap = false; - } - { - key = ""; - mode = ["n" "i"]; - action = ""; - noremap = false; - } - { - key = ""; - mode = ["n" "i"]; - action = ""; - noremap = false; - } - ] - ) - ( - pipe cfg.maps - [ - (mapAttrsToList ( - oldMode: keybinds: - mapAttrsToList ( - key: bind: - bind - // { - inherit key; - mode = legacyMapModes.${oldMode}; - } - ) - keybinds - )) - flatten - ] - ) - ]; + vim.maps = mkIf cfg.disableArrows { + "" = { + mode = ["n" "i"]; + action = ""; + noremap = false; + }; + "" = { + mode = ["n" "i"]; + action = ""; + noremap = false; + }; + "" = { + mode = ["n" "i"]; + action = ""; + noremap = false; + }; + "" = { + mode = ["n" "i"]; + action = ""; + noremap = false; + }; + }; }; } diff --git a/modules/neovim/mappings/options.nix b/modules/neovim/mappings/options.nix index 8f0e8ebf..f4229916 100644 --- a/modules/neovim/mappings/options.nix +++ b/modules/neovim/mappings/options.nix @@ -1,6 +1,6 @@ {lib, ...}: let - inherit (lib.options) mkOption literalMD; - inherit (lib.types) either str listOf attrsOf nullOr submodule; + inherit (lib.options) mkOption; + inherit (lib.types) either str listOf attrsOf nullOr submodule bool; inherit (lib.nvim.config) mkBool; mapConfigOptions = { @@ -31,10 +31,6 @@ options = mapConfigOptions // { - key = mkOption { - type = str; - description = "The key that triggers this keybind."; - }; mode = mkOption { type = either str (listOf str); description = '' @@ -42,56 +38,52 @@ See `:help map-modes` for a list of modes. ''; - example = literalMD ''`["n" "v" "c"]` for normal, visual and command mode''; }; }; }; - legacyMapOption = mode: + # legacy stuff + mapOption = submodule { + options = mapConfigOptions; + }; + + mapOptions = mode: mkOption { description = "Mappings for ${mode} mode"; - type = attrsOf (submodule { - options = mapConfigOptions; - }); + type = attrsOf mapOption; default = {}; }; in { options.vim = { - keymaps = mkOption { - type = listOf mapType; + maps = mkOption { + type = submodule { + freeformType = attrsOf mapType; + options = { + normal = mapOptions "normal"; + insert = mapOptions "insert"; + select = mapOptions "select"; + visual = mapOptions "visual and select"; + terminal = mapOptions "terminal"; + normalVisualOp = mapOptions "normal, visual, select and operator-pending (same as plain 'map')"; + + visualOnly = mapOptions "visual only"; + operator = mapOptions "operator-pending"; + insertCommand = mapOptions "insert and command-line"; + lang = mapOptions "insert, command-line and lang-arg"; + command = mapOptions "command-line"; + }; + }; + default = {}; description = "Custom keybindings."; example = '' - vim.keymaps = [ - { - key = "m"; + maps = { + "m" = { mode = "n"; silent = true; - action = ":make"; - } - { - key = "l"; - mode = ["n" "x"]; - silent = true; - action = "cnext"; - } - ]; + action = "make"; + }; # Same as nnoremap m make + }; ''; - default = {}; - }; - - maps = { - normal = legacyMapOption "normal"; - insert = legacyMapOption "insert"; - select = legacyMapOption "select"; - visual = legacyMapOption "visual and select"; - terminal = legacyMapOption "terminal"; - normalVisualOp = legacyMapOption "normal, visual, select and operator-pending (same as plain 'map')"; - - visualOnly = legacyMapOption "visual only"; - operator = legacyMapOption "operator-pending"; - insertCommand = legacyMapOption "insert and command-line"; - lang = legacyMapOption "insert, command-line and lang-arg"; - command = legacyMapOption "command-line"; }; }; } diff --git a/modules/plugins/utility/surround/config.nix b/modules/plugins/utility/surround/config.nix index 4c98c865..824b8c90 100644 --- a/modules/plugins/utility/surround/config.nix +++ b/modules/plugins/utility/surround/config.nix @@ -3,29 +3,42 @@ lib, ... }: let - inherit (lib.modules) mkIf; + inherit (lib.modules) mkIf mkMerge; + inherit (lib.nvim.binds) addDescriptionsToMappings mkSetBinding; inherit (lib.nvim.dag) entryAnywhere; - inherit (lib.nvim.lua) toLuaObject; cfg = config.vim.utility.surround; + self = import ./surround.nix {inherit lib config;}; + mappingDefinitions = self.options.vim.utility.surround.mappings; + mappings = addDescriptionsToMappings cfg.mappings mappingDefinitions; in { config = mkIf cfg.enable { vim = { - startPlugins = ["nvim-surround"]; - pluginRC.surround = entryAnywhere "require('nvim-surround').setup(${toLuaObject cfg.setupOpts})"; + startPlugins = [ + "nvim-surround" + ]; - utility.surround.setupOpts.keymaps = mkIf cfg.useVendoredKeybindings { - insert = "z"; - insert_line = "Z"; - normal = "gz"; - normal_cur = "gZ"; - normal_line = "gzz"; - normal_cur_line = "gZZ"; - visual = "gz"; - visual_line = "gZ"; - delete = "gzd"; - change = "gzr"; - change_line = "gZR"; + pluginRC.surround = entryAnywhere '' + require('nvim-surround').setup() + ''; + + maps = { + insert = mkMerge [ + (mkIf (mappings.insert != null) (mkSetBinding mappings.insert "(nvim-surround-insert)")) + (mkIf (mappings.insertLine != null) (mkSetBinding mappings.insertLine "(nvim-surround-insert-line)")) + ]; + normal = mkMerge [ + (mkIf (mappings.normal != null) (mkSetBinding mappings.normal "(nvim-surround-normal)")) + (mkIf (mappings.normalCur != null) (mkSetBinding mappings.normalCur "(nvim-surround-normal-cur)")) + (mkIf (mappings.normalLine != null) (mkSetBinding mappings.normalLine "(nvim-surround-normal-line)")) + (mkIf (mappings.normalCurLine != null) (mkSetBinding mappings.normalCurLine "(nvim-surround-normal-cur-line)")) + (mkIf (mappings.delete != null) (mkSetBinding mappings.delete "(nvim-surround-delete)")) + (mkIf (mappings.change != null) (mkSetBinding mappings.change "(nvim-surround-change)")) + ]; + visualOnly = mkMerge [ + (mkIf (mappings.visual != null) (mkSetBinding mappings.visual "(nvim-surround-visual)")) + (mkIf (mappings.visualLine != null) (mkSetBinding mappings.visualLine "(nvim-surround-visual-line)")) + ]; }; }; }; diff --git a/modules/plugins/utility/surround/surround.nix b/modules/plugins/utility/surround/surround.nix index 7d006381..8024c9b4 100644 --- a/modules/plugins/utility/surround/surround.nix +++ b/modules/plugins/utility/surround/surround.nix @@ -1,24 +1,90 @@ -{lib, ...}: let +{ + lib, + config, + ... +}: let + inherit (lib.modules) mkIf mkDefault; inherit (lib.options) mkOption; - inherit (lib.types) bool; - inherit (lib.nvim.types) mkPluginSetupOption; + inherit (lib.types) bool nullOr str; in { options.vim.utility.surround = { enable = mkOption { type = bool; default = false; - description = '' - nvim-surround: add/change/delete surrounding delimiter pairs with ease. - Note that the default mappings deviate from upstreeam to avoid conflicts - with nvim-leap. - ''; + description = "nvim-surround: add/change/delete surrounding delimiter pairs with ease. Note that the default mappings deviate from upstreeam to avoid conflicts with nvim-leap."; }; - setupOpts = mkPluginSetupOption "nvim-surround" {}; - useVendoredKeybindings = mkOption { type = bool; default = true; description = "Use alternative set of keybindings that avoids conflicts with other popular plugins, e.g. nvim-leap"; }; + mappings = { + insert = mkOption { + type = nullOr str; + default = "z"; + description = "Add surround character around the cursor"; + }; + insertLine = mkOption { + type = nullOr str; + default = "Z"; + description = "Add surround character around the cursor on new lines"; + }; + normal = mkOption { + type = nullOr str; + default = "gz"; + description = "Surround motion with character"; + }; + normalCur = mkOption { + type = nullOr str; + default = "gZ"; + description = "Surround motion with character on new lines"; + }; + normalLine = mkOption { + type = nullOr str; + default = "gzz"; + description = "Surround line with character"; + }; + normalCurLine = mkOption { + type = nullOr str; + default = "gZZ"; + description = "Surround line with character on new lines"; + }; + visual = mkOption { + type = nullOr str; + default = "gz"; + description = "Surround selection with character"; + }; + visualLine = mkOption { + type = nullOr str; + default = "gZ"; + description = "Surround selection with character on new lines"; + }; + delete = mkOption { + type = nullOr str; + default = "gzd"; + description = "Delete surrounding character"; + }; + change = mkOption { + type = nullOr str; + default = "gzr"; + description = "Change surrounding character"; + }; + }; + }; + config.vim.utility.surround = let + cfg = config.vim.utility.surround; + in { + mappings = mkIf (! cfg.useVendoredKeybindings) (mkDefault { + insert = null; + insertLine = null; + normal = null; + normalCur = null; + normalLine = null; + normalCurLine = null; + visual = null; + visualLine = null; + delete = null; + change = null; + }); }; } diff --git a/modules/wrapper/rc/config.nix b/modules/wrapper/rc/config.nix index 6f9ed1ce..6c1936e4 100644 --- a/modules/wrapper/rc/config.nix +++ b/modules/wrapper/rc/config.nix @@ -3,8 +3,8 @@ lib, ... }: let - inherit (builtins) map mapAttrs filter; - inherit (lib.attrsets) mapAttrsToList filterAttrs; + inherit (builtins) map mapAttrs filter removeAttrs attrNames; + inherit (lib.attrsets) mapAttrsToList filterAttrs attrsToList; inherit (lib.strings) concatLines concatMapStringsSep; inherit (lib.trivial) showWarnings; inherit (lib.generators) mkLuaInline; @@ -41,9 +41,40 @@ in { inherit (keymap) desc silent nowait script expr unique noremap; }; - toLuaKeymap = bind: "vim.keymap.set(${toLuaObject bind.mode}, ${toLuaObject bind.key}, ${toLuaObject (getAction bind)}, ${toLuaObject (getOpts bind)})"; + toLuaKeymap = { + name, + value, + }: "vim.keymap.set(${toLuaObject value.mode}, ${toLuaObject name}, ${toLuaObject (getAction value)}, ${toLuaObject (getOpts value)})"; - keymaps = concatLines (map toLuaKeymap cfg.keymaps); + namedModes = { + "normal" = ["n"]; + "insert" = ["i"]; + "select" = ["s"]; + "visual" = ["v"]; + "terminal" = ["t"]; + "normalVisualOp" = ["n" "v" "o"]; + "visualOnly" = ["n" "x"]; + "operator" = ["o"]; + "insertCommand" = ["i" "c"]; + "lang" = ["l"]; + "command" = ["c"]; + }; + + maps = + removeAttrs cfg.maps (attrNames namedModes) + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.normal;}) cfg.maps.normal + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.insert;}) cfg.maps.insert + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.select;}) cfg.maps.select + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.visual;}) cfg.maps.visual + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.terminal;}) cfg.maps.terminal + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.normalVisualOp;}) cfg.maps.normalVisualOp + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.visualOnly;}) cfg.maps.visualOnly + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.operator;}) cfg.maps.operator + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.insertCommand;}) cfg.maps.insertCommand + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.lang;}) cfg.maps.lang + // mapAttrs (_: legacyMap: legacyMap // {mode = namedModes.command;}) cfg.maps.command; + + keymaps = concatLines (map toLuaKeymap (attrsToList (filterAttrs (_: value: value != null) maps))); in { vim = { luaConfigRC = {