core: init i18n

parent b3fa78cf
......@@ -5,6 +5,7 @@ go 1.25.0
require (
github.com/fatih/color v1.18.0
github.com/godbus/dbus/v5 v5.1.0
github.com/leonelquinteros/gotext v1.7.2
github.com/urfave/cli/v3 v3.4.1
gopkg.in/yaml.v3 v3.0.1
)
......
......@@ -4,6 +4,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/leonelquinteros/gotext v1.7.2 h1:bDPndU8nt+/kRo1m4l/1OXiiy2v7Z7dfPQ9+YP7G1Mc=
github.com/leonelquinteros/gotext v1.7.2/go.mod h1:9/haCkm5P7Jay1sxKDGJ5WIg4zkz8oZKw4ekNpALob8=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
......
......@@ -2,10 +2,12 @@ package hyprland
import (
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
"ximperconf/utils"
"context"
"errors"
"fmt"
"os"
"os/exec"
......@@ -23,7 +25,7 @@ func HyprlandFixConfigCommand(ctx context.Context, cmd *cli.Command) error {
manager.FixConfig()
color.Green("Конфигурация исправлена")
color.Green(locale.T("Configuration fixed"))
return nil
}
......@@ -39,7 +41,7 @@ func HyprlandCheckCommand(ctx context.Context, cmd *cli.Command) error {
}
if len(result) == 0 {
color.Green("Ошибок нет")
color.Green(locale.T("No errors"))
return nil
}
......@@ -58,7 +60,7 @@ func HyprlandModuleStatusCommand(ctx context.Context, cmd *cli.Command) error {
info := manager.GetModuleInfo(cmd.Args().Get(0), cmd.Bool("user"))
if !info.Available {
color.Red("недопустимое название для модуля.")
color.Red(locale.T("invalid module name"))
return nil
}
fmt.Println(info.Status.Label)
......@@ -68,7 +70,7 @@ func HyprlandModuleStatusCommand(ctx context.Context, cmd *cli.Command) error {
func HyprlandModuleCheckCommand(ctx context.Context, cmd *cli.Command) error {
if cmd.Args().Get(0) == "" {
return fmt.Errorf("укажите модуль для проверки")
return errors.New(locale.T("specify module name"))
}
manager, err := GetHyprlandManager(ctx)
......@@ -79,7 +81,7 @@ func HyprlandModuleCheckCommand(ctx context.Context, cmd *cli.Command) error {
moduleinfo := manager.GetModuleInfo(cmd.Args().Get(0), cmd.Bool("user"))
if !moduleinfo.Available {
return fmt.Errorf("недопустимое название для модуля")
return errors.New(locale.T("invalid module name"))
}
result, err := manager.CheckModule(cmd.Args().Get(0), cmd.Bool("user"))
......@@ -89,7 +91,7 @@ func HyprlandModuleCheckCommand(ctx context.Context, cmd *cli.Command) error {
}
if len(result) == 0 {
color.Green("Ошибок нет")
color.Green(locale.T("No errors"))
return nil
}
......@@ -182,12 +184,12 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
if config.IsJSON(cmd) {
return ui.PrintJSON([]ModuleInfoJSON{})
}
return fmt.Errorf("нет доступных модулей")
return errors.New(locale.T("no available modules"))
}
type moduleData struct {
info HyprModule
errorNum int
info HyprModule
errorNum int
}
data := make([]moduleData, 0, len(modules))
......@@ -222,7 +224,7 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
parts = append(parts, d.info.Meta.Summary)
}
if d.errorNum > 0 {
parts = append(parts, fmt.Sprintf("(ошибки: %d)", d.errorNum))
parts = append(parts, fmt.Sprintf(locale.T("(errors: %d)"), d.errorNum))
}
name := d.info.Name
if d.info.Meta != nil && d.info.Meta.Group != "" {
......@@ -236,7 +238,7 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Modules",
Title: locale.T("Modules"),
Items: items,
Style: ui.DefaultTreeStyle,
Color: true,
......@@ -258,11 +260,11 @@ func HyprlandModuleEditCommand(ctx context.Context, cmd *cli.Command) error {
info := manager.GetModuleInfo(module, user)
if !info.Available {
return fmt.Errorf("недопустимое название для модуля")
return errors.New(locale.T("invalid module name"))
}
if info.Path == "" {
return fmt.Errorf("модуль '%s' не найден: %s", module, modulefile)
return fmt.Errorf(locale.T("module '%s' not found: %s"), module, modulefile)
}
editor := utils.GetEditor()
......@@ -274,7 +276,7 @@ func HyprlandModuleEditCommand(ctx context.Context, cmd *cli.Command) error {
err = editCmd.Run()
if err != nil {
return fmt.Errorf("не удалось запустить редактор: %s", err.Error())
return fmt.Errorf(locale.T("failed to start editor: %s"), err.Error())
}
return nil
......@@ -283,7 +285,7 @@ func HyprlandModuleEditCommand(ctx context.Context, cmd *cli.Command) error {
func HyprlandModuleShowCommand(ctx context.Context, cmd *cli.Command) error {
module := cmd.Args().Get(0)
if module == "" {
return fmt.Errorf("укажите имя модуля")
return errors.New(locale.T("specify module name"))
}
user := cmd.Bool("user")
......@@ -294,7 +296,7 @@ func HyprlandModuleShowCommand(ctx context.Context, cmd *cli.Command) error {
info := manager.GetModuleInfo(module, user)
if !info.Available {
return fmt.Errorf("недопустимое название для модуля")
return errors.New(locale.T("invalid module name"))
}
errors, _ := manager.CheckModule(module, user)
......@@ -311,30 +313,30 @@ func HyprlandModuleShowCommand(ctx context.Context, cmd *cli.Command) error {
}
blue := color.New(color.FgBlue).SprintFunc()
fmt.Printf("%s: %s\n", blue("Модуль"), info.Name)
fmt.Printf("%s: %s\n", blue(locale.T("Module")), info.Name)
if info.Meta != nil {
if info.Meta.Group != "" {
fmt.Printf("%s: %s\n", blue("Группа"), info.Meta.Group)
fmt.Printf("%s: %s\n", blue(locale.T("Group")), info.Meta.Group)
}
if info.Meta.Summary != "" {
fmt.Printf("%s: %s\n", blue("Краткое"), info.Meta.Summary)
fmt.Printf("%s: %s\n", blue(locale.T("Summary")), info.Meta.Summary)
}
if info.Meta.Description != "" {
fmt.Printf("%s: \n%s\n", blue("Описание"), info.Meta.Description)
fmt.Printf("%s: \n%s\n", blue(locale.T("Description")), 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)
fmt.Printf("%s: %s\n", blue(locale.T("Status")), info.Status.Color("%s %s", info.Status.Symbol, info.Status.Label))
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)
if info.Available {
fmt.Printf("%s: да\n", blue("Доступен"))
fmt.Printf("%s: %s\n", blue(locale.T("Available")), locale.T("yes"))
} else {
fmt.Printf("%s: нет\n", blue("Доступен"))
fmt.Printf("%s: %s\n", blue(locale.T("Available")), locale.T("no"))
}
if len(errors) > 0 {
fmt.Printf("\n%s (%d):\n", blue("Ошибки"), len(errors))
fmt.Printf("\n%s (%d):\n", blue(locale.T("Errors")), len(errors))
for _, e := range errors {
fmt.Printf(" %d: %s\n", e.Line, e.Text)
}
......
......@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"ximperconf/config"
"ximperconf/locale"
"github.com/urfave/cli/v3"
)
......@@ -12,11 +13,11 @@ func CommandList() *cli.Command {
return &cli.Command{
Name: "hyprland",
Hidden: config.Env.Hyprland == nil,
Usage: "Hyprland Management",
Usage: locale.T("Hyprland Management"),
Before: func(ctx context.Context, command *cli.Command) (context.Context, error) {
manager, err := NewHyprlandManager()
if err != nil {
return ctx, fmt.Errorf("не удалось инициализировать HyprlandManager: %w", err)
return ctx, fmt.Errorf(locale.T("failed to initialize HyprlandManager: %w"), err)
}
ctx = context.WithValue(ctx, config.HyprManagerKey, manager)
......@@ -25,7 +26,7 @@ func CommandList() *cli.Command {
After: func(ctx context.Context, command *cli.Command) error {
manager, err := GetHyprlandManager(ctx)
if err != nil {
return fmt.Errorf("не удалось инициализировать HyprlandManager: %w", err)
return fmt.Errorf(locale.T("failed to initialize HyprlandManager: %w"), err)
}
manager.Save()
return nil
......@@ -33,22 +34,22 @@ func CommandList() *cli.Command {
Commands: []*cli.Command{
{
Name: "check",
Usage: "Check the Hyprland config",
Usage: locale.T("Check the Hyprland config"),
Action: HyprlandCheckCommand,
},
{
Name: "fix",
Usage: "Fix config: sort modules into sections by order",
Usage: locale.T("Fix config: sort modules into sections by order"),
Action: HyprlandFixConfigCommand,
},
{
Name: "sync-xkb-layouts",
Usage: "Sync layouts with xkb",
Usage: locale.T("Sync layouts with xkb"),
Action: HyprlandSyncSystemLayouts,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "force",
Usage: "Forced update",
Usage: locale.T("Forced update"),
Aliases: []string{"f"},
Value: false,
},
......@@ -56,11 +57,11 @@ func CommandList() *cli.Command {
},
{
Name: "module",
Usage: "Hyprland modules",
Usage: locale.T("Hyprland modules"),
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "user",
Usage: "use user modules",
Usage: locale.T("use user modules"),
Aliases: []string{"u"},
Value: false,
},
......@@ -68,28 +69,28 @@ func CommandList() *cli.Command {
Commands: []*cli.Command{
{
Name: "check",
Usage: "Check Hyprland module",
Usage: locale.T("Check Hyprland module"),
ArgsUsage: "module",
Action: HyprlandModuleCheckCommand,
ShellComplete: ShellCompleteModule("all"),
},
{
Name: "edit",
Usage: "Edit module file",
Usage: locale.T("Edit module file"),
ArgsUsage: "module",
Action: HyprlandModuleEditCommand,
ShellComplete: ShellCompleteModule("all"),
},
{
Name: "status",
Usage: "Hyprland module status",
Usage: locale.T("Hyprland module status"),
ArgsUsage: "module",
Action: HyprlandModuleStatusCommand,
ShellComplete: ShellCompleteModule("all"),
},
{
Name: "show",
Usage: "Show detailed module info",
Usage: locale.T("Show detailed module info"),
ArgsUsage: "module",
Flags: []cli.Flag{
config.FormatFlag,
......@@ -99,11 +100,11 @@ func CommandList() *cli.Command {
},
{
Name: "info",
Usage: "Information about modules",
Usage: locale.T("Information about modules"),
Flags: []cli.Flag{
&cli.StringFlag{
Name: "filter",
Usage: "status filter",
Usage: locale.T("status filter"),
Aliases: []string{"f"},
Value: "all",
},
......@@ -113,18 +114,18 @@ func CommandList() *cli.Command {
},
{
Name: "enable",
Usage: "enable module",
Usage: locale.T("enable module"),
ArgsUsage: "module",
Action: HyprlandModuleEnableCommand,
ShellComplete: ShellCompleteModule("disabled"),
},
{
Name: "disable",
Usage: "disable module",
Usage: locale.T("disable module"),
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "remove",
Usage: "delete module line from config",
Usage: locale.T("delete module line from config"),
Aliases: []string{"r"},
Value: false,
},
......@@ -135,7 +136,7 @@ func CommandList() *cli.Command {
},
{
Name: "toggle",
Usage: "toggle module",
Usage: locale.T("toggle module"),
ArgsUsage: "module",
Action: HyprlandToggleModuleCommand,
ShellComplete: ShellCompleteModule("all"),
......@@ -144,11 +145,11 @@ func CommandList() *cli.Command {
},
{
Name: "var",
Usage: "Hyprland vars",
Usage: locale.T("Hyprland vars"),
Commands: []*cli.Command{
{
Name: "list",
Usage: "vars list",
Usage: locale.T("vars list"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -156,7 +157,7 @@ func CommandList() *cli.Command {
},
{
Name: "info",
Usage: "vars info",
Usage: locale.T("vars info"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -164,18 +165,18 @@ func CommandList() *cli.Command {
},
{
Name: "get",
Usage: "get var value",
Usage: locale.T("get var value"),
Action: HyprlandVarGetCommand,
ShellComplete: ShellCompleteVarList,
},
{
Name: "set",
Usage: "set var value",
Usage: locale.T("set var value"),
Action: HyprlandVarSetCommand,
},
{
Name: "unset",
Usage: "unset var",
Usage: locale.T("unset var"),
Action: HyprlandVarUnsetCommand,
ShellComplete: ShellCompleteVarList,
},
......@@ -183,11 +184,11 @@ func CommandList() *cli.Command {
},
{
Name: "plugin",
Usage: "Hyprland plugins",
Usage: locale.T("Hyprland plugins"),
Commands: []*cli.Command{
{
Name: "list",
Usage: "Hyprland plugins list",
Usage: locale.T("Hyprland plugins list"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -195,18 +196,18 @@ func CommandList() *cli.Command {
},
{
Name: "status",
Usage: "Hyprland plugin status",
Usage: locale.T("Hyprland plugin status"),
ArgsUsage: "plugin",
Action: HyprlandPluginStatusCommand,
ShellComplete: ShellCompletePlugin("all"),
},
{
Name: "info",
Usage: "Information about plugins",
Usage: locale.T("Information about plugins"),
Flags: []cli.Flag{
&cli.StringFlag{
Name: "filter",
Usage: "status filter",
Usage: locale.T("status filter"),
Aliases: []string{"f"},
Value: "all",
},
......@@ -216,21 +217,21 @@ func CommandList() *cli.Command {
},
{
Name: "load",
Usage: "load plugin",
Usage: locale.T("load plugin"),
ArgsUsage: "plugin",
Action: HyprlandPluginLoadCommand,
ShellComplete: ShellCompletePlugin("unloaded"),
},
{
Name: "unload",
Usage: "unload plugin",
Usage: locale.T("unload plugin"),
ArgsUsage: "plugin",
Action: HyprlandPluginUnloadCommand,
ShellComplete: ShellCompletePlugin("loaded"),
},
{
Name: "toggle",
Usage: "toggle plugin",
Usage: locale.T("toggle plugin"),
ArgsUsage: "plugin",
Action: HyprlandPluginToggleCommand,
ShellComplete: ShellCompletePlugin("all"),
......
......@@ -2,8 +2,10 @@ package hyprland
import (
"context"
"errors"
"fmt"
"ximperconf/config"
"ximperconf/locale"
"github.com/fatih/color"
"github.com/godbus/dbus/v5"
......@@ -38,18 +40,18 @@ func HyprlandSyncSystemLayouts(ctx context.Context, cmd *cli.Command) error {
sysLayouts, err := HyprlandGetKeyboardLayouts()
if err != nil {
return fmt.Errorf("не удалось получить системные раскладки: %w", err)
return fmt.Errorf(locale.T("failed to get system layouts: %w"), err)
}
hyprLayouts := manager.GetVar("kb_layout")
if force || hyprLayouts == "" {
if _, err := manager.SetVar("kb_layout", sysLayouts); err != nil {
return fmt.Errorf("не удалось обновить kb_layout в Hyprland: %w", err)
return fmt.Errorf(locale.T("failed to update kb_layout in Hyprland: %w"), err)
}
color.Green("Раскладка обновлена!")
color.Green(locale.T("Layout updated!"))
} else {
return fmt.Errorf("раскладка уже установлена, используйте '--force' для принудительного обновления")
return errors.New(locale.T("layout is already set, use '--force' for forced update"))
}
return nil
......
......@@ -3,6 +3,7 @@ package hyprland
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"os/exec"
......@@ -11,6 +12,7 @@ import (
"strings"
"time"
"ximperconf/config"
"ximperconf/locale"
"ximperconf/utils"
)
......@@ -105,7 +107,7 @@ func NewHyprlandManager() (*HyprlandManager, error) {
func GetHyprlandManager(ctx context.Context) (*HyprlandManager, error) {
mgr, ok := ctx.Value(config.HyprManagerKey).(*HyprlandManager)
if !ok || mgr == nil {
return nil, fmt.Errorf("HyprlandManager не найден в контексте")
return nil, errors.New(locale.T("HyprlandManager not found in context"))
}
return mgr, nil
}
......@@ -136,7 +138,7 @@ func (m *HyprlandManager) Check(configPath string) ([]HyprConfigError, error) {
output, err := cmd.CombinedOutput()
if err != nil {
if _, ok := err.(*exec.ExitError); !ok {
return nil, fmt.Errorf("проверка не удалась")
return nil, errors.New(locale.T("check failed"))
}
}
......@@ -151,7 +153,7 @@ func (m *HyprlandManager) CheckModule(
info := m.GetModuleInfo(module, user)
if info.Path == "" {
return nil, fmt.Errorf("модуль '%s' не найден", module)
return nil, fmt.Errorf(locale.T("module '%s' not found"), module)
}
tmp, err := os.CreateTemp("", "ximperconf-hypr-check-*.conf")
......@@ -339,11 +341,11 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
info := m.GetModuleInfo(module, user)
if !info.Available {
return "", fmt.Errorf("недопустимое название для модуля")
return "", errors.New(locale.T("invalid module name"))
}
if info.Status.IsEqual(config.ModuleStatus.Unknown) {
return "", fmt.Errorf("модуль '%s' не найден: %s", module, info.Path)
return "", fmt.Errorf(locale.T("module '%s' not found: %s"), module, info.Path)
}
switch action {
......@@ -351,12 +353,12 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
// нет файла
if info.Path == "" || info.Status.IsEqual(config.ModuleStatus.Unknown) {
return "", fmt.Errorf("нельзя включить данный модуль")
return "", errors.New(locale.T("cannot enable this module"))
}
// уже включён
if info.Status.IsEqual(config.ModuleStatus.Enabled) {
return "", fmt.Errorf("модуль '%s' уже включён", module)
return "", fmt.Errorf(locale.T("module '%s' is already enabled"), module)
}
// отключить другие модули той же группы
......@@ -378,7 +380,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
// был закомментирован
if info.Status.IsEqual(config.ModuleStatus.Disabled) {
if onlyNew {
return "", fmt.Errorf("модуль '%s' уже присутствует в конфиге (закомментирован) — пропущено", module)
return "", fmt.Errorf(locale.T("module '%s' already present in config (commented) — skipped"), module)
}
m.Lines[info.LineNumber] = strings.TrimPrefix(m.Lines[info.LineNumber], "#")
m.updateSourceCommented(info.LineNumber, false)
......@@ -396,14 +398,14 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
return m.enableMessage(module, disabledGroup), nil
}
return "", fmt.Errorf("модуль '%s' не изменён", module)
return "", fmt.Errorf(locale.T("module '%s' not changed"), module)
case "disable":
// Уже выключен
if info.Status.IsEqual(config.ModuleStatus.Disabled) ||
info.Status.IsEqual(config.ModuleStatus.Unused) {
return "", fmt.Errorf("модуль '%s' уже отключён", module)
return "", fmt.Errorf(locale.T("module '%s' is already disabled"), module)
}
// Включён
......@@ -412,30 +414,30 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
m.Lines[info.LineNumber] = "#" + m.Lines[info.LineNumber]
m.updateSourceCommented(info.LineNumber, true)
m.Changed = true
return fmt.Sprintf("Модуль '%s' отключён", module), nil
return fmt.Sprintf(locale.T("Module '%s' disabled"), module), nil
}
case "remove":
if info.LineNumber <= 0 {
return "", fmt.Errorf("модуль '%s' не найден в конфигурации", module)
return "", fmt.Errorf(locale.T("module '%s' not found in config"), module)
}
m.removeSource(info.LineNumber)
m.removeLine(info.LineNumber)
return fmt.Sprintf("Модуль '%s' удалён", module), nil
return fmt.Sprintf(locale.T("Module '%s' removed"), module), nil
}
return "", nil
}
func (m *HyprlandManager) enableMessage(module string, disabledGroup []string) string {
msg := fmt.Sprintf("Модуль '%s' включён", module)
msg := fmt.Sprintf(locale.T("Module '%s' enabled"), module)
for _, name := range disabledGroup {
msg += fmt.Sprintf("\nМодуль '%s' отключён (группа)", name)
msg += fmt.Sprintf("\n"+locale.T("Module '%s' disabled (group)"), name)
}
if m.hasSourcesOutsideSections() {
msg += "\n\nВнимание: обнаружены модули вне секций. Выполните 'ximperconf hyprland fix' для исправления."
msg += "\n\n" + locale.T("Warning: modules found outside sections. Run 'ximperconf hyprland fix' to fix.")
}
return msg
}
......@@ -790,12 +792,12 @@ func (m *HyprlandManager) GetPluginStatus(name string) config.ItemStatus {
func (m *HyprlandManager) GetPluginFile(name string) (string, error) {
if name == "" {
return "", fmt.Errorf("плагин не указан")
return "", errors.New(locale.T("plugin not specified"))
}
path := filepath.Join(m.PluginsDir, name+".so")
if !utils.FileExists(path) {
return "", fmt.Errorf("плагин не найден")
return "", errors.New(locale.T("plugin not found"))
}
return path, nil
......@@ -818,7 +820,7 @@ func (m *HyprlandManager) GetPluginsList(filter string) []string {
func (m *HyprlandManager) SetPlugin(action string, name string) (string, error) {
if name == "" {
return "", fmt.Errorf("плагин не указан")
return "", errors.New(locale.T("plugin not specified"))
}
path, err := m.GetPluginFile(name)
......@@ -831,7 +833,7 @@ func (m *HyprlandManager) SetPlugin(action string, name string) (string, error)
switch action {
case "load":
if status.IsEqual(config.PluginStatus.Loaded) {
return "", fmt.Errorf("плагин уже загружен")
return "", errors.New(locale.T("plugin is already loaded"))
}
time.Sleep(1 * time.Second)
......@@ -839,11 +841,11 @@ func (m *HyprlandManager) SetPlugin(action string, name string) (string, error)
if out, err := cmd.CombinedOutput(); err != nil {
return "", fmt.Errorf("%v (%s)", err, out)
}
return fmt.Sprintf("Плагин '%s' загружен", name), nil
return fmt.Sprintf(locale.T("Plugin '%s' loaded"), name), nil
case "unload":
if status.IsEqual(config.PluginStatus.Unloaded) {
return "", fmt.Errorf("плагин не загружен")
return "", errors.New(locale.T("plugin is not loaded"))
}
time.Sleep(1 * time.Second)
......@@ -851,7 +853,7 @@ func (m *HyprlandManager) SetPlugin(action string, name string) (string, error)
if out, err := cmd.CombinedOutput(); err != nil {
return "", fmt.Errorf("%v (%s)", err, out)
}
return fmt.Sprintf("Плагин '%s' выгружен", name), nil
return fmt.Sprintf(locale.T("Plugin '%s' unloaded"), name), nil
}
return "", nil
......@@ -882,21 +884,21 @@ func (m *HyprlandManager) GetVar(name string) string {
func (m *HyprlandManager) SetVar(name, value string) (string, error) {
if name == "" {
return "", fmt.Errorf("укажите имя переменной")
return "", errors.New(locale.T("specify variable name"))
}
if value == "" {
return "", fmt.Errorf("укажите значение переменной")
return "", errors.New(locale.T("specify variable value"))
}
for i, v := range m.Vars {
if v.Name == name {
if v.Value == value {
return "", fmt.Errorf("переменная '%s' уже '%s'", v.Name, v.Value)
return "", fmt.Errorf(locale.T("variable '%s' is already '%s'"), v.Name, v.Value)
}
m.Lines[v.LineNumber] = fmt.Sprintf("$%s = %s", name, value)
m.Vars[i].Value = value
m.Changed = true
return fmt.Sprintf("Переменная '%s' обновлена: %s", name, value), nil
return fmt.Sprintf(locale.T("Variable '%s' updated: %s"), name, value), nil
}
}
......@@ -909,19 +911,19 @@ func (m *HyprlandManager) SetVar(name, value string) (string, error) {
m.shiftLineNumbers(insertAt-1, 1)
m.Vars = append(m.Vars, HyprVar{Name: name, Value: value, LineNumber: insertAt})
m.Changed = true
return fmt.Sprintf("Переменная '%s' установлена: %s", name, value), nil
return fmt.Sprintf(locale.T("Variable '%s' set: %s"), name, value), nil
}
insertAt := len(m.Lines)
m.Lines = append(m.Lines, "", sectionHeader(sectionVars), newLine)
m.Vars = append(m.Vars, HyprVar{Name: name, Value: value, LineNumber: insertAt + 2})
m.Changed = true
return fmt.Sprintf("Блок VARS создан, переменная '%s' установлена: %s", name, value), nil
return fmt.Sprintf(locale.T("VARS block created, variable '%s' set: %s"), name, value), nil
}
func (m *HyprlandManager) UnsetVar(name string) error {
if name == "" {
return fmt.Errorf("укажите имя переменной")
return errors.New(locale.T("specify variable name"))
}
for i, v := range m.Vars {
......@@ -931,7 +933,7 @@ func (m *HyprlandManager) UnsetVar(name string) error {
return nil
}
}
return fmt.Errorf("переменная %s не найдена", name)
return fmt.Errorf(locale.T("variable '%s' not found"), name)
}
// ====================
......
......@@ -2,9 +2,11 @@ package hyprland
import (
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
"context"
"errors"
"fmt"
"strings"
......@@ -49,7 +51,7 @@ func HyprlandPluginInfoCommand(ctx context.Context, cmd *cli.Command) error {
if config.IsJSON(cmd) {
return ui.PrintJSON([]ui.JSONItem{})
}
return fmt.Errorf("нет доступных плагинов")
return errors.New(locale.T("no available plugins"))
}
items := make([]ui.TreeItem, 0, len(plugins))
......@@ -76,7 +78,7 @@ func HyprlandPluginInfoCommand(ctx context.Context, cmd *cli.Command) error {
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Plugins",
Title: locale.T("Plugins"),
Items: items,
Style: ui.DefaultTreeStyle,
Color: true,
......
......@@ -3,6 +3,7 @@ package hyprland
import (
"context"
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
"ximperconf/utils"
......@@ -48,7 +49,7 @@ func HyprlandVarInfoCommand(ctx context.Context, cmd *cli.Command) error {
if config.IsJSON(cmd) {
return ui.PrintJSON([]ui.JSONItem{})
}
color.Yellow("Нет переменных в конфигурации")
color.Yellow(locale.T("No variables in configuration"))
return nil
}
......@@ -73,7 +74,7 @@ func HyprlandVarInfoCommand(ctx context.Context, cmd *cli.Command) error {
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Vars",
Title: locale.T("Vars"),
Items: items,
Style: ui.DefaultTreeStyle,
Sort: true,
......@@ -90,7 +91,7 @@ func HyprlandVarGetCommand(ctx context.Context, cmd *cli.Command) error {
}
info := manager.GetVar(v)
if info == "" {
return fmt.Errorf("переменная '%s' не установлена", v)
return fmt.Errorf(locale.T("variable '%s' is not set"), v)
}
fmt.Println(info)
return nil
......@@ -113,15 +114,15 @@ func HyprlandVarSetCommand(ctx context.Context, cmd *cli.Command) error {
func hyprlandVarUnset(name string) error {
if name == "" {
color.Red("Укажите имя переменной")
color.Red(locale.T("specify variable name"))
os.Exit(1)
}
if !regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`).MatchString(name) {
color.Red("Недопустимое имя переменной: %s", name)
color.Red(locale.T("Invalid variable name: %s"), name)
os.Exit(1)
}
if !utils.FileExists(config.Env.Hyprland.Config) {
color.Red("Конфигурация не найдена: %s", config.Env.Hyprland.Config)
color.Red(locale.T("Configuration not found: %s"), config.Env.Hyprland.Config)
os.Exit(1)
}
......@@ -141,11 +142,11 @@ func hyprlandVarUnset(name string) error {
}
if !removed {
color.Red("Переменная %s не найдена", name)
color.Red(locale.T("variable '%s' not found"), name)
os.Exit(1)
}
color.Green("Переменная %s удалена", name)
color.Green(locale.T("Variable '%s' removed"), name)
return os.WriteFile(config.Env.Hyprland.Config, []byte(strings.Join(newLines, "\n")), 0644)
}
......
package locale
import (
"os"
"strings"
"github.com/leonelquinteros/gotext"
)
var LocaleDir string
func Init() {
gotext.Configure(LocaleDir, getLocale(), "ximperconf")
}
// getText is a variable to avoid go vet printf wrapper detection.
var getText = gotext.Get
func T(msgid string) string {
return getText(msgid)
}
func TN(msgid, msgidPlural string, n int) string {
return gotext.GetN(msgid, msgidPlural, n)
}
func getLocale() string {
for _, env := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} {
if v := os.Getenv(env); v != "" {
if idx := strings.Index(v, "."); idx != -1 {
return v[:idx]
}
return v
}
}
return "en"
}
......@@ -5,9 +5,11 @@ import (
"os"
"ximperconf/config"
"ximperconf/hyprland"
"ximperconf/locale"
"ximperconf/preset"
"ximperconf/repo"
"ximperconf/system"
"ximperconf/ui"
"github.com/urfave/cli/v3"
)
......@@ -15,12 +17,14 @@ import (
func main() {
config.InitConfig()
locale.Init()
ui.SetupHelpTemplates()
config.InitDBus()
defer config.DBusConn.Close()
rootCommand := &cli.Command{
Name: "ximperconf",
Usage: "Ximper Linux Configuration Tool",
Usage: locale.T("Ximper Linux Configuration Tool"),
EnableShellCompletion: true,
Version: config.Env.Version,
Commands: []*cli.Command{
......@@ -31,7 +35,7 @@ func main() {
{
Name: "help",
Aliases: []string{"h"},
Usage: "show help",
Usage: locale.T("show help"),
ArgsUsage: "[command]",
HideHelp: true,
},
......
......@@ -7,13 +7,21 @@ project('ximperconf',
],
)
i18n = import('i18n')
go_root = run_command('printenv', 'GOROOT', check: false)
go_bin = go_root.returncode() != 0 ? find_program('go') : find_program(join_paths(go_root.stdout().strip(), 'bin', 'go'))
LOCALES_DIR = get_option('prefix') / get_option('localedir')
ldflags = '-X \'ximperconf/locale.LocaleDir=' + LOCALES_DIR + '\''
if get_option('shell_completion').enabled()
subdir('data/completion')
endif
subdir('po')
custom_target(
'go-build',
build_by_default: true,
......@@ -23,7 +31,10 @@ custom_target(
install: true,
install_dir: get_option('bindir'),
command: [
'go', 'build','-o','@OUTPUT@',meson.current_source_dir()
'go', 'build',
'-ldflags', ldflags,
'-o', '@OUTPUT@',
meson.current_source_dir()
],
env: [
'CGO_ENABLED=0'
......
hyprland/actions.go
hyprland/commands.go
hyprland/keyboard-actions.go
hyprland/manager.go
hyprland/plugin-actions.go
hyprland/var-actions.go
main.go
preset/actions.go
preset/commands.go
preset/tools.go
repo/actions.go
repo/commands.go
system/commands.go
system/grub-actions.go
ui/help.go
#!/bin/sh
# Should run from project root dir
po/update_potfiles
cat ./po/POTFILES | xargs xgettext --language=C --keyword=T --keyword=TN:1,2 -o po/ximperconf.pot --from-code=UTF-8 --add-comments --package-name=ximperconf
i18n.gettext(meson.project_name(), preset: 'glib')
This diff is collapsed. Click to expand it.
#!/bin/bash
# Should run from project root dir
./po/create_pot
update-lang() {
msgmerge -U --backup=off po/$1.po po/ximperconf.pot
}
if [ "$1" = "all" ]; then
for lang in $(cat po/LINGUAS); do
update-lang $lang
done
else
update-lang $1
fi
#!/bin/sh
# Should run from project root dir
touch ./po/unsort-POTFILES
find ./ -iname "*.go" -not -path "./builddir/*" -type f -exec grep -lrE 'locale\.T\(|locale\.TN\(' {} + | while read file; do echo "${file#./}" >> ./po/unsort-POTFILES; done
cat ./po/unsort-POTFILES | sort | uniq > ./po/POTFILES
rm ./po/unsort-POTFILES
......@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"ximperconf/config"
"ximperconf/locale"
"github.com/urfave/cli/v3"
)
......@@ -11,11 +12,11 @@ import (
func CommandList() *cli.Command {
return &cli.Command{
Name: "preset",
Usage: "Manage preset configuration profiles",
Usage: locale.T("Manage preset configuration profiles"),
Commands: []*cli.Command{
{
Name: "info",
Usage: "Show information about a preset profiles",
Usage: locale.T("Show information about preset profiles"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -23,11 +24,11 @@ func CommandList() *cli.Command {
},
{
Name: "apply",
Usage: "Apply a profile",
Usage: locale.T("Apply a profile"),
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "dry-run",
Usage: "Show what would be created without making changes.",
Usage: locale.T("Show what would be created without making changes"),
Aliases: []string{"d"},
Value: false,
},
......@@ -37,11 +38,11 @@ func CommandList() *cli.Command {
},
{
Name: "apply-all",
Usage: "Apply all available profiles",
Usage: locale.T("Apply all available profiles"),
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "dry-run",
Usage: "Show what would be created without making changes.",
Usage: locale.T("Show what would be created without making changes"),
Aliases: []string{"d"},
Value: false,
},
......
......@@ -8,6 +8,7 @@ import (
"strings"
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
)
......@@ -41,13 +42,13 @@ func AppendOpResult(res *Result, r opResult) {
switch {
case r.Status.IsEqual(config.OpStatus.Skipped):
item.Name = fmt.Sprintf("Уже существует: %s", r.Target)
item.Name = fmt.Sprintf(locale.T("Already exists: %s"), r.Target)
case r.Status.IsEqual(config.OpStatus.DryRun):
item.Name = fmt.Sprintf("%s → %s", r.Source, r.Target)
case r.Status.IsEqual(config.OpStatus.Done):
item.Name = fmt.Sprintf("%s → %s", r.Source, r.Target)
case r.Status.IsEqual(config.OpStatus.Error):
item.Name = fmt.Sprintf("Ошибка: %s", r.Reason)
item.Name = fmt.Sprintf(locale.T("Error: %s"), r.Reason)
}
switch r.Kind {
......@@ -81,11 +82,11 @@ func expandPath(path, name string) string {
}
func renderPresetResult(res *Result) {
ui.RenderTreeItems("Копируем", res.Copies)
ui.RenderTreeItems("Создаём ссылки", res.Links)
ui.RenderTreeItems("Обновляем", res.Replaced)
ui.RenderTreeItems("Настраиваем систему", res.System)
ui.RenderTreeItems("Создаём переменные Hyprland", res.HyprVars)
ui.RenderTreeItems("Подключаем модули Hyprland", res.HyprModules)
ui.RenderTreeItems("Синхронизируем раскладку Hyprland", res.SyncSystemLayouts)
ui.RenderTreeItems(locale.T("Copying"), res.Copies)
ui.RenderTreeItems(locale.T("Creating links"), res.Links)
ui.RenderTreeItems(locale.T("Updating"), res.Replaced)
ui.RenderTreeItems(locale.T("Configuring system"), res.System)
ui.RenderTreeItems(locale.T("Creating Hyprland variables"), res.HyprVars)
ui.RenderTreeItems(locale.T("Enabling Hyprland modules"), res.HyprModules)
ui.RenderTreeItems(locale.T("Syncing Hyprland layout"), res.SyncSystemLayouts)
}
......@@ -8,6 +8,7 @@ import (
"os"
"regexp"
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
"github.com/fatih/color"
......@@ -27,14 +28,14 @@ var (
func deferredGetHTML() string {
resp, err := http.Get(config.Env.Repo.DeferredInfoURL)
if err != nil {
color.Red("Ошибка получения данных")
color.Red(locale.T("Error fetching data"))
os.Exit(1)
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
color.Red("Ошибка получения данных")
color.Red(locale.T("Error fetching data"))
os.Exit(1)
}
return string(data)
......@@ -86,8 +87,8 @@ func DeferredInfoCommand(ctx context.Context, cmd *cli.Command) error {
}
color.Green("Deferred:")
fmt.Printf(" Последнее обновление: %s\n", lastUpdate)
fmt.Printf(" Дата архива: %s\n", archiveDate)
fmt.Printf(" %s: %s\n", locale.T("Last update"), lastUpdate)
fmt.Printf(" %s: %s\n", locale.T("Archive date"), archiveDate)
return nil
}
......@@ -2,6 +2,7 @@ package repo
import (
"ximperconf/config"
"ximperconf/locale"
"github.com/urfave/cli/v3"
)
......@@ -9,15 +10,15 @@ import (
func CommandList() *cli.Command {
return &cli.Command{
Name: "repo",
Usage: "Ximper repos",
Usage: locale.T("Ximper repos"),
Commands: []*cli.Command{
{
Name: "deferred",
Usage: "Deferred repo",
Usage: locale.T("Deferred repo"),
Commands: []*cli.Command{
{
Name: "info",
Usage: "Deferred repo info",
Usage: locale.T("Deferred repo info"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -25,12 +26,12 @@ func CommandList() *cli.Command {
},
{
Name: "date",
Usage: "Sisyphus archive date",
Usage: locale.T("Sisyphus archive date"),
Action: DeferredArchiveDateCommand,
},
{
Name: "last-update",
Usage: "Date of last update",
Usage: locale.T("Date of last update"),
Action: DeferredLastUpdateCommand,
},
},
......
......@@ -3,6 +3,7 @@ package system
import (
"fmt"
"ximperconf/config"
"ximperconf/locale"
"context"
......@@ -13,10 +14,10 @@ func CommandList() *cli.Command {
return &cli.Command{
Name: "system",
Hidden: !config.Env.IsRoot,
Usage: "System Management",
Usage: locale.T("System Management"),
Before: func(ctx context.Context, command *cli.Command) (context.Context, error) {
if !config.Env.IsRoot {
fmt.Printf("Эта команда требует root.\n")
fmt.Println(locale.T("This command requires root"))
return nil, fmt.Errorf("")
}
return ctx, nil
......@@ -24,18 +25,18 @@ func CommandList() *cli.Command {
Commands: []*cli.Command{
{
Name: "fix-grub-resolution",
Usage: "Fix GRUB resolution",
Usage: locale.T("Fix GRUB resolution"),
Action: SystemGrubFixResolutionCommand,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "update",
Usage: "Automatically run update-grub after fixing",
Usage: locale.T("Automatically run update-grub after fixing"),
Aliases: []string{"u"},
Value: false,
},
&cli.BoolFlag{
Name: "verbose",
Usage: "Enable verbose output",
Usage: locale.T("Enable verbose output"),
Aliases: []string{"V"},
Value: false,
},
......
......@@ -6,6 +6,7 @@ import (
"os"
"os/exec"
"strings"
"ximperconf/locale"
"github.com/urfave/cli/v3"
)
......@@ -19,7 +20,7 @@ func SystemGrubFixResolution(autoUpdate, verbose bool) error {
content, err := os.ReadFile(grubFile)
if err != nil {
return fmt.Errorf("не удалось прочитать %s: %w", grubFile, err)
return fmt.Errorf(locale.T("failed to read %s: %w"), grubFile, err)
}
lines := strings.Split(string(content), "\n")
......@@ -46,12 +47,12 @@ func SystemGrubFixResolution(autoUpdate, verbose bool) error {
}
if !changed {
return fmt.Errorf("GRUB_GFXMODE уже установлен: %s", oldValue)
return fmt.Errorf(locale.T("GRUB_GFXMODE is already set: %s"), oldValue)
}
newContent := strings.Join(lines, "\n")
if err := os.WriteFile(grubFile, []byte(newContent), 0644); err != nil {
return fmt.Errorf("не удалось записать %s: %w", grubFile, err)
return fmt.Errorf(locale.T("failed to write %s: %w"), grubFile, err)
}
if verbose {
......@@ -62,10 +63,10 @@ func SystemGrubFixResolution(autoUpdate, verbose bool) error {
cmd := exec.Command("update-grub")
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("ошибка при выполнении update-grub: %v (%s)", err, out)
return fmt.Errorf(locale.T("error running update-grub: %v (%s)"), err, out)
}
if verbose {
fmt.Println("Лог update-grub:\n", string(out))
fmt.Println(locale.T("update-grub log:")+" \n", string(out))
}
}
......@@ -82,10 +83,10 @@ func SystemGrubFixResolutionCommand(ctx context.Context, cmd *cli.Command) error
}
if !verbose {
fmt.Println("GRUB_GFXMODE исправлен успешно.")
fmt.Println(locale.T("GRUB_GFXMODE fixed"))
}
if autoUpdate && !verbose {
fmt.Println("Выполнен update-grub.")
fmt.Println(locale.T("update-grub completed"))
}
return nil
......
package ui
import (
"fmt"
"strings"
"ximperconf/locale"
"github.com/fatih/color"
"github.com/urfave/cli/v3"
)
func SetupHelpTemplates() {
cli.HelpFlag = &cli.BoolFlag{
Name: "help",
Aliases: []string{"h"},
Usage: locale.T("show help"),
HideDefault: true,
Local: true,
}
cli.VersionFlag = &cli.BoolFlag{
Name: "version",
Aliases: []string{"v"},
Usage: locale.T("print the version"),
HideDefault: true,
Local: true,
}
title := color.New(color.Bold, color.FgYellow).SprintFunc()
cli.RootCommandHelpTemplate = fmt.Sprintf(`%s
{{template "helpNameTemplate" .}} {{if .Version}}{{if not .HideVersion}}{{.Version}}{{end}}{{end}}{{if .Description}}
%s
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} [command [command options]]{{end}}
%s
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}}
%s{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
%s{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
%s{{template "visibleFlagTemplate" .}}{{end}}
`,
title(locale.T("Module:")),
title(locale.T("Usage:")),
title(locale.T("Description:")),
title(locale.T("Commands:")),
title(locale.T("Options:")),
title(locale.T("Options:")),
)
cli.CommandHelpTemplate = fmt.Sprintf(`%s
{{template "helpNameTemplate" .}}
%s
{{template "usageTemplate" .}}{{if .Category}}
%s
{{.Category}}{{end}}{{if .Description}}
%s
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
%s{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
%s{{template "visibleFlagTemplate" .}}{{end}}{{if .VisiblePersistentFlags}}
%s{{template "visiblePersistentFlagTemplate" .}}{{end}}
`,
title(locale.T("Module:")),
title(locale.T("Usage:")),
title(locale.T("Category:")),
title(locale.T("Description:")),
title(locale.T("Options:")),
title(locale.T("Options:")),
title(locale.T("Global options:")),
)
cli.SubcommandHelpTemplate = fmt.Sprintf(`%s
{{template "helpNameTemplate" .}}
%s
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} [command [command options]]{{end}}{{if .Category}}
%s
{{.Category}}{{end}}{{if .Description}}
%s
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}}
%s{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
%s{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
%s{{template "visibleFlagTemplate" .}}{{end}}
`,
title(locale.T("Module:")),
title(locale.T("Usage:")),
title(locale.T("Category:")),
title(locale.T("Description:")),
title(locale.T("Commands:")),
title(locale.T("Options:")),
title(locale.T("Options:")),
)
cli.FlagStringer = func(fl cli.Flag) string {
df, ok := fl.(cli.DocGenerationFlag)
if !ok {
return ""
}
placeholder, usage := unquoteUsage(df.GetUsage())
needsPlaceholder := df.TakesValue()
if needsPlaceholder && placeholder == "" {
placeholder = ""
}
defaultValueString := ""
if rf, ok := fl.(cli.RequiredFlag); !ok || !rf.IsRequired() {
isVisible := df.IsDefaultVisible()
if s := df.GetDefaultText(); isVisible && s != "" {
defaultValueString = fmt.Sprintf(" (%s: %s)", locale.T("default"), s)
}
}
usageWithDefault := strings.TrimSpace(usage + defaultValueString)
var prefixed string
names := fl.Names()
for i, name := range names {
if name == "" {
continue
}
if len(name) == 1 {
prefixed += "-" + name
} else {
prefixed += "--" + name
}
if placeholder != "" {
prefixed += " " + placeholder
}
if i < len(names)-1 {
prefixed += ", "
}
}
if sliceFlag, ok := fl.(cli.DocGenerationMultiValueFlag); ok && sliceFlag.IsMultiValueFlag() {
prefixed = prefixed + " [ " + prefixed + " ]"
}
envVars := df.GetEnvVars()
envHint := ""
if len(envVars) > 0 {
envHint = fmt.Sprintf(" [%s]", strings.Join(envVars, ", "))
}
return fmt.Sprintf(" %s\t%s%s", prefixed, usageWithDefault, envHint)
}
}
func unquoteUsage(usage string) (string, string) {
for i := 0; i < len(usage); i++ {
if usage[i] == '`' {
for j := i + 1; j < len(usage); j++ {
if usage[j] == '`' {
name := usage[i+1 : j]
usage = usage[:i] + name + usage[j+1:]
return name, usage
}
}
break
}
}
return "", usage
}
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