-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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 colors to CLI commands #1231
base: main
Are you sure you want to change the base?
Conversation
I think this answers #59 but somehow the issue was closed, I'm not sure why |
7095182
to
6291a09
Compare
Thanks for this! Very cool feature!! Can you provide a short snipped of how a user might use this? Thanks much for adding tests. I'll give this a test and we should be able to get it in 2.0 |
Hello, I currently have 2 use cases for this. The first one would be to put an emphasis on a few commands in my CLI. I have a lot of available CMDs, and 3 of them are groups that regroups the rest of the commands (One group for collection of data, one group analysis of the data and the last group for modification of the data). So I thought it'd be nice to put some color to make them easier to see in the list of commands. The second use case was to put a color code on some commands. For example, put in red the commands that might modify data or directly affect production, whereas we can put in green commands that would only read data. Making sure that one can easily see that what they're choosing is potentially a dangerous action. |
Very cool! Can you provide a snippet of code using this new API? That will help me test. |
If you do a simple package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(deleteCmd)
rootCmd.AddCommand(readCmd)
}
var deleteCmd = &cobra.Command{
Use: "delete",
Short: "Delete hosts in production",
Long: `Delete hosts in production`,
Color: cobra.ColorRed,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Write CMD")
},
}
var readCmd = &cobra.Command{
Use: "read",
Short: "read hosts in production",
Long: `read hosts in production`,
Color: cobra.ColorGreen,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("read CMD")
},
} |
After your exchange, I started getting curious about this change. @jpmcb I hope you don't mind, but I tried it out with Helm which is a larger test. @JulesDT This is really cool! I noticed a couple of things:
Notice that the indentation is wrong for Also, the Could this be applied to flags? |
Thanks for testing this! I indeed made a mistake when putting the colors, the sequence starting at Regarding helm I think the issue is that the padding was badly applied indeed. The unseen characters Let me know if you see anything else that is wrong! |
@JulesDT It looks great now. Thanks. But I cannot figure out what happens if the terminal does not support colours? Will the help/usage text be broken? This is important because if a program using Cobra wants to add colours, can it do it blindly or does it have to support some option to allow users to disable colours, in case their terminal does not support them? |
That's a good call. I just wasn't able to disable colors in any of the shells I've used. I've tried If you have a way for me to easily disable colors and see how it behaves I'd be happy to push a fix if needed. Detecting if colors are disabled would probably be the best solution, if this can't be done, I guess a config variable that disables colors could work? I'm tempted to say that people building their own CLI tools will know where it'll run and can enable or disable colors depending on their need, the question arises for global CLI tools (such as helm) where I don't have strong opinion about who should allow to easily disable colors, either the project or Cobra. |
I tried as well without success.
With the current proposed implementation, how do you see a program such as helm telling Cobra to disable colours? |
Well, if helm doesn't want to provide Colors because they're afraid of incompatibilities, it's easy for them to simply not use that feature from Cobra. Then with the current implementation is basically follows the same behavior as before. Do you have an alternative idea in mind? I'm happy to implement a config or a parameter or anything that would allow to disable coloring but I'm not sure how such a feature if it existed should be used. |
Sorry @JulesDT I was pretty vague in my last comment. What I'm imagining is that a program would make use of colors but allow a user to disable them (or vice versa where users would be given the option to enable colors). This could be through a global flag, or some configuration option (that's a detail for the program to choose). So the question becomes, how would the program easily tell Cobra to turn colors on or off in the same compiled binary? Thinking about it now, I guess the program could have its own function:
But I was wondering if it would be easier for Cobra to provide an option so that |
I see. Yeah I wouldn't disagree with giving the user this possibility. In term of design or user experience, I'm not sure what would be the preferred way for Cobra, or what is usually used for such options here. What I guess a program could do indeed is set a global flag such that if this flag is set ColoredNamed would return the normal name or not. What I suggest for this is the following, but I don't love this design so I'm happy to be told a different way you'd prefer. func (c *Command) isColoringDisabled() bool {
if c.DisableColors {
return c.DisableColors
}
if c.parent != nil {
return c.parent.isColoringDisabled()
}
return false
}
func (c *Command) ColoredName() string {
if c.Color != 0 && !c.isColoringDisabled() {
return fmt.Sprintf("\033[%dm%s\033[0m", c.Color, c.Name())
}
return c.Name()
} Then what one could do is add a persistent flag on root to disable colors: rootCmd.PersistentFlags().BoolVarP(&rootCmd.DisableColors, "disable-colors", "d", false, "disable colors in the terminal") What do you think @marckhouzam ? |
@marckhouzam or @jpmcb , any thoughts on this? |
I suggest following the https://no-color.org/ standard. |
I think respecting a |
@JulesDT Sorry for the delay. I like your idea of having a
Then, a program could disable colours using a global flag using something like:
These are just ideas but please be aware I have no final say on this. |
That is the idea behind |
Sounds good to me. |
Some thoughts:
|
@umarcor correct me if I'm wrong, but I think the problem around using viper is that when the help menu is being shown to the user (where the colors are used basically), the config file hasn't been parsed yet. Would the |
I would also like to see a test case around the Checking in on this one, where are we at with this PR? Thanks much for the work on this one :D |
Hello @jpmcb ! Good catch on the tests, I added a test related to the NO_COLOR env variable and the DisableColors parameter. Let me know if you see anything else that is missing. On my end, I don't think anything is missing and I think all concerns above have been considered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tested the latest version of this PR with helm where I added a bunch of sub-commands with colours. It all looks great, both the colours and the ability to disable them. Thanks @JulesDT.
Maybe it would be nice to add little mention of this feature in the docs? And if so, including how to turn it off. What do you think @jpmcb .
So I've just looked at the code out of curiosity. |
@JulesDT. You are correct. If the command does not have a |
What shall we do with this colour PR? Reading the comment from @catthehacker, I don't know if this change will work on Windows, @JulesDT do you have the ability to try it? Maybe using an external package would be a good idea? |
@marckhouzam Yes and no. It will work for people using Windows Terminal app but it will not work in default terminal. |
Thanks for the screenshots and tests @catthehacker. If we are okay with using an external dependency, I can try to make the switch, I don't really have a Windows available for testing it. Do we have any preference around which one to use? |
Just wanted to add that I pointed to those packages as reference, I'm not well versed in using any of them and there might be better/more suitable libraries to use (or not using external deps at all). Also I can test anything on current (Win10 2009), preview (dev builds) and previous (2004, 1909, 1903, Win8.1, Win8, Win7, etc.) Windows versions for you if you need. |
This PR is being marked as stale due to a long period of inactivity |
I like the idea of this, but a little worried since it has such a broad impact on everyone using the library. The biggest area of concern for me is Windows. As I understand it, right now the most common terminals are the legacy There are the options added to disable colorization, but for a Windows user running the default shell, it puts an extra burden on them to have to set the environment variable or add the argument to disable it. I think it would be good to add some detection and automatically disable colorization if we can tell we are running somewhere that doesn't support it. Here is one way I've accomplished this in another project: if runtime.GOOS == "windows" {
// The newer Windows Terminal supports color, cmd and powershell do
// not. Currently the only way to tell if you are running in WinTerm is
// by the presence of a "WT_SESSION" environment variable.
result = os.Getenv("WT_SESSION") != ""
} There may be a better way to determine that, but of course the Windows terminals don't support the same variables and methods that Linux and macOS terminals do. |
@stmcginnis, note that Cygwin, MSYS2, Git for Windows, etc. are available on Windows. Those support ANSI colours. |
Yep, I agree. Based on that, and the complexity of correctly detecting terminal capabilities, and the fact that this impacts all users of Cobra (a lot!) then I am -1 on this proposal. I don't think cobra should be handling color formatting and it should be left to another library to handle it. |
While I agree, I believe it would be interesting to provide a code example about how to achieve it. Maybe cobra can provide some hooks (an API) for users to plug their own (or third-party) colouring package. |
@stmcginnis considering what you said, if we relied on https://github.com/fatih/color in |
This PR is being marked as stale due to a long period of inactivity |
ColoredCobra: https://github.com/ivanpirog/coloredcobra ColoredCobra is a small library that allows you to colorize the text output of the Cobra library, making the console output look better. |
Hello
This PR adds an easy way to add colors to commands when they show up in the terminal.
I personally would use this because amongst my commands, some are more important and having a color code would be helpful and seemed easier / less confusing than generating "categories" or groups in the template.