From 2d7d65f65b61fdfce23278e59ca266ddd0ef0a36 Mon Sep 17 00:00:00 2001 From: Mohamad Fikri Date: Sat, 7 Jun 2025 03:57:26 +0700 Subject: [PATCH] fish: fix the binds.*.erase option (#7186) The `command` option is optional when the `erase` option is true, because when in erase mode, bind does not require any other arguments --- modules/programs/fish.nix | 185 ++++++++++++++------------ tests/modules/programs/fish/binds.nix | 8 ++ 2 files changed, 111 insertions(+), 82 deletions(-) diff --git a/modules/programs/fish.nix b/modules/programs/fish.nix index dbaffecc..4ea39880 100644 --- a/modules/programs/fish.nix +++ b/modules/programs/fish.nix @@ -212,56 +212,68 @@ let }; }; - bindModule = types.submodule { - options = { - enable = mkEnableOption "enable the bind" // { - default = true; + bindModule = types.submodule ( + { config, ... }: + { + options = { + enable = mkEnableOption "enable the bind. Set false if you want to ignore the bind" // { + default = true; + }; + mode = mkOption { + description = "Specify the bind mode that the bind is used in"; + type = + with types; + nullOr (enum [ + "default" + "insert" + "paste" + ]); + default = null; + }; + command = mkOption { + description = "command that will be execute"; + type = + let + origin = + with types; + nullOr (oneOf [ + str + (listOf str) + ]); + in + origin + // { + description = "string or list of string (optional when erase is set to true)"; + check = x: if !config.erase && isNull x then false else origin.check x; + }; + default = null; + }; + setsMode = mkOption { + description = "Change current mode after bind is executed"; + type = + with types; + nullOr (enum [ + "default" + "insert" + "paste" + ]); + default = null; + }; + erase = mkEnableOption "remove bind"; + silent = mkEnableOption "Operate silently"; + operate = mkOption { + description = "Operate on preset bindings or user bindings"; + type = + with types; + nullOr (enum [ + "preset" + "user" + ]); + default = null; + }; }; - mode = mkOption { - description = "Specify the bind mode that the bind is used in"; - type = - with types; - nullOr (enum [ - "default" - "insert" - "paste" - ]); - default = null; - }; - command = mkOption { - description = "command that will be execute"; - type = - with types; - oneOf [ - str - (listOf str) - ]; - }; - setsMode = mkOption { - description = "Change current mode after bind is executed"; - type = - with types; - nullOr (enum [ - "default" - "insert" - "paste" - ]); - default = null; - }; - erase = mkEnableOption "remove bind"; - silent = mkEnableOption "Operate silently"; - operate = mkOption { - description = "Operate on preset bindings or user bindings"; - type = - with types; - nullOr (enum [ - "preset" - "user" - ]); - default = null; - }; - }; - }; + } + ); abbrsStr = lib.concatStringsSep "\n" ( lib.mapAttrsToList ( @@ -306,39 +318,47 @@ let filteredBinds = lib.filterAttrs (_: { enable, ... }: enable) cfg.binds; bindsStr = lib.concatStringsSep "\n" ( - lib.mapAttrsToList ( - k: - { - silent, - erase, - operate, - mode, - setsMode, - command, - ... - }: - let - opts = - lib.optionals silent [ "-s" ] - ++ ( - if erase then - [ "-e" ] - else - lib.optionals (!isNull operate) [ "--${operate}" ] - ++ lib.optionals (!isNull mode) [ - "--mode" - mode - ] - ++ lib.optionals (!isNull setsMode) [ - "--sets-mode" - setsMode - ] + lib.flatten ( + lib.mapAttrsToList ( + k: + { + silent, + erase, + operate, + mode, + setsMode, + command, + ... + }: + let + opts = + lib.optionals silent [ "-s" ] + ++ lib.optionals (!isNull operate) [ "--${operate}" ] + ++ lib.optionals (!isNull mode) [ + "--mode" + mode + ] + ++ lib.optionals (!isNull setsMode) [ + "--sets-mode" + setsMode + ]; + + cmdNormal = lib.concatStringsSep " " ( + [ "bind" ] ++ opts ++ [ k ] ++ map lib.escapeShellArg (lib.flatten [ command ]) ); - in - lib.concatStringsSep " " ( - [ "bind" ] ++ opts ++ [ k ] ++ map lib.escapeShellArg (lib.flatten [ command ]) - ) - ) filteredBinds + + cmdErase = lib.concatStringsSep " " ( + [ + "bind" + "-e" + ] + ++ opts + ++ [ k ] + ); + in + lib.optionals erase [ cmdErase ] ++ lib.optionals (!isNull command) [ cmdNormal ] + ) filteredBinds + ) ); fishIndent = @@ -434,8 +454,9 @@ in lib.literalExpression # nix '' { - "alt-s".command = "fish_commandline_prepend sudo"; "alt-shift-b".command = "fish_commandline_append bat"; + "alt-s".erase = true; + "alt-s".operate = "preset"; } ''; }; diff --git a/tests/modules/programs/fish/binds.nix b/tests/modules/programs/fish/binds.nix index cd7135dc..99c93e74 100644 --- a/tests/modules/programs/fish/binds.nix +++ b/tests/modules/programs/fish/binds.nix @@ -21,6 +21,10 @@ "repaint" ]; }; + + "alt-s".erase = true; + "alt-s".operate = "preset"; + "alt-s".command = "fish_commandline_prepend sudo"; }; }; @@ -40,6 +44,10 @@ "bind --mode insert ctrl-c kill-whole-line repaint" assertFileContains home-files/.config/fish/functions/fish_user_key_bindings.fish \ "bind ctrl-g 'git diff' repaint" + assertFileContains home-files/.config/fish/functions/fish_user_key_bindings.fish \ + "bind -e --preset alt-s" + assertFileContains home-files/.config/fish/functions/fish_user_key_bindings.fish \ + "bind --preset alt-s 'fish_commandline_prepend sudo" ''; }; };