mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-04 04:42:05 -04:00
cli/setup: add subcommands for individual includes
This commit is contained in:
@@ -9,7 +9,9 @@ import (
|
||||
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/config"
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/deps"
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/greeter"
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
|
||||
"github.com/AvengeMedia/DankMaterialShell/core/internal/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -24,6 +26,243 @@ var setupCmd = &cobra.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var setupBindsCmd = &cobra.Command{
|
||||
Use: "binds",
|
||||
Short: "Deploy default keybinds config",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := runSetupDmsConfig("binds"); err != nil {
|
||||
log.Fatalf("Error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var setupLayoutCmd = &cobra.Command{
|
||||
Use: "layout",
|
||||
Short: "Deploy default layout config",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := runSetupDmsConfig("layout"); err != nil {
|
||||
log.Fatalf("Error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var setupColorsCmd = &cobra.Command{
|
||||
Use: "colors",
|
||||
Short: "Deploy default colors config",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := runSetupDmsConfig("colors"); err != nil {
|
||||
log.Fatalf("Error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var setupAlttabCmd = &cobra.Command{
|
||||
Use: "alttab",
|
||||
Short: "Deploy default alt-tab config (niri only)",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := runSetupDmsConfig("alttab"); err != nil {
|
||||
log.Fatalf("Error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var setupOutputsCmd = &cobra.Command{
|
||||
Use: "outputs",
|
||||
Short: "Deploy default outputs config",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := runSetupDmsConfig("outputs"); err != nil {
|
||||
log.Fatalf("Error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var setupCursorCmd = &cobra.Command{
|
||||
Use: "cursor",
|
||||
Short: "Deploy default cursor config",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := runSetupDmsConfig("cursor"); err != nil {
|
||||
log.Fatalf("Error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
var setupWindowrulesCmd = &cobra.Command{
|
||||
Use: "windowrules",
|
||||
Short: "Deploy default window rules config",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := runSetupDmsConfig("windowrules"); err != nil {
|
||||
log.Fatalf("Error: %v", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
type dmsConfigSpec struct {
|
||||
niriFile string
|
||||
hyprFile string
|
||||
niriContent func(terminal string) string
|
||||
hyprContent func(terminal string) string
|
||||
}
|
||||
|
||||
var dmsConfigSpecs = map[string]dmsConfigSpec{
|
||||
"binds": {
|
||||
niriFile: "binds.kdl",
|
||||
hyprFile: "binds.conf",
|
||||
niriContent: func(t string) string {
|
||||
return strings.ReplaceAll(config.NiriBindsConfig, "{{TERMINAL_COMMAND}}", t)
|
||||
},
|
||||
hyprContent: func(t string) string {
|
||||
return strings.ReplaceAll(config.HyprBindsConfig, "{{TERMINAL_COMMAND}}", t)
|
||||
},
|
||||
},
|
||||
"layout": {
|
||||
niriFile: "layout.kdl",
|
||||
hyprFile: "layout.conf",
|
||||
niriContent: func(_ string) string { return config.NiriLayoutConfig },
|
||||
hyprContent: func(_ string) string { return config.HyprLayoutConfig },
|
||||
},
|
||||
"colors": {
|
||||
niriFile: "colors.kdl",
|
||||
hyprFile: "colors.conf",
|
||||
niriContent: func(_ string) string { return config.NiriColorsConfig },
|
||||
hyprContent: func(_ string) string { return config.HyprColorsConfig },
|
||||
},
|
||||
"alttab": {
|
||||
niriFile: "alttab.kdl",
|
||||
niriContent: func(_ string) string { return config.NiriAlttabConfig },
|
||||
},
|
||||
"outputs": {
|
||||
niriFile: "outputs.kdl",
|
||||
hyprFile: "outputs.conf",
|
||||
niriContent: func(_ string) string { return "" },
|
||||
hyprContent: func(_ string) string { return "" },
|
||||
},
|
||||
"cursor": {
|
||||
niriFile: "cursor.kdl",
|
||||
hyprFile: "cursor.conf",
|
||||
niriContent: func(_ string) string { return "" },
|
||||
hyprContent: func(_ string) string { return "" },
|
||||
},
|
||||
"windowrules": {
|
||||
niriFile: "windowrules.kdl",
|
||||
hyprFile: "windowrules.conf",
|
||||
niriContent: func(_ string) string { return "" },
|
||||
hyprContent: func(_ string) string { return "" },
|
||||
},
|
||||
}
|
||||
|
||||
func detectTerminal() (string, error) {
|
||||
terminals := []string{"ghostty", "foot", "kitty", "alacritty"}
|
||||
var found []string
|
||||
for _, t := range terminals {
|
||||
if utils.CommandExists(t) {
|
||||
found = append(found, t)
|
||||
}
|
||||
}
|
||||
|
||||
switch len(found) {
|
||||
case 0:
|
||||
return "ghostty", nil
|
||||
case 1:
|
||||
return found[0], nil
|
||||
}
|
||||
|
||||
fmt.Println("Multiple terminals detected:")
|
||||
for i, t := range found {
|
||||
fmt.Printf("%d) %s\n", i+1, t)
|
||||
}
|
||||
fmt.Printf("\nChoice (1-%d): ", len(found))
|
||||
|
||||
var response string
|
||||
fmt.Scanln(&response)
|
||||
response = strings.TrimSpace(response)
|
||||
|
||||
choice := 0
|
||||
fmt.Sscanf(response, "%d", &choice)
|
||||
if choice < 1 || choice > len(found) {
|
||||
return "", fmt.Errorf("invalid choice")
|
||||
}
|
||||
return found[choice-1], nil
|
||||
}
|
||||
|
||||
func detectCompositorForSetup() (string, error) {
|
||||
compositors := greeter.DetectCompositors()
|
||||
|
||||
switch len(compositors) {
|
||||
case 0:
|
||||
return "", fmt.Errorf("no supported compositors found (niri or Hyprland required)")
|
||||
case 1:
|
||||
return strings.ToLower(compositors[0]), nil
|
||||
}
|
||||
|
||||
selected, err := greeter.PromptCompositorChoice(compositors)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.ToLower(selected), nil
|
||||
}
|
||||
|
||||
func runSetupDmsConfig(name string) error {
|
||||
spec, ok := dmsConfigSpecs[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown config: %s", name)
|
||||
}
|
||||
|
||||
compositor, err := detectCompositorForSetup()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var filename string
|
||||
var contentFn func(string) string
|
||||
switch compositor {
|
||||
case "niri":
|
||||
filename = spec.niriFile
|
||||
contentFn = spec.niriContent
|
||||
case "hyprland":
|
||||
filename = spec.hyprFile
|
||||
contentFn = spec.hyprContent
|
||||
default:
|
||||
return fmt.Errorf("unsupported compositor: %s", compositor)
|
||||
}
|
||||
|
||||
if filename == "" {
|
||||
return fmt.Errorf("%s is not supported for %s", name, compositor)
|
||||
}
|
||||
|
||||
var dmsDir string
|
||||
switch compositor {
|
||||
case "niri":
|
||||
dmsDir = filepath.Join(os.Getenv("HOME"), ".config", "niri", "dms")
|
||||
case "hyprland":
|
||||
dmsDir = filepath.Join(os.Getenv("HOME"), ".config", "hypr", "dms")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(dmsDir, 0o755); err != nil {
|
||||
return fmt.Errorf("failed to create dms directory: %w", err)
|
||||
}
|
||||
|
||||
path := filepath.Join(dmsDir, filename)
|
||||
if info, err := os.Stat(path); err == nil && info.Size() > 0 {
|
||||
return fmt.Errorf("%s already exists and is not empty: %s", name, path)
|
||||
}
|
||||
|
||||
terminal := "ghostty"
|
||||
if contentFn != nil && name == "binds" {
|
||||
terminal, err = detectTerminal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
content := contentFn(terminal)
|
||||
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
||||
return fmt.Errorf("failed to write %s: %w", filename, err)
|
||||
}
|
||||
|
||||
fmt.Printf("Deployed %s to %s\n", name, path)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runSetup() error {
|
||||
fmt.Println("=== DMS Configuration Setup ===")
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ func init() {
|
||||
// Add subcommands to greeter
|
||||
greeterCmd.AddCommand(greeterInstallCmd, greeterSyncCmd, greeterEnableCmd, greeterStatusCmd)
|
||||
|
||||
// Add subcommands to setup
|
||||
setupCmd.AddCommand(setupBindsCmd, setupLayoutCmd, setupColorsCmd, setupAlttabCmd, setupOutputsCmd, setupCursorCmd, setupWindowrulesCmd)
|
||||
|
||||
// Add subcommands to update
|
||||
updateCmd.AddCommand(updateCheckCmd)
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ func init() {
|
||||
// Add subcommands to greeter
|
||||
greeterCmd.AddCommand(greeterSyncCmd, greeterEnableCmd, greeterStatusCmd)
|
||||
|
||||
// Add subcommands to setup
|
||||
setupCmd.AddCommand(setupBindsCmd, setupLayoutCmd, setupColorsCmd, setupAlttabCmd, setupOutputsCmd, setupCursorCmd, setupWindowrulesCmd)
|
||||
|
||||
// Add subcommands to plugins
|
||||
pluginsCmd.AddCommand(pluginsBrowseCmd, pluginsListCmd, pluginsInstallCmd, pluginsUninstallCmd, pluginsUpdateCmd)
|
||||
|
||||
|
||||
@@ -1014,6 +1014,7 @@ Singleton {
|
||||
|
||||
for config_dir in ${_configDir}/gtk-3.0 ${_configDir}/gtk-4.0; do
|
||||
settings_file="$config_dir/settings.ini"
|
||||
[ -f "$settings_file" ] && [ ! -w "$settings_file" ] && continue
|
||||
if [ -f "$settings_file" ]; then
|
||||
if grep -q "^gtk-icon-theme-name=" "$settings_file"; then
|
||||
sed -i 's/^gtk-icon-theme-name=.*/gtk-icon-theme-name=${gtkThemeName}/' "$settings_file"
|
||||
@@ -1863,6 +1864,7 @@ Singleton {
|
||||
|
||||
const script = `
|
||||
xresources_file="${xresourcesPath}"
|
||||
[ -f "$xresources_file" ] && [ ! -w "$xresources_file" ] && exit 0
|
||||
theme_name="${themeName}"
|
||||
cursor_size="${size}"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user