Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Keymap Configurable #38

Closed
wants to merge 11 commits into from

Conversation

MonaMayrhofer
Copy link
Contributor

@MonaMayrhofer MonaMayrhofer commented Apr 7, 2023

Closes #31

With this draft PR i want to explore some possibilities of how an API for a configurable keymap should look like. Initially I have implemented the new api for nvimtree, nvimBufferLine, lsp and nvim-cmp - to get a feel of the different use cases. I will continue to scan the codebase for other use-cases that I cannot yet serve with this api.

The initial implementation is what I call "close to module", because the end-user has to specifiy the key-bindings next to the configuration of the module. The current implementation is "global", so there is a singluar config.vim.keymap attrset, which houses every single keybinding. I found this to be cleaner, as there is no ambiguity as to where keymappings that involve multiple modules should go, and as it reduces boilerplate within the modules.

In order to abstract the underlying plugins away i make use of what I call "actions", that are defined within each module. They can be used to generate normal vim.nnoremap style bindings (e.g nvimtree module) and also weirder lua-defined bindings (e.g the lsp module)

An example end-user configuration could look like this:

{
      keymap = {
        normal = actions: {
          "<silent><leader>e" = actions.nvimTreeLua.toggle;
          # Use some custom keybindings that have no predefined action
          "<C-.>" = actions.executeViml ":RustCodeAction<CR>";
          "<C-p>" = actions.telescope.findFiles;

          "<C-l>" = actions.executeViml ":wincmd l<CR>";
          "<C-h>" = actions.executeViml ":wincmd h<CR>";
          "<M-L>" = actions.nvimBufferline.cycleNext;
          "<M-H>" = actions.nvimBufferline.cyclePrev;
          "<silent><leader>bl" = actions.nvimBufferline.cycleNext;
          "<silent><leader>bh" = actions.nvimBufferline.cyclePrev;
          "<silent><leader>bc" = actions.executeViml ":BufferLinePickClose<CR>";
          # ... And others
        };
        insert = actions: {
          "<C-d>" = actions.autocomplete.docsDown;
          "<C-e>" = actions.autocomplete.abort;
          #And others
      };
      # ... And others
   };
}

I think in the end we will move towards a more "global" api I have now moved to a "global" api, where the user can define all keybindings in a central place - to have a better overview and catch clashes earlier. Also currently there is no sensible place for actions.executeViml if the command they are executing isn't module-specific.

Open Questions

  • Defaults: Ideally neovim-flake would ship with a sensible default keymap, that can be overwritten and extended. I am however really not sure how that should look like to the end user. Negative-Mappings to explicitly remove the defaults would be an option but that doesn't really sound nice to me. Having some sort of keymap.includeDefaults switch could be an option. Maybe every action has a defined default that is used when there exist no other mappings for that action. I really don't know what would be best.
  • Documentation: The initial way of defining actions is extremely hostile against any attempts to generate documentation from them. They will probably later on be defined within the options or a similar place. However I haven't really spent a lot of time thinking about that yet.

Architecture

  • Each module can set config.nvim-flake.keymapActions to supply an actions attrset (see below), that maps action-name to a type and an action (And later on probably also documentation etc.)
    • These attrsets can be constructed more easily using the mkAction helpers.
    • The type attribute is will be used in the next step do distinguish how mappings for this actions should be handled (normal nnoremap or some strange lua-setup-stuff)
{
   config.nvim-flake.keymapActions = {
     nvimTreeLua = {
        toggle = {
            action = ":NvimTreeToggle<CR>";
            type = "vim";
       };
        strangeMapping = {
            action = "someStrangeStuff";
            type = "nvimTreeLua";
       };
  };
}
  • The user can access these defined actions in their keymap (see example user configuration above)
  • The keymap.nix module a) extracts all mappings to actions with the vim type and passes them to vim.[xvsnicto]noremap and b) collects all other mappings in config.nvim-flake.keymappings, which is an attrset that looks like this:
{
    typeOfAction = [
        {
            mode  = "normal";
            type = "typeOfAction";
            binding = "<leader>ptz";
            action = ":lua require'foo'.doBar()<CR>";
        }
        # ... and more
    ];
}
  • Modules that require keymappings within some setup lua function (like lsp/default.nix) can then access config.nvim-flake.keymappings to convert this list of mappings into lua code.

I'd love to get some feedback and thoughts.

@MonaMayrhofer
Copy link
Contributor Author

MonaMayrhofer commented Apr 7, 2023

Oh no it seems like telescope and nvim-cmp weren't formatted prior to me editing them... RIP the diffs... i hope it's still clear what i did...

@MonaMayrhofer
Copy link
Contributor Author

This pull request is currently at a usable state (tho the keymapping is not implemented for all modules yet). There is still work to be done until this can be merged, however I find myself having very little time to do any of those, so this PR can be viewed as being discontinued for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Keymap Override
1 participant