-
-
Notifications
You must be signed in to change notification settings - Fork 7
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
Prompt for country on first run and save to config file #30
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,25 @@ | ||
package cmd | ||
|
||
import ( | ||
"bufio" | ||
"encoding/json" | ||
"fmt" | ||
"io/fs" | ||
"log" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/Xuanwo/go-locale" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
|
||
"github.com/thegreenwebfoundation/grid-intensity-go/ember" | ||
) | ||
|
||
const ( | ||
countryCode = "country-code" | ||
configFileLocation = ".config/grid-intensity/config.yaml" | ||
countryCode = "country-code" | ||
) | ||
|
||
// rootCmd represents the base command when called without any subcommands | ||
|
@@ -29,12 +35,7 @@ grid is greener or at locations where carbon intensity is lower. | |
grid-intensity -c BOL`, | ||
|
||
Run: func(cmd *cobra.Command, args []string) { | ||
country, err := cmd.Flags().GetString(countryCode) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
err = getGridIntensityForCountry(country) | ||
err := runWithError() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
@@ -50,30 +51,92 @@ func Execute() { | |
|
||
func init() { | ||
rootCmd.Flags().StringP(countryCode, "c", "", "Country code in ISO 3 character format") | ||
viper.BindPFlag(countryCode, rootCmd.Flags().Lookup(countryCode)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is how we add viper for managing the config by binding it to the cobra CLI flag. |
||
} | ||
|
||
func getGridIntensityForCountry(countryCode string) error { | ||
if countryCode == "" { | ||
// No country code provided so try to detect it from the user's locale. | ||
tag, err := locale.Detect() | ||
result, err := ember.GetGridIntensityForCountry(countryCode) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry the diff is a bit hard to follow here. All the logic for getting the country code is moved to the getCountryCode func. |
||
if err != nil { | ||
return err | ||
} | ||
|
||
bytes, err := json.MarshalIndent(result, "", "\t") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Println(string(bytes)) | ||
return nil | ||
} | ||
|
||
// getCountryCode prompts the user to enter a country code. We try to detect | ||
// a country code from the user's locale but the user can enter another value. | ||
func getCountryCode() (string, error) { | ||
tag, err := locale.Detect() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
region, _ := tag.Region() | ||
country := region.ISO3() | ||
|
||
fmt.Printf("Provider %s needs an ISO country code as a region parameter.\n", ember.Provider) | ||
if country != "" { | ||
fmt.Printf("%s detected from your locale.\n", country) | ||
} | ||
|
||
var reader = bufio.NewReader(os.Stdin) | ||
country, err = reader.ReadString('\n') | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return strings.TrimSpace(country), nil | ||
} | ||
|
||
func runWithError() error { | ||
homeDir, err := os.UserHomeDir() | ||
if err != nil { | ||
return nil | ||
} | ||
|
||
configFile := filepath.Join(homeDir, configFileLocation) | ||
viper.SetConfigFile(configFile) | ||
|
||
err = viper.ReadInConfig() | ||
if _, ok := err.(*fs.PathError); ok { | ||
// Create config file if it doesn't exist. | ||
_, err = os.Create(configFile) | ||
if err != nil { | ||
return err | ||
} | ||
} else if err != nil { | ||
return err | ||
} | ||
|
||
region, _ := tag.Region() | ||
countryCode = region.ISO3() | ||
country := viper.GetString(countryCode) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
result, err := ember.GetGridIntensityForCountry(countryCode) | ||
if country == "" { | ||
country, err = getCountryCode() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
viper.Set(countryCode, country) | ||
} | ||
|
||
err = getGridIntensityForCountry(country) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think it's worth making explicit that the country code is being used to make the request/lookup against our set of country / carbon intensity codes? I know the returned JSON blob mentions that the country and country code, but for the first time, when I looked over it, I felt like having a short one line outlining what was about to happen before showing the returned value would make it easier to understand what was happening. This probably isn't needed on subsequent uses, but I think it provides a more gentle way into this domain. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I agree I think we should explain more what is going on. I've been thinking we could add an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes. would you mind creating an issue for this? I think this would be a good one to include Fershad for this, so he can create some tutorials and add some reference to it in the developers.tgwf site There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mrchrisadams I created #32 for this. I agree it would be good to work with Fershad on this and to have some tutorials. |
||
if err != nil { | ||
return err | ||
} | ||
|
||
bytes, err := json.MarshalIndent(result, "", "\t") | ||
err = viper.WriteConfig() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Println(string(bytes)) | ||
return nil | ||
} |
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 extracted the logic to this function which simplifies the error handling. So we only need a single log.Fatal call.