Fix gochecknoglobals findings

This commit is contained in:
Igor Chubin 2022-12-23 20:55:30 +01:00
parent 232637db11
commit 9190897277
6 changed files with 221 additions and 200 deletions

View file

@ -60,35 +60,35 @@ type resp struct {
} `json:"data"` } `json:"data"`
} }
func getDataFromAPI() resp { func (g *global) getDataFromAPI() resp {
var ( var (
ret resp ret resp
params []string params []string
) )
if len(config.APIKey) == 0 { if len(g.config.APIKey) == 0 {
log.Fatal("No API key specified. Setup instructions are in the README.") log.Fatal("No API key specified. Setup instructions are in the README.")
} }
params = append(params, "key="+config.APIKey) params = append(params, "key="+g.config.APIKey)
// non-flag shortcut arguments will overwrite possible flag arguments // non-flag shortcut arguments will overwrite possible flag arguments
for _, arg := range flag.Args() { for _, arg := range flag.Args() {
if v, err := strconv.Atoi(arg); err == nil && len(arg) == 1 { if v, err := strconv.Atoi(arg); err == nil && len(arg) == 1 {
config.Numdays = v g.config.Numdays = v
} else { } else {
config.City = arg g.config.City = arg
} }
} }
if len(config.City) > 0 { if len(g.config.City) > 0 {
params = append(params, "q="+url.QueryEscape(config.City)) params = append(params, "q="+url.QueryEscape(g.config.City))
} }
params = append(params, "format=json", "num_of_days="+strconv.Itoa(config.Numdays), "tp=3") params = append(params, "format=json", "num_of_days="+strconv.Itoa(g.config.Numdays), "tp=3")
if config.Lang != "" { if g.config.Lang != "" {
params = append(params, "lang="+config.Lang) params = append(params, "lang="+g.config.Lang)
} }
if debug { if g.debug {
fmt.Fprintln(os.Stderr, params) fmt.Fprintln(os.Stderr, params)
} }
@ -102,7 +102,7 @@ func getDataFromAPI() resp {
log.Fatal(err) log.Fatal(err)
} }
if debug { if g.debug {
var out bytes.Buffer var out bytes.Buffer
json.Indent(&out, body, "", " ") json.Indent(&out, body, "", " ")
@ -111,12 +111,12 @@ func getDataFromAPI() resp {
fmt.Print("\n\n") fmt.Print("\n\n")
} }
if config.Lang == "" { if g.config.Lang == "" {
if err = json.Unmarshal(body, &ret); err != nil { if err = json.Unmarshal(body, &ret); err != nil {
log.Println(err) log.Println(err)
} }
} else { } else {
if err = unmarshalLang(body, &ret); err != nil { if err = g.unmarshalLang(body, &ret); err != nil {
log.Println(err) log.Println(err)
} }
} }
@ -124,7 +124,7 @@ func getDataFromAPI() resp {
return ret return ret
} }
func unmarshalLang(body []byte, r *resp) error { func (g *global) unmarshalLang(body []byte, r *resp) error {
var rv map[string]interface{} var rv map[string]interface{}
if err := json.Unmarshal(body, &rv); err != nil { if err := json.Unmarshal(body, &rv); err != nil {
return err return err
@ -136,7 +136,7 @@ func unmarshalLang(body []byte, r *resp) error {
if !ok { if !ok {
continue continue
} }
langs, ok := cc["lang_"+config.Lang].([]interface{}) langs, ok := cc["lang_"+g.config.Lang].([]interface{})
if !ok || len(langs) == 0 { if !ok || len(langs) == 0 {
continue continue
} }
@ -159,7 +159,7 @@ func unmarshalLang(body []byte, r *resp) error {
if !ok { if !ok {
continue continue
} }
langs, ok := h["lang_"+config.Lang].([]interface{}) langs, ok := h["lang_"+g.config.Lang].([]interface{})
if !ok || len(langs) == 0 { if !ok || len(langs) == 0 {
continue continue
} }

View file

@ -34,12 +34,12 @@ type Configuration struct {
RightToLeft bool RightToLeft bool
} }
var ( type global struct {
ansiEsc *regexp.Regexp ansiEsc *regexp.Regexp
config Configuration config Configuration
configpath string configpath string
debug bool debug bool
) }
const ( const (
wuri = "http://127.0.0.1:5001/premium/v1/weather.ashx?" wuri = "http://127.0.0.1:5001/premium/v1/weather.ashx?"
@ -47,63 +47,66 @@ const (
slotcount = 4 slotcount = 4
) )
func configload() error { func (g *global) configload() error {
b, err := ioutil.ReadFile(configpath) b, err := ioutil.ReadFile(g.configpath)
if err == nil { if err == nil {
return json.Unmarshal(b, &config) return json.Unmarshal(b, &g.config)
} }
return err return err
} }
func configsave() error { func (g *global) configsave() error {
j, err := json.MarshalIndent(config, "", "\t") j, err := json.MarshalIndent(g.config, "", "\t")
if err == nil { if err == nil {
return ioutil.WriteFile(configpath, j, 0o600) return ioutil.WriteFile(g.configpath, j, 0o600)
} }
return err return err
} }
func init() { func (g *global) init() {
flag.IntVar(&config.Numdays, "days", 3, "Number of days of weather forecast to be displayed") flag.IntVar(&g.config.Numdays, "days", 3, "Number of days of weather forecast to be displayed")
flag.StringVar(&config.Lang, "lang", "en", "Language of the report") flag.StringVar(&g.config.Lang, "lang", "en", "Language of the report")
flag.StringVar(&config.City, "city", "New York", "City to be queried") flag.StringVar(&g.config.City, "city", "New York", "City to be queried")
flag.BoolVar(&debug, "debug", false, "Print out raw json response for debugging purposes") flag.BoolVar(&g.debug, "debug", false, "Print out raw json response for debugging purposes")
flag.BoolVar(&config.Imperial, "imperial", false, "Use imperial units") flag.BoolVar(&g.config.Imperial, "imperial", false, "Use imperial units")
flag.BoolVar(&config.Inverse, "inverse", false, "Use inverted colors") flag.BoolVar(&g.config.Inverse, "inverse", false, "Use inverted colors")
flag.BoolVar(&config.Narrow, "narrow", false, "Narrow output (two columns)") flag.BoolVar(&g.config.Narrow, "narrow", false, "Narrow output (two columns)")
flag.StringVar(&config.LocationName, "location_name", "", "Location name (used in the caption)") flag.StringVar(&g.config.LocationName, "location_name", "", "Location name (used in the caption)")
flag.BoolVar(&config.WindMS, "wind_in_ms", false, "Show wind speed in m/s") flag.BoolVar(&g.config.WindMS, "wind_in_ms", false, "Show wind speed in m/s")
flag.BoolVar(&config.RightToLeft, "right_to_left", false, "Right to left script") flag.BoolVar(&g.config.RightToLeft, "right_to_left", false, "Right to left script")
configpath = os.Getenv("WEGORC") g.configpath = os.Getenv("WEGORC")
if configpath == "" { if g.configpath == "" {
usr, err := user.Current() usr, err := user.Current()
if err != nil { if err != nil {
log.Fatalf("%v\nYou can set the environment variable WEGORC to point to your config file as a workaround.", err) log.Fatalf("%v\nYou can set the environment variable WEGORC to point to your config file as a workaround.", err)
} }
configpath = path.Join(usr.HomeDir, ".wegorc") g.configpath = path.Join(usr.HomeDir, ".wegorc")
} }
config.APIKey = "" g.config.APIKey = ""
config.Imperial = false g.config.Imperial = false
config.Lang = "en" g.config.Lang = "en"
err := configload() err := g.configload()
if _, ok := err.(*os.PathError); ok { if _, ok := err.(*os.PathError); ok {
log.Printf("No config file found. Creating %s ...", configpath) log.Printf("No config file found. Creating %s ...", g.configpath)
if err2 := configsave(); err2 != nil { if err2 := g.configsave(); err2 != nil {
log.Fatal(err2) log.Fatal(err2)
} }
} else if err != nil { } else if err != nil {
log.Fatalf("could not parse %v: %v", configpath, err) log.Fatalf("could not parse %v: %v", g.configpath, err)
} }
ansiEsc = regexp.MustCompile("\033.*?m") g.ansiEsc = regexp.MustCompile("\033.*?m")
} }
func Cmd() { func Cmd() {
g := global{}
g.init()
flag.Parse() flag.Parse()
r := getDataFromAPI() r := g.getDataFromAPI()
if r.Data.Req == nil || len(r.Data.Req) < 1 { if r.Data.Req == nil || len(r.Data.Req) < 1 {
if r.Data.Err != nil && len(r.Data.Err) >= 1 { if r.Data.Err != nil && len(r.Data.Err) >= 1 {
@ -112,16 +115,16 @@ func Cmd() {
log.Fatal("Malformed response.") log.Fatal("Malformed response.")
} }
locationName := r.Data.Req[0].Query locationName := r.Data.Req[0].Query
if config.LocationName != "" { if g.config.LocationName != "" {
locationName = config.LocationName locationName = g.config.LocationName
} }
if config.Lang == "he" || config.Lang == "ar" || config.Lang == "fa" { if g.config.Lang == "he" || g.config.Lang == "ar" || g.config.Lang == "fa" {
config.RightToLeft = true g.config.RightToLeft = true
} }
if caption, ok := localizedCaption[config.Lang]; !ok { if caption, ok := localizedCaption()[g.config.Lang]; !ok {
fmt.Printf("Weather report: %s\n\n", locationName) fmt.Printf("Weather report: %s\n\n", locationName)
} else { } else {
if config.RightToLeft { if g.config.RightToLeft {
caption = locationName + " " + caption caption = locationName + " " + caption
space := strings.Repeat(" ", 125-runewidth.StringWidth(caption)) space := strings.Repeat(" ", 125-runewidth.StringWidth(caption))
fmt.Printf("%s%s\n\n", space, caption) fmt.Printf("%s%s\n\n", space, caption)
@ -134,9 +137,9 @@ func Cmd() {
if r.Data.Cur == nil || len(r.Data.Cur) < 1 { if r.Data.Cur == nil || len(r.Data.Cur) < 1 {
log.Fatal("No weather data available.") log.Fatal("No weather data available.")
} }
out := formatCond(make([]string, 5), r.Data.Cur[0], true) out := g.formatCond(make([]string, 5), r.Data.Cur[0], true)
for _, val := range out { for _, val := range out {
if config.RightToLeft { if g.config.RightToLeft {
fmt.Fprint(stdout, strings.Repeat(" ", 94)) fmt.Fprint(stdout, strings.Repeat(" ", 94))
} else { } else {
fmt.Fprint(stdout, " ") fmt.Fprint(stdout, " ")
@ -144,14 +147,14 @@ func Cmd() {
fmt.Fprintln(stdout, val) fmt.Fprintln(stdout, val)
} }
if config.Numdays == 0 { if g.config.Numdays == 0 {
return return
} }
if r.Data.Weather == nil { if r.Data.Weather == nil {
log.Fatal("No detailed weather forecast available.") log.Fatal("No detailed weather forecast available.")
} }
for _, d := range r.Data.Weather { for _, d := range r.Data.Weather {
for _, val := range printDay(d) { for _, val := range g.printDay(d) {
fmt.Fprintln(stdout, val) fmt.Fprintln(stdout, val)
} }
} }

View file

@ -8,29 +8,31 @@ import (
"github.com/mattn/go-runewidth" "github.com/mattn/go-runewidth"
) )
var windDir = map[string]string{ func windDir() map[string]string {
"N": "\033[1m↓\033[0m", return map[string]string{
"NNE": "\033[1m↓\033[0m", "N": "\033[1m↓\033[0m",
"NE": "\033[1m↙\033[0m", "NNE": "\033[1m↓\033[0m",
"ENE": "\033[1m↙\033[0m", "NE": "\033[1m↙\033[0m",
"E": "\033[1m←\033[0m", "ENE": "\033[1m↙\033[0m",
"ESE": "\033[1m←\033[0m", "E": "\033[1m←\033[0m",
"SE": "\033[1m↖\033[0m", "ESE": "\033[1m←\033[0m",
"SSE": "\033[1m↖\033[0m", "SE": "\033[1m↖\033[0m",
"S": "\033[1m↑\033[0m", "SSE": "\033[1m↖\033[0m",
"SSW": "\033[1m↑\033[0m", "S": "\033[1m↑\033[0m",
"SW": "\033[1m↗\033[0m", "SSW": "\033[1m↑\033[0m",
"WSW": "\033[1m↗\033[0m", "SW": "\033[1m↗\033[0m",
"W": "\033[1m→\033[0m", "WSW": "\033[1m↗\033[0m",
"WNW": "\033[1m→\033[0m", "W": "\033[1m→\033[0m",
"NW": "\033[1m↘\033[0m", "WNW": "\033[1m→\033[0m",
"NNW": "\033[1m↘\033[0m", "NW": "\033[1m↘\033[0m",
"NNW": "\033[1m↘\033[0m",
}
} }
func formatTemp(c cond) string { func (g *global) formatTemp(c cond) string {
color := func(temp int, explicitPlus bool) string { color := func(temp int, explicitPlus bool) string {
var col int var col int
if !config.Inverse { if !g.config.Inverse {
// Extremely cold temperature must be shown with violet // Extremely cold temperature must be shown with violet
// because dark blue is too dark // because dark blue is too dark
col = 165 col = 165
@ -125,7 +127,7 @@ func formatTemp(c cond) string {
} }
} }
} }
if config.Imperial { if g.config.Imperial {
temp = (temp*18 + 320) / 10 temp = (temp*18 + 320) / 10
} }
if explicitPlus { if explicitPlus {
@ -160,23 +162,23 @@ func formatTemp(c cond) string {
explicitPlus2 = false explicitPlus2 = false
} }
return pad( return g.pad(
fmt.Sprintf("%s(%s) °%s", fmt.Sprintf("%s(%s) °%s",
color(t, explicitPlus1), color(t, explicitPlus1),
color(c.FeelsLikeC, explicitPlus2), color(c.FeelsLikeC, explicitPlus2),
unitTemp[config.Imperial]), unitTemp()[g.config.Imperial]),
15) 15)
} }
return pad(fmt.Sprintf("%s °%s", color(c.FeelsLikeC, false), unitTemp[config.Imperial]), 15) return g.pad(fmt.Sprintf("%s °%s", color(c.FeelsLikeC, false), unitTemp()[g.config.Imperial]), 15)
} }
func formatWind(c cond) string { func (g *global) formatWind(c cond) string {
windInRightUnits := func(spd int) int { windInRightUnits := func(spd int) int {
if config.WindMS { if g.config.WindMS {
spd = (spd * 1000) / 3600 spd = (spd * 1000) / 3600
} else { } else {
if config.Imperial { if g.config.Imperial {
spd = (spd * 1000) / 1609 spd = (spd * 1000) / 1609
} }
} }
@ -214,12 +216,12 @@ func formatWind(c cond) string {
return fmt.Sprintf("\033[38;5;%03dm%d\033[0m", col, spd) return fmt.Sprintf("\033[38;5;%03dm%d\033[0m", col, spd)
} }
unitWindString := unitWind(0, config.Lang) unitWindString := unitWind(0, g.config.Lang)
if config.WindMS { if g.config.WindMS {
unitWindString = unitWind(2, config.Lang) unitWindString = unitWind(2, g.config.Lang)
} else { } else {
if config.Imperial { if g.config.Imperial {
unitWindString = unitWind(1, config.Lang) unitWindString = unitWind(1, g.config.Lang)
} }
} }
@ -231,50 +233,50 @@ func formatWind(c cond) string {
cWindGustKmph := color(c.WindGustKmph) cWindGustKmph := color(c.WindGustKmph)
cWindspeedKmph := color(c.WindspeedKmph) cWindspeedKmph := color(c.WindspeedKmph)
if windInRightUnits(c.WindGustKmph) > windInRightUnits(c.WindspeedKmph) { if windInRightUnits(c.WindGustKmph) > windInRightUnits(c.WindspeedKmph) {
return pad( return g.pad(
fmt.Sprintf("%s %s%s%s %s", windDir[c.Winddir16Point], cWindspeedKmph, hyphen, cWindGustKmph, unitWindString), fmt.Sprintf("%s %s%s%s %s", windDir()[c.Winddir16Point], cWindspeedKmph, hyphen, cWindGustKmph, unitWindString),
15) 15)
} }
return pad(fmt.Sprintf("%s %s %s", windDir[c.Winddir16Point], cWindspeedKmph, unitWindString), 15) return g.pad(fmt.Sprintf("%s %s %s", windDir()[c.Winddir16Point], cWindspeedKmph, unitWindString), 15)
} }
func formatVisibility(c cond) string { func (g *global) formatVisibility(c cond) string {
if config.Imperial { if g.config.Imperial {
c.VisibleDistKM = (c.VisibleDistKM * 621) / 1000 c.VisibleDistKM = (c.VisibleDistKM * 621) / 1000
} }
return pad(fmt.Sprintf("%d %s", c.VisibleDistKM, unitVis(config.Imperial, config.Lang)), 15) return g.pad(fmt.Sprintf("%d %s", c.VisibleDistKM, unitVis(g.config.Imperial, g.config.Lang)), 15)
} }
func formatRain(c cond) string { func (g *global) formatRain(c cond) string {
rainUnit := c.PrecipMM rainUnit := c.PrecipMM
if config.Imperial { if g.config.Imperial {
rainUnit = c.PrecipMM * 0.039 rainUnit = c.PrecipMM * 0.039
} }
if c.ChanceOfRain != "" { if c.ChanceOfRain != "" {
return pad(fmt.Sprintf( return g.pad(fmt.Sprintf(
"%.1f %s | %s%%", "%.1f %s | %s%%",
rainUnit, rainUnit,
unitRain(config.Imperial, config.Lang), unitRain(g.config.Imperial, g.config.Lang),
c.ChanceOfRain), 15) c.ChanceOfRain), 15)
} }
return pad(fmt.Sprintf("%.1f %s", rainUnit, unitRain(config.Imperial, config.Lang)), 15) return g.pad(fmt.Sprintf("%.1f %s", rainUnit, unitRain(g.config.Imperial, g.config.Lang)), 15)
} }
func formatCond(cur []string, c cond, current bool) []string { func (g *global) formatCond(cur []string, c cond, current bool) []string {
var ( var (
ret []string ret []string
icon []string icon []string
) )
if i, ok := codes[c.WeatherCode]; !ok { if i, ok := codes()[c.WeatherCode]; !ok {
icon = getIcon("iconUnknown") icon = getIcon("iconUnknown")
} else { } else {
icon = i icon = i
} }
if config.Inverse { if g.config.Inverse {
// inverting colors // inverting colors
for i := range icon { for i := range icon {
icon[i] = strings.Replace(icon[i], "38;5;226", "38;5;94", -1) icon[i] = strings.Replace(icon[i], "38;5;226", "38;5;94", -1)
@ -287,7 +289,7 @@ func formatCond(cur []string, c cond, current bool) []string {
} }
// desc := fmt.Sprintf("%-15.15v", c.WeatherDesc[0].Value) // desc := fmt.Sprintf("%-15.15v", c.WeatherDesc[0].Value)
desc := c.WeatherDesc[0].Value desc := c.WeatherDesc[0].Value
if config.RightToLeft { if g.config.RightToLeft {
for runewidth.StringWidth(desc) < 15 { for runewidth.StringWidth(desc) < 15 {
desc = " " + desc desc = " " + desc
} }
@ -305,7 +307,7 @@ func formatCond(cur []string, c cond, current bool) []string {
} }
} }
if current { if current {
if config.RightToLeft { if g.config.RightToLeft {
desc = c.WeatherDesc[0].Value desc = c.WeatherDesc[0].Value
if runewidth.StringWidth(desc) < 15 { if runewidth.StringWidth(desc) < 15 {
desc = strings.Repeat(" ", 15-runewidth.StringWidth(desc)) + desc desc = strings.Repeat(" ", 15-runewidth.StringWidth(desc)) + desc
@ -314,7 +316,7 @@ func formatCond(cur []string, c cond, current bool) []string {
desc = c.WeatherDesc[0].Value desc = c.WeatherDesc[0].Value
} }
} else { } else {
if config.RightToLeft { if g.config.RightToLeft {
if frstRune, size := utf8.DecodeRuneInString(desc); frstRune != ' ' { if frstRune, size := utf8.DecodeRuneInString(desc); frstRune != ' ' {
desc = "…" + desc[size:] desc = "…" + desc[size:]
for runewidth.StringWidth(desc) < 15 { for runewidth.StringWidth(desc) < 15 {
@ -331,22 +333,22 @@ func formatCond(cur []string, c cond, current bool) []string {
} }
} }
} }
if config.RightToLeft { if g.config.RightToLeft {
ret = append( ret = append(
ret, ret,
fmt.Sprintf("%v %v %v", cur[0], desc, icon[0]), fmt.Sprintf("%v %v %v", cur[0], desc, icon[0]),
fmt.Sprintf("%v %v %v", cur[1], formatTemp(c), icon[1]), fmt.Sprintf("%v %v %v", cur[1], g.formatTemp(c), icon[1]),
fmt.Sprintf("%v %v %v", cur[2], formatWind(c), icon[2]), fmt.Sprintf("%v %v %v", cur[2], g.formatWind(c), icon[2]),
fmt.Sprintf("%v %v %v", cur[3], formatVisibility(c), icon[3]), fmt.Sprintf("%v %v %v", cur[3], g.formatVisibility(c), icon[3]),
fmt.Sprintf("%v %v %v", cur[4], formatRain(c), icon[4])) fmt.Sprintf("%v %v %v", cur[4], g.formatRain(c), icon[4]))
} else { } else {
ret = append( ret = append(
ret, ret,
fmt.Sprintf("%v %v %v", cur[0], icon[0], desc), fmt.Sprintf("%v %v %v", cur[0], icon[0], desc),
fmt.Sprintf("%v %v %v", cur[1], icon[1], formatTemp(c)), fmt.Sprintf("%v %v %v", cur[1], icon[1], g.formatTemp(c)),
fmt.Sprintf("%v %v %v", cur[2], icon[2], formatWind(c)), fmt.Sprintf("%v %v %v", cur[2], icon[2], g.formatWind(c)),
fmt.Sprintf("%v %v %v", cur[3], icon[3], formatVisibility(c)), fmt.Sprintf("%v %v %v", cur[3], icon[3], g.formatVisibility(c)),
fmt.Sprintf("%v %v %v", cur[4], icon[4], formatRain(c))) fmt.Sprintf("%v %v %v", cur[4], icon[4], g.formatRain(c)))
} }
return ret return ret
@ -376,25 +378,25 @@ func reverse(s string) string {
return string(r) return string(r)
} }
func pad(s string, mustLen int) string { func (g *global) pad(s string, mustLen int) string {
var ret string var ret string
ret = s ret = s
realLen := utf8.RuneCountInString(ansiEsc.ReplaceAllLiteralString(s, "")) realLen := utf8.RuneCountInString(g.ansiEsc.ReplaceAllLiteralString(s, ""))
delta := mustLen - realLen delta := mustLen - realLen
if delta > 0 { if delta > 0 {
if config.RightToLeft { if g.config.RightToLeft {
ret = strings.Repeat(" ", delta) + ret + "\033[0m" ret = strings.Repeat(" ", delta) + ret + "\033[0m"
} else { } else {
ret += "\033[0m" + strings.Repeat(" ", delta) ret += "\033[0m" + strings.Repeat(" ", delta)
} }
} else if delta < 0 { } else if delta < 0 {
toks := ansiEsc.Split(s, 2) toks := g.ansiEsc.Split(s, 2)
tokLen := utf8.RuneCountInString(toks[0]) tokLen := utf8.RuneCountInString(toks[0])
esc := ansiEsc.FindString(s) esc := g.ansiEsc.FindString(s)
if tokLen > mustLen { if tokLen > mustLen {
ret = fmt.Sprintf("%.*s\033[0m", mustLen, toks[0]) ret = fmt.Sprintf("%.*s\033[0m", mustLen, toks[0])
} else { } else {
ret = fmt.Sprintf("%s%s%s", toks[0], esc, pad(toks[1], mustLen-tokLen)) ret = fmt.Sprintf("%s%s%s", toks[0], esc, g.pad(toks[1], mustLen-tokLen))
} }
} }

View file

@ -158,53 +158,55 @@ func getIcon(name string) []string {
return icon[name] return icon[name]
} }
var codes = map[int][]string{ func codes() map[int][]string {
113: getIcon("iconSunny"), return map[int][]string{
116: getIcon("iconPartlyCloudy"), 113: getIcon("iconSunny"),
119: getIcon("iconCloudy"), 116: getIcon("iconPartlyCloudy"),
122: getIcon("iconVeryCloudy"), 119: getIcon("iconCloudy"),
143: getIcon("iconFog"), 122: getIcon("iconVeryCloudy"),
176: getIcon("iconLightShowers"), 143: getIcon("iconFog"),
179: getIcon("iconLightSleetShowers"), 176: getIcon("iconLightShowers"),
182: getIcon("iconLightSleet"), 179: getIcon("iconLightSleetShowers"),
185: getIcon("iconLightSleet"), 182: getIcon("iconLightSleet"),
200: getIcon("iconThunderyShowers"), 185: getIcon("iconLightSleet"),
227: getIcon("iconLightSnow"), 200: getIcon("iconThunderyShowers"),
230: getIcon("iconHeavySnow"), 227: getIcon("iconLightSnow"),
248: getIcon("iconFog"), 230: getIcon("iconHeavySnow"),
260: getIcon("iconFog"), 248: getIcon("iconFog"),
263: getIcon("iconLightShowers"), 260: getIcon("iconFog"),
266: getIcon("iconLightRain"), 263: getIcon("iconLightShowers"),
281: getIcon("iconLightSleet"), 266: getIcon("iconLightRain"),
284: getIcon("iconLightSleet"), 281: getIcon("iconLightSleet"),
293: getIcon("iconLightRain"), 284: getIcon("iconLightSleet"),
296: getIcon("iconLightRain"), 293: getIcon("iconLightRain"),
299: getIcon("iconHeavyShowers"), 296: getIcon("iconLightRain"),
302: getIcon("iconHeavyRain"), 299: getIcon("iconHeavyShowers"),
305: getIcon("iconHeavyShowers"), 302: getIcon("iconHeavyRain"),
308: getIcon("iconHeavyRain"), 305: getIcon("iconHeavyShowers"),
311: getIcon("iconLightSleet"), 308: getIcon("iconHeavyRain"),
314: getIcon("iconLightSleet"), 311: getIcon("iconLightSleet"),
317: getIcon("iconLightSleet"), 314: getIcon("iconLightSleet"),
320: getIcon("iconLightSnow"), 317: getIcon("iconLightSleet"),
323: getIcon("iconLightSnowShowers"), 320: getIcon("iconLightSnow"),
326: getIcon("iconLightSnowShowers"), 323: getIcon("iconLightSnowShowers"),
329: getIcon("iconHeavySnow"), 326: getIcon("iconLightSnowShowers"),
332: getIcon("iconHeavySnow"), 329: getIcon("iconHeavySnow"),
335: getIcon("iconHeavySnowShowers"), 332: getIcon("iconHeavySnow"),
338: getIcon("iconHeavySnow"), 335: getIcon("iconHeavySnowShowers"),
350: getIcon("iconLightSleet"), 338: getIcon("iconHeavySnow"),
353: getIcon("iconLightShowers"), 350: getIcon("iconLightSleet"),
356: getIcon("iconHeavyShowers"), 353: getIcon("iconLightShowers"),
359: getIcon("iconHeavyRain"), 356: getIcon("iconHeavyShowers"),
362: getIcon("iconLightSleetShowers"), 359: getIcon("iconHeavyRain"),
365: getIcon("iconLightSleetShowers"), 362: getIcon("iconLightSleetShowers"),
368: getIcon("iconLightSnowShowers"), 365: getIcon("iconLightSleetShowers"),
371: getIcon("iconHeavySnowShowers"), 368: getIcon("iconLightSnowShowers"),
374: getIcon("iconLightSleetShowers"), 371: getIcon("iconHeavySnowShowers"),
377: getIcon("iconLightSleet"), 374: getIcon("iconLightSleetShowers"),
386: getIcon("iconThunderyShowers"), 377: getIcon("iconLightSleet"),
389: getIcon("iconThunderyHeavyRain"), 386: getIcon("iconThunderyShowers"),
392: getIcon("iconThunderySnowShowers"), 389: getIcon("iconThunderyHeavyRain"),
395: getIcon("iconHeavySnowShowers"), 392: getIcon("iconThunderySnowShowers"),
395: getIcon("iconHeavySnowShowers"),
}
} }

View file

@ -1,7 +1,7 @@
package v1 package v1
var ( func locale() map[string]string {
locale = map[string]string{ return map[string]string{
"af": "af_ZA", "af": "af_ZA",
"am": "am_ET", "am": "am_ET",
"ar": "ar_TN", "ar": "ar_TN",
@ -73,8 +73,10 @@ var (
"zh": "zh_CN", "zh": "zh_CN",
"zu": "zu_ZA", "zu": "zu_ZA",
} }
}
localizedCaption = map[string]string{ func localizedCaption() map[string]string {
return map[string]string{
"af": "Weer verslag vir:", "af": "Weer verslag vir:",
"am": "የአየር ሁኔታ ዘገባ ለ ፥", "am": "የአየር ሁኔታ ዘገባ ለ ፥",
"ar": "تقرير حالة ألطقس", "ar": "تقرير حالة ألطقس",
@ -147,9 +149,11 @@ var (
"zh-tw": "天氣預報:", "zh-tw": "天氣預報:",
"mg": "Vinavina toetr'andro hoan'ny:", "mg": "Vinavina toetr'andro hoan'ny:",
} }
}
//nolint:misspell //nolint:misspell
daytimeTranslation = map[string][]string{ func daytimeTranslation() map[string][]string {
return map[string][]string{
"af": {"Oggend", "Middag", "Vroegaand", "Laatnag"}, "af": {"Oggend", "Middag", "Vroegaand", "Laatnag"},
"am": {"ጠዋት", "ከሰዓት በኋላ", "ምሽት", "ሌሊት"}, "am": {"ጠዋት", "ከሰዓት በኋላ", "ምሽት", "ሌሊት"},
"ar": {"ﺎﻠﻠﻴﻟ", "ﺎﻠﻤﺳﺍﺀ", "ﺎﻠﻈﻫﺭ", "ﺎﻠﺼﺑﺎﺣ"}, "ar": {"ﺎﻠﻠﻴﻟ", "ﺎﻠﻤﺳﺍﺀ", "ﺎﻠﻈﻫﺭ", "ﺎﻠﺼﺑﺎﺣ"},
@ -223,13 +227,17 @@ var (
"zu": {"Morning", "Noon", "Evening", "Night"}, "zu": {"Morning", "Noon", "Evening", "Night"},
"mg": {"Maraina", "Tolakandro", "Ariva", "Alina"}, "mg": {"Maraina", "Tolakandro", "Ariva", "Alina"},
} }
}
unitTemp = map[bool]string{ func unitTemp() map[bool]string {
return map[bool]string{
false: "C", false: "C",
true: "F", true: "F",
} }
}
localizedRain = map[string]map[bool]string{ func localizedRain() map[string]map[bool]string {
return map[string]map[bool]string{
"en": { "en": {
false: "mm", false: "mm",
true: "in", true: "in",
@ -247,8 +255,10 @@ var (
true: "in", true: "in",
}, },
} }
}
localizedVis = map[string]map[bool]string{ func localizedVis() map[string]map[bool]string {
return map[string]map[bool]string{
"en": { "en": {
false: "km", false: "km",
true: "mi", true: "mi",
@ -266,8 +276,10 @@ var (
true: "mi", true: "mi",
}, },
} }
}
localizedWind = map[string]map[int]string{ func localizedWind() map[string]map[int]string {
return map[string]map[int]string{
"en": { "en": {
0: "km/h", 0: "km/h",
1: "mph", 1: "mph",
@ -294,30 +306,30 @@ var (
2: "м/c", 2: "м/c",
}, },
} }
) }
func unitWind(unit int, lang string) string { func unitWind(unit int, lang string) string {
translation, ok := localizedWind[lang] translation, ok := localizedWind()[lang]
if !ok { if !ok {
translation = localizedWind["en"] translation = localizedWind()["en"]
} }
return translation[unit] return translation[unit]
} }
func unitVis(unit bool, lang string) string { func unitVis(unit bool, lang string) string {
translation, ok := localizedVis[lang] translation, ok := localizedVis()[lang]
if !ok { if !ok {
translation = localizedVis["en"] translation = localizedVis()["en"]
} }
return translation[unit] return translation[unit]
} }
func unitRain(unit bool, lang string) string { func unitRain(unit bool, lang string) string {
translation, ok := localizedRain[lang] translation, ok := localizedRain()[lang]
if !ok { if !ok {
translation = localizedRain["en"] translation = localizedRain()["en"]
} }
return translation[unit] return translation[unit]

View file

@ -7,9 +7,11 @@ import (
"github.com/klauspost/lctime" "github.com/klauspost/lctime"
) )
var slotTimes = [slotcount]int{9 * 60, 12 * 60, 18 * 60, 22 * 60} func slotTimes() []int {
return []int{9 * 60, 12 * 60, 18 * 60, 22 * 60}
}
func printDay(w weather) []string { func (g *global) printDay(w weather) []string {
var ( var (
ret []string ret []string
dateName string dateName string
@ -27,25 +29,25 @@ func printDay(w weather) []string {
for _, h := range hourly { for _, h := range hourly {
c := int(math.Mod(float64(h.Time), 100)) + 60*(h.Time/100) c := int(math.Mod(float64(h.Time), 100)) + 60*(h.Time/100)
for i, s := range slots { for i, s := range slots {
if math.Abs(float64(c-slotTimes[i])) < math.Abs(float64(s.Time-slotTimes[i])) { if math.Abs(float64(c-slotTimes()[i])) < math.Abs(float64(s.Time-slotTimes()[i])) {
h.Time = c h.Time = c
slots[i] = h slots[i] = h
} }
} }
} }
if config.RightToLeft { if g.config.RightToLeft {
slots[0], slots[3] = slots[3], slots[0] slots[0], slots[3] = slots[3], slots[0]
slots[1], slots[2] = slots[2], slots[1] slots[1], slots[2] = slots[2], slots[1]
} }
for i, s := range slots { for i, s := range slots {
if config.Narrow { if g.config.Narrow {
if i == 0 || i == 2 { if i == 0 || i == 2 {
continue continue
} }
} }
ret = formatCond(ret, s, false) ret = g.formatCond(ret, s, false)
for i := range ret { for i := range ret {
ret[i] = ret[i] + "│" ret[i] = ret[i] + "│"
} }
@ -54,23 +56,23 @@ func printDay(w weather) []string {
d, _ := time.Parse("2006-01-02", w.Date) d, _ := time.Parse("2006-01-02", w.Date)
// dateFmt := "┤ " + d.Format("Mon 02. Jan") + " ├" // dateFmt := "┤ " + d.Format("Mon 02. Jan") + " ├"
if val, ok := locale[config.Lang]; ok { if val, ok := locale()[g.config.Lang]; ok {
lctime.SetLocale(val) lctime.SetLocale(val)
} else { } else {
lctime.SetLocale("en_US") lctime.SetLocale("en_US")
} }
if config.RightToLeft { if g.config.RightToLeft {
dow := lctime.Strftime("%a", d) dow := lctime.Strftime("%a", d)
day := lctime.Strftime("%d", d) day := lctime.Strftime("%d", d)
month := lctime.Strftime("%b", d) month := lctime.Strftime("%b", d)
dateName = reverse(month) + " " + day + " " + reverse(dow) dateName = reverse(month) + " " + day + " " + reverse(dow)
} else { } else {
dateName = lctime.Strftime("%a %d %b", d) dateName = lctime.Strftime("%a %d %b", d)
if config.Lang == "ko" { if g.config.Lang == "ko" {
dateName = lctime.Strftime("%b %d일 %a", d) dateName = lctime.Strftime("%b %d일 %a", d)
} }
if config.Lang == "zh" || config.Lang == "zh-tw" || config.Lang == "zh-cn" { if g.config.Lang == "zh" || g.config.Lang == "zh-tw" || g.config.Lang == "zh-cn" {
dateName = lctime.Strftime("%b%d日%A", d) dateName = lctime.Strftime("%b%d日%A", d)
} }
} }
@ -88,11 +90,11 @@ func printDay(w weather) []string {
dateFmt := "┤" + justifyCenter(dateName, 12) + "├" dateFmt := "┤" + justifyCenter(dateName, 12) + "├"
trans := daytimeTranslation["en"] trans := daytimeTranslation()["en"]
if t, ok := daytimeTranslation[config.Lang]; ok { if t, ok := daytimeTranslation()[g.config.Lang]; ok {
trans = t trans = t
} }
if config.Narrow { if g.config.Narrow {
names := "│ " + justifyCenter(trans[1], 16) + names := "│ " + justifyCenter(trans[1], 16) +
"└──────┬──────┘" + justifyCenter(trans[3], 16) + " │" "└──────┬──────┘" + justifyCenter(trans[3], 16) + " │"
@ -108,7 +110,7 @@ func printDay(w weather) []string {
"└──────────────────────────────┴──────────────────────────────┘") "└──────────────────────────────┴──────────────────────────────┘")
} }
if config.RightToLeft { if g.config.RightToLeft {
names = "│" + justifyCenter(trans[3], 29) + "│ " + justifyCenter(trans[2], 16) + names = "│" + justifyCenter(trans[3], 29) + "│ " + justifyCenter(trans[2], 16) +
"└──────┬──────┘" + justifyCenter(trans[1], 16) + " │" + justifyCenter(trans[0], 29) + "│" "└──────┬──────┘" + justifyCenter(trans[1], 16) + " │" + justifyCenter(trans[0], 29) + "│"
} else { } else {