From fc8c5fdce62fb229202659408798a7b6c98f6e8b Mon Sep 17 00:00:00 2001 From: 简律纯 Date: Fri, 28 Apr 2023 01:36:55 +0800 Subject: --- cli/internal/ui/charset.go | 3 - cli/internal/ui/colors.go | 54 ---------------- cli/internal/ui/spinner.go | 80 ------------------------ cli/internal/ui/term/cursor.go | 73 ---------------------- cli/internal/ui/term/cursor_test.go | 43 ------------- cli/internal/ui/ui.go | 121 ------------------------------------ 6 files changed, 374 deletions(-) delete mode 100644 cli/internal/ui/charset.go delete mode 100644 cli/internal/ui/colors.go delete mode 100644 cli/internal/ui/spinner.go delete mode 100644 cli/internal/ui/term/cursor.go delete mode 100644 cli/internal/ui/term/cursor_test.go delete mode 100644 cli/internal/ui/ui.go (limited to 'cli/internal/ui') diff --git a/cli/internal/ui/charset.go b/cli/internal/ui/charset.go deleted file mode 100644 index 0207c10..0000000 --- a/cli/internal/ui/charset.go +++ /dev/null @@ -1,3 +0,0 @@ -package ui - -var charset = []string{" ", "> ", ">> ", ">>>"} diff --git a/cli/internal/ui/colors.go b/cli/internal/ui/colors.go deleted file mode 100644 index 4b2eccd..0000000 --- a/cli/internal/ui/colors.go +++ /dev/null @@ -1,54 +0,0 @@ -package ui - -import ( - "os" - - "github.com/fatih/color" -) - -type ColorMode int - -const ( - ColorModeUndefined ColorMode = iota + 1 - ColorModeSuppressed - ColorModeForced -) - -func GetColorModeFromEnv() ColorMode { - // The FORCED_COLOR behavior and accepted values are taken from the supports-color NodeJS Package: - // The accepted values as documented are "0" to disable, and "1", "2", or "3" to force-enable color - // at the specified support level (1 = 16 colors, 2 = 256 colors, 3 = 16M colors). - // We don't currently use the level for anything specific, and just treat things as on and off. - // - // Note: while "false" and "true" aren't documented, the library coerces these values to 0 and 1 - // respectively, so that behavior is reproduced here as well. - // https://www.npmjs.com/package/supports-color - - switch forceColor := os.Getenv("FORCE_COLOR"); { - case forceColor == "false" || forceColor == "0": - return ColorModeSuppressed - case forceColor == "true" || forceColor == "1" || forceColor == "2" || forceColor == "3": - return ColorModeForced - default: - return ColorModeUndefined - } -} - -func applyColorMode(colorMode ColorMode) ColorMode { - switch colorMode { - case ColorModeForced: - color.NoColor = false - case ColorModeSuppressed: - color.NoColor = true - case ColorModeUndefined: - default: - // color.NoColor already gets its default value based on - // isTTY and/or the presence of the NO_COLOR env variable. - } - - if color.NoColor { - return ColorModeSuppressed - } else { - return ColorModeForced - } -} diff --git a/cli/internal/ui/spinner.go b/cli/internal/ui/spinner.go deleted file mode 100644 index 6e47d2d..0000000 --- a/cli/internal/ui/spinner.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -package ui - -import ( - "fmt" - "io" - "os" - "time" - - "github.com/briandowns/spinner" -) - -// startStopper is the interface to interact with the spinner. -type startStopper interface { - Start() - Stop() -} - -// Spinner represents an indicator that an asynchronous operation is taking place. -// -// For short operations, less than 4 seconds, display only the spinner with the Start and Stop methods. -// For longer operations, display intermediate progress events using the Events method. -type Spinner struct { - spin startStopper -} - -// NewSpinner returns a spinner that outputs to w. -func NewSpinner(w io.Writer) *Spinner { - interval := 125 * time.Millisecond - if os.Getenv("CI") == "true" { - interval = 30 * time.Second - } - s := spinner.New(charset, interval, spinner.WithHiddenCursor(true)) - s.Writer = w - s.Color("faint") - return &Spinner{ - spin: s, - } -} - -// Start starts the spinner suffixed with a label. -func (s *Spinner) Start(label string) { - s.suffix(fmt.Sprintf(" %s", label)) - s.spin.Start() -} - -// Stop stops the spinner and replaces it with a label. -func (s *Spinner) Stop(label string) { - s.finalMSG(fmt.Sprint(label)) - s.spin.Stop() -} - -func (s *Spinner) lock() { - if spinner, ok := s.spin.(*spinner.Spinner); ok { - spinner.Lock() - } -} - -func (s *Spinner) unlock() { - if spinner, ok := s.spin.(*spinner.Spinner); ok { - spinner.Unlock() - } -} - -func (s *Spinner) suffix(label string) { - s.lock() - defer s.unlock() - if spinner, ok := s.spin.(*spinner.Spinner); ok { - spinner.Suffix = label - } -} - -func (s *Spinner) finalMSG(label string) { - s.lock() - defer s.unlock() - if spinner, ok := s.spin.(*spinner.Spinner); ok { - spinner.FinalMSG = label - } -} diff --git a/cli/internal/ui/term/cursor.go b/cli/internal/ui/term/cursor.go deleted file mode 100644 index 253f043..0000000 --- a/cli/internal/ui/term/cursor.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -// Package cursor provides functionality to interact with the terminal cursor. -package cursor - -import ( - "io" - "os" - - "github.com/AlecAivazis/survey/v2/terminal" -) - -type cursor interface { - Up(n int) error - Down(n int) error - Hide() error - Show() error -} - -// fakeFileWriter is a terminal.FileWriter. -// If the underlying writer w does not implement Fd() then a dummy value is returned. -type fakeFileWriter struct { - w io.Writer -} - -// Write delegates to the internal writer. -func (w *fakeFileWriter) Write(p []byte) (int, error) { - return w.w.Write(p) -} - -// Fd is required to be implemented to satisfy the terminal.FileWriter interface. -// If the underlying writer is a file, like os.Stdout, then invoke it. Otherwise, this method allows us to create -// a Cursor that can write to any io.Writer like a bytes.Buffer by returning a dummy value. -func (w *fakeFileWriter) Fd() uintptr { - if v, ok := w.w.(terminal.FileWriter); ok { - return v.Fd() - } - return 0 -} - -// Cursor represents the terminal's cursor. -type Cursor struct { - c cursor -} - -// New creates a new cursor that writes to stderr. -func New() *Cursor { - return &Cursor{ - c: &terminal.Cursor{ - Out: os.Stderr, - }, - } -} - -// EraseLine erases a line from a FileWriter. -func EraseLine(fw terminal.FileWriter) { - terminal.EraseLine(fw, terminal.ERASE_LINE_ALL) -} - -// EraseLinesAbove erases a line and moves the cursor up from fw, repeated n times. -func EraseLinesAbove(fw terminal.FileWriter, n int) { - c := Cursor{ - c: &terminal.Cursor{ - Out: fw, - }, - } - for i := 0; i < n; i += 1 { - EraseLine(fw) - c.c.Up(1) - } - EraseLine(fw) // Erase the nth line as well. -} diff --git a/cli/internal/ui/term/cursor_test.go b/cli/internal/ui/term/cursor_test.go deleted file mode 100644 index 270ebe8..0000000 --- a/cli/internal/ui/term/cursor_test.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build !windows -// +build !windows - -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -package cursor - -import ( - "io" - "strings" - "testing" - - "github.com/AlecAivazis/survey/v2/terminal" - "github.com/stretchr/testify/require" -) - -func TestEraseLine(t *testing.T) { - testCases := map[string]struct { - inWriter func(writer io.Writer) terminal.FileWriter - shouldErase bool - }{ - "should erase a line if the writer is a file": { - inWriter: func(writer io.Writer) terminal.FileWriter { - return &fakeFileWriter{w: writer} - }, - shouldErase: true, - }, - } - - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - // GIVEN - buf := new(strings.Builder) - - // WHEN - EraseLine(tc.inWriter(buf)) - - // THEN - isErased := buf.String() != "" - require.Equal(t, tc.shouldErase, isErased) - }) - } -} diff --git a/cli/internal/ui/ui.go b/cli/internal/ui/ui.go deleted file mode 100644 index 9084c76..0000000 --- a/cli/internal/ui/ui.go +++ /dev/null @@ -1,121 +0,0 @@ -package ui - -import ( - "fmt" - "io" - "math" - "os" - "regexp" - "strings" - - "github.com/fatih/color" - "github.com/mattn/go-isatty" - "github.com/mitchellh/cli" - "github.com/vercel/turbo/cli/internal/ci" -) - -const ansiEscapeStr = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))" - -// IsTTY is true when stdout appears to be a tty -var IsTTY = isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()) - -// IsCI is true when we appear to be running in a non-interactive context. -var IsCI = !IsTTY || ci.IsCi() -var gray = color.New(color.Faint) -var bold = color.New(color.Bold) -var ERROR_PREFIX = color.New(color.Bold, color.FgRed, color.ReverseVideo).Sprint(" ERROR ") -var WARNING_PREFIX = color.New(color.Bold, color.FgYellow, color.ReverseVideo).Sprint(" WARNING ") - -// InfoPrefix is a colored string for warning level log messages -var InfoPrefix = color.New(color.Bold, color.FgWhite, color.ReverseVideo).Sprint(" INFO ") - -var ansiRegex = regexp.MustCompile(ansiEscapeStr) - -// Dim prints out dimmed text -func Dim(str string) string { - return gray.Sprint(str) -} - -func Bold(str string) string { - return bold.Sprint(str) -} - -// Adapted from go-rainbow -// Copyright (c) 2017 Raphael Amorim -// Source: https://github.com/raphamorim/go-rainbow -// SPDX-License-Identifier: MIT -func rgb(i int) (int, int, int) { - var f = 0.275 - - return int(math.Sin(f*float64(i)+4*math.Pi/3)*127 + 128), - // int(math.Sin(f*float64(i)+2*math.Pi/3)*127 + 128), - int(45), - int(math.Sin(f*float64(i)+0)*127 + 128) -} - -// Rainbow function returns a formated colorized string ready to print it to the shell/terminal -// -// Adapted from go-rainbow -// Copyright (c) 2017 Raphael Amorim -// Source: https://github.com/raphamorim/go-rainbow -// SPDX-License-Identifier: MIT -func Rainbow(text string) string { - var rainbowStr []string - for index, value := range text { - r, g, b := rgb(index) - str := fmt.Sprintf("\033[1m\033[38;2;%d;%d;%dm%c\033[0m\033[0;1m", r, g, b, value) - rainbowStr = append(rainbowStr, str) - } - - return strings.Join(rainbowStr, "") -} - -type stripAnsiWriter struct { - wrappedWriter io.Writer -} - -func (into *stripAnsiWriter) Write(p []byte) (int, error) { - n, err := into.wrappedWriter.Write(ansiRegex.ReplaceAll(p, []byte{})) - if err != nil { - // The number of bytes returned here isn't directly related to the input bytes - // if ansi color codes were being stripped out, but we are counting on Stdout.Write - // not failing under typical operation as well. - return n, err - } - - // Write must return a non-nil error if it returns n < len(p). Consequently, if the - // wrappedWrite.Write call succeeded we will return len(p) as the number of bytes - // written. - return len(p), nil -} - -// Default returns the default colored ui -func Default() *cli.ColoredUi { - return BuildColoredUi(ColorModeUndefined) -} - -func BuildColoredUi(colorMode ColorMode) *cli.ColoredUi { - colorMode = applyColorMode(colorMode) - - var outWriter, errWriter io.Writer - - if colorMode == ColorModeSuppressed { - outWriter = &stripAnsiWriter{wrappedWriter: os.Stdout} - errWriter = &stripAnsiWriter{wrappedWriter: os.Stderr} - } else { - outWriter = os.Stdout - errWriter = os.Stderr - } - - return &cli.ColoredUi{ - Ui: &cli.BasicUi{ - Reader: os.Stdin, - Writer: outWriter, - ErrorWriter: errWriter, - }, - OutputColor: cli.UiColorNone, - InfoColor: cli.UiColorNone, - WarnColor: cli.UiColor{Code: int(color.FgYellow), Bold: false}, - ErrorColor: cli.UiColorRed, - } -} -- cgit v1.2.3-70-g09d2