Files
DankMaterialShell/core/cmd/dms/commands_systemd.go
2026-10-20 12:23:25 -04:00

135 lines
3.8 KiB
Go

package main
import (
"fmt"
"strings"
"github.com/duxlabs-dev/dux-shell/core/internal/config"
"github.com/duxlabs-dev/dux-shell/core/internal/deps"
"github.com/spf13/cobra"
)
var systemdCompositorFlag string
var systemdCmd = &cobra.Command{
Use: "systemd",
Short: "Start DMS as a systemd user service with the compositor session",
Long: `Manage dms.service for the compositor session.
enable makes the compositor's own session unit want dms.service, so DMS starts
with that compositor only: hyprland-session.target, niri.service or
mango-session.target. The compositor is the running one, or --compositor.`,
}
var systemdEnableCmd = &cobra.Command{
Use: "enable",
Short: "Start dms.service with the compositor session",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
wm, err := systemdCompositor()
if err != nil {
return err
}
unit, err := config.EnableSession(wm)
if err != nil {
return err
}
fmt.Printf("dms.service starts with %s\n", unit)
now, _ := cmd.Flags().GetBool("now")
if !now {
return nil
}
if err := runSystemctl("--user", "start", dmsSystemdUnit); err != nil {
return err
}
fmt.Println("dms.service started")
return nil
},
}
var systemdDisableCmd = &cobra.Command{
Use: "disable",
Short: "Stop starting dms.service with any compositor session",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
removed, err := config.DisableSession()
if err != nil {
return err
}
if len(removed) == 0 {
fmt.Println("dms.service was not wanted by any compositor session")
} else {
fmt.Printf("dms.service no longer starts with %s\n", strings.Join(removed, ", "))
}
now, _ := cmd.Flags().GetBool("now")
if !now {
return nil
}
return runSystemctl("--user", "stop", dmsSystemdUnit)
},
}
var systemdStatusCmd = &cobra.Command{
Use: "status",
Short: "Show which compositor sessions start dms.service",
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
state := getServiceState("dms", true)
if !state.exists {
fmt.Println("dms.service: not installed")
return
}
fmt.Printf("dms.service: %s", state.enabled)
if state.active != "" {
fmt.Printf(", %s", state.active)
}
fmt.Println()
wanted := config.SessionWanted()
if len(wanted) == 0 {
fmt.Println("Starts with: nothing (run 'dms systemd enable')")
return
}
fmt.Printf("Starts with: %s\n", strings.Join(wanted, ", "))
},
}
func systemdLifecycleCmd(verb string) *cobra.Command {
return &cobra.Command{
Use: verb,
Short: strings.ToUpper(verb[:1]) + verb[1:] + " dms.service",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runSystemctl("--user", verb, dmsSystemdUnit)
},
}
}
func systemdCompositor() (deps.WindowManager, error) {
if systemdCompositorFlag == "" {
if wm, ok := config.RunningCompositor(); ok {
return wm, nil
}
name, err := detectCompositorForSetup()
if err != nil {
return 0, err
}
systemdCompositorFlag = name
}
switch strings.ToLower(systemdCompositorFlag) {
case "hyprland":
return deps.WindowManagerHyprland, nil
case "niri":
return deps.WindowManagerNiri, nil
case "mango", "mangowc":
return deps.WindowManagerMango, nil
}
return 0, fmt.Errorf("unknown compositor %q (hyprland, niri or mango)", systemdCompositorFlag)
}
func init() {
systemdEnableCmd.Flags().StringVar(&systemdCompositorFlag, "compositor", "", "hyprland, niri or mango (default: the running one)")
systemdEnableCmd.Flags().Bool("now", false, "Also start dms.service")
systemdDisableCmd.Flags().Bool("now", false, "Also stop dms.service")
systemdCmd.AddCommand(systemdEnableCmd, systemdDisableCmd, systemdStatusCmd, systemdLifecycleCmd("start"), systemdLifecycleCmd("stop"), systemdLifecycleCmd("restart"))
}