A home/modules/sessions/default-hm-impl.nix => home/modules/sessions/default-hm-impl.nix +18 -0
@@ 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;
+ };
+
+}
A home/modules/sessions/default.nix => home/modules/sessions/default.nix +183 -0
@@ 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
+ '';
+ };
+}