update distro profiles

- add copy - add hyprvars (hyprland only) - add sync-system-layouts (hyprland only)
parent fec7ee86
......@@ -2,9 +2,11 @@ package create
import (
"ximperconf/config"
"ximperconf/hyprland"
"context"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
......@@ -14,14 +16,23 @@ import (
"github.com/urfave/cli/v3"
)
func processProfile(entries []LinkEntry, dryRun bool) {
for _, entry := range entries {
func processProfile(prof Profile, dryRun bool, res *Result) {
// ----- копирование -----
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 {
for _, app := range entry.Apps {
if commandExists(app) {
sys := expandPath(entry.Sys, app)
user := expandPath(entry.User, app)
_ = createLinkIfMissing(sys, user, dryRun)
_ = createLinkIfMissing(sys, user, dryRun, res)
}
}
continue
......@@ -31,7 +42,69 @@ func processProfile(entries []LinkEntry, dryRun bool) {
}
sys := expandPath(entry.Sys, "")
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 {
return err == nil
}
func createLinkIfMissing(src, dest string, dryRun bool) error {
func copyIfMissing(src, dest string, dryRun bool, res *Result) error {
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
}
if dryRun {
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 {
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 {
if dryRun {
color.Yellow("[Dry-run] Уже существует: %s — пропущено", dest)
} else {
color.Yellow("Уже существует: %s — пропущено", dest)
}
res.Links = append(res.Links,
fmt.Sprintf("Уже существует: %s — пропущено", dest))
return nil
}
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
}
......@@ -83,11 +219,27 @@ func createLinkIfMissing(src, dest string, dryRun bool) error {
if err := os.Symlink(src, dest); err != nil {
return err
}
color.Blue("Создана ссылка: %s → %s", dest, src)
res.Links = append(res.Links,
fmt.Sprintf("Создана ссылка: %s → %s", dest, src))
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)
if err != nil {
color.Red("Не удалось загрузить конфигурацию: %v", err)
......@@ -101,13 +253,20 @@ func createProfile(profile string, dryRun bool) error {
}
color.Green("Создаётся профиль: %s", profile)
processProfile(prof.Links, dryRun)
processProfile(prof, dryRun, res)
return nil
}
func CreateConfCommand(ctx context.Context, cmd *cli.Command) error {
profile := cmd.Args().Get(0)
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
}
package create
type CopyEntry struct {
Src string `json:"src"`
Dest string `json:"dest"`
}
type LinkEntry struct {
Apps []string `json:"apps,omitempty"`
App string `json:"app,omitempty"`
......@@ -7,11 +12,28 @@ type LinkEntry struct {
User string `json:"user"`
}
type HyprVar struct {
Name string `json:"name"`
Value string `json:"value"`
}
type Profile struct {
Binary string `json:"binary,omitempty"`
Copy []CopyEntry `json:"copy,omitempty"`
Links []LinkEntry `json:"links"`
// ----- hyprland -----
SyncSystemLayouts bool `json:"sync-system-layouts,omitempty"`
HyprVars []HyprVar `json:"hyprvars,omitempty"`
}
type Config struct {
Profiles map[string]Profile `json:"profiles"`
}
type Result struct {
Links []string
Copies []string
HyprVars []string
SyncSystemLayouts []string
}
......@@ -10,7 +10,7 @@ import (
"github.com/urfave/cli/v3"
)
func hyprlandGetKeyboardLayouts() (string, error) {
func HyprlandGetKeyboardLayouts() (string, error) {
obj := config.DBusConn.Object("org.freedesktop.locale1", "/org/freedesktop/locale1")
variant := dbus.Variant{}
......@@ -31,18 +31,18 @@ func hyprlandGetKeyboardLayouts() (string, error) {
func HyprlandSyncSystemLayouts(ctx context.Context, cmd *cli.Command) error {
force := cmd.Bool("force")
sysLayouts, err := hyprlandGetKeyboardLayouts()
sysLayouts, err := HyprlandGetKeyboardLayouts()
if err != nil {
return fmt.Errorf("не удалось получить системные раскладки: %w", err)
}
hyprLayouts, err := hyprlandVarGet("kb_layout")
hyprLayouts, err := HyprlandVarGet("kb_layout")
if err != nil {
return fmt.Errorf("не удалось получить kb_layout из Hyprland: %w", err)
}
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)
}
color.Green("Раскладка обновлена!")
......
......@@ -117,7 +117,7 @@ func HyprlandVarInfoCommand(ctx context.Context, cmd *cli.Command) error {
return nil
}
func hyprlandVarGet(name string) (string, error) {
func HyprlandVarGet(name string) (string, error) {
if name == "" {
return "", fmt.Errorf("укажите имя переменной")
}
......@@ -151,7 +151,7 @@ func hyprlandVarGet(name string) (string, 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 {
color.Red(err.Error())
return err
......@@ -160,7 +160,7 @@ func HyprlandVarGetCommand(ctx context.Context, cmd *cli.Command) error {
return nil
}
func hyprlandVarSet(name, newValue string) (string, error) {
func HyprlandVarSet(name, newValue string) (string, error) {
if name == "" {
return "", fmt.Errorf("укажите имя переменной")
}
......@@ -230,7 +230,7 @@ func hyprlandVarSet(name, newValue string) (string, 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 {
color.Red(err.Error())
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