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

Initial implementation of 'console' package for stylized & localized console output 😂 #3638

Merged
merged 15 commits into from
Feb 12, 2019

Conversation

tstromberg
Copy link
Contributor

@tstromberg tstromberg commented Feb 8, 2019

Introduces new console package, and replaces most calls to fmt.Print* with the appropriate calls to console.Out* (stdout) or console.Err* (stderr).

Example usage:

console.OutLn("Starting up!")
console.OutStyle("status-change", "Configuring things")

These messages are plumbed through to the message.Printer API, which provides a mechanism for future localization. Full support for styles is currently only enabled for TERM's which mention "color", and only then if it's writing to a TTY. This whitelist does not currently include the Windows console, as that will require further testing.

It is possible to manually turn styles off and on by setting MINIKUBE_IN_COLOR=[01] in your environment.

This resolves #3569 and paves the way for the following roadmap items:

  • Localized output to 5+ written languages
  • Pre-flight error checks for common connectivity and configuration errors

My apologies for touching so many files in a single PR. This was due to heavy testing to make sure that the error messages plumbed to the user were proper enough for an initial implementation.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Feb 8, 2019
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: tstromberg

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 8, 2019
@k8s-ci-robot k8s-ci-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Feb 8, 2019
console.SetErrFile(os.Stderr)
err := console.SetPreferredLanguage(os.Getenv("LANG"))
if err != nil {
glog.Warningf("unable to detect language: %v", err)
Copy link
Contributor

@balopat balopat Feb 11, 2019

Choose a reason for hiding this comment

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

can the user do anything about this? what does it mean? are we falling back to default English? it would be nice to clarify the implications to the user.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Small nitpick here is that LANG is the locale (while LANGUAGE is the language)

LANG=sv_SE.UTF-8
LANGUAGE=sv

Copy link
Contributor Author

@tstromberg tstromberg Feb 11, 2019

Choose a reason for hiding this comment

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

LANG settings are incredibly complicated: LANG, LANGUAGE, and LC_* all control specific locale settings. LANG is the fallback.

To reduce complexity, I've removed the call to SetPreferredLanguage here. I'll re-introduce it once we have a way of loading alternative language strings.

cmd/minikube/cmd/ssh.go Outdated Show resolved Hide resolved
func wantsColor(fd uintptr) bool {
glog.Infof("%s=%q\n", OverrideEnv, os.Getenv(OverrideEnv))
switch os.Getenv(OverrideEnv) {
case "0":
Copy link
Contributor

Choose a reason for hiding this comment

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

I would consider using "true/false" or "on/off" or "yes/no" over "0/1"

Copy link
Collaborator

Choose a reason for hiding this comment

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

Normally you set the env var to enable, and leave it unset to disable.

In Go this means "" and "1", unless you want to bother with LookupEnv ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Since the idea here is to enable the user to opt out of this, and enable it by default...
Maybe we should change the variable name altogether ? like MINIKUBE_NOEMOJIS

Or keep the current approach, and use a string (not "bool") - and let "" mean auto-determine.
Just have to add some more case statements, to cover the above alternative spellings.

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've switched this code to use strconv.ParseBool to allow true/false as well as 0/1. NOTE: Other parts of minikube use the ladder.

I've added some comments as well, to clarify the behavior. I want users to also be able to force color on, if our automatic sniffing isn't appropriate for their environment.

// useColor is whether or not color output should be used, updated by Set*Writer.
useColor = false
// OverrideEnv is the environment variable used to override color/emoji usage
OverrideEnv = "MINIKUBE_IN_COLOR"
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be a const rather

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 intentionally left this as a var, in case someone else wants to abuse this library for their own nefarious uses.


// SetPreferredLanguage configures which language future messages should use, based on a LANG string.
func SetPreferredLanguage(s string) error {
if s == "" || s == "C" {
Copy link
Contributor

Choose a reason for hiding this comment

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

why is "C" default?

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's normally what you get, when you don't have any language support installed (including "en")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a comment describing what C is about. It's hard to find an authoritative declaration of where the value originated, but it's well used and defined in POSIX: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap07.html#tag_07_02

SetPreferredLanguageTag(defaultLanguage)
return nil
}
// Ignore encoding preferences: we always output utf8. Handles "de_DE.utf8"
Copy link
Contributor

Choose a reason for hiding this comment

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

do we want to warn about when we discard encoding preferences?

Copy link
Contributor Author

@tstromberg tstromberg Feb 11, 2019

Choose a reason for hiding this comment

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

Clarified comment. LANG settings which use non-utf8 encodings are fairly exotic, and unsupported in general nowadays. The world as a whole has moved to utf8 for console encodings*

  • The Windows story is slightly more complicated, but Windows also doesn't support overriding the encoding format.

Copy link
Contributor

@balopat balopat left a comment

Choose a reason for hiding this comment

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

besides some of the nits this looks amazing, I tested it on Mac (in color) / Linux (bnw) / Windows Powershell! Great stuff, I'm excited to get this in front of our users :D

@afbjorklund
Copy link
Collaborator

afbjorklund commented Feb 11, 2019

I think you meant "In front of our users 😀" - thanks for making it optional, though
Can we translate minikube using normal gettext objects later, or how does this work ?

@tstromberg
Copy link
Contributor Author

tstromberg commented Feb 11, 2019

Can we translate minikube using normal gettext objects later, or how does this work ?

No need to sling objects around. You can today register a translation from anywhere via:

err := message.SetString(language.Swedish, "Installing Kubernetes version %s ...", "Installerar Kubernetes version %s ...")

Any future outputs that match the string will be translated appropriately. The intent though is to store a translation maps in a data file (JSON? YAML? Go?) that minikube can reference. Any string which does not have a translation value will default to the closest language -- or english.

This behavior is asserted by console_test.

https://phraseapp.com/blog/posts/internationalization-i18n-go/ has more info on this approach.

@balopat
Copy link
Contributor

balopat commented Feb 11, 2019

LGTM, thank you!

pkg/minikube/cluster/cluster.go Outdated Show resolved Hide resolved
@tstromberg tstromberg merged commit ec5107e into kubernetes:master Feb 12, 2019
@balopat
Copy link
Contributor

balopat commented Feb 12, 2019

🎆 🍾

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

minikube output should include version/platform/arch
4 participants