Commit 661d0a49 authored by Kirill Unitsaev's avatar Kirill Unitsaev

hyprland/manager: optimize config handling with caching

- Add SourceLine cache to avoid parsing all lines in GetModuleInfo - Add LoadedPluginsMap for O(1) plugin status lookup - Change GetModulesList to return []HyprModule to eliminate double iteration - Fix cache updates in SetVar, SetModule, removeLine - Remove space normalization in normalizeHyprlandLine
parent e64e7d14
...@@ -173,10 +173,8 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error { ...@@ -173,10 +173,8 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
items := make([]ui.TreeItem, 0, len(modules)) items := make([]ui.TreeItem, 0, len(modules))
for _, module := range modules { for _, info := range modules {
info := manager.GetModuleInfo(module, user) errors, err := manager.CheckModule(info.Name, user)
errors, err := manager.CheckModule(module, user)
if err != nil { if err != nil {
errors = []HyprConfigError{} errors = []HyprConfigError{}
...@@ -187,7 +185,7 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error { ...@@ -187,7 +185,7 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
desc = fmt.Sprintf("(ошибки: %d)", errornum) desc = fmt.Sprintf("(ошибки: %d)", errornum)
} }
items = append(items, ui.TreeItem{ items = append(items, ui.TreeItem{
Name: module, Name: info.Name,
Status: info.Status, Status: info.Status,
Description: desc, Description: desc,
}) })
......
...@@ -237,9 +237,9 @@ func ShellCompleteModule(filter string) func(ctx context.Context, cmd *cli.Comma ...@@ -237,9 +237,9 @@ func ShellCompleteModule(filter string) func(ctx context.Context, cmd *cli.Comma
userFlag := cmd.Bool("user") userFlag := cmd.Bool("user")
data := manager.GetModulesList(userFlag, filter) modules := manager.GetModulesList(userFlag, filter)
for _, t := range data { for _, m := range modules {
fmt.Println(t) fmt.Println(m.Name)
} }
} }
} }
......
...@@ -22,8 +22,16 @@ type HyprlandManager struct { ...@@ -22,8 +22,16 @@ type HyprlandManager struct {
UserModules []string UserModules []string
SystemModules []string SystemModules []string
Vars []HyprVar Vars []HyprVar
Sources []SourceLine
Plugins []string Plugins []string
LoadedPlugins []HyprPlugin LoadedPlugins []HyprPlugin
LoadedPluginsMap map[string]HyprPlugin
}
type SourceLine struct {
Path string
LineNumber int
Commented bool
} }
type HyprModule struct { type HyprModule struct {
...@@ -71,18 +79,24 @@ func NewHyprlandManager() (*HyprlandManager, error) { ...@@ -71,18 +79,24 @@ func NewHyprlandManager() (*HyprlandManager, error) {
} }
manager := &HyprlandManager{ manager := &HyprlandManager{
ConfPath: config.Env.Hyprland.Config, ConfPath: config.Env.Hyprland.Config,
PluginsDir: config.Env.Hyprland.PluginsDir, PluginsDir: config.Env.Hyprland.PluginsDir,
Lines: lines, Lines: lines,
Home: home, Home: home,
LoadedPluginsMap: make(map[string]HyprPlugin),
} }
manager.Vars = manager.GetVarList() manager.Vars = manager.GetVarList()
manager.Sources = manager.parseSourceLines()
manager.UserModules = manager.scanModulesDir(true) manager.UserModules = manager.scanModulesDir(true)
manager.SystemModules = manager.scanModulesDir(false) manager.SystemModules = manager.scanModulesDir(false)
manager.Plugins = manager.scanPluginsDir() manager.Plugins = manager.scanPluginsDir()
manager.LoadedPlugins = manager.GetLoadedPlugins() manager.LoadedPlugins = manager.GetLoadedPlugins()
for _, p := range manager.LoadedPlugins {
manager.LoadedPluginsMap[p.Name] = p
}
return manager, nil return manager, nil
} }
...@@ -199,20 +213,19 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule { ...@@ -199,20 +213,19 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
foundCommented := false foundCommented := false
var LineNumber int var LineNumber int
for i, line := range m.Lines { for _, src := range m.Sources {
path, commented, ok := m.parseModuleLine(line) if src.Path != ConfPath {
if !ok || path != ConfPath {
continue continue
} }
if commented { if src.Commented {
foundCommented = true foundCommented = true
LineNumber = i LineNumber = src.LineNumber
continue continue
} }
foundActive = true foundActive = true
LineNumber = i LineNumber = src.LineNumber
break break
} }
...@@ -289,15 +302,15 @@ func (m *HyprlandManager) GetModuleDir(user bool) string { ...@@ -289,15 +302,15 @@ func (m *HyprlandManager) GetModuleDir(user bool) string {
return config.Env.Hyprland.SystemModulesDir return config.Env.Hyprland.SystemModulesDir
} }
func (m *HyprlandManager) GetModulesList(user bool, filter string) []string { func (m *HyprlandManager) GetModulesList(user bool, filter string) []HyprModule {
var modules []string var modules []string
var res []string
if user { if user {
modules = m.UserModules modules = m.UserModules
} else { } else {
modules = m.SystemModules modules = m.SystemModules
} }
var res []HyprModule
for _, module := range modules { for _, module := range modules {
info := m.GetModuleInfo(module, user) info := m.GetModuleInfo(module, user)
...@@ -306,7 +319,7 @@ func (m *HyprlandManager) GetModulesList(user bool, filter string) []string { ...@@ -306,7 +319,7 @@ func (m *HyprlandManager) GetModulesList(user bool, filter string) []string {
} }
if filter == "" || filter == "all" || info.Status.Label == filter { if filter == "" || filter == "all" || info.Status.Label == filter {
res = append(res, module) res = append(res, info)
} }
} }
return res return res
...@@ -342,6 +355,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) ( ...@@ -342,6 +355,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
return "", fmt.Errorf("модуль '%s' уже присутствует в конфиге (закомментирован) — пропущено", module) return "", fmt.Errorf("модуль '%s' уже присутствует в конфиге (закомментирован) — пропущено", module)
} }
m.Lines[info.LineNumber] = strings.TrimPrefix(m.Lines[info.LineNumber], "#") m.Lines[info.LineNumber] = strings.TrimPrefix(m.Lines[info.LineNumber], "#")
m.updateSourceCommented(info.LineNumber, false)
m.Changed = true m.Changed = true
return fmt.Sprintf("Модуль '%s' включён", module), nil return fmt.Sprintf("Модуль '%s' включён", module), nil
} }
...@@ -349,7 +363,13 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) ( ...@@ -349,7 +363,13 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
// не использовался // не использовался
if info.Status.IsEqual(config.ModuleStatus.Unused) { if info.Status.IsEqual(config.ModuleStatus.Unused) {
line := "source = " + info.ConfPath line := "source = " + info.ConfPath
lineNum := len(m.Lines)
m.Lines = append(m.Lines, line) m.Lines = append(m.Lines, line)
m.Sources = append(m.Sources, SourceLine{
Path: info.ConfPath,
LineNumber: lineNum,
Commented: false,
})
m.Changed = true m.Changed = true
return fmt.Sprintf("Модуль '%s' включён", module), nil return fmt.Sprintf("Модуль '%s' включён", module), nil
} }
...@@ -368,6 +388,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) ( ...@@ -368,6 +388,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
if info.Status.IsEqual(config.ModuleStatus.Enabled) || if info.Status.IsEqual(config.ModuleStatus.Enabled) ||
info.Status.IsEqual(config.ModuleStatus.Missing) { info.Status.IsEqual(config.ModuleStatus.Missing) {
m.Lines[info.LineNumber] = "#" + m.Lines[info.LineNumber] m.Lines[info.LineNumber] = "#" + m.Lines[info.LineNumber]
m.updateSourceCommented(info.LineNumber, true)
m.Changed = true m.Changed = true
return fmt.Sprintf("Модуль '%s' отключён", module), nil return fmt.Sprintf("Модуль '%s' отключён", module), nil
} }
...@@ -378,6 +399,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) ( ...@@ -378,6 +399,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
return "", fmt.Errorf("модуль '%s' не найден в конфигурации", module) return "", fmt.Errorf("модуль '%s' не найден в конфигурации", module)
} }
m.removeSource(info.LineNumber)
m.removeLine(info.LineNumber) m.removeLine(info.LineNumber)
return fmt.Sprintf("Модуль '%s' удалён", module), nil return fmt.Sprintf("Модуль '%s' удалён", module), nil
...@@ -400,11 +422,8 @@ func (m *HyprlandManager) GetLoadedPlugins() []HyprPlugin { ...@@ -400,11 +422,8 @@ func (m *HyprlandManager) GetLoadedPlugins() []HyprPlugin {
} }
func (m *HyprlandManager) GetPluginStatus(name string) config.ItemStatus { func (m *HyprlandManager) GetPluginStatus(name string) config.ItemStatus {
if _, ok := m.LoadedPluginsMap[name]; ok {
for _, p := range m.LoadedPlugins { return config.PluginStatus.Loaded
if p.Name == name {
return config.PluginStatus.Loaded
}
} }
return config.PluginStatus.Unloaded return config.PluginStatus.Unloaded
} }
...@@ -509,12 +528,13 @@ func (m *HyprlandManager) SetVar(name, value string) (string, error) { ...@@ -509,12 +528,13 @@ func (m *HyprlandManager) SetVar(name, value string) (string, error) {
return "", fmt.Errorf("укажите значение переменной") return "", fmt.Errorf("укажите значение переменной")
} }
for _, v := range m.Vars { for i, v := range m.Vars {
if v.Name == name { if v.Name == name {
if v.Value == value { if v.Value == value {
return "", fmt.Errorf("переменная '%s' уже '%s'", v.Name, v.Value) return "", fmt.Errorf("переменная '%s' уже '%s'", v.Name, v.Value)
} }
m.Lines[v.LineNumber] = fmt.Sprintf("$%s = %s", name, value) m.Lines[v.LineNumber] = fmt.Sprintf("$%s = %s", name, value)
m.Vars[i].Value = value
m.Changed = true m.Changed = true
return fmt.Sprintf("Переменная '%s' обновлена: %s", name, value), nil return fmt.Sprintf("Переменная '%s' обновлена: %s", name, value), nil
} }
...@@ -535,15 +555,19 @@ func (m *HyprlandManager) SetVar(name, value string) (string, error) { ...@@ -535,15 +555,19 @@ func (m *HyprlandManager) SetVar(name, value string) (string, error) {
m.Lines[:insertAt], m.Lines[:insertAt],
append([]string{newLine}, m.Lines[insertAt:]...)..., append([]string{newLine}, m.Lines[insertAt:]...)...,
) )
m.shiftLineNumbers(insertAt, 1)
m.Vars = append(m.Vars, HyprVar{Name: name, Value: value, LineNumber: insertAt})
m.Changed = true m.Changed = true
return fmt.Sprintf("Переменная '%s' установлена: %s", name, value), nil return fmt.Sprintf("Переменная '%s' установлена: %s", name, value), nil
} }
newLineNumber := len(m.Lines)
m.Lines = append(m.Lines, m.Lines = append(m.Lines,
"", "",
"#---------- ПЕРЕМЕННЫЕ ---- VARS", "#---------- ПЕРЕМЕННЫЕ ---- VARS",
newLine, newLine,
) )
m.Vars = append(m.Vars, HyprVar{Name: name, Value: value, LineNumber: newLineNumber + 2})
m.Changed = true m.Changed = true
return fmt.Sprintf("Блок VARS создан, переменная '%s' установлена: %s", name, value), nil return fmt.Sprintf("Блок VARS создан, переменная '%s' установлена: %s", name, value), nil
} }
...@@ -553,9 +577,10 @@ func (m *HyprlandManager) UnsetVar(name string) error { ...@@ -553,9 +577,10 @@ func (m *HyprlandManager) UnsetVar(name string) error {
return fmt.Errorf("укажите имя переменной") return fmt.Errorf("укажите имя переменной")
} }
for _, v := range m.Vars { for i, v := range m.Vars {
if v.Name == name { if v.Name == name {
m.removeLine(v.LineNumber) m.removeLine(v.LineNumber)
m.Vars = append(m.Vars[:i], m.Vars[i+1:]...)
return nil return nil
} }
} }
...@@ -564,6 +589,21 @@ func (m *HyprlandManager) UnsetVar(name string) error { ...@@ -564,6 +589,21 @@ func (m *HyprlandManager) UnsetVar(name string) error {
// ==================== // ====================
func (m *HyprlandManager) parseSourceLines() []SourceLine {
var sources []SourceLine
for i, line := range m.Lines {
path, commented, ok := m.parseModuleLine(line)
if ok {
sources = append(sources, SourceLine{
Path: path,
LineNumber: i,
Commented: commented,
})
}
}
return sources
}
func (m *HyprlandManager) parseModuleLine(line string) (path string, commented bool, ok bool) { func (m *HyprlandManager) parseModuleLine(line string) (path string, commented bool, ok bool) {
if strings.HasPrefix(line, "#") { if strings.HasPrefix(line, "#") {
...@@ -667,11 +707,43 @@ func (m *HyprlandManager) parseCheckOutput(out []byte) []HyprConfigError { ...@@ -667,11 +707,43 @@ func (m *HyprlandManager) parseCheckOutput(out []byte) []HyprConfigError {
return res return res
} }
func (m *HyprlandManager) removeLine(LineNumber int) { func (m *HyprlandManager) removeLine(lineNumber int) {
m.Lines = append(m.Lines[:LineNumber], m.Lines[LineNumber+1:]...) m.Lines = append(m.Lines[:lineNumber], m.Lines[lineNumber+1:]...)
m.shiftLineNumbers(lineNumber, -1)
m.Changed = true m.Changed = true
} }
func (m *HyprlandManager) shiftLineNumbers(afterLine, delta int) {
for i := range m.Vars {
if m.Vars[i].LineNumber > afterLine {
m.Vars[i].LineNumber += delta
}
}
for i := range m.Sources {
if m.Sources[i].LineNumber > afterLine {
m.Sources[i].LineNumber += delta
}
}
}
func (m *HyprlandManager) updateSourceCommented(lineNumber int, commented bool) {
for i := range m.Sources {
if m.Sources[i].LineNumber == lineNumber {
m.Sources[i].Commented = commented
return
}
}
}
func (m *HyprlandManager) removeSource(lineNumber int) {
for i := range m.Sources {
if m.Sources[i].LineNumber == lineNumber {
m.Sources = append(m.Sources[:i], m.Sources[i+1:]...)
return
}
}
}
func (m *HyprlandManager) scanModulesDir(user bool) []string { func (m *HyprlandManager) scanModulesDir(user bool) []string {
dir := m.GetModuleDir(user) dir := m.GetModuleDir(user)
...@@ -709,34 +781,9 @@ func (m *HyprlandManager) scanPluginsDir() []string { ...@@ -709,34 +781,9 @@ func (m *HyprlandManager) scanPluginsDir() []string {
} }
func normalizeHyprlandLine(line, home string) string { func normalizeHyprlandLine(line, home string) string {
line = strings.TrimSpace(line)
if line == "" {
return ""
}
// проверяем, закомментирована ли строка
commented := strings.HasPrefix(line, "#")
if commented {
line = strings.TrimSpace(strings.TrimPrefix(line, "#"))
}
// пробелы вокруг "="
if strings.Contains(line, "=") {
parts := strings.SplitN(line, "=", 2)
left := strings.TrimSpace(parts[0])
right := strings.TrimSpace(parts[1])
line = left + " = " + right
}
// HOME → ~ // HOME → ~
if home != "" { if home != "" {
line = strings.ReplaceAll(line, home, "~") line = strings.ReplaceAll(line, home, "~")
} }
if commented {
return "#" + line
}
return line return line
} }
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