@@ -7,38 +7,53 @@ import (
7
7
"time"
8
8
9
9
"github.com/buger/goterm"
10
+ "github.com/compose-spec/compose-go/v2/types"
11
+ "github.com/docker/compose/v2/pkg/api"
10
12
"github.com/docker/compose/v2/pkg/watch"
13
+ "github.com/eiannone/keyboard"
14
+ "github.com/skratchdot/open-golang/open"
11
15
)
12
16
13
17
var DISPLAY_ERROR_TIME = 10
14
18
19
+ type KeyboardError struct {
20
+ err error
21
+ errStart time.Time
22
+ }
23
+ type KeyboardWatch struct {
24
+ Watcher watch.Notify
25
+ Watching bool
26
+ WatchFn func (ctx context.Context , project * types.Project , services []string , options api.WatchOptions ) error
27
+ Ctx context.Context
28
+ Cancel context.CancelFunc
29
+ }
15
30
type LogKeyboard struct {
16
- err error
17
- errStart time. Time
31
+ ErrorHandle KeyboardError
32
+ Watch KeyboardWatch
18
33
started bool
19
34
IsDockerDesktopActive bool
20
- Watcher watch.Notify
21
- Watching bool
22
- Ctx context.Context
23
- Cancel context.CancelFunc
35
+ IsWatchConfigured bool
24
36
}
25
37
26
- var KeyboardManager = LogKeyboard {Watching : true }
38
+ var KeyboardManager * LogKeyboard
39
+
27
40
var errorColor = "\x1b [1;33m"
28
41
29
- func (lk * LogKeyboard ) NewContext (ctx context.Context ) context.CancelFunc {
30
- ctx , cancel := context .WithCancel (ctx )
31
- lk .Ctx = ctx
32
- lk .Cancel = cancel
33
- return cancel
42
+ func NewKeyboardManager (isDockerDesktopActive , IsWatchConfigured bool , watchFn func (ctx context.Context , project * types.Project , services []string , options api.WatchOptions ) error ) {
43
+ km := LogKeyboard {}
44
+ KeyboardManager = & km
45
+ KeyboardManager .Watch .Watching = true
46
+ KeyboardManager .IsDockerDesktopActive = true
47
+ KeyboardManager .IsWatchConfigured = true
48
+ KeyboardManager .Watch .WatchFn = watchFn
34
49
}
35
50
36
51
func (lk * LogKeyboard ) PrintKeyboardInfo (print func ()) {
37
52
fmt .Print ("\033 [?25l" ) // hide cursor
38
53
defer fmt .Printf ("\033 [?25h" ) // show cursor
39
54
40
55
if lk .started {
41
- lk .ClearInfo ()
56
+ lk .clearInfo ()
42
57
} else {
43
58
lk .started = true
44
59
}
@@ -47,13 +62,9 @@ func (lk *LogKeyboard) PrintKeyboardInfo(print func()) {
47
62
lk .printInfo ()
48
63
}
49
64
50
- func (lk * LogKeyboard ) SError (err string ) {
51
- lk .errStart = time .Now ()
52
- lk .err = fmt .Errorf (err )
53
- }
54
65
func (lk * LogKeyboard ) Error (err error ) {
55
- lk .errStart = time .Now ()
56
- lk .err = err
66
+ lk .ErrorHandle . errStart = time .Now ()
67
+ lk .ErrorHandle . err = err
57
68
}
58
69
59
70
// This avoids incorrect printing at the end of the terminal
@@ -64,9 +75,9 @@ func (lk *LogKeyboard) createBuffer() {
64
75
}
65
76
66
77
func (lk * LogKeyboard ) printError (height int ) {
67
- if lk .err != nil && int (time .Since (lk .errStart ).Seconds ()) < DISPLAY_ERROR_TIME {
78
+ if lk .ErrorHandle . err != nil && int (time .Since (lk . ErrorHandle .errStart ).Seconds ()) < DISPLAY_ERROR_TIME {
68
79
fmt .Printf ("\033 [%d;0H" , height - 1 ) // Move to before last line
69
- fmt .Printf ("\033 [K" + errorColor + "[Error] " + lk .err .Error ())
80
+ fmt .Printf ("\033 [K" + errorColor + "[Error] " + lk .ErrorHandle . err .Error ())
70
81
}
71
82
}
72
83
@@ -85,7 +96,7 @@ func (lk *LogKeyboard) infoMessage() {
85
96
if lk .IsDockerDesktopActive {
86
97
options = options + keyColor ("^V" ) + navColor ("iew containers in Docker Desktop" )
87
98
}
88
- if lk .Watching {
99
+ if lk .IsWatchConfigured {
89
100
if strings .Contains (options , "Docker Desktop" ) {
90
101
options = options + navColor (", " )
91
102
}
@@ -95,10 +106,10 @@ func (lk *LogKeyboard) infoMessage() {
95
106
fmt .Print ("\033 [K" + options )
96
107
}
97
108
98
- func (lk * LogKeyboard ) ClearInfo () {
109
+ func (lk * LogKeyboard ) clearInfo () {
99
110
height := goterm .Height ()
100
111
fmt .Print ("\033 7" ) // save cursor position
101
- if lk .err != nil {
112
+ if lk .ErrorHandle . err != nil {
102
113
fmt .Printf ("\033 [%d;0H" , height - 1 )
103
114
fmt .Print ("\033 [2K" ) // clear line
104
115
}
@@ -108,53 +119,74 @@ func (lk *LogKeyboard) ClearInfo() {
108
119
}
109
120
110
121
func (lk * LogKeyboard ) PrintEnter () {
111
- lk .ClearInfo ()
122
+ lk .clearInfo ()
112
123
lk .printInfo ()
113
124
}
114
125
115
- // func HandleKeyEvents(ctx context.Context, event keyboard.KeyEvent, project types.Project, options api.UpOptions, handleTearDown func()) {
116
- // switch key := event.Key; key {
117
- // case keyboard.KeyCtrlC:
118
- // keyboard.Close()
119
- // KeyboardManager.ClearInfo()
120
- // handleTearDown()
121
- // case keyboard.KeyCtrlG:
122
- // if KeyboardManager.IsDockerDesktopActive {
123
- // link := fmt.Sprintf("docker-desktop://dashboard/apps/%s", project.Name)
124
- // err := open.Run(link)
125
- // if err != nil {
126
- // KeyboardManager.SError("Could not open Docker Desktop")
127
- // } else {
128
- // KeyboardManager.Error(nil)
129
- // }
130
- // }
131
- // case keyboard.KeyCtrlW:
132
- // if KeyboardManager.Watching {
133
- // KeyboardManager.Watching = !KeyboardManager.Watching
134
- // fmt.Println("watching shortcut", KeyboardManager.Watching)
135
-
136
- // if KeyboardManager.Watching {
137
- // KeyboardManager.Cancel()
138
- // } else {
139
- // KeyboardManager.NewContext(ctx)
140
- // quit := make(chan error)
141
- // go func() {
142
- // buildOpts := *options.Create.Build
143
- // buildOpts.Quiet = true
144
- // err := s.Watch(KeyboardManager.Ctx, project, options.Start.Services, api.WatchOptions{
145
- // Build: &buildOpts,
146
- // LogTo: options.Start.Attach,
147
- // })
148
- // quit <- err
149
- // }()
150
- // KeyboardManager.Error(<-quit)
151
- // }
152
- // }
153
- // case keyboard.KeyEnter:
154
- // KeyboardManager.PrintEnter()
155
- // default:
156
- // if key != 0 { // If some key is pressed
157
- // fmt.Println("key pressed: ", key)
158
- // }
159
- // }
160
- // }
126
+ func (lk * LogKeyboard ) isWatching () bool {
127
+ return lk .Watch .Watching
128
+ }
129
+
130
+ func (lk * LogKeyboard ) switchWatching () {
131
+ lk .Watch .Watching = ! lk .Watch .Watching
132
+ }
133
+
134
+ func (lk * LogKeyboard ) newContext (ctx context.Context ) context.CancelFunc {
135
+ ctx , cancel := context .WithCancel (ctx )
136
+ lk .Watch .Ctx = ctx
137
+ lk .Watch .Cancel = cancel
138
+ return cancel
139
+ }
140
+
141
+ func (lk * LogKeyboard ) openDockerDesktop (project * types.Project ) {
142
+ if lk .IsDockerDesktopActive {
143
+ link := fmt .Sprintf ("docker-desktop://dashboard/apps/%s" , project .Name )
144
+ err := open .Run (link )
145
+ if err != nil {
146
+ lk .Error (fmt .Errorf ("could not open Docker Desktop" ))
147
+ } else {
148
+ lk .Error (nil )
149
+ }
150
+ }
151
+ }
152
+ func (lk * LogKeyboard ) StartWatch (ctx context.Context , project * types.Project , options api.UpOptions ) {
153
+ lk .switchWatching ()
154
+ if lk .isWatching () {
155
+ fmt .Println ("watching shortcut" )
156
+ lk .Watch .Cancel ()
157
+ } else {
158
+ lk .newContext (ctx )
159
+ errW := make (chan error )
160
+ go func () {
161
+ buildOpts := * options .Create .Build
162
+ buildOpts .Quiet = true
163
+ err := lk .Watch .WatchFn (lk .Watch .Ctx , project , options .Start .Services , api.WatchOptions {
164
+ Build : & buildOpts ,
165
+ LogTo : options .Start .Attach ,
166
+ })
167
+ errW <- err
168
+ }()
169
+ lk .Error (<- errW )
170
+ }
171
+ }
172
+
173
+ func (lk * LogKeyboard ) HandleKeyEvents (ctx context.Context , event keyboard.KeyEvent , project * types.Project , options api.UpOptions , handleTearDown func ()) {
174
+ switch kRune := event .Rune ; kRune {
175
+ case 'V' :
176
+ lk .openDockerDesktop (project )
177
+ case 'W' :
178
+ lk .StartWatch (ctx , project , options )
179
+ }
180
+ switch key := event .Key ; key {
181
+ case keyboard .KeyCtrlC :
182
+ keyboard .Close ()
183
+ lk .clearInfo ()
184
+ handleTearDown ()
185
+ case keyboard .KeyEnter :
186
+ lk .PrintEnter ()
187
+ default :
188
+ if key != 0 { // If some key is pressed
189
+ fmt .Println ("key pressed: " , key )
190
+ }
191
+ }
192
+ }
0 commit comments