aac139368f
Moves all packages from internal/ to pkg/ so they can be imported by external modules (needed for claude-pm integration). - internal/app/ → pkg/app/ - internal/docker/ → pkg/docker/ - internal/config/ → pkg/config/ - internal/utils/ → pkg/utils/ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
646 lines
27 KiB
Go
646 lines
27 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
)
|
|
|
|
type AppColors struct {
|
|
Borders Borders `toml:"borders,omitempty" json:"borders,omitempty"`
|
|
ChartCPU ChartCPU `toml:"chart_cpu,omitempty" json:"chart_cpu,omitempty"`
|
|
ChartMemory ChartMemory `toml:"chart_memory,omitempty" json:"chart_memory,omitempty"`
|
|
ChartBandwidth ChartBandwidth `toml:"chart_bandwidth,omitempty" json:"chart_bandwidth,omitempty"`
|
|
ChartPorts ChartPorts `toml:"chart_ports,omitempty" json:"chart_ports,omitempty"`
|
|
Commands Commands `toml:"commands,omitempty" json:"commands,omitempty"`
|
|
ContainerState ContainerState `toml:"container_state,omitempty" json:"container_state,omitempty"`
|
|
Containers Containers `toml:"containers,omitempty" json:"containers,omitempty"`
|
|
LogSearch LogSearch `toml:"log_search,omitempty" json:"log_search,omitempty"`
|
|
Filter Filter `toml:"filter,omitempty" json:"filter,omitempty"`
|
|
HeadersBar HeadersBar `toml:"headers_bar,omitempty" json:"headers_bar,omitempty"`
|
|
Logs Logs `toml:"logs,omitempty" json:"logs,omitempty"`
|
|
PopupDelete PopupDelete `toml:"popup_delete,omitempty" json:"popup_delete,omitempty"`
|
|
PopupError PopupError `toml:"popup_error,omitempty" json:"popup_error,omitempty"`
|
|
PopupHelp PopupHelp `toml:"popup_help,omitempty" json:"popup_help,omitempty"`
|
|
PopupInfo PopupInfo `toml:"popup_info,omitempty" json:"popup_info,omitempty"`
|
|
}
|
|
|
|
type Borders struct {
|
|
Selected string `toml:"selected,omitempty" json:"selected,omitempty"`
|
|
Unselected string `toml:"unselected,omitempty" json:"unselected,omitempty"`
|
|
}
|
|
|
|
type ChartCPU struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Border string `toml:"border,omitempty" json:"border,omitempty"`
|
|
Title string `toml:"title,omitempty" json:"title,omitempty"`
|
|
Max string `toml:"max,omitempty" json:"max,omitempty"`
|
|
Points string `toml:"points,omitempty" json:"points,omitempty"`
|
|
YAxis string `toml:"y_axis,omitempty" json:"y_axis,omitempty"`
|
|
}
|
|
|
|
type ChartMemory struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Border string `toml:"border,omitempty" json:"border,omitempty"`
|
|
Title string `toml:"title,omitempty" json:"title,omitempty"`
|
|
Max string `toml:"max,omitempty" json:"max,omitempty"`
|
|
Points string `toml:"points,omitempty" json:"points,omitempty"`
|
|
YAxis string `toml:"y_axis,omitempty" json:"y_axis,omitempty"`
|
|
}
|
|
|
|
type ChartBandwidth struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Border string `toml:"border,omitempty" json:"border,omitempty"`
|
|
MaxRX string `toml:"max_rx,omitempty" json:"max_rx,omitempty"`
|
|
MaxTX string `toml:"max_tx,omitempty" json:"max_tx,omitempty"`
|
|
PointsRX string `toml:"points_rx,omitempty" json:"points_rx,omitempty"`
|
|
PointsTX string `toml:"points_tx,omitempty" json:"points_tx,omitempty"`
|
|
TitleRX string `toml:"title_rx,omitempty" json:"title_rx,omitempty"`
|
|
TitleTX string `toml:"title_tx,omitempty" json:"title_tx,omitempty"`
|
|
YAxis string `toml:"y_axis,omitempty" json:"y_axis,omitempty"`
|
|
}
|
|
|
|
type ChartPorts struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Border string `toml:"border,omitempty" json:"border,omitempty"`
|
|
Title string `toml:"title,omitempty" json:"title,omitempty"`
|
|
Headings string `toml:"headings,omitempty" json:"headings,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
}
|
|
|
|
type Commands struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Pause string `toml:"pause,omitempty" json:"pause,omitempty"`
|
|
Restart string `toml:"restart,omitempty" json:"restart,omitempty"`
|
|
Stop string `toml:"stop,omitempty" json:"stop,omitempty"`
|
|
Delete string `toml:"delete,omitempty" json:"delete,omitempty"`
|
|
Resume string `toml:"resume,omitempty" json:"resume,omitempty"`
|
|
Start string `toml:"start,omitempty" json:"start,omitempty"`
|
|
}
|
|
|
|
type ContainerState struct {
|
|
Dead string `toml:"dead,omitempty" json:"dead,omitempty"`
|
|
Exited string `toml:"exited,omitempty" json:"exited,omitempty"`
|
|
Paused string `toml:"paused,omitempty" json:"paused,omitempty"`
|
|
Removing string `toml:"removing,omitempty" json:"removing,omitempty"`
|
|
Restarting string `toml:"restarting,omitempty" json:"restarting,omitempty"`
|
|
RunningHealthy string `toml:"running_healthy,omitempty" json:"running_healthy,omitempty"`
|
|
RunningUnhealthy string `toml:"running_unhealthy,omitempty" json:"running_unhealthy,omitempty"`
|
|
Unknown string `toml:"unknown,omitempty" json:"unknown,omitempty"`
|
|
}
|
|
|
|
type Containers struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Icon string `toml:"icon,omitempty" json:"icon,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
TextRX string `toml:"text_rx,omitempty" json:"text_rx,omitempty"`
|
|
TextTX string `toml:"text_tx,omitempty" json:"text_tx,omitempty"`
|
|
}
|
|
|
|
type LogSearch struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
ButtonText string `toml:"button_text,omitempty" json:"button_text,omitempty"`
|
|
Highlight string `toml:"highlight,omitempty" json:"highlight,omitempty"`
|
|
}
|
|
|
|
type Filter struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
SelectedFilterBackground string `toml:"selected_filter_background,omitempty" json:"selected_filter_background,omitempty"`
|
|
SelectedFilterText string `toml:"selected_filter_text,omitempty" json:"selected_filter_text,omitempty"`
|
|
Highlight string `toml:"highlight,omitempty" json:"highlight,omitempty"`
|
|
}
|
|
|
|
type HeadersBar struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
LoadingSpinner string `toml:"loading_spinner,omitempty" json:"loading_spinner,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
TextSelected string `toml:"text_selected,omitempty" json:"text_selected,omitempty"`
|
|
}
|
|
|
|
type Logs struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
}
|
|
|
|
type PopupDelete struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
TextHighlight string `toml:"text_highlight,omitempty" json:"text_highlight,omitempty"`
|
|
}
|
|
|
|
type PopupError struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
}
|
|
|
|
type PopupHelp struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
TextHighlight string `toml:"text_highlight,omitempty" json:"text_highlight,omitempty"`
|
|
}
|
|
|
|
type PopupInfo struct {
|
|
Background string `toml:"background,omitempty" json:"background,omitempty"`
|
|
Text string `toml:"text,omitempty" json:"text,omitempty"`
|
|
}
|
|
|
|
type Keymap struct {
|
|
Clear []string `toml:"clear,omitempty" json:"clear,omitempty"`
|
|
ClearSecondary []string `toml:"-" json:"-"`
|
|
DeleteConfirm []string `toml:"delete_confirm,omitempty" json:"delete_confirm,omitempty"`
|
|
DeleteConfirmSecondary []string `toml:"-" json:"-"`
|
|
DeleteDeny []string `toml:"delete_deny,omitempty" json:"delete_deny,omitempty"`
|
|
DeleteDenySecondary []string `toml:"-" json:"-"`
|
|
Exec []string `toml:"exec,omitempty" json:"exec,omitempty"`
|
|
ExecSecondary []string `toml:"-" json:"-"`
|
|
FilterMode []string `toml:"filter_mode,omitempty" json:"filter_mode,omitempty"`
|
|
FilterModeSecondary []string `toml:"-" json:"-"`
|
|
Inspect []string `toml:"inspect,omitempty" json:"inspect,omitempty"`
|
|
InspectSecondary []string `toml:"-" json:"-"`
|
|
ForceRedraw []string `toml:"force_redraw,omitempty" json:"force_redraw,omitempty"`
|
|
ForceRedrawSecondary []string `toml:"-" json:"-"`
|
|
ScrollBack []string `toml:"scroll_back,omitempty" json:"scroll_back,omitempty"`
|
|
ScrollBackSecondary []string `toml:"-" json:"-"`
|
|
ScrollForward []string `toml:"scroll_forward,omitempty" json:"scroll_forward,omitempty"`
|
|
ScrollForwardSecondary []string `toml:"-" json:"-"`
|
|
LogSearchMode []string `toml:"log_search_mode,omitempty" json:"log_search_mode,omitempty"`
|
|
LogSearchModeSecondary []string `toml:"-" json:"-"`
|
|
LogSectionHeightDecrease []string `toml:"log_section_height_decrease,omitempty" json:"log_section_height_decrease,omitempty"`
|
|
LogSectionHeightDecreaseSecondary []string `toml:"-" json:"-"`
|
|
LogSectionHeightIncrease []string `toml:"log_section_height_increase,omitempty" json:"log_section_height_increase,omitempty"`
|
|
LogSectionHeightIncreaseSecondary []string `toml:"-" json:"-"`
|
|
LogSectionToggle []string `toml:"log_section_toggle,omitempty" json:"log_section_toggle,omitempty"`
|
|
LogSectionToggleSecondary []string `toml:"-" json:"-"`
|
|
Quit []string `toml:"quit,omitempty" json:"quit,omitempty"`
|
|
QuitSecondary []string `toml:"-" json:"-"`
|
|
SaveLogs []string `toml:"save_logs,omitempty" json:"save_logs,omitempty"`
|
|
SaveLogsSecondary []string `toml:"-" json:"-"`
|
|
ScrollDown []string `toml:"scroll_down,omitempty" json:"scroll_down,omitempty"`
|
|
ScrollDownSecondary []string `toml:"-" json:"-"`
|
|
ScrollEnd []string `toml:"scroll_end,omitempty" json:"scroll_end,omitempty"`
|
|
ScrollEndSecondary []string `toml:"-" json:"-"`
|
|
ScrollStart []string `toml:"scroll_start,omitempty" json:"scroll_start,omitempty"`
|
|
ScrollStartSecondary []string `toml:"-" json:"-"`
|
|
ScrollUp []string `toml:"scroll_up,omitempty" json:"scroll_up,omitempty"`
|
|
ScrollUpSecondary []string `toml:"-" json:"-"`
|
|
SelectNextPanel []string `toml:"select_next_panel,omitempty" json:"select_next_panel,omitempty"`
|
|
SelectNextPanelSecondary []string `toml:"-" json:"-"`
|
|
SelectPreviousPanel []string `toml:"select_previous_panel,omitempty" json:"select_previous_panel,omitempty"`
|
|
SelectPreviousPanelSecondary []string `toml:"-" json:"-"`
|
|
SortByName []string `toml:"sort_by_name,omitempty" json:"sort_by_name,omitempty"`
|
|
SortByNameSecondary []string `toml:"-" json:"-"`
|
|
SortByState []string `toml:"sort_by_state,omitempty" json:"sort_by_state,omitempty"`
|
|
SortByStateSecondary []string `toml:"-" json:"-"`
|
|
SortByStatus []string `toml:"sort_by_status,omitempty" json:"sort_by_status,omitempty"`
|
|
SortByStatusSecondary []string `toml:"-" json:"-"`
|
|
SortByCPU []string `toml:"sort_by_cpu,omitempty" json:"sort_by_cpu,omitempty"`
|
|
SortByCPUSecondary []string `toml:"-" json:"-"`
|
|
SortByMemory []string `toml:"sort_by_memory,omitempty" json:"sort_by_memory,omitempty"`
|
|
SortByMemorySecondary []string `toml:"-" json:"-"`
|
|
SortByID []string `toml:"sort_by_id,omitempty" json:"sort_by_id,omitempty"`
|
|
SortByIDSecondary []string `toml:"-" json:"-"`
|
|
SortByImage []string `toml:"sort_by_image,omitempty" json:"sort_by_image,omitempty"`
|
|
SortByImageSecondary []string `toml:"-" json:"-"`
|
|
SortByRX []string `toml:"sort_by_rx,omitempty" json:"sort_by_rx,omitempty"`
|
|
SortByRXSecondary []string `toml:"-" json:"-"`
|
|
SortByTX []string `toml:"sort_by_tx,omitempty" json:"sort_by_tx,omitempty"`
|
|
SortByTXSecondary []string `toml:"-" json:"-"`
|
|
SortReset []string `toml:"sort_reset,omitempty" json:"sort_reset,omitempty"`
|
|
SortResetSecondary []string `toml:"-" json:"-"`
|
|
ToggleHelp []string `toml:"toggle_help,omitempty" json:"toggle_help,omitempty"`
|
|
ToggleHelpSecondary []string `toml:"-" json:"-"`
|
|
ToggleMouseCapture []string `toml:"toggle_mouse_capture,omitempty" json:"toggle_mouse_capture,omitempty"`
|
|
ToggleMouseCaptureSecondary []string `toml:"-" json:"-"`
|
|
LogSectionToggleAlt []string `toml:"-" json:"-"`
|
|
ScrollMany string `toml:"scroll_many,omitempty" json:"scroll_many,omitempty"`
|
|
}
|
|
|
|
type Config struct {
|
|
AppColors AppColors `toml:"colors,omitempty" json:"colors,omitempty"`
|
|
ColorLogs bool `toml:"color_logs,omitempty" json:"color_logs,omitempty"`
|
|
DirSave string `toml:"save_dir,omitempty" json:"save_dir,omitempty"`
|
|
DirConfig string `toml:"-" json:"-"`
|
|
DockerIntervalMs int `toml:"docker_interval,omitempty" json:"docker_interval,omitempty"`
|
|
GUI bool `toml:"gui,omitempty" json:"gui,omitempty"`
|
|
Host string `toml:"host,omitempty" json:"host,omitempty"`
|
|
InContainer bool `toml:"-" json:"-"`
|
|
Keymap Keymap `toml:"keymap,omitempty" json:"keymap,omitempty"`
|
|
LogSearchCaseSensitive bool `toml:"log_search_case_sensitive,omitempty" json:"log_search_case_sensitive,omitempty"`
|
|
RawLogs bool `toml:"raw_logs,omitempty" json:"raw_logs,omitempty"`
|
|
ShowLogs bool `toml:"show_logs,omitempty" json:"show_logs,omitempty"`
|
|
ShowSelf bool `toml:"show_self,omitempty" json:"show_self,omitempty"`
|
|
ShowStdErr bool `toml:"show_std_err,omitempty" json:"show_std_err,omitempty"`
|
|
ShowTimestamp bool `toml:"show_timestamp,omitempty" json:"show_timestamp,omitempty"`
|
|
TimestampFormat string `toml:"timestamp_format,omitempty" json:"timestamp_format,omitempty"`
|
|
Timezone string `toml:"timezone,omitempty" json:"timezone,omitempty"`
|
|
UseCLI bool `toml:"use_cli,omitempty" json:"use_cli,omitempty"`
|
|
}
|
|
|
|
func NewConfig() *Config {
|
|
return &Config{
|
|
DockerIntervalMs: 1000,
|
|
ShowLogs: true,
|
|
ColorLogs: false,
|
|
RawLogs: false,
|
|
ShowTimestamp: true,
|
|
TimestampFormat: "%Y-%m-%dT%H:%M:%S.%8f",
|
|
Timezone: "UTC",
|
|
UseCLI: false,
|
|
GUI: true,
|
|
LogSearchCaseSensitive: true,
|
|
ShowSelf: false,
|
|
ShowStdErr: true,
|
|
DirSave: "",
|
|
Host: "",
|
|
}
|
|
}
|
|
|
|
func LoadConfigPath(path string, cfg *Config) error {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
content := string(data)
|
|
|
|
if strings.HasSuffix(path, ".toml") {
|
|
_, err = toml.Decode(content, cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else if strings.HasSuffix(path, ".jsonc") || strings.HasSuffix(path, ".json") {
|
|
err = parseJSONC(content, cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
cfg.DirConfig = path
|
|
return nil
|
|
}
|
|
|
|
func LoadConfig(path string) (*Config, error) {
|
|
cfg := NewConfig()
|
|
err := LoadConfigPath(path, cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
func parseJSONC(content string, cfg *Config) error {
|
|
var raw map[string]interface{}
|
|
commentsRemoved := removeJSONCComments(content)
|
|
err := json.Unmarshal([]byte(commentsRemoved), &raw)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if colors, ok := raw["colors"].(map[string]interface{}); ok {
|
|
cfg.AppColors = parseAppColors(colors)
|
|
}
|
|
|
|
if keymap, ok := raw["keymap"].(map[string]interface{}); ok {
|
|
cfg.Keymap = parseKeymap(keymap)
|
|
}
|
|
|
|
if val, ok := raw["color_logs"].(bool); ok {
|
|
cfg.ColorLogs = val
|
|
}
|
|
if val, ok := raw["docker_interval"].(float64); ok {
|
|
cfg.DockerIntervalMs = int(val)
|
|
}
|
|
if val, ok := raw["gui"].(bool); ok {
|
|
cfg.GUI = val
|
|
}
|
|
if val, ok := raw["host"].(string); ok {
|
|
cfg.Host = val
|
|
}
|
|
if val, ok := raw["log_search_case_sensitive"].(bool); ok {
|
|
cfg.LogSearchCaseSensitive = val
|
|
}
|
|
if val, ok := raw["raw_logs"].(bool); ok {
|
|
cfg.RawLogs = val
|
|
}
|
|
if val, ok := raw["save_dir"].(string); ok {
|
|
cfg.DirSave = val
|
|
}
|
|
if val, ok := raw["show_logs"].(bool); ok {
|
|
cfg.ShowLogs = val
|
|
}
|
|
if val, ok := raw["show_self"].(bool); ok {
|
|
cfg.ShowSelf = val
|
|
}
|
|
if val, ok := raw["show_std_err"].(bool); ok {
|
|
cfg.ShowStdErr = val
|
|
}
|
|
if val, ok := raw["show_timestamp"].(bool); ok {
|
|
cfg.ShowTimestamp = val
|
|
}
|
|
if val, ok := raw["timestamp_format"].(string); ok {
|
|
cfg.TimestampFormat = val
|
|
}
|
|
if val, ok := raw["timezone"].(string); ok {
|
|
cfg.Timezone = val
|
|
}
|
|
if val, ok := raw["use_cli"].(bool); ok {
|
|
cfg.UseCLI = val
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func removeJSONCComments(content string) string {
|
|
lines := strings.Split(content, "\n")
|
|
var result []string
|
|
for _, line := range lines {
|
|
trimmed := strings.TrimSpace(line)
|
|
if strings.HasPrefix(trimmed, "//") || strings.HasPrefix(trimmed, "/*") || strings.HasPrefix(trimmed, "*") || strings.HasPrefix(trimmed, "*/") {
|
|
continue
|
|
}
|
|
if idx := strings.Index(trimmed, "//"); idx >= 0 {
|
|
result = append(result, strings.TrimSpace(line[:idx]))
|
|
} else {
|
|
result = append(result, line)
|
|
}
|
|
}
|
|
return strings.Join(result, "\n")
|
|
}
|
|
|
|
func parseAppColors(colors map[string]interface{}) AppColors {
|
|
acc := AppColors{}
|
|
if borders, ok := colors["borders"].(map[string]interface{}); ok {
|
|
acc.Borders = Borders{
|
|
Selected: toString(borders["selected"]),
|
|
Unselected: toString(borders["unselected"]),
|
|
}
|
|
}
|
|
if chartCPU, ok := colors["chart_cpu"].(map[string]interface{}); ok {
|
|
acc.ChartCPU = ChartCPU{
|
|
Background: toString(chartCPU["background"]),
|
|
Border: toString(chartCPU["border"]),
|
|
Title: toString(chartCPU["title"]),
|
|
Max: toString(chartCPU["max"]),
|
|
Points: toString(chartCPU["points"]),
|
|
YAxis: toString(chartCPU["y_axis"]),
|
|
}
|
|
}
|
|
if chartMemory, ok := colors["chart_memory"].(map[string]interface{}); ok {
|
|
acc.ChartMemory = ChartMemory{
|
|
Background: toString(chartMemory["background"]),
|
|
Border: toString(chartMemory["border"]),
|
|
Title: toString(chartMemory["title"]),
|
|
Max: toString(chartMemory["max"]),
|
|
Points: toString(chartMemory["points"]),
|
|
YAxis: toString(chartMemory["y_axis"]),
|
|
}
|
|
}
|
|
if chartBandwidth, ok := colors["chart_bandwidth"].(map[string]interface{}); ok {
|
|
acc.ChartBandwidth = ChartBandwidth{
|
|
Background: toString(chartBandwidth["background"]),
|
|
Border: toString(chartBandwidth["border"]),
|
|
MaxRX: toString(chartBandwidth["max_rx"]),
|
|
MaxTX: toString(chartBandwidth["max_tx"]),
|
|
PointsRX: toString(chartBandwidth["points_rx"]),
|
|
PointsTX: toString(chartBandwidth["points_tx"]),
|
|
TitleRX: toString(chartBandwidth["title_rx"]),
|
|
TitleTX: toString(chartBandwidth["title_tx"]),
|
|
YAxis: toString(chartBandwidth["y_axis"]),
|
|
}
|
|
}
|
|
if chartPorts, ok := colors["chart_ports"].(map[string]interface{}); ok {
|
|
acc.ChartPorts = ChartPorts{
|
|
Background: toString(chartPorts["background"]),
|
|
Border: toString(chartPorts["border"]),
|
|
Title: toString(chartPorts["title"]),
|
|
Headings: toString(chartPorts["headings"]),
|
|
Text: toString(chartPorts["text"]),
|
|
}
|
|
}
|
|
if commands, ok := colors["commands"].(map[string]interface{}); ok {
|
|
acc.Commands = Commands{
|
|
Background: toString(commands["background"]),
|
|
Pause: toString(commands["pause"]),
|
|
Restart: toString(commands["restart"]),
|
|
Stop: toString(commands["stop"]),
|
|
Delete: toString(commands["delete"]),
|
|
Resume: toString(commands["resume"]),
|
|
Start: toString(commands["start"]),
|
|
}
|
|
}
|
|
if containerState, ok := colors["container_state"].(map[string]interface{}); ok {
|
|
acc.ContainerState = ContainerState{
|
|
Dead: toString(containerState["dead"]),
|
|
Exited: toString(containerState["exited"]),
|
|
Paused: toString(containerState["paused"]),
|
|
Removing: toString(containerState["removing"]),
|
|
Restarting: toString(containerState["restarting"]),
|
|
RunningHealthy: toString(containerState["running_healthy"]),
|
|
RunningUnhealthy: toString(containerState["running_unhealthy"]),
|
|
Unknown: toString(containerState["unknown"]),
|
|
}
|
|
}
|
|
if containers, ok := colors["containers"].(map[string]interface{}); ok {
|
|
acc.Containers = Containers{
|
|
Background: toString(containers["background"]),
|
|
Icon: toString(containers["icon"]),
|
|
Text: toString(containers["text"]),
|
|
TextRX: toString(containers["text_rx"]),
|
|
TextTX: toString(containers["text_tx"]),
|
|
}
|
|
}
|
|
if logSearch, ok := colors["log_search"].(map[string]interface{}); ok {
|
|
acc.LogSearch = LogSearch{
|
|
Background: toString(logSearch["background"]),
|
|
Text: toString(logSearch["text"]),
|
|
ButtonText: toString(logSearch["button_text"]),
|
|
Highlight: toString(logSearch["highlight"]),
|
|
}
|
|
}
|
|
if filter, ok := colors["filter"].(map[string]interface{}); ok {
|
|
acc.Filter = Filter{
|
|
Background: toString(filter["background"]),
|
|
Text: toString(filter["text"]),
|
|
SelectedFilterBackground: toString(filter["selected_filter_background"]),
|
|
SelectedFilterText: toString(filter["selected_filter_text"]),
|
|
Highlight: toString(filter["highlight"]),
|
|
}
|
|
}
|
|
if headersBar, ok := colors["headers_bar"].(map[string]interface{}); ok {
|
|
acc.HeadersBar = HeadersBar{
|
|
Background: toString(headersBar["background"]),
|
|
LoadingSpinner: toString(headersBar["loading_spinner"]),
|
|
Text: toString(headersBar["text"]),
|
|
TextSelected: toString(headersBar["text_selected"]),
|
|
}
|
|
}
|
|
if logs, ok := colors["logs"].(map[string]interface{}); ok {
|
|
acc.Logs = Logs{
|
|
Background: toString(logs["background"]),
|
|
Text: toString(logs["text"]),
|
|
}
|
|
}
|
|
if popupDelete, ok := colors["popup_delete"].(map[string]interface{}); ok {
|
|
acc.PopupDelete = PopupDelete{
|
|
Background: toString(popupDelete["background"]),
|
|
Text: toString(popupDelete["text"]),
|
|
TextHighlight: toString(popupDelete["text_highlight"]),
|
|
}
|
|
}
|
|
if popupError, ok := colors["popup_error"].(map[string]interface{}); ok {
|
|
acc.PopupError = PopupError{
|
|
Background: toString(popupError["background"]),
|
|
Text: toString(popupError["text"]),
|
|
}
|
|
}
|
|
if popupHelp, ok := colors["popup_help"].(map[string]interface{}); ok {
|
|
acc.PopupHelp = PopupHelp{
|
|
Background: toString(popupHelp["background"]),
|
|
Text: toString(popupHelp["text"]),
|
|
TextHighlight: toString(popupHelp["text_highlight"]),
|
|
}
|
|
}
|
|
if popupInfo, ok := colors["popup_info"].(map[string]interface{}); ok {
|
|
acc.PopupInfo = PopupInfo{
|
|
Background: toString(popupInfo["background"]),
|
|
Text: toString(popupInfo["text"]),
|
|
}
|
|
}
|
|
return acc
|
|
}
|
|
|
|
func parseKeymap(keymap map[string]interface{}) Keymap {
|
|
k := Keymap{}
|
|
applyKeymapEntry(&k.Clear, keymap, "clear")
|
|
applyKeymapEntry(&k.DeleteConfirm, keymap, "delete_confirm")
|
|
applyKeymapEntry(&k.DeleteDeny, keymap, "delete_deny")
|
|
applyKeymapEntry(&k.Exec, keymap, "exec")
|
|
applyKeymapEntry(&k.FilterMode, keymap, "filter_mode")
|
|
applyKeymapEntry(&k.Inspect, keymap, "inspect")
|
|
applyKeymapEntry(&k.ForceRedraw, keymap, "force_redraw")
|
|
applyKeymapEntry(&k.ScrollBack, keymap, "scroll_back")
|
|
applyKeymapEntry(&k.ScrollForward, keymap, "scroll_forward")
|
|
applyKeymapEntry(&k.LogSearchMode, keymap, "log_search_mode")
|
|
applyKeymapEntry(&k.LogSectionHeightDecrease, keymap, "log_section_height_decrease")
|
|
applyKeymapEntry(&k.LogSectionHeightIncrease, keymap, "log_section_height_increase")
|
|
applyKeymapEntry(&k.LogSectionToggle, keymap, "log_section_toggle")
|
|
applyKeymapEntry(&k.Quit, keymap, "quit")
|
|
applyKeymapEntry(&k.SaveLogs, keymap, "save_logs")
|
|
applyKeymapEntry(&k.ScrollDown, keymap, "scroll_down")
|
|
applyKeymapEntry(&k.ScrollEnd, keymap, "scroll_end")
|
|
applyKeymapEntry(&k.ScrollStart, keymap, "scroll_start")
|
|
applyKeymapEntry(&k.ScrollUp, keymap, "scroll_up")
|
|
applyKeymapEntry(&k.SelectNextPanel, keymap, "select_next_panel")
|
|
applyKeymapEntry(&k.SelectPreviousPanel, keymap, "select_previous_panel")
|
|
applyKeymapEntry(&k.SortByName, keymap, "sort_by_name")
|
|
applyKeymapEntry(&k.SortByState, keymap, "sort_by_state")
|
|
applyKeymapEntry(&k.SortByStatus, keymap, "sort_by_status")
|
|
applyKeymapEntry(&k.SortByCPU, keymap, "sort_by_cpu")
|
|
applyKeymapEntry(&k.SortByMemory, keymap, "sort_by_memory")
|
|
applyKeymapEntry(&k.SortByID, keymap, "sort_by_id")
|
|
applyKeymapEntry(&k.SortByImage, keymap, "sort_by_image")
|
|
applyKeymapEntry(&k.SortByRX, keymap, "sort_by_rx")
|
|
applyKeymapEntry(&k.SortByTX, keymap, "sort_by_tx")
|
|
applyKeymapEntry(&k.SortReset, keymap, "sort_reset")
|
|
applyKeymapEntry(&k.ToggleHelp, keymap, "toggle_help")
|
|
applyKeymapEntry(&k.ToggleMouseCapture, keymap, "toggle_mouse_capture")
|
|
if scrollMany, ok := keymap["scroll_many"].(string); ok {
|
|
k.ScrollMany = scrollMany
|
|
}
|
|
return k
|
|
}
|
|
|
|
func applyKeymapEntry(target *[]string, keymap map[string]interface{}, key string) {
|
|
if val, ok := keymap[key].([]interface{}); ok {
|
|
for _, v := range val {
|
|
if s, ok := v.(string); ok {
|
|
*target = append(*target, s)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func toString(val interface{}) string {
|
|
if s, ok := val.(string); ok {
|
|
return s
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (c *Config) SaveConfig() error {
|
|
path := c.DirConfig
|
|
if path == "" {
|
|
var err error
|
|
path, err = GetDefaultConfigPath()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
|
|
if strings.HasSuffix(path, ".toml") {
|
|
return toml.NewEncoder(file).Encode(c)
|
|
} else if strings.HasSuffix(path, ".jsonc") || strings.HasSuffix(path, ".json") {
|
|
data, err := json.MarshalIndent(c, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = file.Write(data)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func GetDefaultConfigPath() (string, error) {
|
|
home, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
configDir := filepath.Join(home, ".config", "oxker")
|
|
return filepath.Join(configDir, "config.toml"), nil
|
|
}
|
|
|
|
func (c *Config) MergeCLIArgs(cliArgs *CLIArgs) {
|
|
if cliArgs == nil {
|
|
return
|
|
}
|
|
if cliArgs.DockerIntervalMs > 0 {
|
|
c.DockerIntervalMs = cliArgs.DockerIntervalMs
|
|
}
|
|
c.RawLogs = cliArgs.RawLogs
|
|
c.ColorLogs = cliArgs.ColorLogs
|
|
c.ShowTimestamp = !cliArgs.ShowTimestamp
|
|
c.UseCLI = cliArgs.UseCLI
|
|
c.GUI = !cliArgs.DebugMode
|
|
if cliArgs.Host != "" {
|
|
c.Host = cliArgs.Host
|
|
}
|
|
c.DirConfig = cliArgs.ConfigFile
|
|
}
|
|
|
|
type CLIArgs struct {
|
|
DockerIntervalMs int
|
|
RawLogs bool
|
|
ColorLogs bool
|
|
ShowTimestamp bool
|
|
ShowSelf bool
|
|
DebugMode bool
|
|
ConfigFile string
|
|
Host string
|
|
NoStdErr bool
|
|
SaveDir string
|
|
Timezone string
|
|
UseCLI bool
|
|
}
|