{ config, lib, pkgs, ... }: with lib; let cfg = config.services.fusuma; yamlFormat = pkgs.formats.yaml { }; configJson = pkgs.writeText "config.json" (builtins.toJSON cfg.settings); configYamlRaw = pkgs.runCommand "config.yaml.raw" { } '' ${pkgs.remarshal}/bin/json2yaml -i ${configJson} -o $out; ''; # convert keys into literal numbers where necessary, # fusuma does not support string type finger count. strToInt = pkgs.writers.writePython3 "str2int" { libraries = [ pkgs.python3Packages.pyyaml ]; } '' import yaml from yaml import FullLoader def str2int(config): if type(config) is not dict: return for key in list(config): if type(config[key]) is dict and key.isdigit(): t = config[key] del config[key] config[int(key)] = t else: str2int(config[key]) if __name__ == '__main__': path = "${configYamlRaw}" with open(path) as f: config = yaml.load(f, Loader=FullLoader) str2int(config) print(yaml.dump(config)) ''; configYaml = pkgs.stdenv.mkDerivation { name = "config.yaml"; buildCommand = '' ${strToInt} > $out ''; }; makeBinPath = packages: foldl (a: b: if a == "" then b else "${a}:${b}") "" (map (pkg: "${pkg}/bin") packages); in { meta.maintainers = [ hm.maintainers.iosmanthus ]; options.services.fusuma = { enable = mkEnableOption "the fusuma systemd service to automatically enable touchpad gesture"; package = mkOption { type = types.package; default = pkgs.fusuma; defaultText = literalExpression "pkgs.fusuma"; description = "Package providing {command}`fusuma`."; }; settings = mkOption { type = yamlFormat.type; example = literalExpression '' { threshold = { swipe = 0.1; }; interval = { swipe = 0.7; }; swipe = { "3" = { left = { # GNOME: Switch to left workspace command = "xdotool key ctrl+alt+Right"; }; }; }; }; ''; description = '' YAML config that will override the default fusuma configuration. ''; }; extraPackages = mkOption { type = types.listOf types.package; default = with pkgs; [ xdotool coreutils xorg.xprop ]; defaultText = literalExpression "pkgs.xdotool pkgs.coreutils pkgs.xorg.xprop"; example = literalExpression '' with pkgs; [ xdotool coreutils xorg.xprop ]; ''; description = '' Extra packages needs to bring to the scope of fusuma service. ''; }; }; config = mkIf cfg.enable { assertions = [ (lib.hm.assertions.assertPlatform "services.fusuma" pkgs lib.platforms.linux) ]; xdg.configFile."fusuma/config.yml".source = configYaml; systemd.user.services.fusuma = { Unit = { Description = "Fusuma services"; After = [ "graphical-session-pre.target" ]; PartOf = [ "graphical-session.target" ]; }; Service = { Environment = with pkgs; "PATH=${makeBinPath cfg.extraPackages}"; ExecStart = "${cfg.package}/bin/fusuma"; }; Install = { WantedBy = [ "graphical-session.target" ]; }; }; }; }