summaryrefslogtreecommitdiff
path: root/internal/render/icons.go
blob: 59ae3d3656531c35add93e22637e44d8361c1a63 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package render

// Weather glyphs per icon set, keyed by WMO code group.
//
// The "nerd" codepoints are from the Nerd Fonts Weather range (U+E300-U+E3E3),
// which JetBrains Mono Nerd Font and MesloLGS NF both carry. They are single
// cell and monochrome, so they take the terminal's foreground colour and do not
// break a remapped palette.
//
// The "emoji" set is colour and comes from a fallback font. Its glyphs are not
// all one cell wide -- see width.go -- which is why every pad goes through
// DisplayWidth.
var iconSets = map[string]map[string]string{
	"nerd": {
		"clear":   "",
		"partly":  "",
		"cloudy":  "",
		"fog":     "",
		"drizzle": "",
		"rain":    "",
		"snow":    "",
		"storm":   "",
	},
	"emoji": {
		"clear":   "☀",
		"partly":  "⛅",
		"cloudy":  "☁",
		"fog":     "\U0001F32B",
		"drizzle": "\U0001F326",
		"rain":    "\U0001F327",
		"snow":    "\U0001F328",
		"storm":   "⛈",
	},
}

// iconGroup maps a WMO weather code onto a glyph group.
func iconGroup(code int) string {
	switch {
	case code == 0 || code == 1:
		return "clear"
	case code == 2:
		return "partly"
	case code == 3:
		return "cloudy"
	case code == 45 || code == 48:
		return "fog"
	case code >= 51 && code <= 57:
		return "drizzle"
	case code >= 61 && code <= 67, code >= 80 && code <= 82:
		return "rain"
	case code >= 71 && code <= 77, code == 85 || code == 86:
		return "snow"
	case code >= 95:
		return "storm"
	}
	return "cloudy"
}

// Icon returns the glyph for a weather code in the named set. An unknown set,
// or "none", yields an empty string so the column simply renders blank.
func Icon(set string, code int) string {
	glyphs, ok := iconSets[set]
	if !ok {
		return ""
	}
	return glyphs[iconGroup(code)]
}

// IconWidth is the display width the icon column should reserve for a set.
// The emoji set contains wide glyphs, so its column is two cells even for the
// entries that happen to be one.
func IconWidth(set string) int {
	glyphs, ok := iconSets[set]
	if !ok {
		return 0
	}
	w := 1
	for _, g := range glyphs {
		if gw := DisplayWidth(g); gw > w {
			w = gw
		}
	}
	return w
}