-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.go
135 lines (112 loc) · 2.47 KB
/
main.go
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
import (
"context"
"fmt"
"net/http"
"os"
"strings"
"github.com/charmbracelet/bubbles/spinner"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/nicolasparada/go-tea-weather/metaweather"
)
func main() {
t := textinput.NewModel()
t.Focus()
s := spinner.NewModel()
s.Spinner = spinner.Dot
initialModel := Model{
textInput: t,
spinner: s,
typing: true,
metaWeather: &metaweather.Client{HTTPClient: http.DefaultClient},
}
err := tea.NewProgram(initialModel, tea.WithAltScreen()).Start()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
type Model struct {
textInput textinput.Model
spinner spinner.Model
metaWeather *metaweather.Client
typing bool
loading bool
err error
location metaweather.Location
}
type GotWeather struct {
Err error
Location metaweather.Location
}
func (m Model) fetchWeather(query string) tea.Cmd {
return func() tea.Msg {
loc, err := m.metaWeather.LocationByQuery(context.Background(), query)
if err != nil {
return GotWeather{Err: err}
}
return GotWeather{Location: loc}
}
}
func (m Model) Init() tea.Cmd {
return textinput.Blink
}
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c":
return m, tea.Quit
case "enter":
if m.typing {
query := strings.TrimSpace(m.textInput.Value())
if query != "" {
m.typing = false
m.loading = true
return m, tea.Batch(
spinner.Tick,
m.fetchWeather(query),
)
}
}
case "esc":
if !m.typing && !m.loading {
m.typing = true
m.err = nil
return m, nil
}
}
case GotWeather:
m.loading = false
if err := msg.Err; err != nil {
m.err = err
return m, nil
}
m.location = msg.Location
return m, nil
}
if m.typing {
var cmd tea.Cmd
m.textInput, cmd = m.textInput.Update(msg)
return m, cmd
}
if m.loading {
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
return m, cmd
}
return m, nil
}
func (m Model) View() string {
if m.typing {
return fmt.Sprintf("Enter location:\n%s", m.textInput.View())
}
if m.loading {
return fmt.Sprintf("%s fetching weather... please wait.", m.spinner.View())
}
if err := m.err; err != nil {
return fmt.Sprintf("Could not fetch weather: %v", err)
}
return fmt.Sprintf("Current weather in %s is %.0f °C", m.location.Title, m.location.ConsolidatedWeather[0].TheTemp)
}