Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
ximperconf
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
1
Merge Requests
1
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
ximperconf
Commits
ef91ff59
Verified
Commit
ef91ff59
authored
Mar 03, 2026
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hyprland/module: add dependency system
parent
f1638e59
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
170 additions
and
75 deletions
+170
-75
actions.go
hyprland/actions.go
+40
-4
commands.go
hyprland/commands.go
+8
-8
json.go
hyprland/json.go
+7
-6
manager.go
hyprland/manager.go
+110
-53
meta.go
hyprland/meta.go
+5
-4
No files found.
hyprland/actions.go
View file @
ef91ff59
...
...
@@ -190,6 +190,15 @@ func HyprlandToggleModuleCommand(ctx context.Context, cmd *cli.Command) error {
func
HyprlandInfoModulesCommand
(
ctx
context
.
Context
,
cmd
*
cli
.
Command
)
error
{
filter
:=
cmd
.
String
(
"filter"
)
// Скрывать модули с отсутствующими зависимостями по умолчанию
if
!
strings
.
Contains
(
filter
,
"all"
)
&&
!
strings
.
Contains
(
filter
,
"deps:"
)
{
if
filter
==
""
{
filter
=
"deps:installed"
}
else
{
filter
+=
",deps:installed"
}
}
manager
,
err
:=
GetHyprlandManager
(
ctx
)
if
err
!=
nil
{
return
err
...
...
@@ -221,10 +230,11 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
jsonItems
:=
make
([]
ModuleInfoJSON
,
len
(
data
))
for
i
,
d
:=
range
data
{
jsonItems
[
i
]
=
ModuleInfoJSON
{
Name
:
d
.
info
.
ShortName
(),
User
:
d
.
info
.
User
,
Status
:
d
.
info
.
Status
.
Label
,
Errors
:
d
.
errorNum
,
Name
:
d
.
info
.
ShortName
(),
User
:
d
.
info
.
User
,
Status
:
d
.
info
.
Status
.
Label
,
DepsInstalled
:
d
.
info
.
DepsInstalled
,
Errors
:
d
.
errorNum
,
}
if
d
.
info
.
Meta
!=
nil
{
jsonItems
[
i
]
.
Group
=
d
.
info
.
Meta
.
Group
...
...
@@ -247,6 +257,12 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
if
d
.
info
.
Meta
!=
nil
&&
d
.
info
.
Meta
.
Group
!=
""
{
name
=
d
.
info
.
Meta
.
Group
+
"/"
+
name
}
if
!
d
.
info
.
DepsInstalled
{
missing
:=
missingDeps
(
d
.
info
.
Meta
)
if
len
(
missing
)
>
0
{
parts
=
append
(
parts
,
fmt
.
Sprintf
(
"(requires: %s)"
,
strings
.
Join
(
missing
,
", "
)))
}
}
item
:=
ui
.
TreeItem
{
Name
:
name
,
Status
:
d
.
info
.
Status
,
...
...
@@ -285,6 +301,15 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
func
HyprlandModuleListCommand
(
ctx
context
.
Context
,
cmd
*
cli
.
Command
)
error
{
filter
:=
cmd
.
String
(
"filter"
)
// Скрывать модули с отсутствующими зависимостями по умолчанию
if
!
strings
.
Contains
(
filter
,
"all"
)
&&
!
strings
.
Contains
(
filter
,
"deps:"
)
{
if
filter
==
""
{
filter
=
"deps:installed"
}
else
{
filter
+=
",deps:installed"
}
}
manager
,
err
:=
GetHyprlandManager
(
ctx
)
if
err
!=
nil
{
return
err
...
...
@@ -381,6 +406,17 @@ func HyprlandModuleShowCommand(ctx context.Context, cmd *cli.Command) error {
}
}
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
locale
.
T
(
"Status"
)),
info
.
Status
.
Color
(
"%s %s"
,
info
.
Status
.
Symbol
,
info
.
Status
.
Label
))
if
info
.
Meta
!=
nil
&&
len
(
info
.
Meta
.
Requires
)
>
0
{
var
deps
[]
string
for
_
,
bin
:=
range
info
.
Meta
.
Requires
{
if
_
,
err
:=
exec
.
LookPath
(
bin
);
err
==
nil
{
deps
=
append
(
deps
,
color
.
GreenString
(
"✓"
)
+
" "
+
bin
)
}
else
{
deps
=
append
(
deps
,
color
.
RedString
(
"✗"
)
+
" "
+
bin
)
}
}
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
locale
.
T
(
"Dependencies"
)),
strings
.
Join
(
deps
,
", "
))
}
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
locale
.
T
(
"Path"
)),
info
.
Path
)
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
locale
.
T
(
"Config path"
)),
info
.
ConfPath
)
fmt
.
Printf
(
"%s: %d
\n
"
,
blue
(
locale
.
T
(
"Config line"
)),
info
.
LineNumber
)
...
...
hyprland/commands.go
View file @
ef91ff59
...
...
@@ -71,21 +71,21 @@ func CommandList() *cli.Command {
ArgsUsage
:
"module"
,
Flags
:
[]
cli
.
Flag
{
config
.
FormatFlag
},
Action
:
HyprlandModuleCheckCommand
,
ShellComplete
:
ShellCompleteModule
(
""
),
ShellComplete
:
ShellCompleteModule
(
"
all
"
),
},
{
Name
:
"edit"
,
Usage
:
locale
.
T
(
"Edit module file"
),
ArgsUsage
:
"module"
,
Action
:
HyprlandModuleEditCommand
,
ShellComplete
:
ShellCompleteModule
(
""
),
ShellComplete
:
ShellCompleteModule
(
"
all
"
),
},
{
Name
:
"status"
,
Usage
:
locale
.
T
(
"Hyprland module status"
),
ArgsUsage
:
"module"
,
Action
:
HyprlandModuleStatusCommand
,
ShellComplete
:
ShellCompleteModule
(
""
),
ShellComplete
:
ShellCompleteModule
(
"
all
"
),
},
{
Name
:
"show"
,
...
...
@@ -95,7 +95,7 @@ func CommandList() *cli.Command {
config
.
FormatFlag
,
},
Action
:
HyprlandModuleShowCommand
,
ShellComplete
:
ShellCompleteModule
(
""
),
ShellComplete
:
ShellCompleteModule
(
"
all
"
),
},
{
Name
:
"list"
,
...
...
@@ -103,7 +103,7 @@ func CommandList() *cli.Command {
Flags
:
[]
cli
.
Flag
{
&
cli
.
StringFlag
{
Name
:
"filter"
,
Usage
:
locale
.
T
(
"module filter (e.g. status:enabled, type:user, group:themes)"
),
Usage
:
locale
.
T
(
"module filter (e.g. status:enabled, type:user, group:themes
, deps:installed
)"
),
Aliases
:
[]
string
{
"f"
},
},
config
.
FormatFlag
,
...
...
@@ -116,7 +116,7 @@ func CommandList() *cli.Command {
Flags
:
[]
cli
.
Flag
{
&
cli
.
StringFlag
{
Name
:
"filter"
,
Usage
:
locale
.
T
(
"module filter (e.g. status:enabled, type:user, group:themes)"
),
Usage
:
locale
.
T
(
"module filter (e.g. status:enabled, type:user, group:themes
, deps:installed
)"
),
Aliases
:
[]
string
{
"f"
},
},
config
.
FormatFlag
,
...
...
@@ -128,7 +128,7 @@ func CommandList() *cli.Command {
Usage
:
locale
.
T
(
"enable module"
),
ArgsUsage
:
"module"
,
Action
:
HyprlandModuleEnableCommand
,
ShellComplete
:
ShellCompleteModule
(
"status:
disab
led"
),
ShellComplete
:
ShellCompleteModule
(
"status:
noenabled,deps:instal
led"
),
},
{
Name
:
"disable"
,
...
...
@@ -150,7 +150,7 @@ func CommandList() *cli.Command {
Usage
:
locale
.
T
(
"toggle module"
),
ArgsUsage
:
"module"
,
Action
:
HyprlandToggleModuleCommand
,
ShellComplete
:
ShellCompleteModule
(
""
),
ShellComplete
:
ShellCompleteModule
(
"
deps:installed
"
),
},
},
},
...
...
hyprland/json.go
View file @
ef91ff59
...
...
@@ -11,10 +11,11 @@ type ModuleErrorJSON struct {
}
type
ModuleInfoJSON
struct
{
Name
string
`json:"name"`
User
bool
`json:"user"`
Group
string
`json:"group"`
Summary
string
`json:"summary"`
Status
string
`json:"status"`
Errors
int
`json:"errors"`
Name
string
`json:"name"`
User
bool
`json:"user"`
Group
string
`json:"group"`
Summary
string
`json:"summary"`
Status
string
`json:"status"`
DepsInstalled
bool
`json:"deps_installed"`
Errors
int
`json:"errors"`
}
hyprland/manager.go
View file @
ef91ff59
...
...
@@ -37,14 +37,15 @@ type SourceLine struct {
}
type
HyprModule
struct
{
Name
string
`json:"name"`
User
bool
`json:"user"`
Status
config
.
ItemStatus
`json:"status"`
Path
string
`json:"path"`
ConfPath
string
`json:"conf_path"`
LineNumber
int
`json:"line_number"`
Available
bool
`json:"available"`
Meta
*
ModuleMeta
`json:"meta,omitempty"`
Name
string
`json:"name"`
User
bool
`json:"user"`
Status
config
.
ItemStatus
`json:"status"`
Path
string
`json:"path"`
ConfPath
string
`json:"conf_path"`
LineNumber
int
`json:"line_number"`
Available
bool
`json:"available"`
DepsInstalled
bool
`json:"deps_installed"`
Meta
*
ModuleMeta
`json:"meta,omitempty"`
}
func
(
m
HyprModule
)
ShortName
()
string
{
...
...
@@ -213,14 +214,40 @@ func (m *HyprlandManager) GetModuleInfo(module string) HyprModule {
fullName
,
user
,
found
:=
m
.
resolveModule
(
module
)
if
!
found
{
return
HyprModule
{
Name
:
module
,
Status
:
config
.
ModuleStatus
.
Unknown
,
Available
:
!
slices
.
Contains
(
config
.
HyprlandSkipModules
,
module
),
Name
:
module
,
Status
:
config
.
ModuleStatus
.
Unknown
,
Available
:
!
slices
.
Contains
(
config
.
HyprlandSkipModules
,
module
),
DepsInstalled
:
true
,
}
}
return
m
.
getModuleInfo
(
fullName
,
user
)
}
func
checkDeps
(
meta
*
ModuleMeta
)
bool
{
if
meta
==
nil
||
len
(
meta
.
Requires
)
==
0
{
return
true
}
for
_
,
bin
:=
range
meta
.
Requires
{
if
_
,
err
:=
exec
.
LookPath
(
bin
);
err
!=
nil
{
return
false
}
}
return
true
}
func
missingDeps
(
meta
*
ModuleMeta
)
[]
string
{
if
meta
==
nil
{
return
nil
}
var
missing
[]
string
for
_
,
bin
:=
range
meta
.
Requires
{
if
_
,
err
:=
exec
.
LookPath
(
bin
);
err
!=
nil
{
missing
=
append
(
missing
,
bin
)
}
}
return
missing
}
func
(
m
*
HyprlandManager
)
getModuleInfo
(
module
string
,
user
bool
)
HyprModule
{
modulePath
:=
m
.
GetModuleFile
(
module
,
user
)
...
...
@@ -237,21 +264,24 @@ func (m *HyprlandManager) getModuleInfo(module string, user bool) HyprModule {
// Конфиг Hyprland отсутствует
if
!
config
.
FileExists
(
config
.
Env
.
Hyprland
.
Config
)
{
if
fileExists
{
meta
:=
ParseModuleMeta
(
modulePath
)
return
HyprModule
{
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Unused
,
Path
:
modulePath
,
ConfPath
:
confPath
,
Available
:
available
,
Meta
:
ParseModuleMeta
(
modulePath
),
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Unused
,
Path
:
modulePath
,
ConfPath
:
confPath
,
Available
:
available
,
DepsInstalled
:
checkDeps
(
meta
),
Meta
:
meta
,
}
}
return
HyprModule
{
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Missing
,
Available
:
available
,
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Missing
,
Available
:
available
,
DepsInstalled
:
true
,
}
}
...
...
@@ -280,39 +310,44 @@ func (m *HyprlandManager) getModuleInfo(module string, user bool) HyprModule {
// файла нет
if
!
fileExists
{
return
HyprModule
{
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Missing
,
LineNumber
:
lineNumber
,
Available
:
available
,
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Missing
,
LineNumber
:
lineNumber
,
Available
:
available
,
DepsInstalled
:
true
,
}
}
// файл есть
meta
:=
ParseModuleMeta
(
modulePath
)
return
HyprModule
{
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Enabled
,
Path
:
modulePath
,
ConfPath
:
confPath
,
LineNumber
:
lineNumber
,
Available
:
available
,
Meta
:
ParseModuleMeta
(
modulePath
),
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Enabled
,
Path
:
modulePath
,
ConfPath
:
confPath
,
LineNumber
:
lineNumber
,
Available
:
available
,
DepsInstalled
:
checkDeps
(
meta
),
Meta
:
meta
,
}
}
// закомментирован
if
foundCommented
{
mod
:=
HyprModule
{
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Disabled
,
Path
:
modulePath
,
ConfPath
:
confPath
,
LineNumber
:
lineNumber
,
Available
:
available
,
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Disabled
,
Path
:
modulePath
,
ConfPath
:
confPath
,
LineNumber
:
lineNumber
,
Available
:
available
,
DepsInstalled
:
true
,
}
if
fileExists
{
mod
.
Meta
=
ParseModuleMeta
(
modulePath
)
mod
.
DepsInstalled
=
checkDeps
(
mod
.
Meta
)
}
else
{
mod
.
Path
=
""
}
...
...
@@ -321,23 +356,26 @@ func (m *HyprlandManager) getModuleInfo(module string, user bool) HyprModule {
// файл есть, но строка отсутствует
if
fileExists
{
meta
:=
ParseModuleMeta
(
modulePath
)
return
HyprModule
{
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Unused
,
Path
:
modulePath
,
ConfPath
:
confPath
,
Available
:
available
,
Meta
:
ParseModuleMeta
(
modulePath
),
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Unused
,
Path
:
modulePath
,
ConfPath
:
confPath
,
Available
:
available
,
DepsInstalled
:
checkDeps
(
meta
),
Meta
:
meta
,
}
}
// Файла нет и упоминаний нет
return
HyprModule
{
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Unknown
,
Available
:
available
,
Name
:
module
,
User
:
user
,
Status
:
config
.
ModuleStatus
.
Unknown
,
Available
:
available
,
DepsInstalled
:
true
,
}
}
...
...
@@ -435,6 +473,19 @@ func matchModuleFilter(info HyprModule, filters map[string]string) bool {
}
}
if
v
,
ok
:=
filters
[
"deps"
];
ok
{
switch
v
{
case
"installed"
:
if
!
info
.
DepsInstalled
{
return
false
}
case
"uninstalled"
:
if
info
.
DepsInstalled
{
return
false
}
}
}
return
true
}
...
...
@@ -451,6 +502,12 @@ func (m *HyprlandManager) SetModule(action, module string, onlyNew bool) (string
switch
action
{
case
"enable"
:
// зависимости не установлены
if
!
info
.
DepsInstalled
{
return
""
,
fmt
.
Errorf
(
locale
.
T
(
"missing module dependencies: %s"
),
strings
.
Join
(
missingDeps
(
info
.
Meta
),
", "
))
}
// нет файла
if
info
.
Path
==
""
||
info
.
Status
.
IsEqual
(
config
.
ModuleStatus
.
Unknown
)
{
return
""
,
errors
.
New
(
locale
.
T
(
"cannot enable this module"
))
...
...
hyprland/meta.go
View file @
ef91ff59
...
...
@@ -10,10 +10,11 @@ import (
const
metaDelimiter
=
"#---"
type
ModuleMeta
struct
{
Summary
string
`yaml:"summary,omitempty"`
Description
string
`yaml:"description,omitempty"`
Group
string
`yaml:"group,omitempty"`
Order
int
`yaml:"order,omitempty"`
Summary
string
`yaml:"summary,omitempty"`
Description
string
`yaml:"description,omitempty"`
Group
string
`yaml:"group,omitempty"`
Order
int
`yaml:"order,omitempty"`
Requires
[]
string
`yaml:"requires,omitempty"`
}
func
ParseModuleMeta
(
filePath
string
)
*
ModuleMeta
{
...
...
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