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