forked from kelda/dksnap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
132 lines (116 loc) · 3.45 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main
import (
"context"
"flag"
"fmt"
"os"
"strconv"
"github.com/docker/docker/client"
"github.com/gdamore/tcell"
"github.com/rivo/tview"
)
var forceGenericSnapshot = flag.Bool("force-generic", false, "disable database aware snapshots")
func main() {
flag.Parse()
dockerClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to create Docker client: %s\n", err)
os.Exit(1)
}
app := tview.NewApplication()
createUI := newCreateUI(dockerClient, app)
infoUI := newInfoUI(dockerClient, app)
ctx := context.Background()
go createUI.run(ctx)
go infoUI.run(ctx)
// Setup tab navigation. The tab's index in the following list is used as
// the tab's identifier in the Pages view, and as the Region in the tab
// tracker.
tabs := []struct {
title string
contents tview.Primitive
}{
{"Create Snapshot", createUI},
{"View Snapshots", infoUI},
}
tabTracker := tview.NewTextView().
SetDynamicColors(true).
SetRegions(true).
SetWrap(false)
currentTab := 0
tabTracker.Highlight(strconv.Itoa(currentTab))
tabbedView := tview.NewPages()
previousTab := func() {
currentTab = (currentTab - 1 + len(tabs)) % len(tabs)
tabTracker.Highlight(strconv.Itoa(currentTab)).
ScrollToHighlight()
tabbedView.SwitchToPage(strconv.Itoa(currentTab))
}
nextTab := func() {
currentTab = (currentTab + 1) % len(tabs)
tabTracker.Highlight(strconv.Itoa(currentTab)).
ScrollToHighlight()
tabbedView.SwitchToPage(strconv.Itoa(currentTab))
}
fmt.Fprintf(tabTracker, "[yellow]TABS[-] |")
for index, tab := range tabs {
tabbedView.AddPage(strconv.Itoa(index), tab.contents, true, index == currentTab)
fmt.Fprintf(tabTracker, ` ["%d"][darkcyan]%s[-][""] |`, index, tab.title)
}
app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyCtrlP:
previousTab()
return nil
case tcell.KeyCtrlN:
nextTab()
return nil
default:
return event
}
})
controls := NewControlsView([]KeyMapping{
{"Ctrl-C", "Quit"},
{"Ctrl-N", "Next tab"},
{"Ctrl-P", "Previous tab"},
{"↑↓←→", "Select item"},
{"ENTER", "Pick item"},
{"ESC", "Cancel"},
})
// Show the tab tracker at the top of the screen, followed by the tab
// contents, and the controls at the bottom.
root := tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(tabTracker, 1, 1, false).
AddItem(tabbedView, 0, 1, true).
AddItem(controls, 2, 1, false)
if err := app.SetRoot(root, true).Run(); err != nil {
fmt.Fprintf(os.Stderr, "Failed to view snapshots: %s\n", err)
}
}
// KeyMapping represents a control used to interact with the UI.
type KeyMapping struct {
Key string
Action string
}
// NewControlsView creates a new tview component that displays the given controls.
func NewControlsView(controls []KeyMapping) *tview.TextView {
text := tview.NewTextView().
SetDynamicColors(true).
SetText("[yellow]NAVIGATION[-] |")
for _, mapping := range controls {
fmt.Fprintf(text, " [darkcyan]%s[-] %s |", mapping.Key, mapping.Action)
}
return text
}
func alert(app *tview.Application, root *tview.Pages, message string, focusAfter tview.Primitive) {
root.AddPage("alert-modal", tview.NewModal().
SetText(message).
AddButtons([]string{"OK"}).
SetButtonBackgroundColor(buttonColor).
SetDoneFunc(func(_ int, _ string) {
root.RemovePage("alert-modal")
if focusAfter != nil {
app.SetFocus(focusAfter)
}
}), true, true)
}