Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pop of color to terminal output with a color formatter #857

Merged

Conversation

bobcatfish
Copy link
Contributor

This implementation avoids needing to instantiate a formatter object
(as seen in #850) by using a global function pointer to override the
IsTerminal logic. This means any code at any time could output in
whatever color it wants to. (Thanks @r2d4 for suggesting this
implementation in the first place!)

Skaffold draws a distinction between log output, which goes to stdout,
and output from Skaffold to the user, which goes to stdout and is
interleaved with output from the tools Skaffold users (e.g. docker for
building). This commit changes the output from Skaffold to the user to
be Blue!

The escape codes to make the text blue (or other colors, in the case of
the kube pod-specific logging) will only be output if stdout is a
terminal. If output is being redirected to a file for example, the
escape codes will not be included.

This change makes use of the exciting colors.go logic but splits it
into the picker (specifically for mapping images to colors consistently)
from the logic to add escape codes.

Other alternatives:

@@ -117,7 +118,7 @@ func (h *HelmDeployer) deployRelease(out io.Writer, r v1alpha2.HelmRelease, buil
return nil, errors.Wrap(err, "cannot parse the release name template")
}
if err := h.helm(out, "get", releaseName); err != nil {
fmt.Fprintf(out, "Helm release %s not installed. Installing...\n", releaseName)
color.Fprintf(out, color.Red, "Helm release %s not installed. Installing...\n", releaseName)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this red just for fun!

Copy link
Contributor

@r2d4 r2d4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We can merge the existing "colorpicker" codes with the new ones in either this PR or a new PR at some point.


var (
// LightRed can format text to be displayed to the terminal in light red, using ANSI escape codes.
LightRed = Color(91)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other file looks like it's duplicating this but actually it is only specifying the order of the colors to use when coloring pod output

@@ -0,0 +1,69 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One kind of odd nit:

Maybe package pkg/skaffold/util/color?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing you want to do this b/c the color functionality isn't really a "core part" of skaffold, it's like an extra utility, and I see what you're saying, but I find that calling packages util or lib or anything like that b/c it makes it very hard to reason about what should and should not be inside them. I'd be more inclined to take the contents of pkg/skaffold/util/ and move them into their own packages.

See "bad package names" at https://blog.golang.org/package-names

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But also it's not great that the Color type is color.Color :(

@bobcatfish
Copy link
Contributor Author

@r2d4 in this version I forgot to update the kube logger not to output to a terminal, added in f16cefe - let me know what you think! (I'm not 100% happy with it but can't think of anything hugely btter at the moment)

Copy link
Contributor

@dgageot dgageot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small nitpick. Other than that LGTM!

@@ -48,7 +48,7 @@ func NewCmdFix(out io.Writer) *cobra.Command {
return
}
if cfg.GetVersion() == config.LatestVersion {
fmt.Fprintln(out, "config is already latest version")
color.Fprintln(out, color.Default, "config is already latest version")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about color.Default.Fprintln(out, "config is already latest version")? If you like it, it can be done in another PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooooo that's a cool idea

@bobcatfish
Copy link
Contributor Author

image

daviiiiiiiiiiiid

This implementation avoids needing to instantiate a formatter object
(as seen in GoogleContainerTools#850) by using a global function pointer to override the
IsTerminal logic. This means any code at any time could output in
whatever color it wants to. (Thanks @r2d4 for suggesting this
implementation in the first place!)

Skaffold draws a distinction between log output, which goes to stdout,
and output from Skaffold to the user, which goes to stdout and is
interleaved with output from the tools Skaffold users (e.g. docker for
building). This commit changes the output from Skaffold to the user to
be Blue!

The escape codes to make the text blue (or other colors, in the case of
the kube pod-specific logging) will only be output if stdout is a
terminal. If output is being redirected to a file for example, the
escape codes will not be included.

This change makes use of the exciting colors.go logic but splits it
into the picker (specifically for mapping images to colors consistently)
from the logic to add escape codes.

Other alternatives:
* GoogleContainerTools#856 - Wrap io.Writer
* GoogleContainerTools#850 - Instantiate a formatter object
* Separate formatting logic from writing logic (I tried this out and it
  didn't seem like it improved anything as it didn't align well with
  how `fmt` is implemented)
Before this change, if you redirected output to a file, you'd get the
ANSI color escape codes as well surrounding the name of the pod. Now
they will only be output if the output is a terminal.
dgageot@ suggested that instead of passing the color into the formatting
methods, we could make these methods be on the color struct itself,
which makes for a pretty slick interface imo.

One thing that still isn't clear is how to output one line in multiple
colors in a terminal safe way - Sprint/Sprintf would have to bebe aware
of the target output stream to make this happen, or we'd need to
introduce some kind of formatting syntax (e.g. '{blue}blue
text{reset:blue}') but I think that can wait until we really need it,
the workaround in log.go seems find for now.
@bobcatfish
Copy link
Contributor Author

Made the change you suggested @dgageot !

@dgageot
Copy link
Contributor

dgageot commented Jul 27, 2018

LGTM!

@dgageot dgageot merged commit 292c13f into GoogleContainerTools:master Jul 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants