status: improve the status system

parent e86cb735
package config
import "github.com/fatih/color"
type ItemStatus struct {
Symbol string
Color func(format string, a ...interface{}) string
Label string
}
var unknown ItemStatus = ItemStatus{
Symbol: "?",
Color: color.YellowString,
Label: "unknown",
}
func (s ItemStatus) IsEqual(other ItemStatus) bool {
return s.Label == other.Label
}
var ModuleStatus = struct {
Unknown ItemStatus
Enabled ItemStatus
Disabled ItemStatus
Missing ItemStatus
Unused ItemStatus
}{
Unknown: unknown,
Enabled: ItemStatus{
Symbol: "●",
Color: color.GreenString,
Label: "enabled",
},
Disabled: ItemStatus{
Symbol: "○",
Color: color.RedString,
Label: "disabled",
},
Missing: ItemStatus{
Symbol: "!",
Color: color.YellowString,
Label: "missing",
},
Unused: ItemStatus{
Symbol: "-",
Color: color.HiBlackString,
Label: "unused",
},
}
var PluginStatus = struct {
Unknown ItemStatus
Loaded ItemStatus
Unloaded ItemStatus
}{
Unknown: unknown,
Loaded: ItemStatus{
Symbol: "●",
Color: color.GreenString,
Label: "loaded",
},
Unloaded: ItemStatus{
Symbol: "○",
Color: color.RedString,
Label: "unloaded",
},
}
var ProfileStatus = struct {
Unknown ItemStatus
Available ItemStatus
Unavailable ItemStatus
}{
Unknown: unknown,
Available: ItemStatus{
Symbol: "●",
Color: color.GreenString,
Label: "available",
},
Unavailable: ItemStatus{
Symbol: "○",
Color: color.RedString,
Label: "unavailable",
},
}
package hyprland
import (
"ximperconf/config"
"ximperconf/ui"
"ximperconf/utils"
......@@ -35,22 +36,6 @@ func HyprlandCheckCommand(ctx context.Context, cmd *cli.Command) error {
return nil
}
func hyprlandModuleStatusStruct(manager *HyprlandManager, module string, user bool) ui.ItemStatus {
info := manager.GetModuleInfo(module, user)
switch info.Status {
case "enabled":
return ui.StatusEnabled
case "disabled":
return ui.StatusDisabled
case "missing":
return ui.StatusMissing
case "unused":
return ui.StatusUnused
}
return ui.StatusUnknown
}
func HyprlandModuleStatusCommand(ctx context.Context, cmd *cli.Command) error {
manager, err := GetHyprlandManager(ctx)
......@@ -63,7 +48,7 @@ func HyprlandModuleStatusCommand(ctx context.Context, cmd *cli.Command) error {
color.Red("недопустимое название для модуля.")
return nil
}
fmt.Println(info.Status)
fmt.Println(info.Status.Label)
return nil
}
......@@ -153,10 +138,14 @@ func HyprlandToggleModuleCommand(ctx context.Context, cmd *cli.Command) error {
var msg string
switch info.Status {
case "enabled":
switch info.Status.Label {
case config.ModuleStatus.Enabled.Label:
msg, err = manager.SetModule("disable", module, user, false)
case config.ModuleStatus.Disabled.Label, config.ModuleStatus.Unused.Label:
msg, err = manager.SetModule("enable", module, user, false)
case config.ModuleStatus.Missing.Label:
msg, err = manager.SetModule("disable", module, user, false)
case "disabled", "unused":
default:
msg, err = manager.SetModule("enable", module, user, false)
}
......@@ -185,7 +174,7 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
items := make([]ui.TreeItem, 0, len(modules))
for _, module := range modules {
status := hyprlandModuleStatusStruct(manager, module, user)
info := manager.GetModuleInfo(module, user)
errors, err := manager.CheckModule(module, user)
......@@ -199,17 +188,17 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
}
items = append(items, ui.TreeItem{
Name: module,
Status: status,
Status: info.Status,
Description: desc,
})
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Modules",
Items: items,
Style: ui.DefaultTreeStyle,
StatusMap: ui.ColorStatusMap,
Sort: true,
Title: "Modules",
Items: items,
Style: ui.DefaultTreeStyle,
Color: true,
Sort: true,
})
return nil
......
......@@ -28,7 +28,7 @@ type HyprlandManager struct {
type HyprModule struct {
Name string
Status string
Status config.ItemStatus
Path string
ConfPath string
LineNumber int
......@@ -182,7 +182,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
if FileExists {
return HyprModule{
Name: module,
Status: "unused",
Status: config.ModuleStatus.Unused,
Path: sysFile,
ConfPath: ConfPath,
Available: Available,
......@@ -190,7 +190,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
}
return HyprModule{
Name: module,
Status: "missing",
Status: config.ModuleStatus.Missing,
Available: Available,
}
}
......@@ -222,7 +222,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
if !FileExists {
return HyprModule{
Name: module,
Status: "missing",
Status: config.ModuleStatus.Missing,
LineNumber: LineNumber,
Available: Available,
}
......@@ -230,7 +230,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
// файл есть
return HyprModule{
Name: module,
Status: "enabled",
Status: config.ModuleStatus.Enabled,
Path: sysFile,
ConfPath: ConfPath,
LineNumber: LineNumber,
......@@ -248,7 +248,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
// файл есть
return HyprModule{
Name: module,
Status: "disabled",
Status: config.ModuleStatus.Disabled,
Path: Path,
ConfPath: ConfPath,
LineNumber: LineNumber,
......@@ -260,7 +260,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
if FileExists {
return HyprModule{
Name: module,
Status: "unused",
Status: config.ModuleStatus.Unused,
Path: sysFile,
ConfPath: ConfPath,
Available: Available,
......@@ -270,7 +270,7 @@ func (m *HyprlandManager) GetModuleInfo(module string, user bool) HyprModule {
// Файла нет и упоминаний нет
return HyprModule{
Name: module,
Status: "unknown",
Status: config.ModuleStatus.Unknown,
Available: Available,
}
}
......@@ -305,7 +305,7 @@ func (m *HyprlandManager) GetModulesList(user bool, filter string) []string {
continue
}
if filter == "" || filter == "all" || info.Status == filter {
if filter == "" || filter == "all" || info.Status.Label == filter {
res = append(res, module)
}
}
......@@ -319,7 +319,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
return "", fmt.Errorf("недопустимое название для модуля")
}
if info.Status == "unknown" {
if info.Status.IsEqual(config.ModuleStatus.Unknown) {
return "", fmt.Errorf("модуль '%s' не найден: %s", module, info.Path)
}
......@@ -327,17 +327,17 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
case "enable":
// нет файла
if info.Path == "" || info.Status == "missing" {
if info.Path == "" || info.Status.IsEqual(config.ModuleStatus.Unknown) {
return "", fmt.Errorf("нельзя включить данный модуль")
}
// уже включён
if info.Status == "enabled" {
if info.Status.IsEqual(config.ModuleStatus.Enabled) {
return "", fmt.Errorf("модуль '%s' уже включён", module)
}
// был закомментирован
if info.Status == "disabled" {
if info.Status.IsEqual(config.ModuleStatus.Disabled) {
if onlyNew {
return "", fmt.Errorf("модуль '%s' уже присутствует в конфиге (закомментирован) — пропущено", module)
}
......@@ -347,7 +347,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
}
// не использовался
if info.Status == "unused" {
if info.Status.IsEqual(config.ModuleStatus.Unused) {
line := "source = " + info.ConfPath
m.Lines = append(m.Lines, line)
m.Changed = true
......@@ -359,12 +359,14 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
case "disable":
// Уже выключен
if info.Status == "disabled" || info.Status == "unused" {
if info.Status.IsEqual(config.ModuleStatus.Disabled) ||
info.Status.IsEqual(config.ModuleStatus.Unused) {
return "", fmt.Errorf("модуль '%s' уже отключён", module)
}
// Включён
if info.Status == "enabled" || info.Status == "missing" {
if info.Status.IsEqual(config.ModuleStatus.Enabled) ||
info.Status.IsEqual(config.ModuleStatus.Missing) {
m.Lines[info.LineNumber] = "#" + m.Lines[info.LineNumber]
m.Changed = true
return fmt.Sprintf("Модуль '%s' отключён", module), nil
......@@ -397,14 +399,14 @@ func (m *HyprlandManager) GetLoadedPlugins() []HyprPlugin {
return plugins
}
func (m *HyprlandManager) GetPluginStatus(name string) string {
func (m *HyprlandManager) GetPluginStatus(name string) config.ItemStatus {
for _, p := range m.LoadedPlugins {
if p.Name == name {
return "loaded"
return config.PluginStatus.Loaded
}
}
return "unloaded"
return config.PluginStatus.Unloaded
}
func (m *HyprlandManager) GetPluginFile(name string) (string, error) {
......@@ -427,7 +429,7 @@ func (m *HyprlandManager) GetPluginsList(filter string) []string {
for _, plugin := range plugins {
status := m.GetPluginStatus(plugin)
if filter == "" || filter == "all" || filter == status {
if filter == "" || filter == "all" || status.Label == filter {
list = append(list, plugin)
}
}
......@@ -449,7 +451,7 @@ func (m *HyprlandManager) SetPlugin(action string, name string) (string, error)
switch action {
case "load":
if status == "loaded" {
if status.IsEqual(config.PluginStatus.Loaded) {
return "", fmt.Errorf("плагин уже загружен")
}
......@@ -461,7 +463,7 @@ func (m *HyprlandManager) SetPlugin(action string, name string) (string, error)
return fmt.Sprintf("Плагин '%s' загружен", name), nil
case "unload":
if status == "unloaded" {
if status.IsEqual(config.PluginStatus.Unloaded) {
return "", fmt.Errorf("плагин не загружен")
}
......
package hyprland
import (
"ximperconf/config"
"ximperconf/ui"
"context"
......@@ -10,16 +11,6 @@ import (
"github.com/urfave/cli/v3"
)
func hyprlandPluginStatusStruct(status string) ui.ItemStatus {
switch status {
case "loaded":
return ui.StatusLoaded
case "unloaded":
return ui.StatusUnloaded
}
return ui.StatusUnknown
}
func HyprlandPluginListCommand(ctx context.Context, cmd *cli.Command) error {
manager, err := GetHyprlandManager(ctx)
if err != nil {
......@@ -35,7 +26,7 @@ func HyprlandPluginStatusCommand(ctx context.Context, cmd *cli.Command) error {
if err != nil {
return err
}
fmt.Println(manager.GetPluginStatus(cmd.Args().Get(0)))
fmt.Println(manager.GetPluginStatus(cmd.Args().Get(0)).Label)
return nil
}
......@@ -52,10 +43,9 @@ func HyprlandPluginInfoCommand(ctx context.Context, cmd *cli.Command) error {
items := make([]ui.TreeItem, 0, len(plugins))
for _, plugin := range plugins {
_status := manager.GetPluginStatus(plugin)
status := hyprlandPluginStatusStruct(_status)
status := manager.GetPluginStatus(plugin)
desc := ""
if _status == "loaded" {
if status.IsEqual(config.PluginStatus.Loaded) {
for _, plug := range manager.LoadedPlugins {
if plug.Name == plugin {
desc = plug.Description
......@@ -70,11 +60,11 @@ func HyprlandPluginInfoCommand(ctx context.Context, cmd *cli.Command) error {
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Plugins",
Items: items,
Style: ui.DefaultTreeStyle,
StatusMap: ui.ColorStatusMap,
Sort: true,
Title: "Plugins",
Items: items,
Style: ui.DefaultTreeStyle,
Color: true,
Sort: true,
})
return nil
}
......@@ -120,10 +110,10 @@ func HyprlandPluginToggleCommand(ctx context.Context, cmd *cli.Command) error {
path := cmd.Args().Get(0)
status := manager.GetPluginStatus(path)
switch status {
case "loaded":
switch status.Label {
case config.PluginStatus.Loaded.Label:
msg, err = manager.SetPlugin("unload", path)
case "unloaded":
case config.PluginStatus.Unloaded.Label:
msg, err = manager.SetPlugin("load", path)
}
......
......@@ -49,17 +49,15 @@ func HyprlandVarInfoCommand(ctx context.Context, cmd *cli.Command) error {
}
items = append(items, ui.TreeItem{
Name: v.Name,
Status: ui.StatusNo,
Description: desc,
})
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Vars",
Items: items,
Style: ui.DefaultTreeStyle,
StatusMap: ui.ColorStatusMap,
Sort: true,
Title: "Vars",
Items: items,
Style: ui.DefaultTreeStyle,
Sort: true,
})
return nil
......
......@@ -339,11 +339,11 @@ func ShowProfilesInfo() {
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Profiles",
Items: items,
Style: ui.DefaultTreeStyle,
StatusMap: ui.ColorStatusMap,
Sort: true,
Title: "Profiles",
Items: items,
Style: ui.DefaultTreeStyle,
Color: true,
Sort: true,
})
}
......
......@@ -27,11 +27,11 @@ func profileAvailable(p config.PresetProfile) bool {
return allowed
}
func profileStatus(p config.PresetProfile) ui.ItemStatus {
func profileStatus(p config.PresetProfile) config.ItemStatus {
if profileAvailable(p) {
return ui.StatusAvailable
return config.ProfileStatus.Available
}
return ui.StatusUnavailable
return config.ProfileStatus.Unavailable
}
func AppendOpResult(res *config.PresetResult, r opResult) {
......
......@@ -3,100 +3,12 @@ package ui
import (
"fmt"
"sort"
"github.com/fatih/color"
"ximperconf/config"
)
type ItemStatus int
const (
StatusUnknown ItemStatus = iota
StatusNo
StatusEnabled
StatusLoaded
StatusAvailable
StatusDisabled
StatusUnavailable
StatusUnloaded
StatusMissing
StatusUnused
)
type StatusInfo struct {
Symbol string
Color func(format string, a ...interface{}) string
Label string
}
var ColorStatusMap = map[ItemStatus]StatusInfo{
StatusUnknown: {
Symbol: "?",
Color: color.YellowString,
Label: "unknown",
},
StatusNo: {
Symbol: "",
Color: color.YellowString,
Label: "no",
},
StatusEnabled: {
Symbol: "●",
Color: color.GreenString,
Label: "enabled",
},
StatusLoaded: {
Symbol: "●",
Color: color.GreenString,
Label: "loaded",
},
StatusAvailable: {
Symbol: "●",
Color: color.GreenString,
Label: "available",
},
StatusDisabled: {
Symbol: "○",
Color: color.RedString,
Label: "disabled",
},
StatusUnloaded: {
Symbol: "○",
Color: color.RedString,
Label: "unloaded",
},
StatusUnavailable: {
Symbol: "○",
Color: color.RedString,
Label: "unavailable",
},
StatusMissing: {
Symbol: "!",
Color: color.YellowString,
Label: "missing",
},
StatusUnused: {
Symbol: "-",
Color: color.HiBlackString,
Label: "unused",
},
}
var PlainStatusMap = map[ItemStatus]StatusInfo{
StatusEnabled: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "enabled"},
StatusLoaded: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "loaded"},
StatusAvailable: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "available"},
StatusDisabled: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "disabled"},
StatusUnloaded: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "unloaded"},
StatusUnavailable: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "unavailable"},
StatusMissing: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "missing"},
StatusUnused: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "unused"},
StatusUnknown: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "unknown"},
StatusNo: {Symbol: "", Color: func(format string, a ...interface{}) string { return fmt.Sprintf(format, a...) }, Label: "no"},
}
type TreeItem struct {
Name string
Status ItemStatus
Status config.ItemStatus
Description string
}
......@@ -113,11 +25,18 @@ var DefaultTreeStyle = TreeStyle{
}
type RenderTreeOptions struct {
Title string
Items []TreeItem
Style TreeStyle
StatusMap map[ItemStatus]StatusInfo
Sort bool
Title string
Items []TreeItem
Style TreeStyle
Color bool
Sort bool
}
func colorize(item TreeItem, color bool) (string, string) {
if color && item.Status.Color != nil {
return item.Status.Color(item.Status.Symbol), item.Status.Color(item.Name)
}
return item.Status.Symbol, item.Name
}
func RenderTree(opts RenderTreeOptions) {
......@@ -125,10 +44,6 @@ func RenderTree(opts RenderTreeOptions) {
opts.Style = DefaultTreeStyle
}
if opts.StatusMap == nil {
opts.StatusMap = ColorStatusMap
}
if opts.Sort {
sort.Slice(opts.Items, func(i, j int) bool {
return opts.Items[i].Name < opts.Items[j].Name
......@@ -145,17 +60,13 @@ func RenderTree(opts RenderTreeOptions) {
prefix = opts.Style.PrefixLast
}
info, ok := opts.StatusMap[it.Status]
if !ok {
info = opts.StatusMap[StatusUnknown]
}
symbol, name := colorize(it, opts.Color)
line := fmt.Sprintf(
"%s %s %s",
prefix,
info.Color(info.Symbol),
info.Color(it.Name),
)
line := prefix + " "
if symbol != "" {
line += symbol + " "
}
line += name
if it.Description != "" {
line += opts.Style.Separator + it.Description
......
package ui
import (
"fmt"
"github.com/fatih/color"
)
......@@ -16,15 +14,13 @@ func RenderTreeLines(title string, lines []string) {
items := make([]TreeItem, len(lines))
for i, line := range lines {
items[i] = TreeItem{
Name: line,
Status: StatusUnknown,
Name: line,
}
}
RenderTree(RenderTreeOptions{
Items: items,
Style: DefaultTreeStyle,
StatusMap: PlainStatusMap,
Items: items,
Style: DefaultTreeStyle,
Color: false,
})
fmt.Println()
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment