diff --git a/config/config_test.go b/config/config_test.go index 1f1b3bd..d0da68c 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -9,26 +9,231 @@ import ( ) func TestReadConfig(t *testing.T) { - tests := []struct { UserConfig string Want map[string]any }{ - { - UserConfig: "", - Want: map[string]any{"config.Polling-Time": 500, "config.Tab-Order": []any{"images", "containers", "volumes"}, "config.Notification-Timeout": 2000}, - }, - { - UserConfig: `config: - Polling-Time: 100`, - Want: map[string]any{"config.Polling-Time": 100, "config.Tab-Order": []any{"images", "containers", "volumes"}, "config.Notification-Timeout": 2000}, - }, +// { +// UserConfig: "", +// Want: map[string]any{ +// "config.Polling-Time": 500, +// "config.Tab-Order": []any{"images", "containers", "volumes"}, +// "config.Notification-Timeout": 2000, +// "keybindings.navigation.Enter": []any{"enter"}, +// "keybindings.navigation.Back": []any{"esc"}, +// "keybindings.navigation.Quit": []any{"q", "ctrl+c"}, +// "keybindings.navigation.Select": []any{" "}, +// "keybindings.navigation.NextTab": []any{"right", "tab", "l"}, +// "keybindings.navigation.PrevTab": []any{"left", "shift+tab", "h"}, +// "keybindings.navigation.NextItem": []any{"down", "j"}, +// "keybindings.navigation.PrevItem": []any{"up", "k"}, +// "keybindings.navigation.PrevPage": []any{"["}, +// "keybindings.navigation.NextPage": []any{"]"}, +// "keybindings.image.Build": []any{"b"}, +// "keybindings.image.CopyId": []any{"c"}, +// "keybindings.image.Delete": []any{"d"}, +// "keybindings.image.DeleteForce": []any{"D"}, +// "keybindings.image.DeleteForceBulk": []any{"D"}, +// "keybindings.image.ExitSelectionMode": []any{"esc"}, +// "keybindings.image.Prune": []any{"p"}, +// "keybindings.image.Rename": []any{"R"}, +// "keybindings.image.Run": []any{"r"}, +// "keybindings.image.RunAndExec": []any{"x"}, +// "keybindings.image.Scout": []any{"s"}, +// "keybindings.container.CopyId": []any{"c"}, +// "keybindings.container.Delete": []any{"d"}, +// "keybindings.container.DeleteForce": []any{"D"}, +// "keybindings.container.Exec": []any{"x"}, +// "keybindings.container.Prune": []any{"p"}, +// "keybindings.container.Restart": []any{"r"}, +// "keybindings.container.ShowLogs": []any{"L"}, +// "keybindings.container.ToggleListAll": []any{"a"}, +// "keybindings.container.TogglePause": []any{"t"}, +// "keybindings.container.ToggleStartStop": []any{"s"}, +// "keybindings.containerBulk.DeleteForce": []any{"D"}, +// "keybindings.containerBulk.ExitSelectionMode": []any{"esc"}, +// "keybindings.containerBulk.Restart": []any{"r"}, +// "keybindings.containerBulk.ToggleListAll": []any{"a"}, +// "keybindings.containerBulk.TogglePause": []any{"t"}, +// "keybindings.containerBulk.ToggleStartStop": []any{"s"}, +// "keybindings.volume.Delete": []any{"d"}, +// "keybindings.volume.DeleteForce": []any{"D"}, +// "keybindings.volume.Prune": []any{"p"}, +// "keybindings.volume.CopyId": []any{"c"}, +// "keybindings.volumeBulk.DeleteForce": []any{"D"}, +// "keybindings.volumeBulk.ExitSelectionMode": []any{"esc"}, +// }, +// }, +// { +// UserConfig: `config: +// Polling-Time: 100`, +// Want: map[string]any{ +// "config.Polling-Time": 100, +// "config.Tab-Order": []any{"images", "containers", "volumes"}, +// "config.Notification-Timeout": 2000, +// "keybindings.navigation.Enter": []any{"enter"}, +// "keybindings.navigation.Back": []any{"esc"}, +// "keybindings.navigation.Quit": []any{"q", "ctrl+c"}, +// "keybindings.navigation.Select": []any{" "}, +// "keybindings.navigation.NextTab": []any{"right", "tab", "l"}, +// "keybindings.navigation.PrevTab": []any{"left", "shift+tab", "h"}, +// "keybindings.navigation.NextItem": []any{"down", "j"}, +// "keybindings.navigation.PrevItem": []any{"up", "k"}, +// "keybindings.navigation.PrevPage": []any{"["}, +// "keybindings.navigation.NextPage": []any{"]"}, +// "keybindings.image.Build": []any{"b"}, +// "keybindings.image.CopyId": []any{"c"}, +// "keybindings.image.Delete": []any{"d"}, +// "keybindings.image.DeleteForce": []any{"D"}, +// "keybindings.image.DeleteForceBulk": []any{"D"}, +// "keybindings.image.ExitSelectionMode": []any{"esc"}, +// "keybindings.image.Prune": []any{"p"}, +// "keybindings.image.Rename": []any{"R"}, +// "keybindings.image.Run": []any{"r"}, +// "keybindings.image.RunAndExec": []any{"x"}, +// "keybindings.image.Scout": []any{"s"}, +// "keybindings.container.CopyId": []any{"c"}, +// "keybindings.container.Delete": []any{"d"}, +// "keybindings.container.DeleteForce": []any{"D"}, +// "keybindings.container.Exec": []any{"x"}, +// "keybindings.container.Prune": []any{"p"}, +// "keybindings.container.Restart": []any{"r"}, +// "keybindings.container.ShowLogs": []any{"L"}, +// "keybindings.container.ToggleListAll": []any{"a"}, +// "keybindings.container.TogglePause": []any{"t"}, +// "keybindings.container.ToggleStartStop": []any{"s"}, +// "keybindings.containerBulk.DeleteForce": []any{"D"}, +// "keybindings.containerBulk.ExitSelectionMode": []any{"esc"}, +// "keybindings.containerBulk.Restart": []any{"r"}, +// "keybindings.containerBulk.ToggleListAll": []any{"a"}, +// "keybindings.containerBulk.TogglePause": []any{"t"}, +// "keybindings.containerBulk.ToggleStartStop": []any{"s"}, +// "keybindings.volume.Delete": []any{"d"}, +// "keybindings.volume.DeleteForce": []any{"D"}, +// "keybindings.volume.Prune": []any{"p"}, +// "keybindings.volume.CopyId": []any{"c"}, +// "keybindings.volumeBulk.DeleteForce": []any{"D"}, +// "keybindings.volumeBulk.ExitSelectionMode": []any{"esc"}, +// }, +// }, +// { +// UserConfig: `config: +// Polling-Time: 200 +// Tab-Order: [containers, volumes] +// Notification-Timeout: 10000`, +// Want: map[string]any{ +// "config.Polling-Time": 200, +// "config.Tab-Order": []any{"containers", "volumes"}, +// "config.Notification-Timeout": 10000, +// "keybindings.navigation.Enter": []any{"enter"}, +// "keybindings.navigation.Back": []any{"esc"}, +// "keybindings.navigation.Quit": []any{"q", "ctrl+c"}, +// "keybindings.navigation.Select": []any{" "}, +// "keybindings.navigation.NextTab": []any{"right", "tab", "l"}, +// "keybindings.navigation.PrevTab": []any{"left", "shift+tab", "h"}, +// "keybindings.navigation.NextItem": []any{"down", "j"}, +// "keybindings.navigation.PrevItem": []any{"up", "k"}, +// "keybindings.navigation.PrevPage": []any{"["}, +// "keybindings.navigation.NextPage": []any{"]"}, +// "keybindings.image.Build": []any{"b"}, +// "keybindings.image.CopyId": []any{"c"}, +// "keybindings.image.Delete": []any{"d"}, +// "keybindings.image.DeleteForce": []any{"D"}, +// "keybindings.image.DeleteForceBulk": []any{"D"}, +// "keybindings.image.ExitSelectionMode": []any{"esc"}, +// "keybindings.image.Prune": []any{"p"}, +// "keybindings.image.Rename": []any{"R"}, +// "keybindings.image.Run": []any{"r"}, +// "keybindings.image.RunAndExec": []any{"x"}, +// "keybindings.image.Scout": []any{"s"}, +// "keybindings.container.CopyId": []any{"c"}, +// "keybindings.container.Delete": []any{"d"}, +// "keybindings.container.DeleteForce": []any{"D"}, +// "keybindings.container.Exec": []any{"x"}, +// "keybindings.container.Prune": []any{"p"}, +// "keybindings.container.Restart": []any{"r"}, +// "keybindings.container.ShowLogs": []any{"L"}, +// "keybindings.container.ToggleListAll": []any{"a"}, +// "keybindings.container.TogglePause": []any{"t"}, +// "keybindings.container.ToggleStartStop": []any{"s"}, +// "keybindings.containerBulk.DeleteForce": []any{"D"}, +// "keybindings.containerBulk.ExitSelectionMode": []any{"esc"}, +// "keybindings.containerBulk.Restart": []any{"r"}, +// "keybindings.containerBulk.ToggleListAll": []any{"a"}, +// "keybindings.containerBulk.TogglePause": []any{"t"}, +// "keybindings.containerBulk.ToggleStartStop": []any{"s"}, +// "keybindings.volume.Delete": []any{"d"}, +// "keybindings.volume.DeleteForce": []any{"D"}, +// "keybindings.volume.Prune": []any{"p"}, +// "keybindings.volume.CopyId": []any{"c"}, +// "keybindings.volumeBulk.DeleteForce": []any{"D"}, +// "keybindings.volumeBulk.ExitSelectionMode": []any{"esc"}, +// }, +// }, { UserConfig: `config: Polling-Time: 200 Tab-Order: [containers, volumes] - Notification-Timeout: 10000`, - Want: map[string]any{"config.Polling-Time": 200, "config.Tab-Order": []any{"containers", "volumes"}, "config.Notification-Timeout": 10000}, + Notification-Timeout: 10000 +keybindings: + navigation: + Enter: [e] + Quit: [q, ctrl+a] + image: + Build: [B] + CopyId: [C] + container: + CopyId: [C] + Delete: [D] + `, + Want: map[string]any{ + "config.Polling-Time": 200, + "config.Tab-Order": []any{"containers", "volumes"}, + "config.Notification-Timeout": 10000, + "keybindings.navigation.Enter": []any{"e"}, + "keybindings.navigation.Back": []any{"esc"}, + "keybindings.navigation.Quit": []any{"q", "ctrl+a"}, + "keybindings.navigation.Select": []any{" "}, + "keybindings.navigation.NextTab": []any{"right", "tab", "l"}, + "keybindings.navigation.PrevTab": []any{"left", "shift+tab", "h"}, + "keybindings.navigation.NextItem": []any{"down", "j"}, + "keybindings.navigation.PrevItem": []any{"up", "k"}, + "keybindings.navigation.PrevPage": []any{"["}, + "keybindings.navigation.NextPage": []any{"]"}, + "keybindings.image.Build": []any{"B"}, + "keybindings.image.CopyId": []any{"C"}, + "keybindings.image.Delete": []any{"d"}, + "keybindings.image.DeleteForce": []any{"D"}, + "keybindings.image.DeleteForceBulk": []any{"D"}, + "keybindings.image.ExitSelectionMode": []any{"esc"}, + "keybindings.image.Prune": []any{"p"}, + "keybindings.image.Rename": []any{"R"}, + "keybindings.image.Run": []any{"r"}, + "keybindings.image.RunAndExec": []any{"x"}, + "keybindings.image.Scout": []any{"s"}, + "keybindings.container.CopyId": []any{"C"}, + "keybindings.container.Delete": []any{"D"}, + "keybindings.container.DeleteForce": []any{"D"}, + "keybindings.container.Exec": []any{"x"}, + "keybindings.container.Prune": []any{"p"}, + "keybindings.container.Restart": []any{"r"}, + "keybindings.container.ShowLogs": []any{"L"}, + "keybindings.container.ToggleListAll": []any{"a"}, + "keybindings.container.TogglePause": []any{"t"}, + "keybindings.container.ToggleStartStop": []any{"s"}, + "keybindings.containerBulk.DeleteForce": []any{"D"}, + "keybindings.containerBulk.ExitSelectionMode": []any{"esc"}, + "keybindings.containerBulk.Restart": []any{"r"}, + "keybindings.containerBulk.ToggleListAll": []any{"a"}, + "keybindings.containerBulk.TogglePause": []any{"t"}, + "keybindings.containerBulk.ToggleStartStop": []any{"s"}, + "keybindings.volume.Delete": []any{"d"}, + "keybindings.volume.DeleteForce": []any{"D"}, + "keybindings.volume.Prune": []any{"p"}, + "keybindings.volume.CopyId": []any{"c"}, + "keybindings.volumeBulk.DeleteForce": []any{"D"}, + "keybindings.volumeBulk.ExitSelectionMode": []any{"esc"}, + }, }, } diff --git a/config/defaultConfig.yaml b/config/defaultConfig.yaml index 3ee8e0a..3bbc968 100644 --- a/config/defaultConfig.yaml +++ b/config/defaultConfig.yaml @@ -2,3 +2,53 @@ config: Polling-Time: 500 Tab-Order: [images, containers, volumes] Notification-Timeout: 2000 +keybindings: + navigation: + Enter: [enter] + Back: [esc] + Quit: [q, ctrl+c] + Select: [" "] + NextTab: [right, tab, l] + PrevTab: [left, shift+tab, h] + NextItem: [down, j] + PrevItem: [up, k] + PrevPage: ["["] + NextPage: ["]"] + image: + Run: [r] + Rename: [R] + Build: [b] + Scout: [s] + Prune: [p] + Delete: [d] + DeleteForce: [D] + CopyId: [c] + RunAndExec: [x] + DeleteForceBulk: [D] + ExitSelectionMode: [esc] + container: + ToggleListAll: [a] + ToggleStartStop: [s] + TogglePause: [t] + Restart: [r] + Delete: [d] + DeleteForce: [D] + Exec: [x] + Prune: [p] + CopyId: [c] + ShowLogs: [L] + containerBulk: + ToggleListAll: [a] + ToggleStartStop: [s] + TogglePause: [t] + Restart: [r] + DeleteForce: [D] + ExitSelectionMode: [esc] + volume: + Delete: [d] + DeleteForce: [D] + Prune: [p] + CopyId: [c] + volumeBulk: + DeleteForce: [D] + ExitSelectionMode: [esc] diff --git a/tui/constants.go b/tui/constants.go new file mode 100644 index 0000000..1199974 --- /dev/null +++ b/tui/constants.go @@ -0,0 +1,137 @@ +package tui + +type KeyBindings struct { + navigationKeyBindings navigationKeyBindings + imageKeyBindings imageKeyBindings + imageKeyBindingsBulk imageKeyBindingsBulk + containerKeyBindings containerKeyBindings + containerKeyBindingsBulk containerKeyBindingsBulk + volumeKeyBindings volumeKeyBindings + volumeKeyBindingsBulk volumeKeyBindingsBulk +} + +type navigationKeyBindings struct { + Enter []string + Back []string + Quit []string + Select []string + NextTab []string + PrevTab []string + NextItem []string + PrevItem []string + PrevPage []string + NextPage []string +} + +type imageKeyBindings struct { + Run []string + Rename []string + Build []string + Scout []string + Prune []string + Delete []string + DeleteForce []string + CopyId []string + RunAndExec []string +} + +type imageKeyBindingsBulk struct { + DeleteForceBulk []string + ExitSelectionMode []string +} + +type containerKeyBindings struct { + ToggleListAll []string + ToggleStartStop []string + TogglePause []string + Restart []string + Delete []string + DeleteForce []string + Exec []string + Prune []string + CopyId []string + ShowLogs []string +} + +type containerKeyBindingsBulk struct { + ToggleListAll []string + ToggleStartStop []string + TogglePause []string + Restart []string + DeleteForce []string + ExitSelectionMode []string +} + +type volumeKeyBindings struct { + Delete []string + DeleteForce []string + Prune []string + CopyId []string +} + +type volumeKeyBindingsBulk struct { + DeleteForce []string + ExitSelectionMode []string +} + +func initKeyBindingsConstant() *KeyBindings { + return &KeyBindings{ + navigationKeyBindings: navigationKeyBindings{ + Enter: globalConfig.Strings("keybindings.navigation.Enter"), + Back: globalConfig.Strings("keybindings.navigation.Back"), + Quit: globalConfig.Strings("keybindings.navigation.Quit"), + Select: globalConfig.Strings("keybindings.navigation.Select"), + NextTab: globalConfig.Strings("keybindings.navigation.NextTab"), + PrevTab: globalConfig.Strings("keybindings.navigation.PrevTab"), + NextItem: globalConfig.Strings("keybindings.navigation.NextItem"), + PrevItem: globalConfig.Strings("keybindings.navigation.PrevItem"), + PrevPage: globalConfig.Strings("keybindings.navigation.PrevPage"), + NextPage: globalConfig.Strings("keybindings.navigation.NextPage"), + }, + imageKeyBindings: imageKeyBindings{ + Run: globalConfig.Strings("keybindings.image.Run"), + Rename: globalConfig.Strings("keybindings.image.Rename"), + Build: globalConfig.Strings("keybindings.image.Build"), + Scout: globalConfig.Strings("keybindings.image.Scout"), + Prune: globalConfig.Strings("keybindings.image.Prune"), + Delete: globalConfig.Strings("keybindings.image.Delete"), + DeleteForce: globalConfig.Strings("keybindings.image.DeleteForce"), + CopyId: globalConfig.Strings("keybindings.image.CopyId"), + RunAndExec: globalConfig.Strings("keybindings.image.RunAndExec"), + }, + imageKeyBindingsBulk: imageKeyBindingsBulk{ + DeleteForceBulk: globalConfig.Strings("keybindings.image.DeleteForce"), + ExitSelectionMode: globalConfig.Strings("keybindings.image.ExitSelectionMode"), + }, + containerKeyBindings: containerKeyBindings{ + ToggleListAll: globalConfig.Strings("keybindings.container.ToggleListAll"), + ToggleStartStop: globalConfig.Strings("keybindings.container.ToggleStartStop"), + TogglePause: globalConfig.Strings("keybindings.container.TogglePause"), + Restart: globalConfig.Strings("keybindings.container.Restart"), + Delete: globalConfig.Strings("keybindings.container.Delete"), + DeleteForce: globalConfig.Strings("keybindings.container.DeleteForce"), + Exec: globalConfig.Strings("keybindings.container.Exec"), + Prune: globalConfig.Strings("keybindings.container.Prune"), + CopyId: globalConfig.Strings("keybindings.container.CopyId"), + ShowLogs: globalConfig.Strings("keybindings.container.ShowLogs"), + }, + containerKeyBindingsBulk: containerKeyBindingsBulk{ + ToggleListAll: globalConfig.Strings("keybindings.containerBulk.ToggleListAll"), + ToggleStartStop: globalConfig.Strings("keybindings.containerBulk.ToggleStartStop"), + TogglePause: globalConfig.Strings("keybindings.containerBulk.TogglePause"), + Restart: globalConfig.Strings("keybindings.containerBulk.Restart"), + DeleteForce: globalConfig.Strings("keybindings.containerBulk.DeleteForce"), + ExitSelectionMode: globalConfig.Strings("keybindings.containerBulk.ExitSelectionMode"), + }, + volumeKeyBindings: volumeKeyBindings{ + Delete: globalConfig.Strings("keybindings.volume.Delete"), + DeleteForce: globalConfig.Strings("keybindings.volume.DeleteForce"), + Prune: globalConfig.Strings("keybindings.volume.Prune"), + CopyId: globalConfig.Strings("keybindings.volume.CopyId"), + }, + volumeKeyBindingsBulk: volumeKeyBindingsBulk{ + DeleteForce: globalConfig.Strings("keybindings.volume.DeleteForce"), + ExitSelectionMode: globalConfig.Strings("keybindings.volume.ExitSelectionMode"), + }, + } +} diff --git a/tui/entry.go b/tui/entry.go index 95efc77..55fba91 100644 --- a/tui/entry.go +++ b/tui/entry.go @@ -22,9 +22,18 @@ var ( VOLUMES tabId ) -var CONFIG_POLLING_TIME time.Duration -var CONFIG_TAB_ORDERING []string -var CONFIG_NOTIFICATION_TIMEOUT time.Duration +var ( + CONFIG_POLLING_TIME time.Duration + CONFIG_TAB_ORDERING []string + CONFIG_NOTIFICATION_TIMEOUT time.Duration + NavKeymap *navigationKeymap + ImageKeymap *imgKeymap + imageKeymapBulk *imgKeymapBulk + ContainerKeymap *contKeymap + ContainerKeymapBulk *contKeymapBulk + VolumeKeymap *volKeymap + volumeKeymapBulk *volKeymapBulk +) var globalConfig = koanf.New(".") @@ -44,6 +53,7 @@ func StartTUI(debug bool) error { readConfig() loadConfig() + loadKeyBindings() m := NewModel() if _, err := tea.NewProgram(m, tea.WithAltScreen()).Run(); err != nil { @@ -64,7 +74,6 @@ func StartTUI(debug bool) error { func readConfig() { configPath, err := os.UserConfigDir() - if err != nil { log.Println("$HOME could not be determined") } @@ -80,6 +89,17 @@ func loadConfig() { setTabConstants(CONFIG_TAB_ORDERING) } +func loadKeyBindings() { + keybinds := initKeyBindingsConstant() + NavKeymap = keybinds.initNavigationKeys() + ImageKeymap = keybinds.initImageKeys() + imageKeymapBulk = keybinds.initImageKeysBulk() + ContainerKeymap = keybinds.initContainerKeys() + ContainerKeymapBulk = keybinds.initContainerKeysBulk() + VolumeKeymap = keybinds.initVolumeKeys() + volumeKeymapBulk = keybinds.initVolumeKeysBulk() +} + // set tab variables, AKA IMAGES, CONTAINERS, VOLUMES, etc. func setTabConstants(configOrder []string) TabOrderingMap { tabIndexMap := make(TabOrderingMap) diff --git a/tui/keys.go b/tui/keys.go index 90fd041..1a41d85 100644 --- a/tui/keys.go +++ b/tui/keys.go @@ -2,7 +2,6 @@ package tui import ( "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" ) var KeymapAvailableWidth int @@ -29,47 +28,49 @@ func (m navigationKeymap) ShortHelp() []key.Binding { return []key.Binding{} } -var NavKeymap = navigationKeymap{ - Enter: key.NewBinding( - key.WithKeys("enter"), - key.WithHelp("enter", "select"), - ), - Back: key.NewBinding( - key.WithKeys("esc"), - key.WithHelp("esc", "back"), - ), - Quit: key.NewBinding( - key.WithKeys("ctrl+c", "q"), - key.WithHelp("q", "quit"), - ), - Select: key.NewBinding( - key.WithKeys(tea.KeySpace.String()), - key.WithHelp("", "Select"), - ), - NextTab: key.NewBinding( - key.WithKeys("right", "l", "tab"), - key.WithHelp("->/l/tab", "next"), - ), - PrevTab: key.NewBinding( - key.WithKeys("left", "h", "shift+tab"), - key.WithHelp("<-/h/S-tab", "prev"), - ), - NextItem: key.NewBinding( - key.WithKeys("down", "j"), - key.WithHelp("↓/j", "next item"), - ), - PrevItem: key.NewBinding( - key.WithKeys("up", "k"), - key.WithHelp("↑/h", "prev item"), - ), - PrevPage: key.NewBinding( - key.WithKeys("["), - key.WithHelp("[", "prev page"), - ), - NextPage: key.NewBinding( - key.WithKeys("]"), - key.WithHelp("]", "next page"), - ), +func (keybinds *KeyBindings) initNavigationKeys() *navigationKeymap { + return &navigationKeymap{ + Enter: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.Enter...), + key.WithHelp(ArrayToString(keybinds.navigationKeyBindings.Enter), "select"), + ), + Back: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.Back...), + key.WithHelp(ArrayToString(keybinds.navigationKeyBindings.Back), "back"), + ), + Quit: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.Quit...), + key.WithHelp(ArrayToString(keybinds.navigationKeyBindings.Quit), "quit"), + ), + Select: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.Select...), + key.WithHelp(ArrayToString(keybinds.navigationKeyBindings.Select), "Select"), + ), + NextTab: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.NextTab...), + key.WithHelp(ArrayToString(keybinds.navigationKeyBindings.NextTab), "next"), + ), + PrevTab: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.PrevTab...), + key.WithHelp(ArrayToString(keybinds.navigationKeyBindings.PrevTab), "prev"), + ), + NextItem: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.NextItem...), + key.WithHelp(ArrayToString(keybinds.navigationKeyBindings.NextItem), "next item"), + ), + PrevItem: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.PrevItem...), + key.WithHelp(ArrayToString(keybinds.navigationKeyBindings.PrevItem), "prev item"), + ), + PrevPage: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.NextPage...), + key.WithHelp("[", "prev page"), + ), + NextPage: key.NewBinding( + key.WithKeys(keybinds.navigationKeyBindings.NextPage...), + key.WithHelp("]", "next page"), + ), + } } type imgKeymap struct { @@ -84,44 +85,45 @@ type imgKeymap struct { RunAndExec key.Binding } -var ImageKeymap = imgKeymap{ - Run: key.NewBinding( - key.WithKeys("r"), - key.WithHelp("r", "run"), - ), - Rename: key.NewBinding( - key.WithKeys("R"), - key.WithHelp("r", "rename"), - ), - Build: key.NewBinding( - key.WithKeys("b"), - key.WithHelp("b", "build"), - ), - Delete: key.NewBinding( - key.WithKeys("d"), - key.WithHelp("d", "delete"), - ), - DeleteForce: key.NewBinding( - key.WithKeys("D"), - key.WithHelp("D", "delete (force)"), - ), - Scout: key.NewBinding( - key.WithKeys("s"), - key.WithHelp("s", "scout"), - ), - Prune: key.NewBinding( - key.WithKeys("p"), - key.WithHelp("p", "prune images"), - ), - CopyId: key.NewBinding( - key.WithKeys("c"), - key.WithHelp("c", "copy Image ID"), - ), - - RunAndExec: key.NewBinding( - key.WithKeys("x"), - key.WithHelp("x", "run and exec"), - ), +func (keybinds *KeyBindings) initImageKeys() *imgKeymap { + return &imgKeymap{ + Run: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindings.Run...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindings.Run), "run"), + ), + Rename: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindings.Rename...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindings.Rename), "rename"), + ), + Build: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindings.Build...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindings.Build), "build"), + ), + Delete: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindings.Delete...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindings.Delete), "delete"), + ), + DeleteForce: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindings.DeleteForce...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindings.DeleteForce), "delete (force)"), + ), + Scout: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindings.Scout...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindings.Scout), "scout"), + ), + Prune: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindings.Prune...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindings.Prune), "prune images"), + ), + CopyId: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindings.CopyId...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindings.CopyId), "copy Image ID"), + ), + RunAndExec: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindings.RunAndExec...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindings.RunAndExec), "run and exec"), + ), + } } func (m imgKeymap) FullHelp() [][]key.Binding { @@ -137,7 +139,6 @@ func (m imgKeymap) FullHelp() [][]key.Binding { } return packKeybindings(allBindings, KeymapAvailableWidth) - } // This not required and is there only to satisfy the @@ -150,15 +151,18 @@ type imgKeymapBulk struct { ExitSelectionMode key.Binding } -var imageKeymapBulk = imgKeymapBulk{ - DeleteForce: key.NewBinding( - key.WithKeys("D"), - key.WithHelp("D", "bulk delete (force)"), - ), - ExitSelectionMode: key.NewBinding( - key.WithKeys("esc"), - key.WithHelp("esc", "exit selection mode"), - ), +// var imageKeymapBulk = +func (keybinds *KeyBindings) initImageKeysBulk() *imgKeymapBulk { + return &imgKeymapBulk{ + DeleteForce: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindingsBulk.DeleteForceBulk...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindingsBulk.DeleteForceBulk), "bulk delete (force)"), + ), + ExitSelectionMode: key.NewBinding( + key.WithKeys(keybinds.imageKeyBindingsBulk.ExitSelectionMode...), + key.WithHelp(ArrayToString(keybinds.imageKeyBindingsBulk.ExitSelectionMode), "exit selection mode"), + ), + } } // not required, only there to satify the help.KeyMap interface @@ -217,47 +221,49 @@ func (m contKeymap) ShortHelp() []key.Binding { } } -var ContainerKeymap = contKeymap{ - ToggleListAll: key.NewBinding( - key.WithKeys("a"), - key.WithHelp("a", "toggle list all"), - ), - ToggleStartStop: key.NewBinding( - key.WithKeys("s"), - key.WithHelp("s", "toggle Start/Stop"), - ), - TogglePause: key.NewBinding( - key.WithKeys("t"), - key.WithHelp("t", "toggle Pause/unPause"), - ), - Restart: key.NewBinding( - key.WithKeys("r"), - key.WithHelp("r", "restart"), - ), - Delete: key.NewBinding( - key.WithKeys("d"), - key.WithHelp("d", "delete"), - ), - DeleteForce: key.NewBinding( - key.WithKeys("D"), - key.WithHelp("D", "delete (force)"), - ), - Prune: key.NewBinding( - key.WithKeys("p"), - key.WithHelp("p", "prune"), - ), - Exec: key.NewBinding( - key.WithKeys("x"), - key.WithHelp("x", "exec"), - ), - CopyId: key.NewBinding( - key.WithKeys("c"), - key.WithHelp("c", "copy ID"), - ), - ShowLogs: key.NewBinding( - key.WithKeys("L"), - key.WithHelp("L", "Show Logs"), - ), +func (keybinds *KeyBindings) initContainerKeys() *contKeymap { + return &contKeymap{ + ToggleListAll: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.ToggleListAll...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.ToggleListAll), "toggle list all"), + ), + ToggleStartStop: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.ToggleStartStop...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.ToggleStartStop), "toggle Start/Stop"), + ), + TogglePause: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.TogglePause...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.TogglePause), "toggle Pause/unPause"), + ), + Restart: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.Restart...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.Restart), "restart"), + ), + Delete: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.Delete...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.Delete), "delete"), + ), + DeleteForce: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.DeleteForce...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.DeleteForce), "delete (force)"), + ), + Prune: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.Prune...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.Prune), "prune"), + ), + Exec: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.Exec...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.Exec), "exec"), + ), + CopyId: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.CopyId...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.CopyId), "copy ID"), + ), + ShowLogs: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindings.ShowLogs...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindings.ShowLogs), "Show Logs"), + ), + } } type contKeymapBulk struct { @@ -286,31 +292,33 @@ func (co contKeymapBulk) FullHelp() [][]key.Binding { return packKeybindings(bindings, KeymapAvailableWidth) } -var ContainerKeymapBulk = contKeymapBulk{ - ToggleListAll: key.NewBinding( - key.WithKeys("a"), - key.WithHelp("a", "toggle list all"), - ), - ToggleStartStop: key.NewBinding( - key.WithKeys("s"), - key.WithHelp("s", "Bulk toggle Start/Stop"), - ), - TogglePause: key.NewBinding( - key.WithKeys("t"), - key.WithHelp("t", "Bulk toggle Pause/unPause"), - ), - Restart: key.NewBinding( - key.WithKeys("r"), - key.WithHelp("r", "Bulk restart"), - ), - DeleteForce: key.NewBinding( - key.WithKeys("D"), - key.WithHelp("D", "Bulk delete (force)"), - ), - ExitSelectionMode: key.NewBinding( - key.WithKeys("esc"), - key.WithHelp("esc", "exit selection mode"), - ), +func (keybinds *KeyBindings) initContainerKeysBulk() *contKeymapBulk { + return &contKeymapBulk{ + ToggleListAll: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindingsBulk.ToggleListAll...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindingsBulk.ToggleListAll), "toggle list all"), + ), + ToggleStartStop: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindingsBulk.ToggleStartStop...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindingsBulk.ToggleStartStop), "Bulk toggle Start/Stop"), + ), + TogglePause: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindingsBulk.TogglePause...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindingsBulk.TogglePause), "Bulk toggle Pause/unPause"), + ), + Restart: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindingsBulk.Restart...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindingsBulk.Restart), "Bulk restart"), + ), + DeleteForce: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindingsBulk.DeleteForce...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindingsBulk.DeleteForce), "Bulk delete (force)"), + ), + ExitSelectionMode: key.NewBinding( + key.WithKeys(keybinds.containerKeyBindingsBulk.ExitSelectionMode...), + key.WithHelp(ArrayToString(keybinds.containerKeyBindingsBulk.ExitSelectionMode), "exit selection mode"), + ), + } } type volKeymap struct { @@ -328,23 +336,25 @@ func (m volKeymap) FullHelp() [][]key.Binding { return [][]key.Binding{{m.Delete}, {m.Prune}, {m.CopyId}} } -var VolumeKeymap = volKeymap{ - Delete: key.NewBinding( - key.WithKeys("d"), - key.WithHelp("d", "delete"), - ), - DeleteForce: key.NewBinding( - key.WithKeys("D"), - key.WithHelp("D", "delete (force)"), - ), - Prune: key.NewBinding( - key.WithKeys("p"), - key.WithHelp("p", "prune"), - ), - CopyId: key.NewBinding( - key.WithKeys("c"), - key.WithHelp("c", "copy Name"), - ), +func (keybinds *KeyBindings) initVolumeKeys() *volKeymap { + return &volKeymap{ + Delete: key.NewBinding( + key.WithKeys(keybinds.volumeKeyBindings.Delete...), + key.WithHelp(ArrayToString(keybinds.volumeKeyBindings.Delete), "delete"), + ), + DeleteForce: key.NewBinding( + key.WithKeys(keybinds.volumeKeyBindings.DeleteForce...), + key.WithHelp(ArrayToString(keybinds.volumeKeyBindings.DeleteForce), "delete (force)"), + ), + Prune: key.NewBinding( + key.WithKeys(keybinds.volumeKeyBindings.Prune...), + key.WithHelp(ArrayToString(keybinds.volumeKeyBindings.Prune), "prune"), + ), + CopyId: key.NewBinding( + key.WithKeys(keybinds.volumeKeyBindings.CopyId...), + key.WithHelp(ArrayToString(keybinds.volumeKeyBindings.CopyId), "copy Name"), + ), + } } type volKeymapBulk struct { @@ -362,15 +372,17 @@ func (vo volKeymapBulk) FullHelp() [][]key.Binding { } } -var volumeKeymapBulk = volKeymapBulk{ - DeleteForce: key.NewBinding( - key.WithKeys("D"), - key.WithHelp("D", "bulk delete (force)"), - ), - ExitSelectionMode: key.NewBinding( - key.WithKeys("esc"), - key.WithHelp("esc", "exit selection mode"), - ), +func (keybinds *KeyBindings) initVolumeKeysBulk() *volKeymapBulk { + return &volKeymapBulk{ + DeleteForce: key.NewBinding( + key.WithKeys(keybinds.volumeKeyBindingsBulk.DeleteForce...), + key.WithHelp(ArrayToString(keybinds.volumeKeyBindingsBulk.DeleteForce), "bulk delete (force)"), + ), + ExitSelectionMode: key.NewBinding( + key.WithKeys(keybinds.volumeKeyBindingsBulk.ExitSelectionMode...), + key.WithHelp(ArrayToString(keybinds.volumeKeyBindingsBulk.ExitSelectionMode), "exit selection mode"), + ), + } } func packKeybindings(keybindings []key.Binding, width int) [][]key.Binding { diff --git a/tui/util.go b/tui/util.go index e53617c..413b847 100644 --- a/tui/util.go +++ b/tui/util.go @@ -1,6 +1,8 @@ package tui import ( + "strings" + "github.com/ajayd-san/gomanagedocker/tui/components/list" tea "github.com/charmbracelet/bubbletea" ) @@ -19,3 +21,16 @@ func NewNotification(id tabId, msg string) notificationMetadata { id, msg, } } + +func mapSpecialCharactersToString(c string) string { + strings.ToLower(c) + c = strings.ReplaceAll(c, "down", "↓") + c = strings.ReplaceAll(c, "up", "↑") + c = strings.ReplaceAll(c, "left", "←") + c = strings.ReplaceAll(c, "right", "→") + return c +} + +func ArrayToString(arr []string) string { + return mapSpecialCharactersToString(strings.Join(arr, "/")) +} diff --git a/tui/util_test.go b/tui/util_test.go index b2c584a..8dd6694 100644 --- a/tui/util_test.go +++ b/tui/util_test.go @@ -27,6 +27,12 @@ func TestNotifyList(t *testing.T) { mockcli := dockercmd.NewMockCli(&api) + readConfig() + loadConfig() + keybinds := initKeyBindingsConstant() + NavKeymap = keybinds.initNavigationKeys() + ContainerKeymap = keybinds.initContainerKeys() + ContainerKeymapBulk = keybinds.initContainerKeysBulk() CONTAINERS = 0 model := MainModel{ dockerClient: mockcli,