Skip to content

Commit

Permalink
fix watch log
Browse files Browse the repository at this point in the history
  • Loading branch information
jhrotko committed Mar 14, 2024
1 parent 92266c3 commit ee4834f
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 79 deletions.
194 changes: 132 additions & 62 deletions cmd/formatter/shortcut.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"os"
"os/exec"
"syscall"
"time"

Expand All @@ -30,40 +29,47 @@ type KeyboardWatch struct {
Ctx context.Context
Cancel context.CancelFunc
}
type KEYBOARD_LOG_LEVEL int

const (
NONE KEYBOARD_LOG_LEVEL = 0
INFO KEYBOARD_LOG_LEVEL = 1
DEBUG KEYBOARD_LOG_LEVEL = 2
)

type LogKeyboard struct {
SignalChannel chan<- os.Signal
ErrorHandle KeyboardError
Watch KeyboardWatch
started bool
IsDockerDesktopActive bool
IsWatchConfigured bool
shouldPrintInfo bool
printerStop func()
printerStart func()
logLevel KEYBOARD_LOG_LEVEL
SignalChannel chan<- os.Signal
// services []string
// printerStop func()
// printerStart func()
}

var KeyboardManager *LogKeyboard
var eg multierror.Group
var errorColor = "\x1b[1;33m"

func NewKeyboardManager(isDockerDesktopActive, isWatchConfigured, startWatch bool, watchFn func(ctx context.Context, project *types.Project, services []string, options api.WatchOptions) error, stop func(), start func(), sc chan<- os.Signal) {
func NewKeyboardManager(isDockerDesktopActive, isWatchConfigured bool, sc chan<- os.Signal, watchFn func(ctx context.Context, project *types.Project, services []string, options api.WatchOptions) error) {
// func NewKeyboardManager(isDockerDesktopActive, isWatchConfigured, startWatch bool, watchFn func(ctx context.Context, project *types.Project, services []string, options api.WatchOptions) error, stop func(), start func(), sc chan<- os.Signal) {
km := LogKeyboard{}
km.IsDockerDesktopActive = isDockerDesktopActive
km.IsWatchConfigured = isWatchConfigured
km.printerStart = start
km.printerStop = stop
km.shouldPrintInfo = true
// km.printerStart = start
// km.printerStop = stop
km.logLevel = INFO
// if up --watch and there is a watch config, we should start with watch running
km.Watch.Watching = isWatchConfigured && startWatch
km.Watch.Watching = false
km.Watch.WatchFn = watchFn
km.SignalChannel = sc
KeyboardManager = &km
}

func (lk *LogKeyboard) PrintKeyboardInfo(print func()) {
if !lk.shouldPrintInfo {
return
}
fmt.Print("\033[?25l") // hide cursor
defer fmt.Printf("\033[?25h") // show cursor

Expand All @@ -73,8 +79,14 @@ func (lk *LogKeyboard) PrintKeyboardInfo(print func()) {
lk.started = true
}
print()
lk.createBuffer()
lk.printInfo()
switch lk.logLevel {
case INFO:
lk.createBuffer(2)
lk.printInfo()
case DEBUG:
lk.createBuffer(3)
// lk.printDebugOptions()
}
}

func (lk *LogKeyboard) Error(prefix string, err error) {
Expand All @@ -83,10 +95,12 @@ func (lk *LogKeyboard) Error(prefix string, err error) {
}

// This avoids incorrect printing at the end of the terminal
func (lk *LogKeyboard) createBuffer() {
fmt.Print("\012") // new line
fmt.Print("\012")
fmt.Print("\033[2A") // go back 3 lines
func (lk *LogKeyboard) createBuffer(lines int) {
for i := 0; i < lines; i++ {
fmt.Print("\033[K") // clear
fmt.Print("\012") // new line
}
fmt.Printf("\033[%dA", lines) // go back x lines
}

func (lk *LogKeyboard) printError(height int) {
Expand All @@ -97,13 +111,15 @@ func (lk *LogKeyboard) printError(height int) {
}

func (lk *LogKeyboard) printInfo() {
height := goterm.Height()
fmt.Print("\0337") // save cursor position
lk.printError(height)
fmt.Printf("\033[%d;0H", height) // Move to last line
// clear line
lk.infoMessage()
fmt.Print("\0338") // restore cursor position
if lk.logLevel == INFO {
height := goterm.Height()
fmt.Print("\0337") // save cursor position
lk.printError(height)
fmt.Printf("\033[%d;0H", height) // Move to last line
// clear line
lk.infoMessage()
fmt.Print("\0338") // restore cursor position
}
}

func (lk *LogKeyboard) infoMessage() {
Expand All @@ -124,21 +140,23 @@ func (lk *LogKeyboard) infoMessage() {
}

func (lk *LogKeyboard) clearInfo() {
height := goterm.Height()
fmt.Print("\0337") // save cursor position
if lk.ErrorHandle.err != nil {
fmt.Printf("\033[%d;0H", height-1)
fmt.Print("\033[2K") // clear line
if lk.logLevel == INFO {
height := goterm.Height()
fmt.Print("\0337") // save cursor position
if lk.ErrorHandle.err != nil {
fmt.Printf("\033[%d;0H", height-1)
fmt.Print("\033[2K") // clear line
}
fmt.Printf("\033[%d;0H", height) // Move to last line
fmt.Print("\033[2K") // clear line
fmt.Print("\0338") // restore cursor position
}
if lk.logLevel == DEBUG {

}
fmt.Printf("\033[%d;0H", height) // Move to last line
fmt.Print("\033[2K") // clear line
fmt.Print("\0338") // restore cursor position
}

func (lk *LogKeyboard) PrintEnter() {
if !lk.shouldPrintInfo {
return
}
lk.clearInfo()
lk.printInfo()
}
Expand Down Expand Up @@ -176,6 +194,7 @@ func (lk *LogKeyboard) StartWatch(ctx context.Context, project *types.Project, o
return
}
lk.switchWatching()
fmt.Println("lk.isWatching()", lk.isWatching())
if !lk.isWatching() && lk.Watch.Cancel != nil {
lk.Watch.Cancel()
} else {
Expand All @@ -193,48 +212,99 @@ func (lk *LogKeyboard) StartWatch(ctx context.Context, project *types.Project, o
}
}

func (lk *LogKeyboard) debug() {
cmd := exec.Command("docker", "debug", "keep-not-latest-app-1")
cmd.Stdout = os.Stdout
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
// func (lk *LogKeyboard) printDebugOptions() {
// if len(lk.services) == 0 {
// lk.logLevel = INFO
// return
// }
// height := goterm.Height()
// //clear
// fmt.Print("\0337") // save cursor position
// fmt.Printf("\033[%d;0H\033[2K", height-2)
// fmt.Printf("\033[%d;0H\033[2K", height-1)
// fmt.Printf("\033[%d;0H\033[2K", height)
// //clear

lk.printerStop()
if err := cmd.Start(); err != nil {
lk.printerStart()
lk.Error("Debug", fmt.Errorf("Could not start debug process."))
return
}
err := cmd.Wait()
lk.printerStart()
if err != nil {
lk.Error("Debug", err)
}
}
// fmt.Printf("\033[%d;0H", height-2) // Move to last line
// fmt.Print("\033[2K[Debug] Select Service:")
// fmt.Printf("\033[%d;0H", height-1) // Move to last line
// serviceOpts := ""
// for i := 0; i < len(lk.services); i++ {
// serviceOpts = serviceOpts + fmt.Sprintf("(%d) %s ", i+1, lk.services[i])
// }
// fmt.Printf("\033[2K%s", serviceOpts)
// fmt.Print("\0338") // restore cursor position
// }

// func (lk *LogKeyboard) debug(project *types.Project) {
// lk.services = project.ServiceNames()
// // show list
// lk.clearInfo()
// lk.logLevel = DEBUG
// // select
// // clear line
// choice := make(chan []byte)
// eg.Go(func() error {
// for {
// data := make([]byte, 8)
// n, err := os.Stdin.Read(data)

// // error handling : the basic thing to do is "on error, return"
// if err != nil {
// // if os.Stdin got closed, .Read() will return 'io.EOF'
// if err == io.EOF {
// log.Printf("stdin closed, exiting")
// } else {
// log.Printf("stdin: %s", err)
// }
// return err
// }
// // a habit to have : truncate your read buffers to 'n' after a .Read()
// choice <- data[:n]
// // return nil
// }
// })
// out := <-choice
// fmt.Println(out)
//run
// cmd := exec.Command("docker", "debug", "keep-not-latest-app-1")
// cmd.Stdout = os.Stdout
// cmd.Stdin = os.Stdin
// cmd.Stderr = os.Stderr

// lk.printerStop()
// if err := cmd.Start(); err != nil {
// lk.printerStart()
// lk.Error("Debug", fmt.Errorf("Could not start debug process."))
// return
// }
// err := cmd.Wait()
// lk.printerStart()
// lk.logLevel = INFO
// if err != nil {
// lk.Error("Debug", err)
// }
// }

func (lk *LogKeyboard) HandleKeyEvents(event keyboard.KeyEvent, ctx context.Context, project *types.Project, options api.UpOptions) {
switch kRune := event.Rune; kRune {
case 'V':
lk.openDockerDesktop(project)
case 'W':
lk.StartWatch(ctx, project, options)
case 'D':
lk.debug()
// case 'D':
// lk.debug(project)
}
switch key := event.Key; key {
case keyboard.KeyCtrlC:
keyboard.Close()
lk.clearInfo()
lk.shouldPrintInfo = false
lk.logLevel = NONE
if lk.Watch.Watching && lk.Watch.Cancel != nil {
// fmt.Println("canceling")
lk.Watch.Cancel()
// fmt.Println("canceling watch?")
err := eg.Wait().ErrorOrNil() // Need to print this ?
fmt.Println("done@", err)
_ = eg.Wait().ErrorOrNil() // Need to print this ?
}
// will notify main thread to kill and will handle gracefully
fmt.Println("tear down")
lk.SignalChannel <- syscall.SIGINT
case keyboard.KeyEnter:
lk.PrintEnter()
Expand Down
32 changes: 17 additions & 15 deletions pkg/compose/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,21 +95,23 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
if err != nil {
panic(err)
}
formatter.NewKeyboardManager(true, s.shouldWatch(project), options.Start.Watch, s.Watch, printer.Cancel, func() {
eg.Go(func() error {
_, err := printer.Run(options.Start.CascadeStop, options.Start.ExitCodeFrom, func() error {
fmt.Fprintln(s.stdinfo(), "Aborting on container exit...")
return progress.Run(ctx, func(ctx context.Context) error {
return s.Stop(ctx, project.Name, api.StopOptions{
Services: options.Create.Services,
Project: project,
})
}, s.stdinfo())
})
return err
})
}, signalChan) // change after test
if formatter.KeyboardManager.Watch.Watching {
formatter.NewKeyboardManager(true, options.Start.Watch, signalChan, s.Watch)

// formatter.NewKeyboardManager(true, s.shouldWatch(project), options.Start.Watch, s.Watch, printer.Cancel, func() {
// eg.Go(func() error {
// _, err := printer.Run(options.Start.CascadeStop, options.Start.ExitCodeFrom, func() error {
// fmt.Fprintln(s.stdinfo(), "Aborting on container exit...")
// return progress.Run(ctx, func(ctx context.Context) error {
// return s.Stop(ctx, project.Name, api.StopOptions{
// Services: options.Create.Services,
// Project: project,
// })
// }, s.stdinfo())
// })
// return err
// })
// }, signalChan) // change after test
if options.Start.Watch {
formatter.KeyboardManager.StartWatch(ctx, project, options)
}
// formatter.NewKeyboardManager(s.isDesktopIntegrationActive(), s.shouldWatch(project), options.Start.Watch, s.Watch)
Expand Down
8 changes: 6 additions & 2 deletions pkg/compose/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func (s *composeService) Watch(ctx context.Context, project *types.Project, serv
// options.LogTo.Err(api.WatchLogger, "FAILED")
return fmt.Errorf("none of the selected services is configured for watch, consider setting an 'develop' section")
}
options.LogTo.Log(api.WatchLogger, "watch enabled")
options.LogTo.Log(api.WatchLogger, "Watch started")

return eg.Wait()
}
Expand All @@ -198,10 +198,12 @@ func (s *composeService) watch(ctx context.Context, project *types.Project, name

events := make(chan fileEvent)
batchEvents := batchDebounceEvents(ctx, s.clock, quietPeriod, events)
quit := make(chan bool)
go func() {
for {
select {
case <-ctx.Done():
quit <- true
return
case batch := <-batchEvents:
start := time.Now()
Expand All @@ -217,9 +219,11 @@ func (s *composeService) watch(ctx context.Context, project *types.Project, name

for {
select {
case <-ctx.Done():
case <-quit:
options.LogTo.Log(api.WatchLogger, "Watch stoped")
return nil
case err := <-watcher.Errors():
options.LogTo.Err(api.WatchLogger, "Watch stoped with errors")
return err
case event := <-watcher.Events():
hostPath := event.Path()
Expand Down

0 comments on commit ee4834f

Please sign in to comment.