1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-15 10:12:07 -04:00

keybinds: always parse binds.kdl, show warning on position-conflicts

This commit is contained in:
bbedward
2025-12-03 10:31:55 -05:00
parent 33e655becd
commit 5f5427266f
7 changed files with 450 additions and 55 deletions

View File

@@ -26,35 +26,78 @@ type NiriSection struct {
}
type NiriParser struct {
configDir string
processedFiles map[string]bool
bindMap map[string]*NiriKeyBinding
bindOrder []string
currentSource string
dmsBindsIncluded bool
configDir string
processedFiles map[string]bool
bindMap map[string]*NiriKeyBinding
bindOrder []string
currentSource string
dmsBindsIncluded bool
dmsBindsExists bool
includeCount int
dmsIncludePos int
bindsBeforeDMS int
bindsAfterDMS int
dmsBindKeys map[string]bool
configBindKeys map[string]bool
dmsProcessed bool
dmsBindMap map[string]*NiriKeyBinding
conflictingConfigs map[string]*NiriKeyBinding
}
func NewNiriParser(configDir string) *NiriParser {
return &NiriParser{
configDir: configDir,
processedFiles: make(map[string]bool),
bindMap: make(map[string]*NiriKeyBinding),
bindOrder: []string{},
currentSource: "",
configDir: configDir,
processedFiles: make(map[string]bool),
bindMap: make(map[string]*NiriKeyBinding),
bindOrder: []string{},
currentSource: "",
dmsIncludePos: -1,
dmsBindKeys: make(map[string]bool),
configBindKeys: make(map[string]bool),
dmsBindMap: make(map[string]*NiriKeyBinding),
conflictingConfigs: make(map[string]*NiriKeyBinding),
}
}
func (p *NiriParser) Parse() (*NiriSection, error) {
dmsBindsPath := filepath.Join(p.configDir, "dms", "binds.kdl")
if _, err := os.Stat(dmsBindsPath); err == nil {
p.dmsBindsExists = true
}
configPath := filepath.Join(p.configDir, "config.kdl")
section, err := p.parseFile(configPath, "")
if err != nil {
return nil, err
}
if p.dmsBindsExists && !p.dmsProcessed {
p.parseDMSBindsDirectly(dmsBindsPath, section)
}
section.Keybinds = p.finalizeBinds()
return section, nil
}
func (p *NiriParser) parseDMSBindsDirectly(dmsBindsPath string, section *NiriSection) {
data, err := os.ReadFile(dmsBindsPath)
if err != nil {
return
}
doc, err := kdl.Parse(strings.NewReader(string(data)))
if err != nil {
return
}
prevSource := p.currentSource
p.currentSource = dmsBindsPath
baseDir := filepath.Dir(dmsBindsPath)
p.processNodes(doc.Nodes, section, baseDir)
p.currentSource = prevSource
p.dmsProcessed = true
}
func (p *NiriParser) finalizeBinds() []NiriKeyBinding {
binds := make([]NiriKeyBinding, 0, len(p.bindOrder))
for _, key := range p.bindOrder {
@@ -67,6 +110,20 @@ func (p *NiriParser) finalizeBinds() []NiriKeyBinding {
func (p *NiriParser) addBind(kb *NiriKeyBinding) {
key := p.formatBindKey(kb)
isDMSBind := strings.Contains(kb.Source, "dms/binds.kdl")
if isDMSBind {
p.dmsBindKeys[key] = true
p.dmsBindMap[key] = kb
} else if p.dmsBindKeys[key] {
p.bindsAfterDMS++
p.conflictingConfigs[key] = kb
p.configBindKeys[key] = true
return
} else {
p.configBindKeys[key] = true
}
if _, exists := p.bindMap[key]; !exists {
p.bindOrder = append(p.bindOrder, key)
}
@@ -105,9 +162,11 @@ func (p *NiriParser) parseFile(filePath, sectionName string) (*NiriSection, erro
Name: sectionName,
}
prevSource := p.currentSource
p.currentSource = absPath
baseDir := filepath.Dir(absPath)
p.processNodes(doc.Nodes, section, baseDir)
p.currentSource = prevSource
return section, nil
}
@@ -133,8 +192,13 @@ func (p *NiriParser) handleInclude(node *document.Node, section *NiriSection, ba
}
includePath := strings.Trim(node.Arguments[0].String(), "\"")
if includePath == "dms/binds.kdl" || strings.HasSuffix(includePath, "/dms/binds.kdl") {
isDMSInclude := includePath == "dms/binds.kdl" || strings.HasSuffix(includePath, "/dms/binds.kdl")
p.includeCount++
if isDMSInclude {
p.dmsBindsIncluded = true
p.dmsIncludePos = p.includeCount
p.bindsBeforeDMS = len(p.bindMap)
}
fullPath := filepath.Join(baseDir, includePath)
@@ -142,6 +206,10 @@ func (p *NiriParser) handleInclude(node *document.Node, section *NiriSection, ba
fullPath = includePath
}
if isDMSInclude {
p.dmsProcessed = true
}
includedSection, err := p.parseFile(fullPath, "")
if err != nil {
return
@@ -230,8 +298,49 @@ func (p *NiriParser) parseKeyCombo(combo string) ([]string, string) {
}
type NiriParseResult struct {
Section *NiriSection
DMSBindsIncluded bool
Section *NiriSection
DMSBindsIncluded bool
DMSStatus *DMSBindsStatusInfo
ConflictingConfigs map[string]*NiriKeyBinding
}
type DMSBindsStatusInfo struct {
Exists bool
Included bool
IncludePosition int
TotalIncludes int
BindsAfterDMS int
Effective bool
OverriddenBy int
StatusMessage string
}
func (p *NiriParser) buildDMSStatus() *DMSBindsStatusInfo {
status := &DMSBindsStatusInfo{
Exists: p.dmsBindsExists,
Included: p.dmsBindsIncluded,
IncludePosition: p.dmsIncludePos,
TotalIncludes: p.includeCount,
BindsAfterDMS: p.bindsAfterDMS,
}
switch {
case !p.dmsBindsExists:
status.Effective = false
status.StatusMessage = "dms/binds.kdl does not exist"
case !p.dmsBindsIncluded:
status.Effective = false
status.StatusMessage = "dms/binds.kdl is not included in config.kdl"
case p.bindsAfterDMS > 0:
status.Effective = true
status.OverriddenBy = p.bindsAfterDMS
status.StatusMessage = "Some DMS binds may be overridden by config binds"
default:
status.Effective = true
status.StatusMessage = "DMS binds are active"
}
return status
}
func ParseNiriKeys(configDir string) (*NiriParseResult, error) {
@@ -241,7 +350,9 @@ func ParseNiriKeys(configDir string) (*NiriParseResult, error) {
return nil, err
}
return &NiriParseResult{
Section: section,
DMSBindsIncluded: parser.HasDMSBindsIncluded(),
Section: section,
DMSBindsIncluded: parser.HasDMSBindsIncluded(),
DMSStatus: parser.buildDMSStatus(),
ConflictingConfigs: parser.conflictingConfigs,
}, nil
}