mirror of
https://github.com/nix-community/nixvim.git
synced 2025-06-21 08:35:43 +02:00
modules/keymaps: factor out helper functions for use in plugins
This commit is contained in:
parent
7eb1a85ccb
commit
418bf5da17
6 changed files with 416 additions and 407 deletions
520
lib/helpers.nix
520
lib/helpers.nix
|
@ -1,286 +1,286 @@
|
||||||
{lib, ...}:
|
{lib, ...}:
|
||||||
with lib;
|
with lib; rec {
|
||||||
(import ./keymap-helpers.nix {inherit lib;})
|
keymaps = 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);
|
|
||||||
|
|
||||||
# Black functional magic that converts a bunch of different Nix types to their
|
# vim dictionaries are, in theory, compatible with JSON
|
||||||
# lua equivalents!
|
toVimDict = args:
|
||||||
toLuaObject = args:
|
toJSON
|
||||||
if builtins.isAttrs args
|
(lib.filterAttrs (n: v: v != null) 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 "";
|
|
||||||
|
|
||||||
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;
|
emptyTable = {"__empty" = null;};
|
||||||
submodule {
|
|
||||||
# Adds flexibility for other keys
|
|
||||||
freeformType = types.attrs;
|
|
||||||
|
|
||||||
# :help nvim_set_hl()
|
highlightType = with lib.types;
|
||||||
options = {
|
submodule {
|
||||||
fg = mkNullOrOption str "Color for the foreground (color name or '#RRGGBB').";
|
# Adds flexibility for other keys
|
||||||
bg = mkNullOrOption str "Color for the background (color name or '#RRGGBB').";
|
freeformType = types.attrs;
|
||||||
sp = mkNullOrOption str "Special color (color name or '#RRGGBB').";
|
|
||||||
blend = mkNullOrOption (numbers.between 0 100) "Integer between 0 and 100.";
|
# :help nvim_set_hl()
|
||||||
bold = mkNullOrOption bool "";
|
options = {
|
||||||
standout = mkNullOrOption bool "";
|
fg = mkNullOrOption str "Color for the foreground (color name or '#RRGGBB').";
|
||||||
underline = mkNullOrOption bool "";
|
bg = mkNullOrOption str "Color for the background (color name or '#RRGGBB').";
|
||||||
undercurl = mkNullOrOption bool "";
|
sp = mkNullOrOption str "Special color (color name or '#RRGGBB').";
|
||||||
underdouble = mkNullOrOption bool "";
|
blend = mkNullOrOption (numbers.between 0 100) "Integer between 0 and 100.";
|
||||||
underdotted = mkNullOrOption bool "";
|
bold = mkNullOrOption bool "";
|
||||||
underdashed = mkNullOrOption bool "";
|
standout = mkNullOrOption bool "";
|
||||||
strikethrough = mkNullOrOption bool "";
|
underline = mkNullOrOption bool "";
|
||||||
italic = mkNullOrOption bool "";
|
undercurl = mkNullOrOption bool "";
|
||||||
reverse = mkNullOrOption bool "";
|
underdouble = mkNullOrOption bool "";
|
||||||
nocombine = mkNullOrOption bool "";
|
underdotted = mkNullOrOption bool "";
|
||||||
link = mkNullOrOption str "Name of another highlight group to link to.";
|
underdashed = mkNullOrOption bool "";
|
||||||
default = mkNullOrOption bool "Don't override existing definition.";
|
strikethrough = mkNullOrOption bool "";
|
||||||
ctermfg = mkNullOrOption str "Sets foreground of cterm color.";
|
italic = mkNullOrOption bool "";
|
||||||
ctermbg = mkNullOrOption str "Sets background of cterm color.";
|
reverse = mkNullOrOption bool "";
|
||||||
cterm = mkNullOrOption attrs ''
|
nocombine = mkNullOrOption bool "";
|
||||||
cterm attribute map, like |highlight-args|.
|
link = mkNullOrOption str "Name of another highlight group to link to.";
|
||||||
If not set, cterm attributes will match those from the attribute map documented above.
|
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.
|
# Creates an option with a nullable type that defaults to null.
|
||||||
mkNullOrOption = type: desc:
|
mkNullOrOption = type: desc:
|
||||||
lib.mkOption {
|
lib.mkOption {
|
||||||
type = lib.types.nullOr type;
|
type = lib.types.nullOr type;
|
||||||
default = null;
|
default = null;
|
||||||
description = desc;
|
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:
|
ifNonNull' = x: y:
|
||||||
if (x == null)
|
if (x == null)
|
||||||
then null
|
then null
|
||||||
else y;
|
else y;
|
||||||
|
|
||||||
mkCompositeOption = desc: options:
|
mkCompositeOption = desc: options:
|
||||||
mkNullOrOption (types.submodule {inherit options;}) desc;
|
mkNullOrOption (types.submodule {inherit options;}) desc;
|
||||||
|
|
||||||
defaultNullOpts = rec {
|
defaultNullOpts = rec {
|
||||||
mkNullable = type: default: desc:
|
mkNullable = type: default: desc:
|
||||||
mkNullOrOption type (
|
mkNullOrOption type (
|
||||||
let
|
let
|
||||||
defaultDesc = "default: `${default}`";
|
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.
|
|
||||||
'';
|
|
||||||
in
|
in
|
||||||
if desc == ""
|
if desc == ""
|
||||||
then defaultDesc
|
then defaultDesc
|
||||||
else ''
|
else ''
|
||||||
${desc}
|
${desc}
|
||||||
|
|
||||||
${defaultDesc}
|
${defaultDesc}
|
||||||
'');
|
''
|
||||||
|
);
|
||||||
|
|
||||||
mkHighlight = default: name: desc:
|
mkNum = default: mkNullable lib.types.number (toString default);
|
||||||
mkNullable
|
mkInt = default: mkNullable lib.types.int (toString default);
|
||||||
highlightType
|
# Positive: >0
|
||||||
default
|
mkPositiveInt = default: mkNullable lib.types.ints.positive (toString default);
|
||||||
(
|
# Unsigned: >=0
|
||||||
if desc == ""
|
mkUnsignedInt = default: mkNullable lib.types.ints.unsigned (toString default);
|
||||||
then "Highlight settings."
|
mkBool = default:
|
||||||
else desc
|
mkNullable lib.types.bool (
|
||||||
);
|
if default
|
||||||
};
|
then "true"
|
||||||
|
else "false"
|
||||||
mkPackageOption = name: default:
|
);
|
||||||
mkOption {
|
mkStr = default: mkNullable lib.types.str ''${builtins.toString default}'';
|
||||||
type = types.package;
|
mkAttributeSet = default: mkNullable lib.types.attrs ''${default}'';
|
||||||
inherit default;
|
mkEnum = enum: default: mkNullable (lib.types.enum enum) ''"${default}"'';
|
||||||
description = "Plugin to use for ${name}";
|
mkEnumFirstDefault = enum: mkEnum enum (head enum);
|
||||||
};
|
mkBorder = default: name: desc:
|
||||||
|
mkNullable
|
||||||
mkPlugin = {
|
(
|
||||||
config,
|
with lib.types;
|
||||||
lib,
|
oneOf [
|
||||||
...
|
str
|
||||||
}: {
|
(listOf str)
|
||||||
name,
|
(listOf (listOf str))
|
||||||
description,
|
]
|
||||||
package ? null,
|
)
|
||||||
extraPlugins ? [],
|
default
|
||||||
extraPackages ? [],
|
(let
|
||||||
options ? {},
|
defaultDesc = ''
|
||||||
globalPrefix ? "",
|
Defines the border to use for ${name}.
|
||||||
...
|
Accepts same border values as `nvim_open_win()`. See `:help nvim_open_win()` for more info.
|
||||||
}: 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)
|
|
||||||
'';
|
'';
|
||||||
|
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: ''
|
extraOptionsOptions = {
|
||||||
do
|
extraOptions = mkOption {
|
||||||
${string}
|
default = {};
|
||||||
end
|
type = types.attrs;
|
||||||
'';
|
description = ''
|
||||||
|
These attributes will be added to the table parameter for the setup function.
|
||||||
rawType = mkOptionType {
|
(Can override other attributes set by nixvim)
|
||||||
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;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,145 @@
|
||||||
{lib, ...}:
|
{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 <silent> to a map.";
|
||||||
|
|
||||||
|
nowait =
|
||||||
|
helpers.defaultNullOpts.mkBool false
|
||||||
|
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
|
||||||
|
|
||||||
|
script =
|
||||||
|
helpers.defaultNullOpts.mkBool false
|
||||||
|
"Equivalent to adding <script> to a map.";
|
||||||
|
|
||||||
|
expr =
|
||||||
|
helpers.defaultNullOpts.mkBool false
|
||||||
|
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
|
||||||
|
|
||||||
|
unique =
|
||||||
|
helpers.defaultNullOpts.mkBool false
|
||||||
|
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
|
||||||
|
|
||||||
|
noremap =
|
||||||
|
helpers.defaultNullOpts.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.";
|
||||||
|
|
||||||
|
remap =
|
||||||
|
helpers.defaultNullOpts.mkBool false
|
||||||
|
"Make the mapping recursive. Inverses \"noremap\"";
|
||||||
|
|
||||||
|
desc =
|
||||||
|
helpers.mkNullOrOption types.str
|
||||||
|
"A textual description of this keybind, to be shown in which-key, if you have it.";
|
||||||
|
};
|
||||||
|
|
||||||
|
modes = {
|
||||||
|
normal.short = "n";
|
||||||
|
insert.short = "i";
|
||||||
|
visual = {
|
||||||
|
desc = "visual and select";
|
||||||
|
short = "v";
|
||||||
|
};
|
||||||
|
visualOnly = {
|
||||||
|
desc = "visual only";
|
||||||
|
short = "x";
|
||||||
|
};
|
||||||
|
select.short = "s";
|
||||||
|
terminal.short = "t";
|
||||||
|
normalVisualOp = {
|
||||||
|
desc = "normal, visual, select and operator-pending (same as plain 'map')";
|
||||||
|
short = "";
|
||||||
|
};
|
||||||
|
operator.short = "o";
|
||||||
|
lang = {
|
||||||
|
desc = "normal, visual, select and operator-pending (same as plain 'map')";
|
||||||
|
short = "l";
|
||||||
|
};
|
||||||
|
insertCommand = {
|
||||||
|
desc = "insert and command-line";
|
||||||
|
short = "!";
|
||||||
|
};
|
||||||
|
command.short = "c";
|
||||||
|
};
|
||||||
|
|
||||||
|
modeEnum =
|
||||||
|
types.enum
|
||||||
|
# ["" "n" "v" ...]
|
||||||
|
(
|
||||||
|
map
|
||||||
|
(
|
||||||
|
{short, ...}: short
|
||||||
|
)
|
||||||
|
(attrValues modes)
|
||||||
|
);
|
||||||
|
|
||||||
|
# TODO: When `maps` will have to be deprecated (early December 2023), change this.
|
||||||
|
# mapOptionSubmodule = {...} (no need for options... except for 'optionalAction')
|
||||||
|
mkMapOptionSubmodule = {
|
||||||
|
defaultMode ? "",
|
||||||
|
withKeyOpt ? true,
|
||||||
|
flatConfig ? false,
|
||||||
|
actionIsOptional ? false,
|
||||||
|
}:
|
||||||
|
with types;
|
||||||
|
either
|
||||||
|
str
|
||||||
|
(submodule {
|
||||||
|
options =
|
||||||
|
(
|
||||||
|
if withKeyOpt
|
||||||
|
then {
|
||||||
|
key = mkOption {
|
||||||
|
type = str;
|
||||||
|
description = "The key to map.";
|
||||||
|
example = "<C-m>";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
)
|
||||||
|
// {
|
||||||
|
mode = mkOption {
|
||||||
|
type = either modeEnum (listOf modeEnum);
|
||||||
|
description = ''
|
||||||
|
One or several modes.
|
||||||
|
Use the short-names (`"n"`, `"v"`, ...).
|
||||||
|
See `:h map-modes` to learn more.
|
||||||
|
'';
|
||||||
|
default = defaultMode;
|
||||||
|
example = ["n" "v"];
|
||||||
|
};
|
||||||
|
|
||||||
|
action =
|
||||||
|
if actionIsOptional
|
||||||
|
then helpers.mkNullOrOption str "The action to execute"
|
||||||
|
else
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// (
|
||||||
|
if flatConfig
|
||||||
|
then mapConfigOptions
|
||||||
|
else {
|
||||||
|
options = mapConfigOptions;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
# Correctly merge two attrs (partially) representing a mapping.
|
# Correctly merge two attrs (partially) representing a mapping.
|
||||||
mergeKeymap = defaults: keymap: let
|
mergeKeymap = defaults: keymap: let
|
||||||
# First, merge the `options` attrs of both options.
|
# First, merge the `options` attrs of both options.
|
||||||
|
|
|
@ -5,142 +5,6 @@
|
||||||
}:
|
}:
|
||||||
with lib; let
|
with lib; let
|
||||||
helpers = import ../lib/helpers.nix {inherit lib;};
|
helpers = import ../lib/helpers.nix {inherit lib;};
|
||||||
|
|
||||||
# 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 <silent> to a map.";
|
|
||||||
|
|
||||||
nowait =
|
|
||||||
helpers.defaultNullOpts.mkBool false
|
|
||||||
"Whether to wait for extra input on ambiguous mappings. Equivalent to adding <nowait> to a map.";
|
|
||||||
|
|
||||||
script =
|
|
||||||
helpers.defaultNullOpts.mkBool false
|
|
||||||
"Equivalent to adding <script> to a map.";
|
|
||||||
|
|
||||||
expr =
|
|
||||||
helpers.defaultNullOpts.mkBool false
|
|
||||||
"Means that the action is actually an expression. Equivalent to adding <expr> to a map.";
|
|
||||||
|
|
||||||
unique =
|
|
||||||
helpers.defaultNullOpts.mkBool false
|
|
||||||
"Whether to fail if the map is already defined. Equivalent to adding <unique> to a map.";
|
|
||||||
|
|
||||||
noremap =
|
|
||||||
helpers.defaultNullOpts.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.";
|
|
||||||
|
|
||||||
remap =
|
|
||||||
helpers.defaultNullOpts.mkBool false
|
|
||||||
"Make the mapping recursive. Inverses \"noremap\"";
|
|
||||||
|
|
||||||
desc =
|
|
||||||
helpers.mkNullOrOption types.str
|
|
||||||
"A textual description of this keybind, to be shown in which-key, if you have it.";
|
|
||||||
};
|
|
||||||
|
|
||||||
modes = {
|
|
||||||
normal.short = "n";
|
|
||||||
insert.short = "i";
|
|
||||||
visual = {
|
|
||||||
desc = "visual and select";
|
|
||||||
short = "v";
|
|
||||||
};
|
|
||||||
visualOnly = {
|
|
||||||
desc = "visual only";
|
|
||||||
short = "x";
|
|
||||||
};
|
|
||||||
select.short = "s";
|
|
||||||
terminal.short = "t";
|
|
||||||
normalVisualOp = {
|
|
||||||
desc = "normal, visual, select and operator-pending (same as plain 'map')";
|
|
||||||
short = "";
|
|
||||||
};
|
|
||||||
operator.short = "o";
|
|
||||||
lang = {
|
|
||||||
desc = "normal, visual, select and operator-pending (same as plain 'map')";
|
|
||||||
short = "l";
|
|
||||||
};
|
|
||||||
insertCommand = {
|
|
||||||
desc = "insert and command-line";
|
|
||||||
short = "!";
|
|
||||||
};
|
|
||||||
command.short = "c";
|
|
||||||
};
|
|
||||||
|
|
||||||
mkMapOptionSubmodule = {
|
|
||||||
defaultMode ? "",
|
|
||||||
withKeyOpt ? true,
|
|
||||||
flatConfig ? false,
|
|
||||||
}:
|
|
||||||
with types;
|
|
||||||
either
|
|
||||||
str
|
|
||||||
(types.submodule {
|
|
||||||
options =
|
|
||||||
(
|
|
||||||
if withKeyOpt
|
|
||||||
then {
|
|
||||||
key = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "The key to map.";
|
|
||||||
example = "<C-m>";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {}
|
|
||||||
)
|
|
||||||
// {
|
|
||||||
mode = mkOption {
|
|
||||||
type = let
|
|
||||||
modeEnum =
|
|
||||||
enum
|
|
||||||
# ["" "n" "v" ...]
|
|
||||||
(
|
|
||||||
map
|
|
||||||
(
|
|
||||||
{short, ...}: short
|
|
||||||
)
|
|
||||||
(attrValues modes)
|
|
||||||
);
|
|
||||||
in
|
|
||||||
either modeEnum (listOf modeEnum);
|
|
||||||
description = ''
|
|
||||||
One or several modes.
|
|
||||||
Use the short-names (`"n"`, `"v"`, ...).
|
|
||||||
See `:h map-modes` to learn more.
|
|
||||||
'';
|
|
||||||
default = defaultMode;
|
|
||||||
example = ["n" "v"];
|
|
||||||
};
|
|
||||||
|
|
||||||
action =
|
|
||||||
if config.plugins.which-key.enable
|
|
||||||
then helpers.mkNullOrOption types.str "The action to execute"
|
|
||||||
else
|
|
||||||
mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "The action to execute.";
|
|
||||||
};
|
|
||||||
|
|
||||||
lua = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
description = ''
|
|
||||||
If true, `action` is considered to be lua code.
|
|
||||||
Thus, it will not be wrapped in `""`.
|
|
||||||
'';
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// (
|
|
||||||
if flatConfig
|
|
||||||
then mapConfigOptions
|
|
||||||
else {
|
|
||||||
options = mapConfigOptions;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
maps =
|
maps =
|
||||||
|
@ -157,21 +21,26 @@ in {
|
||||||
either
|
either
|
||||||
str
|
str
|
||||||
(
|
(
|
||||||
mkMapOptionSubmodule
|
helpers.keymaps.mkMapOptionSubmodule
|
||||||
{
|
{
|
||||||
defaultMode = modeProps.short;
|
defaultMode = modeProps.short;
|
||||||
withKeyOpt = false;
|
withKeyOpt = false;
|
||||||
flatConfig = true;
|
flatConfig = true;
|
||||||
|
actionIsOptional = config.plugins.which-key.enable;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
default = {};
|
default = {};
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
modes;
|
helpers.keymaps.modes;
|
||||||
|
|
||||||
keymaps = mkOption {
|
keymaps = mkOption {
|
||||||
type = types.listOf (mkMapOptionSubmodule {});
|
type =
|
||||||
|
types.listOf
|
||||||
|
(helpers.keymaps.mkMapOptionSubmodule {
|
||||||
|
actionIsOptional = config.plugins.which-key.enable;
|
||||||
|
});
|
||||||
default = [];
|
default = [];
|
||||||
example = [
|
example = [
|
||||||
{
|
{
|
||||||
|
@ -246,7 +115,7 @@ in {
|
||||||
// {
|
// {
|
||||||
options =
|
options =
|
||||||
getAttrs
|
getAttrs
|
||||||
(attrNames mapConfigOptions)
|
(attrNames helpers.keymaps.mapConfigOptions)
|
||||||
action;
|
action;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -254,7 +123,7 @@ in {
|
||||||
)
|
)
|
||||||
config.maps.${modeOptionName}
|
config.maps.${modeOptionName}
|
||||||
)
|
)
|
||||||
modes
|
helpers.keymaps.modes
|
||||||
);
|
);
|
||||||
|
|
||||||
mappings = let
|
mappings = let
|
||||||
|
|
|
@ -35,7 +35,7 @@ in {
|
||||||
extraPackages = with pkgs; [typst];
|
extraPackages = with pkgs; [typst];
|
||||||
|
|
||||||
keymaps = with cfg.keymaps;
|
keymaps = with cfg.keymaps;
|
||||||
helpers.mkKeymaps
|
helpers.keymaps.mkKeymaps
|
||||||
{
|
{
|
||||||
mode = "n";
|
mode = "n";
|
||||||
options.silent = silent;
|
options.silent = silent;
|
||||||
|
|
|
@ -34,7 +34,7 @@ in {
|
||||||
extraPlugins = [cfg.package];
|
extraPlugins = [cfg.package];
|
||||||
|
|
||||||
keymaps = with cfg.keymaps;
|
keymaps = with cfg.keymaps;
|
||||||
helpers.mkKeymaps
|
helpers.keymaps.mkKeymaps
|
||||||
{
|
{
|
||||||
mode = "n";
|
mode = "n";
|
||||||
options.silent = cfg.keymapsSilent;
|
options.silent = cfg.keymapsSilent;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
legacy-mkMaps = {
|
legacy-mkMaps = {
|
||||||
maps = helpers.mkMaps {silent = true;} {
|
maps = helpers.keymaps.mkMaps {silent = true;} {
|
||||||
normal."," = "<cmd>echo \"test\"<cr>";
|
normal."," = "<cmd>echo \"test\"<cr>";
|
||||||
visual = {
|
visual = {
|
||||||
"<C-a>" = {
|
"<C-a>" = {
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
legacy-mkModeMaps = {
|
legacy-mkModeMaps = {
|
||||||
maps.normal = helpers.mkModeMaps {silent = true;} {
|
maps.normal = helpers.keymaps.mkModeMaps {silent = true;} {
|
||||||
"," = "<cmd>echo \"test\"<cr>";
|
"," = "<cmd>echo \"test\"<cr>";
|
||||||
"<C-a>" = {
|
"<C-a>" = {
|
||||||
action = "function() print('toto') end";
|
action = "function() print('toto') end";
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
|
|
||||||
mkMaps = {
|
mkMaps = {
|
||||||
keymaps =
|
keymaps =
|
||||||
helpers.mkKeymaps
|
helpers.keymaps.mkKeymaps
|
||||||
{
|
{
|
||||||
mode = "x";
|
mode = "x";
|
||||||
options.silent = true;
|
options.silent = true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue