hyprland/module: ordered insertion with config sections

parent 19c74f34
......@@ -7,6 +7,7 @@ import (
"os"
"os/exec"
"path/filepath"
"slices"
"strings"
"time"
"ximperconf/config"
......@@ -387,15 +388,11 @@ 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
order := 0
if info.Meta != nil {
order = info.Meta.Order
}
m.insertSourceLine(info.ConfPath, user, order)
return m.enableMessage(module, disabledGroup), nil
}
......@@ -440,6 +437,173 @@ func (m *HyprlandManager) enableMessage(module string, disabledGroup []string) s
return msg
}
// Sections
// Порядок секций: VARS → SYSTEM MODULES → USER MODULES
const sectionMarkerPrefix = "#----------"
var sectionVars = [2]string{"ПЕРЕМЕННЫЕ", "VARS"}
var sectionSystemModules = [2]string{"СИСТЕМНЫЕ МОДУЛИ", "SYSTEM MODULES"}
var sectionUserModules = [2]string{"ПОЛЬЗОВАТЕЛЬСКИЕ МОДУЛИ", "USER MODULES"}
func sectionHeader(section [2]string) string {
return fmt.Sprintf("#---------- %s ---- %s", section[0], section[1])
}
func (m *HyprlandManager) findSectionMarker(section [2]string) int {
for i, line := range m.Lines {
if strings.Contains(line, section[0]) && strings.Contains(line, section[1]) {
return i
}
}
return -1
}
func (m *HyprlandManager) findSectionEnd(markerLine int) int {
for i := markerLine + 1; i < len(m.Lines); i++ {
if strings.HasPrefix(strings.TrimSpace(m.Lines[i]), sectionMarkerPrefix) {
return i
}
}
return len(m.Lines)
}
func (m *HyprlandManager) findSectionRange(section [2]string) (start, end int, found bool) {
markerLine := m.findSectionMarker(section)
if markerLine < 0 {
return 0, 0, false
}
return markerLine, m.findSectionEnd(markerLine), true
}
func (m *HyprlandManager) modulesSection(user bool) [2]string {
if user {
return sectionUserModules
}
return sectionSystemModules
}
func (m *HyprlandManager) createModulesSection(user bool) int {
section := m.modulesSection(user)
// Ищем предшествующую секцию и вставляем после неё
insertAt := len(m.Lines)
if user {
if _, end, found := m.findSectionRange(sectionSystemModules); found {
insertAt = end
} else if varsLine := m.findSectionMarker(sectionVars); varsLine >= 0 {
insertAt = m.findSectionEnd(varsLine)
}
} else {
if varsLine := m.findSectionMarker(sectionVars); varsLine >= 0 {
insertAt = m.findSectionEnd(varsLine)
}
}
m.Lines = slices.Insert(m.Lines, insertAt, "", sectionHeader(section))
m.shiftLineNumbers(insertAt-1, 2)
return insertAt + 1 // строка маркера
}
func (m *HyprlandManager) getModuleOrder(src SourceLine) int {
name := strings.TrimSuffix(filepath.Base(src.Path), ".conf")
isUser := strings.HasPrefix(src.Path, "~")
meta := ParseModuleMeta(m.GetModuleFile(name, isUser))
if meta != nil {
return meta.Order
}
return 0
}
func (m *HyprlandManager) insertSourceLine(confPath string, user bool, order int) int {
start, end, found := m.findSectionRange(m.modulesSection(user))
if !found {
markerLine := m.createModulesSection(user)
start = markerLine
end = markerLine + 1
}
// Собрать source-строки секции, отсортированные по позиции
type sourceWithOrder struct {
lineNum int
order int
}
var sectionSources []sourceWithOrder
for _, src := range m.Sources {
if src.LineNumber > start && src.LineNumber < end && !src.Commented {
sectionSources = append(sectionSources, sourceWithOrder{
lineNum: src.LineNumber,
order: m.getModuleOrder(src),
})
}
}
slices.SortFunc(sectionSources, func(a, b sourceWithOrder) int {
return a.lineNum - b.lineNum
})
var insertAt int
if order > 0 && len(sectionSources) > 0 {
// Вставить перед первым модулем с order больше нового
// или перед первым без order (order=0 → после всех явных)
insertAt = -1
for _, s := range sectionSources {
if s.order == 0 || s.order > order {
insertAt = s.lineNum
break
}
}
if insertAt < 0 {
insertAt = sectionSources[len(sectionSources)-1].lineNum + 1
}
} else if len(sectionSources) > 0 {
insertAt = sectionSources[len(sectionSources)-1].lineNum + 1
} else {
insertAt = start + 1
}
// Определить order соседних source-строк
prevOrder := -1
nextOrder := -1
for _, s := range sectionSources {
if s.lineNum < insertAt {
prevOrder = s.order
} else if nextOrder < 0 {
nextOrder = s.order
}
}
// Пустая строка перед, если order отличается от предыдущего
if prevOrder >= 0 && prevOrder != order && insertAt > 0 && m.Lines[insertAt-1] != "" {
m.insertLine(insertAt, "")
insertAt++
}
m.insertLine(insertAt, "source = "+confPath)
// Пустая строка после, если order отличается от следующего
if nextOrder >= 0 && nextOrder != order && insertAt+1 < len(m.Lines) && m.Lines[insertAt+1] != "" {
m.insertLine(insertAt+1, "")
}
m.Sources = append(m.Sources, SourceLine{
Path: confPath,
LineNumber: insertAt,
Commented: false,
})
return insertAt
}
func (m *HyprlandManager) insertLine(at int, line string) {
m.Lines = slices.Insert(m.Lines, at, line)
m.shiftLineNumbers(at-1, 1)
m.Changed = true
}
// Plugins
func (m *HyprlandManager) GetLoadedPlugins() []HyprPlugin {
......@@ -573,34 +737,21 @@ func (m *HyprlandManager) SetVar(name, value string) (string, error) {
}
}
insertAt := -1
for i, line := range m.Lines {
if strings.Contains(line, "ПЕРЕМЕННЫЕ") && strings.Contains(line, "VARS") {
insertAt = i + 1
break
}
}
newLine := fmt.Sprintf("$%s = %s", name, value)
if insertAt >= 0 {
m.Lines = append(
m.Lines[:insertAt],
append([]string{newLine}, m.Lines[insertAt:]...)...,
)
m.shiftLineNumbers(insertAt, 1)
varsMarker := m.findSectionMarker(sectionVars)
if varsMarker >= 0 {
insertAt := varsMarker + 1
m.Lines = slices.Insert(m.Lines, insertAt, newLine)
m.shiftLineNumbers(insertAt-1, 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})
insertAt := len(m.Lines)
m.Lines = append(m.Lines, "", sectionHeader(sectionVars), newLine)
m.Vars = append(m.Vars, HyprVar{Name: name, Value: value, LineNumber: insertAt + 2})
m.Changed = true
return fmt.Sprintf("Блок VARS создан, переменная '%s' установлена: %s", name, value), nil
}
......
......@@ -13,6 +13,7 @@ type ModuleMeta struct {
Summary string `yaml:"summary,omitempty"`
Description string `yaml:"description,omitempty"`
Group string `yaml:"group,omitempty"`
Order int `yaml:"order,omitempty"`
}
func ParseModuleMeta(filePath string) *ModuleMeta {
......@@ -69,7 +70,7 @@ func ParseModuleMeta(filePath string) *ModuleMeta {
return nil
}
if meta.Summary == "" && meta.Description == "" && meta.Group == "" {
if meta.Summary == "" && meta.Description == "" && meta.Group == "" && meta.Order == 0 {
return nil
}
......
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