{ pkgs, config, lib, utils, ... }: let cfg = config.jade.input.remapping; evremap = pkgs.rustPlatform.buildRustPackage { pname = "evremap"; version = "0.1.0"; src = pkgs.fetchFromGitHub { owner = "wez"; repo = "evremap"; rev = "4480c4eda223b98899b0fbd926bc34f7bd0e1a18"; sha256 = "sha256-BxSrphgW1n465FX6bKVkq6O0XE2JqanfSYlsGwWUWkQ="; }; cargoHash = ""; cargoLock.lockFile = ../../../other/evremap.Cargo.lock; postPatch = '' cp ${../../../other/evremap.Cargo.lock} Cargo.lock ''; nativeBuildInputs = [pkgs.pkg-config]; buildInputs = [pkgs.libevdev]; }; toml = pkgs.formats.toml {}; in with lib; { options.jade.input.remapping = { enable = mkEnableOption "Enable evremap"; devices = mkOption { type = types.attrsOf (types.submodule ({name, ...}: { options = { device_name = mkOption { type = types.str; description = "The device name"; default = name; }; remap = mkOption { type = types.listOf (types.submodule ({...}: { options.input = mkOption {type = types.listOf types.str;}; options.output = mkOption {type = types.listOf types.str;}; })); default = []; }; swapKeys = mkOption { description = "Lists with two keys to be swapped on the keyboard layout."; type = types.listOf ( # verify that each key swapping list contains two elements types.addCheck (types.listOf types.str) (v: builtins.length v == 2) ); default = []; }; dual_role = mkOption { type = types.listOf (types.submodule ({...}: { options.input = mkOption {type = types.str;}; options.hold = mkOption {type = types.listOf types.str;}; options.tap = mkOption {type = types.listOf types.str;}; })); default = []; }; }; })); }; }; config = mkIf cfg.enable ( with builtins; let devs = map ({ device_name, remap, swapKeys, dual_role, }: { inherit device_name dual_role; # expand swapKeys to normal remaps remap = concatLists [ remap (lib.lists.flatten (map (keys: [ { input = [(head keys)]; output = [(lib.lists.last keys)]; } { input = [(lib.lists.last keys)]; output = [(head keys)]; } ]) swapKeys)) ]; }) (attrValues cfg.devices); in { # generate numbered systemd services for each device to be remapped # https://github.com/wez/evremap/issues/17 systemd.services = listToAttrs (genList (i: { name = "evremap${toString i}"; value = let cfgFile = toml.generate "remaps-${toString i}.toml" (elemAt devs i); in { script = "${evremap}/bin/evremap remap ${cfgFile}"; wantedBy = ["multi-user.target"]; unitConfig = { Restart = "on-failure"; }; }; }) (length devs)); environment.systemPackages = [evremap]; } ); }