From a1128e507b85a32d4a700727c24d11151284a954 Mon Sep 17 00:00:00 2001 From: Frantisek Bohacek Date: Wed, 31 Jul 2024 11:32:41 +0200 Subject: [PATCH] feat(home): add desktop session startup options --- home/modules/sessions/default-hm-impl.nix | 18 +++ home/modules/sessions/default.nix | 183 ++++++++++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 home/modules/sessions/default-hm-impl.nix create mode 100644 home/modules/sessions/default.nix diff --git a/home/modules/sessions/default-hm-impl.nix b/home/modules/sessions/default-hm-impl.nix new file mode 100644 index 0000000..d267331 --- /dev/null +++ b/home/modules/sessions/default-hm-impl.nix @@ -0,0 +1,18 @@ +{ config, lib, ... }: + +let + cfg = config.desktopSessions; +in { + options.desktopSessions.autoStart = { + enableBashIntegration = lib.mkEnableOption "enable bash integration to .profile" // { default = true; }; + enableZshIntegration = lib.mkEnableOption "enable zsh integration to .zprofile" // { default = true; }; + }; + + config = lib.mkIf (cfg.enable) { + programs.zsh.profileExtra = lib.optionalString (cfg.autoStart.enable && cfg.autoStart.enableZshIntegration) cfg.autoStart.profileSelectContent; + programs.bash.profileExtra = lib.optionalString (cfg.autoStart.enable && cfg.autoStart.enableBashIntegration) cfg.autoStart.profileSelectContent; + + home.file.".start-session".source = cfg.selectSession; + }; + +} diff --git a/home/modules/sessions/default.nix b/home/modules/sessions/default.nix new file mode 100644 index 0000000..f283849 --- /dev/null +++ b/home/modules/sessions/default.nix @@ -0,0 +1,183 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.desktopSessions; + + availableSessionsConfig = lib.filterAttrs (name: x: x.enable) cfg.instances; + availableSessions = lib.attrNames availableSessionsConfig; + sessionStartScripts = lib.map (x: x.startSession) (lib.attrValues availableSessionsConfig); + + desktopSessionType = lib.types.submodule ({ config, name, ... }: { + options = { + enable = lib.mkEnableOption "desktop session instance enable" // { default = true; }; + name = lib.mkOption { + type = lib.types.str; + default = name; + }; + + startSession = lib.mkOption { + type = lib.types.package; + }; + + preStartHook = lib.mkOption { + type = lib.types.str; + default = ""; + }; + + postStartHook = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + This is executed after the session is started. + However, it's started outside of the session, + so you won't get any environment variables from + the session. If you need that, you need to utilize + configuration, or flags of the session executable. + + There is $pid available to know the pid of the started + session process. + ''; + }; + exitHook = lib.mkOption { + type = lib.types.str; + default = '' + systemctl stop --user graphical-session.target + ''; + }; + + executable = lib.mkOption { + type = lib.types.path; + }; + arguments = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = []; + }; + environment = lib.mkOption { + type = lib.types.attrsOf (lib.types.oneOf [ lib.types.str lib.types.number ]); + }; + }; + + config = { + startSession = pkgs.writeShellScript "start-${name}" '' + ${lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs (name: value: "export ${name}='${value}'") config.environment))} + + ${config.preStartHook} + ${config.executable} ${lib.concatStringsSep " " config.arguments} & + pid=$! + ${config.postStartHook} + wait $pid + ${config.exitHook} + ''; + }; + }); +in { + options.desktopSessions = { + instances = lib.mkOption { + type = lib.types.attrsOf desktopSessionType; + default = {}; + }; + + enable = lib.mkEnableOption "desktop session configuration"; + + selectSession = lib.mkOption { + type = lib.types.path; + }; + + defaultSession = lib.mkOption { + type = lib.types.str; + default = "tty"; + }; + + availableSessions = lib.mkOption { + type = lib.types.listOf lib.types.str; + readOnly = true; + }; + + sessionStartScripts = lib.mkOption { + type = lib.types.listOf lib.types.package; + readOnly = true; + }; + + sessionStartScriptsPath = lib.mkOption { + type = lib.types.package; + readOnly = true; + }; + + autoStart = { + enable = lib.mkEnableOption "auto start profile selection on tty login" // { default = true; }; + tty = lib.mkOption { + type = lib.types.int; + default = 1; + }; + profileSelectContent = lib.mkOption { + type = lib.types.str; + }; + }; + }; + + config.desktopSessions = { + inherit availableSessions; + inherit sessionStartScripts; + + sessionStartScriptsPath = let + sessionsCopy = (lib.concatStringsSep "\n" (lib.map (x: '' + cp "${x.startSession}" "$out/bin/start-${x.name}" + '') (lib.attrValues availableSessionsConfig))); + in pkgs.runCommandNoCCLocal "session-start-scripts" {} '' + mkdir -p $out/bin + ${sessionsCopy} + ''; + + autoStart.profileSelectContent = '' + if [[ "$(tty)" == "/dev/tty${builtins.toString cfg.autoStart.tty}" && "$(id -u)" != 0 ]]; then + ${cfg.selectSession} + fi + ''; + + selectSession = pkgs.writeShellScript "select-session" '' + sessions=(${lib.concatStringsSep " " cfg.availableSessions}) + session_indices=(''${!sessions[@]}) + + timeout=3 + selected="${cfg.defaultSession}" # default + + echo "Default session to start is $selected" + + echo "Available sessions:" + for i in ''${!sessions[@]}; do + echo " $((i+1))) ''${sessions[$i]}" + done + echo " q) Enter tty." + + echo -n "Choose session to start: " + read -t"$timeout" -n1 user_input + echo + + if [[ $user_input == "q" ]]; then + exit + elif [[ $user_input ]]; then + user_input=$((user_input-1)) + echo $user_input + if [[ " ''${session_indices[@]} " =~ " $user_input " ]]; then + selected="''${sessions[$user_input]}" + echo "Got $user_input. Going to start $selected" + else + echo "Got unknown option. Exiting." + exit + fi + else + echo "Got no input, starting $selected" + fi + + echo "Going to start $selected" + + # tty name is treated specially. It just exits. Use default session of tty, + # to not start any session. + if [[ $selected == "tty" ]]; then + exit + fi + + ${cfg.sessionStartScriptsPath}/bin/start-$selected + ''; + }; +} -- 2.48.1