mirror of
https://github.com/docker/compose.git
synced 2025-07-28 16:14:06 +02:00
simpler stop UI
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
c89f30170d
commit
3875e13fad
@ -42,13 +42,6 @@ func restoreCursor() {
|
|||||||
fmt.Print(ansi("8"))
|
fmt.Print(ansi("8"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func hideCursor() {
|
|
||||||
if disableAnsi {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Print(ansi("[?25l"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func showCursor() {
|
func showCursor() {
|
||||||
if disableAnsi {
|
if disableAnsi {
|
||||||
return
|
return
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 Docker Compose CLI authors
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package formatter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/buger/goterm"
|
|
||||||
"github.com/docker/compose/v2/pkg/api"
|
|
||||||
"github.com/docker/compose/v2/pkg/progress"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Stopping struct {
|
|
||||||
api.LogConsumer
|
|
||||||
enabled bool
|
|
||||||
spinner *progress.Spinner
|
|
||||||
ticker *time.Ticker
|
|
||||||
startedAt time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewStopping(l api.LogConsumer) *Stopping {
|
|
||||||
s := &Stopping{}
|
|
||||||
s.LogConsumer = logDecorator{
|
|
||||||
decorated: l,
|
|
||||||
Before: s.clear,
|
|
||||||
After: s.print,
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stopping) ApplicationTermination() {
|
|
||||||
if progress.Mode != progress.ModeAuto {
|
|
||||||
// User explicitly opted for output format
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if disableAnsi {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.enabled = true
|
|
||||||
s.spinner = progress.NewSpinner()
|
|
||||||
hideCursor()
|
|
||||||
s.startedAt = time.Now()
|
|
||||||
s.ticker = time.NewTicker(100 * time.Millisecond)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
<-s.ticker.C
|
|
||||||
s.print()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stopping) Close() {
|
|
||||||
showCursor()
|
|
||||||
if s.ticker != nil {
|
|
||||||
s.ticker.Stop()
|
|
||||||
}
|
|
||||||
s.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stopping) clear() {
|
|
||||||
if !s.enabled {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
height := goterm.Height()
|
|
||||||
carriageReturn()
|
|
||||||
saveCursor()
|
|
||||||
|
|
||||||
// clearLine()
|
|
||||||
for i := 0; i < height; i++ {
|
|
||||||
moveCursorDown(1)
|
|
||||||
clearLine()
|
|
||||||
}
|
|
||||||
restoreCursor()
|
|
||||||
}
|
|
||||||
|
|
||||||
const stoppingBanner = "Gracefully Stopping... (press Ctrl+C again to force)"
|
|
||||||
|
|
||||||
func (s *Stopping) print() {
|
|
||||||
if !s.enabled {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
height := goterm.Height()
|
|
||||||
width := goterm.Width()
|
|
||||||
carriageReturn()
|
|
||||||
saveCursor()
|
|
||||||
|
|
||||||
moveCursor(height, 0)
|
|
||||||
clearLine()
|
|
||||||
elapsed := time.Since(s.startedAt).Seconds()
|
|
||||||
timer := fmt.Sprintf("%.1fs ", elapsed)
|
|
||||||
pad := width - len(timer) - len(stoppingBanner) - 5
|
|
||||||
fmt.Printf("%s %s %s %s",
|
|
||||||
progress.CountColor(s.spinner.String()),
|
|
||||||
stoppingBanner,
|
|
||||||
strings.Repeat(" ", pad),
|
|
||||||
progress.TimerColor(timer),
|
|
||||||
)
|
|
||||||
|
|
||||||
carriageReturn()
|
|
||||||
restoreCursor()
|
|
||||||
}
|
|
@ -92,10 +92,6 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tui := formatter.NewStopping(logConsumer)
|
|
||||||
defer tui.Close()
|
|
||||||
logConsumer = tui
|
|
||||||
|
|
||||||
watcher, err := NewWatcher(project, options, s.watch, logConsumer)
|
watcher, err := NewWatcher(project, options, s.watch, logConsumer)
|
||||||
if err != nil && options.Start.Watch {
|
if err != nil && options.Start.Watch {
|
||||||
return err
|
return err
|
||||||
@ -112,7 +108,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
|
|||||||
first := true
|
first := true
|
||||||
gracefulTeardown := func() {
|
gracefulTeardown := func() {
|
||||||
first = false
|
first = false
|
||||||
tui.ApplicationTermination()
|
fmt.Println("Gracefully Stopping... press Ctrl+C again to force")
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
return progress.RunWithLog(context.WithoutCancel(ctx), func(ctx context.Context) error {
|
return progress.RunWithLog(context.WithoutCancel(ctx), func(ctx context.Context) error {
|
||||||
return s.stop(ctx, project.Name, api.StopOptions{
|
return s.stop(ctx, project.Name, api.StopOptions{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user