diff --git a/lib/helpers.nix b/lib/helpers.nix index 41dad3f7..4898d227 100644 --- a/lib/helpers.nix +++ b/lib/helpers.nix @@ -1,286 +1,286 @@ {lib, ...}: -with lib; - (import ./keymap-helpers.nix {inherit lib;}) - // rec { - # vim dictionaries are, in theory, compatible with JSON - toVimDict = args: - toJSON - (lib.filterAttrs (n: v: v != null) args); +with lib; rec { + keymaps = import ./keymap-helpers.nix {inherit lib;}; - # Black functional magic that converts a bunch of different Nix types to their - # lua equivalents! - toLuaObject = args: - if builtins.isAttrs args - then - if hasAttr "__raw" args - then args.__raw - else if hasAttr "__empty" args - then "{ }" - else - "{" - + (concatStringsSep "," - (mapAttrsToList - (n: v: - if head (stringToCharacters n) == "@" - then toLuaObject v - else if n == "__emptyString" - then "[''] = " + (toLuaObject v) - else "[${toLuaObject n}] = " + (toLuaObject v)) - (filterAttrs - ( - n: v: - v != null && (toLuaObject v != "{}") - ) - args))) - + "}" - else if builtins.isList args - then "{" + concatMapStringsSep "," toLuaObject args + "}" - else if builtins.isString args - then - # This should be enough! - builtins.toJSON args - else if builtins.isPath args - then builtins.toJSON (toString args) - else if builtins.isBool args - then "${boolToString args}" - else if builtins.isFloat args - then "${toString args}" - else if builtins.isInt args - then "${toString args}" - else if (args == null) - then "nil" - else ""; + # vim dictionaries are, in theory, compatible with JSON + toVimDict = args: + toJSON + (lib.filterAttrs (n: v: v != null) args); - emptyTable = {"__empty" = null;}; + # Black functional magic that converts a bunch of different Nix types to their + # lua equivalents! + toLuaObject = args: + if builtins.isAttrs args + then + if hasAttr "__raw" args + then args.__raw + else if hasAttr "__empty" args + then "{ }" + else + "{" + + (concatStringsSep "," + (mapAttrsToList + (n: v: + if head (stringToCharacters n) == "@" + then toLuaObject v + else if n == "__emptyString" + then "[''] = " + (toLuaObject v) + else "[${toLuaObject n}] = " + (toLuaObject v)) + (filterAttrs + ( + n: v: + v != null && (toLuaObject v != "{}") + ) + args))) + + "}" + else if builtins.isList args + then "{" + concatMapStringsSep "," toLuaObject args + "}" + else if builtins.isString args + then + # This should be enough! + builtins.toJSON args + else if builtins.isPath args + then builtins.toJSON (toString args) + else if builtins.isBool args + then "${boolToString args}" + else if builtins.isFloat args + then "${toString args}" + else if builtins.isInt args + then "${toString args}" + else if (args == null) + then "nil" + else ""; - highlightType = with lib.types; - submodule { - # Adds flexibility for other keys - freeformType = types.attrs; + emptyTable = {"__empty" = null;}; - # :help nvim_set_hl() - options = { - fg = mkNullOrOption str "Color for the foreground (color name or '#RRGGBB')."; - bg = mkNullOrOption str "Color for the background (color name or '#RRGGBB')."; - sp = mkNullOrOption str "Special color (color name or '#RRGGBB')."; - blend = mkNullOrOption (numbers.between 0 100) "Integer between 0 and 100."; - bold = mkNullOrOption bool ""; - standout = mkNullOrOption bool ""; - underline = mkNullOrOption bool ""; - undercurl = mkNullOrOption bool ""; - underdouble = mkNullOrOption bool ""; - underdotted = mkNullOrOption bool ""; - underdashed = mkNullOrOption bool ""; - strikethrough = mkNullOrOption bool ""; - italic = mkNullOrOption bool ""; - reverse = mkNullOrOption bool ""; - nocombine = mkNullOrOption bool ""; - link = mkNullOrOption str "Name of another highlight group to link to."; - default = mkNullOrOption bool "Don't override existing definition."; - ctermfg = mkNullOrOption str "Sets foreground of cterm color."; - ctermbg = mkNullOrOption str "Sets background of cterm color."; - cterm = mkNullOrOption attrs '' - cterm attribute map, like |highlight-args|. - If not set, cterm attributes will match those from the attribute map documented above. - ''; - }; + highlightType = with lib.types; + submodule { + # Adds flexibility for other keys + freeformType = types.attrs; + + # :help nvim_set_hl() + options = { + fg = mkNullOrOption str "Color for the foreground (color name or '#RRGGBB')."; + bg = mkNullOrOption str "Color for the background (color name or '#RRGGBB')."; + sp = mkNullOrOption str "Special color (color name or '#RRGGBB')."; + blend = mkNullOrOption (numbers.between 0 100) "Integer between 0 and 100."; + bold = mkNullOrOption bool ""; + standout = mkNullOrOption bool ""; + underline = mkNullOrOption bool ""; + undercurl = mkNullOrOption bool ""; + underdouble = mkNullOrOption bool ""; + underdotted = mkNullOrOption bool ""; + underdashed = mkNullOrOption bool ""; + strikethrough = mkNullOrOption bool ""; + italic = mkNullOrOption bool ""; + reverse = mkNullOrOption bool ""; + nocombine = mkNullOrOption bool ""; + link = mkNullOrOption str "Name of another highlight group to link to."; + default = mkNullOrOption bool "Don't override existing definition."; + ctermfg = mkNullOrOption str "Sets foreground of cterm color."; + ctermbg = mkNullOrOption str "Sets background of cterm color."; + cterm = mkNullOrOption attrs '' + cterm attribute map, like |highlight-args|. + If not set, cterm attributes will match those from the attribute map documented above. + ''; }; + }; - # Creates an option with a nullable type that defaults to null. - mkNullOrOption = type: desc: - lib.mkOption { - type = lib.types.nullOr type; - default = null; - description = desc; - }; + # Creates an option with a nullable type that defaults to null. + mkNullOrOption = type: desc: + lib.mkOption { + type = lib.types.nullOr type; + default = null; + description = desc; + }; - mkIfNonNull' = x: y: (mkIf (x != null) y); + mkIfNonNull' = x: y: (mkIf (x != null) y); - mkIfNonNull = x: (mkIfNonNull' x x); + mkIfNonNull = x: (mkIfNonNull' x x); - ifNonNull' = x: y: - if (x == null) - then null - else y; + ifNonNull' = x: y: + if (x == null) + then null + else y; - mkCompositeOption = desc: options: - mkNullOrOption (types.submodule {inherit options;}) desc; + mkCompositeOption = desc: options: + mkNullOrOption (types.submodule {inherit options;}) desc; - defaultNullOpts = rec { - mkNullable = type: default: desc: - mkNullOrOption type ( - let - defaultDesc = "default: `${default}`"; - in - if desc == "" - then defaultDesc - else '' - ${desc} - - ${defaultDesc} - '' - ); - - mkNum = default: mkNullable lib.types.number (toString default); - mkInt = default: mkNullable lib.types.int (toString default); - # Positive: >0 - mkPositiveInt = default: mkNullable lib.types.ints.positive (toString default); - # Unsigned: >=0 - mkUnsignedInt = default: mkNullable lib.types.ints.unsigned (toString default); - mkBool = default: - mkNullable lib.types.bool ( - if default - then "true" - else "false" - ); - mkStr = default: mkNullable lib.types.str ''${builtins.toString default}''; - mkAttributeSet = default: mkNullable lib.types.attrs ''${default}''; - mkEnum = enum: default: mkNullable (lib.types.enum enum) ''"${default}"''; - mkEnumFirstDefault = enum: mkEnum enum (head enum); - mkBorder = default: name: desc: - mkNullable - ( - with lib.types; - oneOf [ - str - (listOf str) - (listOf (listOf str)) - ] - ) - default - (let - defaultDesc = '' - Defines the border to use for ${name}. - Accepts same border values as `nvim_open_win()`. See `:help nvim_open_win()` for more info. - ''; + defaultNullOpts = rec { + mkNullable = type: default: desc: + mkNullOrOption type ( + let + defaultDesc = "default: `${default}`"; in if desc == "" then defaultDesc else '' ${desc} + ${defaultDesc} - ''); + '' + ); - mkHighlight = default: name: desc: - mkNullable - highlightType - default - ( - if desc == "" - then "Highlight settings." - else desc - ); - }; - - mkPackageOption = name: default: - mkOption { - type = types.package; - inherit default; - description = "Plugin to use for ${name}"; - }; - - mkPlugin = { - config, - lib, - ... - }: { - name, - description, - package ? null, - extraPlugins ? [], - extraPackages ? [], - options ? {}, - globalPrefix ? "", - ... - }: let - cfg = config.plugins.${name}; - # TODO support nested options! - pluginOptions = mapAttrs (k: v: v.option) options; - globals = - mapAttrs' - (name: opt: { - name = globalPrefix + opt.global; - value = - if cfg.${name} != null - then opt.value cfg.${name} - else null; - }) - options; - # does this evaluate package? - packageOption = - if package == null - then {} - else { - package = mkPackageOption name package; - }; - in { - options.plugins.${name} = - { - enable = mkEnableOption description; - } - // packageOption - // pluginOptions; - - config = mkIf cfg.enable { - inherit extraPackages globals; - # does this evaluate package? it would not be desired to evaluate pacakge if we use another package. - extraPlugins = extraPlugins ++ optional (package != null) cfg.package; - }; - }; - - globalVal = val: - if builtins.isBool val - then - ( - if !val - then 0 - else 1 - ) - else val; - - mkDefaultOpt = { - type, - global, - description ? null, - example ? null, - default ? null, - value ? v: (globalVal v), - ... - }: { - option = mkOption { - type = types.nullOr type; - inherit default description example; - }; - - inherit value global; - }; - - extraOptionsOptions = { - extraOptions = mkOption { - default = {}; - type = types.attrs; - description = '' - These attributes will be added to the table parameter for the setup function. - (Can override other attributes set by nixvim) + mkNum = default: mkNullable lib.types.number (toString default); + mkInt = default: mkNullable lib.types.int (toString default); + # Positive: >0 + mkPositiveInt = default: mkNullable lib.types.ints.positive (toString default); + # Unsigned: >=0 + mkUnsignedInt = default: mkNullable lib.types.ints.unsigned (toString default); + mkBool = default: + mkNullable lib.types.bool ( + if default + then "true" + else "false" + ); + mkStr = default: mkNullable lib.types.str ''${builtins.toString default}''; + mkAttributeSet = default: mkNullable lib.types.attrs ''${default}''; + mkEnum = enum: default: mkNullable (lib.types.enum enum) ''"${default}"''; + mkEnumFirstDefault = enum: mkEnum enum (head enum); + mkBorder = default: name: desc: + mkNullable + ( + with lib.types; + oneOf [ + str + (listOf str) + (listOf (listOf str)) + ] + ) + default + (let + defaultDesc = '' + Defines the border to use for ${name}. + Accepts same border values as `nvim_open_win()`. See `:help nvim_open_win()` for more info. ''; + in + if desc == "" + then defaultDesc + else '' + ${desc} + ${defaultDesc} + ''); + + mkHighlight = default: name: desc: + mkNullable + highlightType + default + ( + if desc == "" + then "Highlight settings." + else desc + ); + }; + + mkPackageOption = name: default: + mkOption { + type = types.package; + inherit default; + description = "Plugin to use for ${name}"; + }; + + mkPlugin = { + config, + lib, + ... + }: { + name, + description, + package ? null, + extraPlugins ? [], + extraPackages ? [], + options ? {}, + globalPrefix ? "", + ... + }: let + cfg = config.plugins.${name}; + # TODO support nested options! + pluginOptions = mapAttrs (k: v: v.option) options; + globals = + mapAttrs' + (name: opt: { + name = globalPrefix + opt.global; + value = + if cfg.${name} != null + then opt.value cfg.${name} + else null; + }) + options; + # does this evaluate package? + packageOption = + if package == null + then {} + else { + package = mkPackageOption name package; }; + in { + options.plugins.${name} = + { + enable = mkEnableOption description; + } + // packageOption + // pluginOptions; + + config = mkIf cfg.enable { + inherit extraPackages globals; + # does this evaluate package? it would not be desired to evaluate pacakge if we use another package. + extraPlugins = extraPlugins ++ optional (package != null) cfg.package; + }; + }; + + globalVal = val: + if builtins.isBool val + then + ( + if !val + then 0 + else 1 + ) + else val; + + mkDefaultOpt = { + type, + global, + description ? null, + example ? null, + default ? null, + value ? v: (globalVal v), + ... + }: { + option = mkOption { + type = types.nullOr type; + inherit default description example; }; - mkRaw = r: {__raw = r;}; + inherit value global; + }; - wrapDo = string: '' - do - ${string} - end - ''; - - rawType = mkOptionType { - name = "rawType"; - description = "raw lua code"; - descriptionClass = "noun"; - merge = mergeEqualOption; - check = isRawType; + extraOptionsOptions = { + extraOptions = mkOption { + default = {}; + type = types.attrs; + description = '' + These attributes will be added to the table parameter for the setup function. + (Can override other attributes set by nixvim) + ''; }; + }; - isRawType = v: lib.isAttrs v && lib.hasAttr "__raw" v && lib.isString v.__raw; - } + mkRaw = r: {__raw = r;}; + + wrapDo = string: '' + do + ${string} + end + ''; + + rawType = mkOptionType { + name = "rawType"; + description = "raw lua code"; + descriptionClass = "noun"; + merge = mergeEqualOption; + check = isRawType; + }; + + isRawType = v: lib.isAttrs v && lib.hasAttr "__raw" v && lib.isString v.__raw; +} diff --git a/lib/keymap-helpers.nix b/lib/keymap-helpers.nix index 6219597c..98395c29 100644 --- a/lib/keymap-helpers.nix +++ b/lib/keymap-helpers.nix @@ -1,5 +1,145 @@ {lib, ...}: -with lib; rec { +with lib; let + helpers = import ../lib/helpers.nix {inherit lib;}; +in rec { + # These are the configuration options that change the behavior of each mapping. + mapConfigOptions = { + silent = + helpers.defaultNullOpts.mkBool false + "Whether this mapping should be silent. Equivalent to adding to a map."; + + nowait = + helpers.defaultNullOpts.mkBool false + "Whether to wait for extra input on ambiguous mappings. Equivalent to adding to a map."; + + script = + helpers.defaultNullOpts.mkBool false + "Equivalent to adding