{ config, lib, qmk_firmware, system, pkgs, ... }: let cfg = config.soispha.programs.river; esa = lib.strings.escapeShellArg; riverctl = lib.getExe' pkgs.river "riverctl"; mkOutputFlags = output: flags: let expandedFlags = builtins.concatStringsSep " " (lib.attrsets.mapAttrsToList (flag: value: "--${esa flag} ${esa value}") flags); in '' err_fail ${lib.getExe pkgs.wlr-randr} --output ${esa output} ${expandedFlags} ''; screenSetupCode = builtins.concatStringsSep "" (lib.attrsets.mapAttrsToList mkOutputFlags cfg.init.screenSetupCode); mkLrProgram = input: let program = builtins.concatStringsSep " " ( if lib.isDerivation input then [(lib.getExe input)] else builtins.map esa input ); in "err_fail ${program} &"; longRunningPrograms = builtins.concatStringsSep "\n" (builtins.map mkLrProgram cfg.init.backgroundStart); keymapFormat = pkgs.formats.json {}; keymappings = '' err_fail ${riverctl} keyboard-layout ${esa cfg.init.mappings.layout} err_fail ${lib.getExe pkgs.river-mk-keymap} ${keymapFormat.generate "keys.json" cfg.init.mappings.keymap} ''; mkRule = { app-id, title, action, }: '' err_fail ${riverctl} rule-add -app-id ${esa app-id} -title ${esa title} ${esa action} ''; ruleSetup = builtins.concatStringsSep "" (builtins.map mkRule cfg.init.rules); mkSetting = name: maybe_values: let rawValues = if builtins.isString maybe_values then [maybe_values] else maybe_values; values = builtins.concatStringsSep " " (builtins.map esa rawValues); in '' err_fail ${riverctl} ${esa name} ${values} ''; generalSettings = builtins.concatStringsSep "" (lib.attrsets.mapAttrsToList mkSetting cfg.init.generalSettings); mkInput = name: arguments: builtins.concatStringsSep "" (builtins.map (argumentLine: mkSetting "input" ([name] ++ argumentLine)) arguments); inputs = builtins.concatStringsSep "" (lib.attrsets.mapAttrsToList mkInput cfg.init.inputs); in { options.soispha.programs.river = { enable = lib.mkEnableOption "river"; unicodeInput = { enable = lib.mkEnableOption "udev rules for rawhid based unicode input"; }; init = { mappings = { layout = lib.mkOption { type = lib.types.str; description = "The keymap to use"; default = "dvorak-modified"; }; keymap = lib.mkOption { type = lib.types.submodule { freeformType = keymapFormat.type; options = {}; }; default = {}; description = '' Configuration for river-mk-keymap via `keys.json`. ''; }; }; rules = lib.mkOption { type = lib.types.listOf (lib.types.attrsOf lib.types.str); default = []; example = '' [ { app-id = "*"; title = "floating please"; action = "float"; } { app-id = "*"; title = "*"; action = "ssd"; } ] ''; description = '' Configuration for river_init_lesser via `keys.json`. ''; }; generalSettings = lib.mkOption { type = lib.types.attrsOf (lib.types.either (lib.types.listOf lib.types.str) lib.types.str); description = "Simple key value settings."; default = {}; example = '' { background-color = "0x002b36"; set-repeat = ["50" "300"]; hide-cursor = ["when-typing" "enabled"]; } ''; }; inputs = lib.mkOption { type = lib.types.attrsOf (lib.types.listOf (lib.types.listOf lib.types.str)); description = "Options to set per input device"; default = {}; example = '' { pointer-1133-49970-Logitech_Gaming_Mouse_G502 = [["pointer-accel" "0"] ["accel-profile" "none"]]; pointer-12951-6505-ZSA_Technology_Labs_Moonlander_Mark_I = [["pointer-accel" "0"] ["accel-profile" "none"]]; } ''; }; backgroundStart = lib.mkOption { type = lib.types.listOf (lib.types.either lib.types.package (lib.types.listOf lib.types.str)); description = "List of programs to start in the background"; example = '' [ pkgs.gammastep ] ''; }; screenSetupCode = lib.mkOption { type = lib.types.attrsOf (lib.types.attrsOf lib.types.str); default = {}; description = '' `wlr-randr` flags to set up outputs. The attribute names are the `--output` keys and the attrs are flag value pairs to setup. ''; example = '' { "Virtual-1" = {mode = "1920x1080";}; "DP-2" = {pos = "2560,0";}; "DP-1" = {scale = "1.5"; pos = "0,0";}; } ''; }; }; }; config = lib.mkIf cfg.enable { services.udev.packages = lib.mkIf cfg.unicodeInput.enable [qmk_firmware.packages.${system}.qmk_unicode_type]; home-manager.users.soispha = { home.sessionVariables = { WM = "river"; XDG_CURRENT_DESKTOP = "river"; DESKTOP_SESSION = "river"; # Export Wayland env Vars {{{ QT_QPA_PLATFORM = "wayland"; QT_QPA_PLATFORMTHEME = "qt5ct"; # needs qt5ct CLUTTER_BACKEND = "wayland"; SDL_VIDEODRIVER = "wayland"; # might brake some things # }}} }; home.packages = [ pkgs.river-start ]; xdg.configFile."river/init".text = let mkHeading = text: other_stuff: '' # ${text} ${other_stuff} ''; in builtins.readFile ./init_base.sh + # bash mkHeading "Environment variables" '' err_fail ${riverctl} spawn "${lib.getExe' pkgs.dbus "dbus-update-activation-environment"} --verbose --systemd SEATD_SOCK DISPLAY WAYLAND_DISPLAY DESKTOP_SESSION=river XDG_CURRENT_DESKTOP=river" export XDG_CURRENT_DESKTOP=river DESKTOP_SESSION=river; '' + mkHeading "Key Mappings" keymappings + mkHeading "Rules" ruleSetup + mkHeading "General Settings" generalSettings + mkHeading "Input Section" inputs + mkHeading "Screen setup code" screenSetupCode + mkHeading "Background services" longRunningPrograms + mkHeading "Layout Setup" '' err_fail ${riverctl} default-layout rivertile ${lib.getExe' pkgs.river "rivertile"} -main-ratio 0.5 -view-padding 1 -outer-padding 0 ''; }; }; }