Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
ximper-shell-panel
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ximper Linux
ximper-shell-panel
Commits
384be8f5
Verified
Commit
384be8f5
authored
May 22, 2026
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
support user module overrides
parent
4ed2eb67
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
114 additions
and
10 deletions
+114
-10
README.md
README.md
+6
-2
config.go
config.go
+12
-0
generate.go
generate.go
+17
-7
main.go
main.go
+1
-1
registry.go
registry.go
+78
-0
No files found.
README.md
View file @
384be8f5
...
...
@@ -8,6 +8,7 @@ user-facing configuration UI is expected to live in `ximperconf shell panel`.
## Paths
-
User config:
`~/.config/ximper-shell/panel/config.json`
-
User modules:
`~/.config/ximper-shell/panel/modules.json`
-
System modules:
`/usr/share/ximperdistro/wm/base/waybar/modules.json`
## Commands
...
...
@@ -40,8 +41,11 @@ panel, floating, islands
## Module Resolution
The config stores logical module names. At generation time, the panel resolves
them against
`modules.json`
.
The config stores logical module names. At generation time, the panel merges
system and user modules, then resolves names against the merged registry.
User modules override system modules with the same name. Object values are
merged recursively, so a user module can override a single option without
copying the whole system module.
Examples:
...
...
config.go
View file @
384be8f5
package
main
import
(
"bytes"
"encoding/json"
"errors"
"fmt"
...
...
@@ -41,6 +42,9 @@ func LoadConfig(path string) (Config, error) {
}
return
cfg
,
err
}
if
len
(
bytes
.
TrimSpace
(
data
))
==
0
{
return
cfg
,
nil
}
if
err
:=
json
.
Unmarshal
(
data
,
&
cfg
);
err
!=
nil
{
return
cfg
,
fmt
.
Errorf
(
"parse panel config: %w"
,
err
)
}
...
...
@@ -73,6 +77,10 @@ func UserConfigPath() string {
return
filepath
.
Join
(
os
.
Getenv
(
"HOME"
),
".config"
,
"ximper-shell"
,
"panel"
,
"config.json"
)
}
func
UserModulesPath
()
string
{
return
filepath
.
Join
(
os
.
Getenv
(
"HOME"
),
".config"
,
"ximper-shell"
,
"panel"
,
"modules.json"
)
}
func
RuntimeDir
()
string
{
return
filepath
.
Join
(
os
.
TempDir
(),
"ximper-shell"
,
"panel"
)
}
...
...
@@ -81,6 +89,10 @@ func RuntimeConfigPath() string {
return
filepath
.
Join
(
RuntimeDir
(),
"config.jsonc"
)
}
func
RuntimeModulesPath
()
string
{
return
filepath
.
Join
(
RuntimeDir
(),
"modules.jsonc"
)
}
func
RuntimePIDPath
()
string
{
return
filepath
.
Join
(
RuntimeDir
(),
"waybar.pid"
)
}
...
...
generate.go
View file @
384be8f5
...
...
@@ -19,7 +19,7 @@ func GenerateConfig(cfg Config, registry Registry) ([]byte, error) {
"fixed-center"
:
true
,
"reload_style_on_change"
:
true
,
"include"
:
[]
string
{
ModulesFile
,
RuntimeModulesPath
()
,
},
"modules-left"
:
[]
string
{},
"modules-center"
:
[]
string
{},
...
...
@@ -66,6 +66,9 @@ func GenerateRuntimeConfig() ([]byte, error) {
if
err
!=
nil
{
return
nil
,
err
}
if
err
:=
WriteRuntimeModules
(
registry
);
err
!=
nil
{
return
nil
,
err
}
return
GenerateConfig
(
cfg
,
registry
)
}
...
...
@@ -74,11 +77,7 @@ func GenerateAndWriteRuntimeConfig() (string, error) {
if
err
!=
nil
{
return
""
,
err
}
path
,
err
:=
WriteRuntimeConfig
(
data
)
if
err
!=
nil
{
return
""
,
err
}
return
path
,
nil
return
WriteRuntimeConfig
(
data
)
}
func
WriteRuntimeConfig
(
data
[]
byte
)
(
string
,
error
)
{
...
...
@@ -92,12 +91,23 @@ func WriteRuntimeConfig(data []byte) (string, error) {
return
path
,
nil
}
func
WriteRuntimeModules
(
registry
Registry
)
error
{
data
,
err
:=
registry
.
Marshal
()
if
err
!=
nil
{
return
err
}
if
err
:=
os
.
MkdirAll
(
filepath
.
Dir
(
RuntimeModulesPath
()),
0755
);
err
!=
nil
{
return
err
}
return
os
.
WriteFile
(
RuntimeModulesPath
(),
data
,
0644
)
}
func
loadInputs
()
(
Config
,
Registry
,
error
)
{
cfg
,
err
:=
LoadConfig
(
UserConfigPath
())
if
err
!=
nil
{
return
Config
{},
Registry
{},
err
}
registry
,
err
:=
Load
Registry
(
ModulesFile
)
registry
,
err
:=
Load
MergedRegistry
(
ModulesFile
,
UserModulesPath
()
)
if
err
!=
nil
{
return
Config
{},
Registry
{},
err
}
...
...
main.go
View file @
384be8f5
...
...
@@ -82,7 +82,7 @@ func applyCommandSetting(cliCommand *cli.Command) {
}
func
listModulesCommand
(
ctx
context
.
Context
,
cmd
*
cli
.
Command
)
error
{
registry
,
err
:=
Load
Registry
(
ModulesFile
)
registry
,
err
:=
Load
MergedRegistry
(
ModulesFile
,
UserModulesPath
()
)
if
err
!=
nil
{
return
err
}
...
...
registry.go
View file @
384be8f5
package
main
import
(
"bytes"
"encoding/json"
"errors"
"fmt"
"os"
"sort"
...
...
@@ -12,11 +14,38 @@ type Registry struct {
Modules
map
[
string
]
json
.
RawMessage
}
func
LoadMergedRegistry
(
systemPath
,
userPath
string
)
(
Registry
,
error
)
{
systemRegistry
,
err
:=
LoadRegistry
(
systemPath
)
if
err
!=
nil
{
return
Registry
{},
err
}
userRegistry
,
err
:=
LoadRegistry
(
userPath
)
if
err
!=
nil
{
if
errors
.
Is
(
err
,
os
.
ErrNotExist
)
{
return
systemRegistry
,
nil
}
return
Registry
{},
err
}
for
name
,
raw
:=
range
userRegistry
.
Modules
{
merged
,
err
:=
mergeModule
(
systemRegistry
.
Modules
[
name
],
raw
)
if
err
!=
nil
{
return
Registry
{},
fmt
.
Errorf
(
"merge module %q: %w"
,
name
,
err
)
}
systemRegistry
.
Modules
[
name
]
=
merged
}
return
systemRegistry
,
nil
}
func
LoadRegistry
(
path
string
)
(
Registry
,
error
)
{
data
,
err
:=
os
.
ReadFile
(
path
)
if
err
!=
nil
{
return
Registry
{},
err
}
if
len
(
bytes
.
TrimSpace
(
data
))
==
0
{
return
Registry
{
Modules
:
map
[
string
]
json
.
RawMessage
{}},
nil
}
var
modules
map
[
string
]
json
.
RawMessage
if
err
:=
json
.
Unmarshal
(
StripJSONC
(
data
),
&
modules
);
err
!=
nil
{
...
...
@@ -26,6 +55,55 @@ func LoadRegistry(path string) (Registry, error) {
return
Registry
{
Modules
:
modules
},
nil
}
func
mergeModule
(
base
,
override
json
.
RawMessage
)
(
json
.
RawMessage
,
error
)
{
if
len
(
base
)
==
0
{
return
override
,
nil
}
var
baseValue
any
if
err
:=
json
.
Unmarshal
(
base
,
&
baseValue
);
err
!=
nil
{
return
nil
,
err
}
var
overrideValue
any
if
err
:=
json
.
Unmarshal
(
override
,
&
overrideValue
);
err
!=
nil
{
return
nil
,
err
}
merged
:=
mergeValue
(
baseValue
,
overrideValue
)
data
,
err
:=
json
.
Marshal
(
merged
)
if
err
!=
nil
{
return
nil
,
err
}
return
data
,
nil
}
func
mergeValue
(
base
,
override
any
)
any
{
baseMap
,
baseOK
:=
base
.
(
map
[
string
]
any
)
overrideMap
,
overrideOK
:=
override
.
(
map
[
string
]
any
)
if
!
baseOK
||
!
overrideOK
{
return
override
}
for
key
,
overrideValue
:=
range
overrideMap
{
if
baseValue
,
ok
:=
baseMap
[
key
];
ok
{
baseMap
[
key
]
=
mergeValue
(
baseValue
,
overrideValue
)
}
else
{
baseMap
[
key
]
=
overrideValue
}
}
return
baseMap
}
func
(
r
Registry
)
Marshal
()
([]
byte
,
error
)
{
data
,
err
:=
json
.
MarshalIndent
(
r
.
Modules
,
""
,
" "
)
if
err
!=
nil
{
return
nil
,
err
}
return
append
(
data
,
'\n'
),
nil
}
func
(
r
Registry
)
Names
()
[]
string
{
names
:=
make
([]
string
,
0
,
len
(
r
.
Modules
))
for
name
:=
range
r
.
Modules
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment