1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-08-02 03:28:28 -04:00

fix(niri): update custom keyboard shortcut parsing properties

Fixes #2187
This commit is contained in:
purian23
2026-07-04 22:25:53 -04:00
parent 78f2ea4642
commit 33384e4d5d
2 changed files with 87 additions and 9 deletions
+35 -9
View File
@@ -19,6 +19,20 @@ type NiriProvider struct {
parsed bool
}
type niriActionPart struct {
value string
quoted bool
}
var niriActionPropertyOrder = []string{"focus", "show-pointer", "write-to-disk", "skip-confirmation", "delay-ms"}
var niriActionProperties = map[string]struct{}{
"focus": {},
"show-pointer": {},
"write-to-disk": {},
"skip-confirmation": {},
"delay-ms": {},
}
func NewNiriProvider(configDir string) *NiriProvider {
if configDir == "" {
configDir = defaultNiriConfigDir()
@@ -353,7 +367,7 @@ func (n *NiriProvider) buildActionFromNode(bindNode *document.Node) string {
}
if actionNode.Properties != nil {
for _, propName := range []string{"focus", "show-pointer", "write-to-disk", "skip-confirmation", "delay-ms"} {
for _, propName := range niriActionPropertyOrder {
if val, ok := actionNode.Properties.Get(propName); ok {
parts = append(parts, propName+"="+val.String())
}
@@ -441,10 +455,10 @@ func (n *NiriProvider) buildActionNode(action string) *document.Node {
return node
}
node.SetName(parts[0])
node.SetName(parts[0].value)
for _, arg := range parts[1:] {
if strings.Contains(arg, "=") {
kv := strings.SplitN(arg, "=", 2)
if n.isNiriActionPropertyToken(arg) {
kv := strings.SplitN(arg.value, "=", 2)
switch kv[1] {
case "true":
node.AddProperty(kv[0], true, "")
@@ -455,13 +469,25 @@ func (n *NiriProvider) buildActionNode(action string) *document.Node {
}
continue
}
node.AddArgument(arg, "")
node.AddArgument(arg.value, "")
}
return node
}
func (n *NiriProvider) parseActionParts(action string) []string {
var parts []string
func (n *NiriProvider) isNiriActionPropertyToken(part niriActionPart) bool {
if part.quoted || !strings.Contains(part.value, "=") {
return false
}
key, _, ok := strings.Cut(part.value, "=")
if !ok {
return false
}
_, ok = niriActionProperties[key]
return ok
}
func (n *NiriProvider) parseActionParts(action string) []niriActionPart {
var parts []niriActionPart
var current strings.Builder
var inQuote, escaped, wasQuoted bool
@@ -477,7 +503,7 @@ func (n *NiriProvider) parseActionParts(action string) []string {
inQuote = !inQuote
case r == ' ' && !inQuote:
if current.Len() > 0 || wasQuoted {
parts = append(parts, current.String())
parts = append(parts, niriActionPart{value: current.String(), quoted: wasQuoted})
current.Reset()
wasQuoted = false
}
@@ -486,7 +512,7 @@ func (n *NiriProvider) parseActionParts(action string) []string {
}
}
if current.Len() > 0 || wasQuoted {
parts = append(parts, current.String())
parts = append(parts, niriActionPart{value: current.String(), quoted: wasQuoted})
}
return parts
}
@@ -234,6 +234,58 @@ func TestNiriGenerateBindsContent(t *testing.T) {
expected: `binds {
Mod+Space hotkey-overlay-title="Application Launcher" { spawn "dms" "ipc" "call" "spotlight" "toggle"; }
}
`,
},
{
name: "spawn with equals arg",
binds: map[string]*overrideBind{
"Mod+B": {
Key: "Mod+B",
Action: `spawn /opt/browser --profile-directory=Default`,
},
},
expected: `binds {
Mod+B { spawn "/opt/browser" "--profile-directory=Default"; }
}
`,
},
{
name: "spawn shell command with quoted equals args",
binds: map[string]*overrideBind{
"Mod+C": {
Key: "Mod+C",
Action: `spawn sh -c "chrome --profile-directory=Default --app=x"`,
},
},
expected: `binds {
Mod+C { spawn "sh" "-c" "chrome --profile-directory=Default --app=x"; }
}
`,
},
{
name: "spawn env assignment stays arg",
binds: map[string]*overrideBind{
"Mod+E": {
Key: "Mod+E",
Action: `spawn env FOO=bar mycmd`,
},
},
expected: `binds {
Mod+E { spawn "env" "FOO=bar" "mycmd"; }
}
`,
},
{
name: "niri action property remains property",
binds: map[string]*overrideBind{
"Print": {
Key: "Print",
Action: `screenshot show-pointer=false`,
},
},
expected: `binds {
Print { screenshot show-pointer=false; }
}
`,
},
{