Skip to content

Commit

Permalink
vim.maps rewrite (#352)
Browse files Browse the repository at this point in the history
* feat: rewrite vim.maps

* modules/mappings: enable silent by default

* docs: add entry for vim.maps rewrite

* lib/binds: improve code, adjust functions to new api
  • Loading branch information
diniamo authored Aug 12, 2024
1 parent fd65c83 commit b71bf75
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 268 deletions.
26 changes: 26 additions & 0 deletions docs/release-notes/rl-0.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Release notes for release 0.7

## Breaking Changes and Migration Guide {#sec-breaking-changes-and-migration-guide-0-7}

### `vim.configRC` removed

In v0.7 we are removing `vim.configRC` in favor of making `vim.luaConfigRC` the
top-level DAG, and thereby making the entire configuration Lua based. This
change introduces a few breaking changes:
Expand All @@ -24,6 +26,28 @@ making good use of its extensive Lua API. Additionally, Vimscript is slow and
brings unnecessary performance overhead while working with different
configuration formats.

### `vim.maps` rewrite

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:

```nix
vim.maps.normal."<leader>m" = { ... };
```

has to be replaced by

```nix
vim.maps."<leader>m" = {
mode = "n";
...
};
```

## Changelog {#sec-release-0.7-changelog}

[ItsSorae](https://github.com/ItsSorae):
Expand Down Expand Up @@ -114,6 +138,8 @@ configuration formats.
has been introduced for setting up internal plugins. See the "DAG entries in
nvf" manual page for more information.

- Rewrite `vim.maps`, see the breaking changes section above.

[NotAShelf](https://github.com/notashelf):

[ts-error-translator.nvim]: https://github.com/dmmulroy/ts-error-translator.nvim
Expand Down
109 changes: 54 additions & 55 deletions lib/binds.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,69 +4,68 @@
inherit (lib.types) nullOr str;
inherit (lib.attrsets) isAttrs mapAttrs;

binds = rec {
mkLuaBinding = key: action: desc:
mkIf (key != null) {
"${key}" = {
inherit action desc;
lua = true;
silent = true;
};
mkLuaBinding = mode: key: action: desc:
mkIf (key != null) {
${key} = {
inherit mode action desc;
lua = true;
silent = true;
};
};

mkExprBinding = key: action: desc:
mkIf (key != null) {
"${key}" = {
inherit action desc;
lua = true;
silent = true;
expr = true;
};
mkExprBinding = mode: key: action: desc:
mkIf (key != null) {
${key} = {
inherit mode action desc;
lua = true;
silent = true;
expr = true;
};
};

mkBinding = key: action: desc:
mkIf (key != null) {
"${key}" = {
inherit action desc;
silent = true;
};
mkBinding = mode: key: action: desc:
mkIf (key != null) {
${key} = {
inherit mode action desc;
silent = true;
};
};

mkMappingOption = description: default:
mkOption {
type = nullOr str;
inherit default description;
};
mkMappingOption = description: default:
mkOption {
type = nullOr str;
inherit default description;
};

# Utility function that takes two attrsets:
# { someKey = "some_value" } and
# { someKey = { description = "Some Description"; }; }
# and merges them into
# { someKey = { value = "some_value"; description = "Some Description"; }; }
addDescriptionsToMappings = actualMappings: mappingDefinitions:
mapAttrs (name: value: let
isNested = isAttrs value;
returnedValue =
if isNested
then addDescriptionsToMappings actualMappings."${name}" mappingDefinitions."${name}"
else {
inherit value;
inherit (mappingDefinitions."${name}") description;
};
in
returnedValue)
actualMappings;
# Utility function that takes two attrsets:
# { someKey = "some_value" } and
# { someKey = { description = "Some Description"; }; }
# and merges them into
# { someKey = { value = "some_value"; description = "Some Description"; }; }
addDescriptionsToMappings = actualMappings: mappingDefinitions:
mapAttrs (name: value: let
isNested = isAttrs value;
returnedValue =
if isNested
then addDescriptionsToMappings actualMappings.${name} mappingDefinitions.${name}
else {
inherit value;
inherit (mappingDefinitions.${name}) description;
};
in
returnedValue)
actualMappings;

mkSetBinding = binding: action:
mkBinding binding.value action binding.description;
mkSetBinding = mode: binding: action:
mkBinding mode binding.value action binding.description;

mkSetExprBinding = binding: action:
mkExprBinding binding.value action binding.description;
mkSetExprBinding = mode: binding: action:
mkExprBinding mode binding.value action binding.description;

mkSetLuaBinding = binding: action:
mkLuaBinding binding.value action binding.description;
mkSetLuaBinding = mode: binding: action:
mkLuaBinding mode binding.value action binding.description;

pushDownDefault = attr: mapAttrs (_: mkDefault) attr;
};
in
binds
pushDownDefault = attr: mapAttrs (_: mkDefault) attr;
in {
inherit mkLuaBinding mkExprBinding mkBinding mkMappingOption addDescriptionsToMappings mkSetBinding mkSetExprBinding mkSetLuaBinding pushDownDefault;
}
57 changes: 19 additions & 38 deletions modules/neovim/mappings/config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,26 @@
cfg = config.vim;
in {
config = {
vim.maps = {
normal = mkIf cfg.disableArrows {
"<up>" = {
action = "<nop>";

noremap = false;
};
"<down>" = {
action = "<nop>";

noremap = false;
};
"<left>" = {
action = "<nop>";
noremap = false;
};
"<right>" = {
action = "<nop>";
noremap = false;
};
vim.maps = mkIf cfg.disableArrows {
"<up>" = {
mode = ["n" "i"];
action = "<nop>";
noremap = false;
};

insert = mkIf cfg.disableArrows {
"<up>" = {
action = "<nop>";
noremap = false;
};
"<down>" = {
action = "<nop>";
noremap = false;
};
"<left>" = {
action = "<nop>";
noremap = false;
};
"<right>" = {
action = "<nop>";
noremap = false;
};
"<down>" = {
mode = ["n" "i"];
action = "<nop>";
noremap = false;
};
"<left>" = {
mode = ["n" "i"];
action = "<nop>";
noremap = false;
};
"<right>" = {
mode = ["n" "i"];
action = "<nop>";
noremap = false;
};
};
};
Expand Down
103 changes: 28 additions & 75 deletions modules/neovim/mappings/options.nix
Original file line number Diff line number Diff line change
@@ -1,96 +1,49 @@
{lib, ...}: let
inherit (lib.options) mkOption;
inherit (lib.types) bool str attrsOf nullOr submodule;
inherit (lib.types) either str listOf attrsOf nullOr submodule;
inherit (lib.nvim.config) mkBool;
# Most of the keybindings code is highly inspired by pta2002/nixvim.
# Thank you!
mapConfigOptions = {
silent =
mkBool false
"Whether this mapping should be silent. Equivalent to adding <silent> to a map.";

nowait =
mkBool false
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";

script =
mkBool false
"Equivalent to adding <script> to a map.";

expr =
mkBool false
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";

unique =
mkBool false
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";

noremap =
mkBool true
"Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
mapType = submodule {
mode = mkOption {
type = either str (listOf str);
description = ''
The short-name of the mode to set the keymapping for. Passing an empty string is the equivalent of `:map`.
See `:help map-modes` for a list of modes.
'';
};
desc = mkOption {
type = nullOr str;
default = null;
description = "A description of this keybind, to be shown in which-key, if you have it enabled.";
};
};

mapOption = submodule {
options =
mapConfigOptions
// {
action = mkOption {
type = str;
description = "The action to execute.";
};

lua = mkOption {
type = bool;
description = ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.
'';
default = false;
};
};
};

mapOptions = mode:
mkOption {
description = "Mappings for ${mode} mode";
type = attrsOf mapOption;
default = {};
action = mkOption {
type = str;
description = "The command to execute.";
};
lua = mkBool false ''
If true, `action` is considered to be lua code.
Thus, it will not be wrapped in `""`.
'';

silent = mkBool true "Whether this mapping should be silent. Equivalent to adding <silent> to a map.";
nowait = mkBool false "Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
script = mkBool false "Equivalent to adding <script> to a map.";
expr = mkBool false "Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
unique = mkBool false "Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
noremap = mkBool true "Whether to use the 'noremap' variant of the command, ignoring any custom mappings on the defined action. It is highly advised to keep this on, which is the default.";
};
in {
options.vim = {
maps = mkOption {
type = submodule {
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";
};
};
type = attrsOf mapType;
default = {};
description = ''
Custom keybindings for any mode.
For plain maps (e.g. just 'map' or 'remap') use `maps.normalVisualOp`.
'';

description = "Custom keybindings.";
example = ''
maps = {
normal."<leader>m" = {
"<leader>m" = {
mode = "n";
silent = true;
action = "<cmd>make<CR>";
}; # Same as nnoremap <leader>m <silent> <cmd>make<CR>
Expand Down
Loading

0 comments on commit b71bf75

Please sign in to comment.