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
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
ximperconf
Commits
19c74f34
Verified
Commit
19c74f34
authored
Feb 14, 2026
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hyprland/module: add metainfo for modules
parent
e0f51b85
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
209 additions
and
56 deletions
+209
-56
status.go
config/status.go
+9
-1
actions.go
hyprland/actions.go
+64
-32
json.go
hyprland/json.go
+9
-6
manager.go
hyprland/manager.go
+50
-17
meta.go
hyprland/meta.go
+77
-0
No files found.
config/status.go
View file @
19c74f34
package
config
package
config
import
"github.com/fatih/color"
import
(
"encoding/json"
"github.com/fatih/color"
)
type
ItemStatus
struct
{
type
ItemStatus
struct
{
Symbol
string
Symbol
string
...
@@ -18,6 +22,10 @@ func (s ItemStatus) IsEqual(other ItemStatus) bool {
...
@@ -18,6 +22,10 @@ func (s ItemStatus) IsEqual(other ItemStatus) bool {
return
s
.
Label
==
other
.
Label
return
s
.
Label
==
other
.
Label
}
}
func
(
s
ItemStatus
)
MarshalJSON
()
([]
byte
,
error
)
{
return
json
.
Marshal
(
s
.
Label
)
}
var
ModuleStatus
=
struct
{
var
ModuleStatus
=
struct
{
Unknown
ItemStatus
Unknown
ItemStatus
Enabled
ItemStatus
Enabled
ItemStatus
...
...
hyprland/actions.go
View file @
19c74f34
...
@@ -9,6 +9,7 @@ import (
...
@@ -9,6 +9,7 @@ import (
"fmt"
"fmt"
"os"
"os"
"os/exec"
"os/exec"
"strings"
"github.com/fatih/color"
"github.com/fatih/color"
"github.com/urfave/cli/v3"
"github.com/urfave/cli/v3"
...
@@ -107,14 +108,12 @@ func HyprlandModuleDisableCommand(ctx context.Context, cmd *cli.Command) error {
...
@@ -107,14 +108,12 @@ func HyprlandModuleDisableCommand(ctx context.Context, cmd *cli.Command) error {
return
err
return
err
}
}
var
msg
string
action
:=
"disable"
action
:=
"disable"
if
remove
{
if
remove
{
action
=
"remove"
action
=
"remove"
}
}
msg
,
err
=
manager
.
SetModule
(
msg
,
err
:
=
manager
.
SetModule
(
action
,
cmd
.
Args
()
.
Get
(
0
),
cmd
.
Bool
(
"user"
),
false
,
action
,
cmd
.
Args
()
.
Get
(
0
),
cmd
.
Bool
(
"user"
),
false
,
)
)
...
@@ -169,33 +168,59 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
...
@@ -169,33 +168,59 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
modules
:=
manager
.
GetModulesList
(
user
,
filter
)
modules
:=
manager
.
GetModulesList
(
user
,
filter
)
if
len
(
modules
)
==
0
{
if
len
(
modules
)
==
0
{
if
config
.
IsJSON
(
cmd
)
{
if
config
.
IsJSON
(
cmd
)
{
return
ui
.
PrintJSON
([]
ui
.
JSONItem
{})
return
ui
.
PrintJSON
([]
ModuleInfoJSON
{})
}
}
return
fmt
.
Errorf
(
"нет доступных модулей"
)
return
fmt
.
Errorf
(
"нет доступных модулей"
)
}
}
items
:=
make
([]
ui
.
TreeItem
,
0
,
len
(
modules
))
type
moduleData
struct
{
info
HyprModule
errorNum
int
}
data
:=
make
([]
moduleData
,
0
,
len
(
modules
))
for
_
,
info
:=
range
modules
{
for
_
,
info
:=
range
modules
{
errors
,
err
:=
manager
.
CheckModule
(
info
.
Name
,
user
)
errors
,
err
:=
manager
.
CheckModule
(
info
.
Name
,
user
)
if
err
!=
nil
{
if
err
!=
nil
{
errors
=
[]
HyprConfigError
{}
errors
=
nil
}
}
errornum
:=
len
(
errors
)
data
=
append
(
data
,
moduleData
{
info
:
info
,
errorNum
:
len
(
errors
)})
desc
:=
""
if
errornum
>
0
{
desc
=
fmt
.
Sprintf
(
"(ошибки: %d)"
,
errornum
)
}
items
=
append
(
items
,
ui
.
TreeItem
{
Name
:
info
.
Name
,
Status
:
info
.
Status
,
Description
:
desc
,
})
}
}
if
config
.
IsJSON
(
cmd
)
{
if
config
.
IsJSON
(
cmd
)
{
return
ui
.
PrintJSON
(
ui
.
TreeItemsToJSON
(
items
))
jsonItems
:=
make
([]
ModuleInfoJSON
,
len
(
data
))
for
i
,
d
:=
range
data
{
jsonItems
[
i
]
=
ModuleInfoJSON
{
Name
:
d
.
info
.
Name
,
Status
:
d
.
info
.
Status
.
Label
,
Errors
:
d
.
errorNum
,
}
if
d
.
info
.
Meta
!=
nil
{
jsonItems
[
i
]
.
Group
=
d
.
info
.
Meta
.
Group
jsonItems
[
i
]
.
Summary
=
d
.
info
.
Meta
.
Summary
}
}
return
ui
.
PrintJSON
(
jsonItems
)
}
items
:=
make
([]
ui
.
TreeItem
,
0
,
len
(
data
))
for
_
,
d
:=
range
data
{
var
parts
[]
string
if
d
.
info
.
Meta
!=
nil
&&
d
.
info
.
Meta
.
Summary
!=
""
{
parts
=
append
(
parts
,
d
.
info
.
Meta
.
Summary
)
}
if
d
.
errorNum
>
0
{
parts
=
append
(
parts
,
fmt
.
Sprintf
(
"(ошибки: %d)"
,
d
.
errorNum
))
}
name
:=
d
.
info
.
Name
if
d
.
info
.
Meta
!=
nil
&&
d
.
info
.
Meta
.
Group
!=
""
{
name
=
d
.
info
.
Meta
.
Group
+
"/"
+
d
.
info
.
Name
}
items
=
append
(
items
,
ui
.
TreeItem
{
Name
:
name
,
Status
:
d
.
info
.
Status
,
Description
:
strings
.
Join
(
parts
,
" "
),
})
}
}
ui
.
RenderTree
(
ui
.
RenderTreeOptions
{
ui
.
RenderTree
(
ui
.
RenderTreeOptions
{
...
@@ -268,29 +293,36 @@ func HyprlandModuleShowCommand(ctx context.Context, cmd *cli.Command) error {
...
@@ -268,29 +293,36 @@ func HyprlandModuleShowCommand(ctx context.Context, cmd *cli.Command) error {
jsonErrors
[
i
]
=
ModuleErrorJSON
{
Line
:
e
.
Line
,
Text
:
e
.
Text
}
jsonErrors
[
i
]
=
ModuleErrorJSON
{
Line
:
e
.
Line
,
Text
:
e
.
Text
}
}
}
return
ui
.
PrintJSON
(
ModuleShowJSON
{
return
ui
.
PrintJSON
(
ModuleShowJSON
{
Name
:
info
.
Name
,
HyprModule
:
info
,
Status
:
info
.
Status
.
Label
,
Path
:
info
.
Path
,
ConfPath
:
info
.
ConfPath
,
LineNumber
:
info
.
LineNumber
,
Available
:
info
.
Available
,
Errors
:
jsonErrors
,
Errors
:
jsonErrors
,
})
})
}
}
fmt
.
Printf
(
"Модуль: %s
\n
"
,
info
.
Name
)
blue
:=
color
.
New
(
color
.
FgBlue
)
.
SprintFunc
()
fmt
.
Printf
(
"Статус: %s
\n
"
,
info
.
Status
.
Color
(
"%s %s"
,
info
.
Status
.
Symbol
,
info
.
Status
.
Label
))
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
"Модуль"
),
info
.
Name
)
fmt
.
Printf
(
"Путь: %s
\n
"
,
info
.
Path
)
if
info
.
Meta
!=
nil
{
fmt
.
Printf
(
"Путь в конфиге: %s
\n
"
,
info
.
ConfPath
)
if
info
.
Meta
.
Group
!=
""
{
fmt
.
Printf
(
"Строка в конфиге: %d
\n
"
,
info
.
LineNumber
)
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
"Группа"
),
info
.
Meta
.
Group
)
}
if
info
.
Meta
.
Summary
!=
""
{
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
"Краткое"
),
info
.
Meta
.
Summary
)
}
if
info
.
Meta
.
Description
!=
""
{
fmt
.
Printf
(
"%s:
\n
%s
\n
"
,
blue
(
"Описание"
),
info
.
Meta
.
Description
)
}
}
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
"Статус"
),
info
.
Status
.
Color
(
"%s %s"
,
info
.
Status
.
Symbol
,
info
.
Status
.
Label
))
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
"Путь"
),
info
.
Path
)
fmt
.
Printf
(
"%s: %s
\n
"
,
blue
(
"Путь в конфиге"
),
info
.
ConfPath
)
fmt
.
Printf
(
"%s: %d
\n
"
,
blue
(
"Строка в конфиге"
),
info
.
LineNumber
)
if
info
.
Available
{
if
info
.
Available
{
fmt
.
Print
ln
(
"Доступен: да"
)
fmt
.
Print
f
(
"%s: да
\n
"
,
blue
(
"Доступен"
)
)
}
else
{
}
else
{
fmt
.
Print
ln
(
"Доступен: нет"
)
fmt
.
Print
f
(
"%s: нет
\n
"
,
blue
(
"Доступен"
)
)
}
}
if
len
(
errors
)
>
0
{
if
len
(
errors
)
>
0
{
fmt
.
Printf
(
"
\n
Ошибки (%d):
\n
"
,
len
(
errors
))
fmt
.
Printf
(
"
\n
%s (%d):
\n
"
,
blue
(
"Ошибки"
)
,
len
(
errors
))
for
_
,
e
:=
range
errors
{
for
_
,
e
:=
range
errors
{
fmt
.
Printf
(
" %d: %s
\n
"
,
e
.
Line
,
e
.
Text
)
fmt
.
Printf
(
" %d: %s
\n
"
,
e
.
Line
,
e
.
Text
)
}
}
...
...
hyprland/json.go
View file @
19c74f34
package
hyprland
package
hyprland
type
ModuleShowJSON
struct
{
type
ModuleShowJSON
struct
{
Name
string
`json:"name"`
HyprModule
Status
string
`json:"status"`
Path
string
`json:"path"`
ConfPath
string
`json:"conf_path"`
LineNumber
int
`json:"line_number"`
Available
bool
`json:"available"`
Errors
[]
ModuleErrorJSON
`json:"errors"`
Errors
[]
ModuleErrorJSON
`json:"errors"`
}
}
...
@@ -14,3 +9,11 @@ type ModuleErrorJSON struct {
...
@@ -14,3 +9,11 @@ type ModuleErrorJSON struct {
Line
int
`json:"line"`
Line
int
`json:"line"`
Text
string
`json:"text"`
Text
string
`json:"text"`
}
}
type
ModuleInfoJSON
struct
{
Name
string
`json:"name"`
Group
string
`json:"group"`
Summary
string
`json:"summary"`
Status
string
`json:"status"`
Errors
int
`json:"errors"`
}
hyprland/manager.go
View file @
19c74f34
...
@@ -35,12 +35,13 @@ type SourceLine struct {
...
@@ -35,12 +35,13 @@ type SourceLine struct {
}
}
type
HyprModule
struct
{
type
HyprModule
struct
{
Name
string
Name
string
`json:"name"`
Status
config
.
ItemStatus
Status
config
.
ItemStatus
`json:"status"`
Path
string
Path
string
`json:"path"`
ConfPath
string
ConfPath
string
`json:"conf_path"`
LineNumber
int
LineNumber
int
`json:"line_number"`
Available
bool
Available
bool
`json:"available"`
Meta
*
ModuleMeta
`json:"meta,omitempty"`
}
}
type
HyprVar
struct
{
type
HyprVar
struct
{
...
@@ -200,6 +201,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
...
@@ -200,6 +201,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
Path
:
sysFile
,
Path
:
sysFile
,
ConfPath
:
ConfPath
,
ConfPath
:
ConfPath
,
Available
:
Available
,
Available
:
Available
,
Meta
:
ParseModuleMeta
(
sysFile
),
}
}
}
}
return
HyprModule
{
return
HyprModule
{
...
@@ -248,25 +250,26 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
...
@@ -248,25 +250,26 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
ConfPath
:
ConfPath
,
ConfPath
:
ConfPath
,
LineNumber
:
LineNumber
,
LineNumber
:
LineNumber
,
Available
:
Available
,
Available
:
Available
,
Meta
:
ParseModuleMeta
(
sysFile
),
}
}
}
}
// закомментирован
// закомментирован
if
foundCommented
{
if
foundCommented
{
// файла нет
mod
:=
HyprModule
{
Path
:=
sysFile
if
!
FileExists
{
Path
=
""
}
// файл есть
return
HyprModule
{
Name
:
module
,
Name
:
module
,
Status
:
config
.
ModuleStatus
.
Disabled
,
Status
:
config
.
ModuleStatus
.
Disabled
,
Path
:
Path
,
Path
:
sysFile
,
ConfPath
:
ConfPath
,
ConfPath
:
ConfPath
,
LineNumber
:
LineNumber
,
LineNumber
:
LineNumber
,
Available
:
Available
,
Available
:
Available
,
}
}
if
FileExists
{
mod
.
Meta
=
ParseModuleMeta
(
sysFile
)
}
else
{
mod
.
Path
=
""
}
return
mod
}
}
// файл есть, но строка отсутствует
// файл есть, но строка отсутствует
...
@@ -277,6 +280,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
...
@@ -277,6 +280,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
Path
:
sysFile
,
Path
:
sysFile
,
ConfPath
:
ConfPath
,
ConfPath
:
ConfPath
,
Available
:
Available
,
Available
:
Available
,
Meta
:
ParseModuleMeta
(
sysFile
),
}
}
}
}
...
@@ -310,6 +314,9 @@ func (m *HyprlandManager) GetModulesList(user bool, filter string) []HyprModule
...
@@ -310,6 +314,9 @@ func (m *HyprlandManager) GetModulesList(user bool, filter string) []HyprModule
modules
=
m
.
SystemModules
modules
=
m
.
SystemModules
}
}
groupFilter
:=
strings
.
TrimPrefix
(
filter
,
"group:"
)
isGroupFilter
:=
groupFilter
!=
filter
var
res
[]
HyprModule
var
res
[]
HyprModule
for
_
,
module
:=
range
modules
{
for
_
,
module
:=
range
modules
{
info
:=
m
.
GetModuleInfo
(
module
,
user
)
info
:=
m
.
GetModuleInfo
(
module
,
user
)
...
@@ -318,7 +325,9 @@ func (m *HyprlandManager) GetModulesList(user bool, filter string) []HyprModule
...
@@ -318,7 +325,9 @@ func (m *HyprlandManager) GetModulesList(user bool, filter string) []HyprModule
continue
continue
}
}
if
filter
==
""
||
filter
==
"all"
||
info
.
Status
.
Label
==
filter
{
if
filter
==
""
||
filter
==
"all"
||
info
.
Status
.
Label
==
filter
||
(
isGroupFilter
&&
info
.
Meta
!=
nil
&&
info
.
Meta
.
Group
==
groupFilter
)
{
res
=
append
(
res
,
info
)
res
=
append
(
res
,
info
)
}
}
}
}
...
@@ -349,6 +358,22 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
...
@@ -349,6 +358,22 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
return
""
,
fmt
.
Errorf
(
"модуль '%s' уже включён"
,
module
)
return
""
,
fmt
.
Errorf
(
"модуль '%s' уже включён"
,
module
)
}
}
// отключить другие модули той же группы
var
disabledGroup
[]
string
if
info
.
Meta
!=
nil
&&
info
.
Meta
.
Group
!=
""
{
for
_
,
other
:=
range
m
.
GetModulesList
(
user
,
"enabled"
)
{
if
other
.
Name
==
module
{
continue
}
if
other
.
Meta
!=
nil
&&
other
.
Meta
.
Group
==
info
.
Meta
.
Group
{
m
.
Lines
[
other
.
LineNumber
]
=
"#"
+
m
.
Lines
[
other
.
LineNumber
]
m
.
updateSourceCommented
(
other
.
LineNumber
,
true
)
m
.
Changed
=
true
disabledGroup
=
append
(
disabledGroup
,
other
.
Name
)
}
}
}
// был закомментирован
// был закомментирован
if
info
.
Status
.
IsEqual
(
config
.
ModuleStatus
.
Disabled
)
{
if
info
.
Status
.
IsEqual
(
config
.
ModuleStatus
.
Disabled
)
{
if
onlyNew
{
if
onlyNew
{
...
@@ -357,7 +382,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
...
@@ -357,7 +382,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
m
.
Lines
[
info
.
LineNumber
]
=
strings
.
TrimPrefix
(
m
.
Lines
[
info
.
LineNumber
],
"#"
)
m
.
Lines
[
info
.
LineNumber
]
=
strings
.
TrimPrefix
(
m
.
Lines
[
info
.
LineNumber
],
"#"
)
m
.
updateSourceCommented
(
info
.
LineNumber
,
false
)
m
.
updateSourceCommented
(
info
.
LineNumber
,
false
)
m
.
Changed
=
true
m
.
Changed
=
true
return
fmt
.
Sprintf
(
"Модуль '%s' включён"
,
module
),
nil
return
m
.
enableMessage
(
module
,
disabledGroup
),
nil
}
}
// не использовался
// не использовался
...
@@ -371,7 +396,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
...
@@ -371,7 +396,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
Commented
:
false
,
Commented
:
false
,
})
})
m
.
Changed
=
true
m
.
Changed
=
true
return
fmt
.
Sprintf
(
"Модуль '%s' включён"
,
module
),
nil
return
m
.
enableMessage
(
module
,
disabledGroup
),
nil
}
}
return
""
,
fmt
.
Errorf
(
"модуль '%s' не изменён"
,
module
)
return
""
,
fmt
.
Errorf
(
"модуль '%s' не изменён"
,
module
)
...
@@ -407,6 +432,14 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
...
@@ -407,6 +432,14 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
return
""
,
nil
return
""
,
nil
}
}
func
(
m
*
HyprlandManager
)
enableMessage
(
module
string
,
disabledGroup
[]
string
)
string
{
msg
:=
fmt
.
Sprintf
(
"Модуль '%s' включён"
,
module
)
for
_
,
name
:=
range
disabledGroup
{
msg
+=
fmt
.
Sprintf
(
"
\n
Модуль '%s' отключён (группа)"
,
name
)
}
return
msg
}
// Plugins
// Plugins
func
(
m
*
HyprlandManager
)
GetLoadedPlugins
()
[]
HyprPlugin
{
func
(
m
*
HyprlandManager
)
GetLoadedPlugins
()
[]
HyprPlugin
{
...
...
hyprland/meta.go
0 → 100644
View file @
19c74f34
package
hyprland
import
(
"os"
"strings"
"gopkg.in/yaml.v3"
)
const
metaDelimiter
=
"#---"
type
ModuleMeta
struct
{
Summary
string
`yaml:"summary,omitempty"`
Description
string
`yaml:"description,omitempty"`
Group
string
`yaml:"group,omitempty"`
}
func
ParseModuleMeta
(
filePath
string
)
*
ModuleMeta
{
data
,
err
:=
os
.
ReadFile
(
filePath
)
if
err
!=
nil
{
return
nil
}
lines
:=
strings
.
Split
(
string
(
data
),
"
\n
"
)
// Найти открывающий #---
start
:=
-
1
for
i
,
line
:=
range
lines
{
trimmed
:=
strings
.
TrimSpace
(
line
)
if
trimmed
==
""
{
continue
}
if
trimmed
==
metaDelimiter
{
start
=
i
break
}
// Первая непустая строка не #--- — метаинформации нет
return
nil
}
if
start
<
0
{
return
nil
}
// Собрать строки до закрывающего #---
var
yamlLines
[]
string
for
i
:=
start
+
1
;
i
<
len
(
lines
);
i
++
{
trimmed
:=
strings
.
TrimSpace
(
lines
[
i
])
if
trimmed
==
metaDelimiter
{
break
}
line
:=
lines
[
i
]
if
strings
.
HasPrefix
(
line
,
"# "
)
{
line
=
line
[
2
:
]
// снимаем "# "
}
else
if
strings
.
HasPrefix
(
line
,
"#"
)
{
line
=
line
[
1
:
]
// снимаем "#"
}
yamlLines
=
append
(
yamlLines
,
line
)
}
if
len
(
yamlLines
)
==
0
{
return
nil
}
var
meta
ModuleMeta
if
err
:=
yaml
.
Unmarshal
([]
byte
(
strings
.
Join
(
yamlLines
,
"
\n
"
)),
&
meta
);
err
!=
nil
{
return
nil
}
if
meta
.
Summary
==
""
&&
meta
.
Description
==
""
&&
meta
.
Group
==
""
{
return
nil
}
return
&
meta
}
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