update distro profiles

- add copy - add hyprvars (hyprland only) - add sync-system-layouts (hyprland only)
parent fec7ee86
...@@ -2,9 +2,11 @@ package create ...@@ -2,9 +2,11 @@ package create
import ( import (
"ximperconf/config" "ximperconf/config"
"ximperconf/hyprland"
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
...@@ -14,14 +16,23 @@ import ( ...@@ -14,14 +16,23 @@ import (
"github.com/urfave/cli/v3" "github.com/urfave/cli/v3"
) )
func processProfile(entries []LinkEntry, dryRun bool) { func processProfile(prof Profile, dryRun bool, res *Result) {
for _, entry := range entries {
// ----- копирование -----
for _, c := range prof.Copy {
src := expandPath(c.Src, "")
dest := expandPath(c.Dest, "")
_ = copyIfMissing(src, dest, dryRun, res)
}
// ----- ссылки -----
for _, entry := range prof.Links {
if len(entry.Apps) > 0 { if len(entry.Apps) > 0 {
for _, app := range entry.Apps { for _, app := range entry.Apps {
if commandExists(app) { if commandExists(app) {
sys := expandPath(entry.Sys, app) sys := expandPath(entry.Sys, app)
user := expandPath(entry.User, app) user := expandPath(entry.User, app)
_ = createLinkIfMissing(sys, user, dryRun) _ = createLinkIfMissing(sys, user, dryRun, res)
} }
} }
continue continue
...@@ -31,7 +42,69 @@ func processProfile(entries []LinkEntry, dryRun bool) { ...@@ -31,7 +42,69 @@ func processProfile(entries []LinkEntry, dryRun bool) {
} }
sys := expandPath(entry.Sys, "") sys := expandPath(entry.Sys, "")
user := expandPath(entry.User, "") user := expandPath(entry.User, "")
_ = createLinkIfMissing(sys, user, dryRun) _ = createLinkIfMissing(sys, user, dryRun, res)
}
// ----- hyprvars -----
for _, v := range prof.HyprVars {
_, err := hyprland.HyprlandVarGet(v.Name)
if err == nil {
res.HyprVars = append(res.HyprVars,
fmt.Sprintf("Уже существует: '%s' — пропущено", v.Name))
continue
}
if dryRun {
res.HyprVars = append(res.HyprVars,
fmt.Sprintf("[Dry-run] Установлена переменная: %s = %s", v.Name, v.Value))
continue
}
if _, err := hyprland.HyprlandVarSet(v.Name, v.Value); err != nil {
res.HyprVars = append(res.HyprVars,
fmt.Sprintf("Ошибка установки переменной %s: %v", v.Name, err))
} else {
res.HyprVars = append(res.HyprVars,
fmt.Sprintf("Установлена переменная: %s = %s", v.Name, v.Value))
}
}
// ----- синхронизация раскладок Hyprland-----
if prof.SyncSystemLayouts && !dryRun {
sysLayouts, err := hyprland.HyprlandGetKeyboardLayouts()
if err != nil {
res.SyncSystemLayouts = append(res.SyncSystemLayouts,
"Не удалось получить системные раскладки")
return
}
hyprLayouts, err := hyprland.HyprlandVarGet("kb_layout")
if err != nil {
res.SyncSystemLayouts = append(res.SyncSystemLayouts,
"Не удалось получить раскладки Hyprland")
return
}
if hyprLayouts == "" {
hyprLayouts = "<empty>"
}
res.SyncSystemLayouts = append(res.SyncSystemLayouts,
fmt.Sprintf("Раскладка XCB: %s", sysLayouts))
res.SyncSystemLayouts = append(res.SyncSystemLayouts,
fmt.Sprintf("Раскладка Hyprland: %s", hyprLayouts))
if hyprLayouts == "<empty>" {
if _, err := hyprland.HyprlandVarSet("kb_layout", sysLayouts); err != nil {
res.SyncSystemLayouts = append(res.SyncSystemLayouts,
"Не удалось обновить kb_layout")
return
}
res.SyncSystemLayouts = append(res.SyncSystemLayouts,
fmt.Sprintf("Раскладка обновлена: %s", sysLayouts))
} else {
res.SyncSystemLayouts = append(res.SyncSystemLayouts,
fmt.Sprintf("Раскладка уже установлена: %s", hyprLayouts))
}
} }
} }
...@@ -59,21 +132,84 @@ func commandExists(name string) bool { ...@@ -59,21 +132,84 @@ func commandExists(name string) bool {
return err == nil return err == nil
} }
func createLinkIfMissing(src, dest string, dryRun bool) error { func copyIfMissing(src, dest string, dryRun bool, res *Result) error {
if _, err := os.Stat(src); os.IsNotExist(err) { info, err := os.Stat(src)
if err != nil {
return err
}
if _, err := os.Stat(dest); err == nil {
res.Copies = append(res.Copies,
fmt.Sprintf("Уже существует: %s — пропущено", dest))
return nil return nil
} }
if _, err := os.Lstat(dest); err == nil {
if dryRun { if dryRun {
color.Yellow("[Dry-run] Уже существует: %s — пропущено", dest) res.Copies = append(res.Copies,
fmt.Sprintf("[Dry-run] Скопировано: %s → %s", src, dest))
return nil
}
if info.IsDir() {
if err := copyDir(src, dest); err != nil {
return err
}
} else { } else {
color.Yellow("Уже существует: %s — пропущено", dest) if err := copyFile(src, dest); err != nil {
return err
} }
}
res.Copies = append(res.Copies,
fmt.Sprintf("Скопировано: %s → %s", src, dest))
return nil
}
func copyFile(src, dest string) error {
if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil {
return err
}
data, err := os.ReadFile(src)
if err != nil {
return err
}
return os.WriteFile(dest, data, 0644)
}
func copyDir(src, dest string) error {
return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
rel, err := filepath.Rel(src, path)
if err != nil {
return err
}
target := filepath.Join(dest, rel)
if info.IsDir() {
return os.MkdirAll(target, info.Mode())
}
data, err := os.ReadFile(path)
if err != nil {
return err
}
return os.WriteFile(target, data, info.Mode())
})
}
func createLinkIfMissing(src, dest string, dryRun bool, res *Result) error {
if _, err := os.Stat(src); os.IsNotExist(err) {
return nil
}
if _, err := os.Lstat(dest); err == nil {
res.Links = append(res.Links,
fmt.Sprintf("Уже существует: %s — пропущено", dest))
return nil return nil
} }
if dryRun { if dryRun {
color.Blue("[Dry-run] Создана ссылка: %s → %s", dest, src) res.Links = append(res.Links,
fmt.Sprintf("[Dry-run] Создана ссылка: %s → %s", dest, src))
return nil return nil
} }
...@@ -83,11 +219,27 @@ func createLinkIfMissing(src, dest string, dryRun bool) error { ...@@ -83,11 +219,27 @@ func createLinkIfMissing(src, dest string, dryRun bool) error {
if err := os.Symlink(src, dest); err != nil { if err := os.Symlink(src, dest); err != nil {
return err return err
} }
color.Blue("Создана ссылка: %s → %s", dest, src) res.Links = append(res.Links,
fmt.Sprintf("Создана ссылка: %s → %s", dest, src))
return nil return nil
} }
func createProfile(profile string, dryRun bool) error { func printTree(title string, lines []string) {
if len(lines) == 0 {
return
}
color.Blue("%s", title)
for i, line := range lines {
branch := "├──"
if i == len(lines)-1 {
branch = "└──"
}
fmt.Printf("%s %s\n", branch, line)
}
fmt.Println()
}
func createProfile(profile string, dryRun bool, res *Result) error {
cfg, err := loadConfig(config.Env.Create.Config) cfg, err := loadConfig(config.Env.Create.Config)
if err != nil { if err != nil {
color.Red("Не удалось загрузить конфигурацию: %v", err) color.Red("Не удалось загрузить конфигурацию: %v", err)
...@@ -101,13 +253,20 @@ func createProfile(profile string, dryRun bool) error { ...@@ -101,13 +253,20 @@ func createProfile(profile string, dryRun bool) error {
} }
color.Green("Создаётся профиль: %s", profile) color.Green("Создаётся профиль: %s", profile)
processProfile(prof.Links, dryRun) processProfile(prof, dryRun, res)
return nil return nil
} }
func CreateConfCommand(ctx context.Context, cmd *cli.Command) error { func CreateConfCommand(ctx context.Context, cmd *cli.Command) error {
profile := cmd.Args().Get(0) profile := cmd.Args().Get(0)
dryRun := cmd.Bool("dry-run") dryRun := cmd.Bool("dry-run")
createProfile(profile, dryRun) res := &Result{}
createProfile(profile, dryRun, res)
printTree("Копируем", res.Copies)
printTree("Создаём ссылки", res.Links)
printTree("Создаём переменные Hyprland", res.HyprVars)
printTree("Синхронизируем раскладку Hyprland", res.SyncSystemLayouts)
return nil return nil
} }
package create package create
type CopyEntry struct {
Src string `json:"src"`
Dest string `json:"dest"`
}
type LinkEntry struct { type LinkEntry struct {
Apps []string `json:"apps,omitempty"` Apps []string `json:"apps,omitempty"`
App string `json:"app,omitempty"` App string `json:"app,omitempty"`
...@@ -7,11 +12,28 @@ type LinkEntry struct { ...@@ -7,11 +12,28 @@ type LinkEntry struct {
User string `json:"user"` User string `json:"user"`
} }
type HyprVar struct {
Name string `json:"name"`
Value string `json:"value"`
}
type Profile struct { type Profile struct {
Binary string `json:"binary,omitempty"` Binary string `json:"binary,omitempty"`
Copy []CopyEntry `json:"copy,omitempty"`
Links []LinkEntry `json:"links"` Links []LinkEntry `json:"links"`
// ----- hyprland -----
SyncSystemLayouts bool `json:"sync-system-layouts,omitempty"`
HyprVars []HyprVar `json:"hyprvars,omitempty"`
} }
type Config struct { type Config struct {
Profiles map[string]Profile `json:"profiles"` Profiles map[string]Profile `json:"profiles"`
} }
type Result struct {
Links []string
Copies []string
HyprVars []string
SyncSystemLayouts []string
}
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
"github.com/urfave/cli/v3" "github.com/urfave/cli/v3"
) )
func hyprlandGetKeyboardLayouts() (string, error) { func HyprlandGetKeyboardLayouts() (string, error) {
obj := config.DBusConn.Object("org.freedesktop.locale1", "/org/freedesktop/locale1") obj := config.DBusConn.Object("org.freedesktop.locale1", "/org/freedesktop/locale1")
variant := dbus.Variant{} variant := dbus.Variant{}
...@@ -31,18 +31,18 @@ func hyprlandGetKeyboardLayouts() (string, error) { ...@@ -31,18 +31,18 @@ func hyprlandGetKeyboardLayouts() (string, error) {
func HyprlandSyncSystemLayouts(ctx context.Context, cmd *cli.Command) error { func HyprlandSyncSystemLayouts(ctx context.Context, cmd *cli.Command) error {
force := cmd.Bool("force") force := cmd.Bool("force")
sysLayouts, err := hyprlandGetKeyboardLayouts() sysLayouts, err := HyprlandGetKeyboardLayouts()
if err != nil { if err != nil {
return fmt.Errorf("не удалось получить системные раскладки: %w", err) return fmt.Errorf("не удалось получить системные раскладки: %w", err)
} }
hyprLayouts, err := hyprlandVarGet("kb_layout") hyprLayouts, err := HyprlandVarGet("kb_layout")
if err != nil { if err != nil {
return fmt.Errorf("не удалось получить kb_layout из Hyprland: %w", err) return fmt.Errorf("не удалось получить kb_layout из Hyprland: %w", err)
} }
if force || hyprLayouts == "" { if force || hyprLayouts == "" {
if _, err := hyprlandVarSet("kb_layout", sysLayouts); err != nil { if _, err := HyprlandVarSet("kb_layout", sysLayouts); err != nil {
return fmt.Errorf("не удалось обновить kb_layout в Hyprland: %w", err) return fmt.Errorf("не удалось обновить kb_layout в Hyprland: %w", err)
} }
color.Green("Раскладка обновлена!") color.Green("Раскладка обновлена!")
......
...@@ -117,7 +117,7 @@ func HyprlandVarInfoCommand(ctx context.Context, cmd *cli.Command) error { ...@@ -117,7 +117,7 @@ func HyprlandVarInfoCommand(ctx context.Context, cmd *cli.Command) error {
return nil return nil
} }
func hyprlandVarGet(name string) (string, error) { func HyprlandVarGet(name string) (string, error) {
if name == "" { if name == "" {
return "", fmt.Errorf("укажите имя переменной") return "", fmt.Errorf("укажите имя переменной")
} }
...@@ -151,7 +151,7 @@ func hyprlandVarGet(name string) (string, error) { ...@@ -151,7 +151,7 @@ func hyprlandVarGet(name string) (string, error) {
func HyprlandVarGetCommand(ctx context.Context, cmd *cli.Command) error { func HyprlandVarGetCommand(ctx context.Context, cmd *cli.Command) error {
info, err := hyprlandVarGet(cmd.Args().Get(0)) info, err := HyprlandVarGet(cmd.Args().Get(0))
if err != nil { if err != nil {
color.Red(err.Error()) color.Red(err.Error())
return err return err
...@@ -160,7 +160,7 @@ func HyprlandVarGetCommand(ctx context.Context, cmd *cli.Command) error { ...@@ -160,7 +160,7 @@ func HyprlandVarGetCommand(ctx context.Context, cmd *cli.Command) error {
return nil return nil
} }
func hyprlandVarSet(name, newValue string) (string, error) { func HyprlandVarSet(name, newValue string) (string, error) {
if name == "" { if name == "" {
return "", fmt.Errorf("укажите имя переменной") return "", fmt.Errorf("укажите имя переменной")
} }
...@@ -230,7 +230,7 @@ func hyprlandVarSet(name, newValue string) (string, error) { ...@@ -230,7 +230,7 @@ func hyprlandVarSet(name, newValue string) (string, error) {
func HyprlandVarSetCommand(ctx context.Context, cmd *cli.Command) error { func HyprlandVarSetCommand(ctx context.Context, cmd *cli.Command) error {
msg, err := hyprlandVarSet(cmd.Args().Get(0), cmd.Args().Get(1)) msg, err := HyprlandVarSet(cmd.Args().Get(0), cmd.Args().Get(1))
if err != nil { if err != nil {
color.Red(err.Error()) color.Red(err.Error())
return err return err
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment