From 8d1872e15fa79446a813db19218ec20eee4f2320 Mon Sep 17 00:00:00 2001 From: Theo <18051685+theol-git@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:21:20 +0200 Subject: [PATCH 1/4] mappings: add ft option for filetype-scoped keymaps --- docs/manual/configuring/keybinds.md | 14 ++++++++++++++ docs/manual/release-notes/rl-26.12.md | 6 ++++++ modules/neovim/init/mappings.nix | 21 +++++++++++++++++++++ modules/wrapper/rc/config.nix | 16 ++++++++++++++-- 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/docs/manual/configuring/keybinds.md b/docs/manual/configuring/keybinds.md index a7c5a6266..4dc1de7f1 100644 --- a/docs/manual/configuring/keybinds.md +++ b/docs/manual/configuring/keybinds.md @@ -6,6 +6,10 @@ to disable individual keymaps with options by setting them to `null`. If a keymap is not provided by a module, you may easily register your own custom keymaps via {option}`vim.keymaps`. +Keymaps can be restricted to specific filetypes by setting `ft`. When `ft` is +non-empty (it defaults to an empty list), the mapping is not created globally; +instead, a `FileType` autocmd registers a buffer-local mapping. + ```nix { config.vim.keymaps = [ @@ -35,6 +39,16 @@ keymaps via {option}`vim.keymaps`. end ''; } + { + # `ft` restricts the keymap to buffers of the given filetypes. + # Instead of a global mapping, a `FileType` autocmd creates a + # buffer-local mapping when such a buffer is opened. + key = "p"; + mode = "n"; + action = "Git push"; + desc = "Push commit"; + ft = ["fugitive"]; + } ]; } ``` diff --git a/docs/manual/release-notes/rl-26.12.md b/docs/manual/release-notes/rl-26.12.md index e53f82054..7405e6bb2 100644 --- a/docs/manual/release-notes/rl-26.12.md +++ b/docs/manual/release-notes/rl-26.12.md @@ -66,6 +66,12 @@ ## Changelog {#sec-release-26-12-changelog} +[theol-git](https://github.com/theol-git): + +- Added an `ft` option to {option}`vim.keymaps`, scoping a keymap to the given + filetypes via a `FileType` autocmd. Defaults to an empty list, i.e. a global + mapping. + [Snoweuph](https://github.com/snoweuph) [bun ORM]: https://bun.uptrace.dev/ diff --git a/modules/neovim/init/mappings.nix b/modules/neovim/init/mappings.nix index b9fe9225c..7f67b9706 100644 --- a/modules/neovim/init/mappings.nix +++ b/modules/neovim/init/mappings.nix @@ -38,6 +38,20 @@ expr = mkBool false "Means that the action is actually an expression. Equivalent to adding to a map."; unique = mkBool false "Whether to fail if the map is already defined. Equivalent to adding 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."; + + ft = mkOption { + type = listOf str; + default = []; + description = '' + The filetypes that this keybind should apply to, e.g. `[ "fugitive" ]`. + Defaults to an empty list. + + When non-empty, the keybind will not be created as a global mapping. + Instead, a `FileType` autocmd is registered for the given filetypes that + creates a buffer-local mapping whenever a buffer with one of these + filetypes is opened. + ''; + }; }; mapType = submodule { @@ -110,6 +124,13 @@ in { silent = true; action = "cnext"; } + { + key = "p"; + mode = "n"; + action = "Git push"; + desc = "Push commit"; + ft = ["fugitive"]; + } ]; ''; default = {}; diff --git a/modules/wrapper/rc/config.nix b/modules/wrapper/rc/config.nix index de14c0842..44ca10509 100644 --- a/modules/wrapper/rc/config.nix +++ b/modules/wrapper/rc/config.nix @@ -5,7 +5,7 @@ }: let inherit (builtins) map mapAttrs filter; inherit (lib.lists) partition; - inherit (lib.attrsets) mapAttrsToList; + inherit (lib.attrsets) mapAttrsToList optionalAttrs; inherit (lib.strings) concatLines concatMapStringsSep optionalString; inherit (lib.trivial) showWarnings; inherit (lib.generators) mkLuaInline; @@ -43,7 +43,19 @@ in { remap = !keymap.noremap; }; - toLuaKeymap = bind: "vim.keymap.set(${toLuaObject bind.mode}, ${toLuaObject bind.key}, ${toLuaObject (getAction bind)}, ${toLuaObject (getOpts bind)})"; + toLuaKeymap = keymap: let + isFtKeymap = keymap.ft != []; + setKeymapLua = "vim.keymap.set(${toLuaObject keymap.mode}, ${toLuaObject keymap.key}, ${toLuaObject (getAction keymap)}, ${toLuaObject (getOpts keymap // optionalAttrs isFtKeymap {buffer = true;})})"; + in + if isFtKeymap + then '' + vim.api.nvim_create_autocmd("FileType", { + pattern = ${toLuaObject keymap.ft}, + callback = function() + ${setKeymapLua} + end, + })'' + else setKeymapLua; keymaps = concatLines (map toLuaKeymap (filter (x: x.key != null) cfg.keymaps)); in { From c484990b0289c09c503bca834b4b66ff06c9cf90 Mon Sep 17 00:00:00 2001 From: Theo <18051685+theol-git@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:49:39 +0200 Subject: [PATCH 2/4] docs: drop redundant prose in keybinds guide --- docs/manual/configuring/keybinds.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/manual/configuring/keybinds.md b/docs/manual/configuring/keybinds.md index 4dc1de7f1..412c22185 100644 --- a/docs/manual/configuring/keybinds.md +++ b/docs/manual/configuring/keybinds.md @@ -6,10 +6,6 @@ to disable individual keymaps with options by setting them to `null`. If a keymap is not provided by a module, you may easily register your own custom keymaps via {option}`vim.keymaps`. -Keymaps can be restricted to specific filetypes by setting `ft`. When `ft` is -non-empty (it defaults to an empty list), the mapping is not created globally; -instead, a `FileType` autocmd registers a buffer-local mapping. - ```nix { config.vim.keymaps = [ From d9807e7f14ddd99aa00e1994f0f59df83bbc9946 Mon Sep 17 00:00:00 2001 From: Theo <18051685+theol-git@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:54:23 +0200 Subject: [PATCH 3/4] mappings: shorten ft option description --- modules/neovim/init/mappings.nix | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/neovim/init/mappings.nix b/modules/neovim/init/mappings.nix index 7f67b9706..d39e9e883 100644 --- a/modules/neovim/init/mappings.nix +++ b/modules/neovim/init/mappings.nix @@ -44,12 +44,8 @@ default = []; description = '' The filetypes that this keybind should apply to, e.g. `[ "fugitive" ]`. - Defaults to an empty list. - - When non-empty, the keybind will not be created as a global mapping. - Instead, a `FileType` autocmd is registered for the given filetypes that - creates a buffer-local mapping whenever a buffer with one of these - filetypes is opened. + When non-empty, the keymap is created buffer-locally via a FileType + autocmd instead of globally. ''; }; }; From e27d4367b043e6464cf2465e0bee11c23a30a65d Mon Sep 17 00:00:00 2001 From: Theo <18051685+theol-git@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:55:35 +0200 Subject: [PATCH 4/4] keymaps: extract opts binding in toLuaKeymap --- modules/wrapper/rc/config.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/wrapper/rc/config.nix b/modules/wrapper/rc/config.nix index 44ca10509..09d81c34a 100644 --- a/modules/wrapper/rc/config.nix +++ b/modules/wrapper/rc/config.nix @@ -45,7 +45,8 @@ in { toLuaKeymap = keymap: let isFtKeymap = keymap.ft != []; - setKeymapLua = "vim.keymap.set(${toLuaObject keymap.mode}, ${toLuaObject keymap.key}, ${toLuaObject (getAction keymap)}, ${toLuaObject (getOpts keymap // optionalAttrs isFtKeymap {buffer = true;})})"; + opts = getOpts keymap // optionalAttrs isFtKeymap {buffer = true;}; + setKeymapLua = "vim.keymap.set(${toLuaObject keymap.mode}, ${toLuaObject keymap.key}, ${toLuaObject (getAction keymap)}, ${toLuaObject opts})"; in if isFtKeymap then ''