feat: Add flag for opening result in web-browser
Signed-off-by: Tim Hårek Andreassen <tim@harek.no>
This commit is contained in:
parent
a638c0b678
commit
10e1c770af
8 changed files with 62 additions and 16 deletions
|
@ -6,4 +6,5 @@ const (
|
||||||
JSON = "json"
|
JSON = "json"
|
||||||
INTERVAL = "interval"
|
INTERVAL = "interval"
|
||||||
UTC = "utc"
|
UTC = "utc"
|
||||||
|
WEB = "web"
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"git.sr.ht/~timharek/yr-go/yr"
|
"git.sr.ht/~timharek/yr-go/yr"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
"github.com/charmbracelet/lipgloss/table"
|
"github.com/charmbracelet/lipgloss/table"
|
||||||
|
"github.com/pkg/browser"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,6 +33,8 @@ func forecast(cmd *cobra.Command, args []string) {
|
||||||
cobra.CheckErr(err)
|
cobra.CheckErr(err)
|
||||||
isUTC, err := cmd.Flags().GetBool(flags.UTC)
|
isUTC, err := cmd.Flags().GetBool(flags.UTC)
|
||||||
cobra.CheckErr(err)
|
cobra.CheckErr(err)
|
||||||
|
isWeb, err := cmd.Flags().GetBool(flags.WEB)
|
||||||
|
cobra.CheckErr(err)
|
||||||
lon, _ := cmd.Flags().GetFloat64(flags.LON)
|
lon, _ := cmd.Flags().GetFloat64(flags.LON)
|
||||||
lat, _ := cmd.Flags().GetFloat64(flags.LAT)
|
lat, _ := cmd.Flags().GetFloat64(flags.LAT)
|
||||||
interval, _ := cmd.Flags().GetInt(flags.INTERVAL)
|
interval, _ := cmd.Flags().GetInt(flags.INTERVAL)
|
||||||
|
@ -43,7 +46,7 @@ func forecast(cmd *cobra.Command, args []string) {
|
||||||
fmt.Fprintln(os.Stderr, "No location or coordinates provided.")
|
fmt.Fprintln(os.Stderr, "No location or coordinates provided.")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
var f []yr.Forecast
|
f := &yr.ForecastResult{}
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
f, err = c.ForecastCoords(&nominatim.Coordinates{Longitude: lon, Latitude: lat}, nil)
|
f, err = c.ForecastCoords(&nominatim.Coordinates{Longitude: lon, Latitude: lat}, nil)
|
||||||
cobra.CheckErr(err)
|
cobra.CheckErr(err)
|
||||||
|
@ -53,8 +56,17 @@ func forecast(cmd *cobra.Command, args []string) {
|
||||||
cobra.CheckErr(err)
|
cobra.CheckErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isWeb {
|
||||||
|
url := fmt.Sprintf("https://www.yr.no/en/forecast/daily-table/%.4f,%.4f", f.Coordinates.Latitude, f.Coordinates.Longitude)
|
||||||
|
err := browser.OpenURL(url)
|
||||||
|
if err != nil {
|
||||||
|
cobra.CheckErr(err)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
if interval > 0 {
|
if interval > 0 {
|
||||||
f = f[:interval]
|
f.Forecast = f.Forecast[:interval]
|
||||||
}
|
}
|
||||||
|
|
||||||
if isJson {
|
if isJson {
|
||||||
|
@ -92,7 +104,7 @@ func forecast(cmd *cobra.Command, args []string) {
|
||||||
}).
|
}).
|
||||||
Headers("time", "temp.", "rain", "wind")
|
Headers("time", "temp.", "rain", "wind")
|
||||||
|
|
||||||
for _, item := range f {
|
for _, item := range f.Forecast {
|
||||||
itemTime := item.Time.Local()
|
itemTime := item.Time.Local()
|
||||||
if isUTC {
|
if isUTC {
|
||||||
itemTime = item.Time
|
itemTime = item.Time
|
||||||
|
|
22
cmd/now.go
22
cmd/now.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"git.sr.ht/~timharek/yr-go/cmd/flags"
|
"git.sr.ht/~timharek/yr-go/cmd/flags"
|
||||||
"git.sr.ht/~timharek/yr-go/internal/nominatim"
|
"git.sr.ht/~timharek/yr-go/internal/nominatim"
|
||||||
"git.sr.ht/~timharek/yr-go/yr"
|
"git.sr.ht/~timharek/yr-go/yr"
|
||||||
|
"github.com/pkg/browser"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,6 +30,8 @@ func now(cmd *cobra.Command, args []string) {
|
||||||
cobra.CheckErr(err)
|
cobra.CheckErr(err)
|
||||||
isUTC, err := cmd.Flags().GetBool(flags.UTC)
|
isUTC, err := cmd.Flags().GetBool(flags.UTC)
|
||||||
cobra.CheckErr(err)
|
cobra.CheckErr(err)
|
||||||
|
isWeb, err := cmd.Flags().GetBool(flags.WEB)
|
||||||
|
cobra.CheckErr(err)
|
||||||
lon, _ := cmd.Flags().GetFloat64(flags.LON)
|
lon, _ := cmd.Flags().GetFloat64(flags.LON)
|
||||||
lat, _ := cmd.Flags().GetFloat64(flags.LAT)
|
lat, _ := cmd.Flags().GetFloat64(flags.LAT)
|
||||||
|
|
||||||
|
@ -39,20 +42,31 @@ func now(cmd *cobra.Command, args []string) {
|
||||||
fmt.Fprintln(os.Stderr, "No location or coordinates provided.")
|
fmt.Fprintln(os.Stderr, "No location or coordinates provided.")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
n := &yr.Forecast{}
|
f := &yr.ForecastResult{}
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
n, err = c.NowCoords(&nominatim.Coordinates{Longitude: lon, Latitude: lat}, nil)
|
f, err = c.NowCoords(&nominatim.Coordinates{Longitude: lon, Latitude: lat}, nil)
|
||||||
cobra.CheckErr(err)
|
cobra.CheckErr(err)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
location := args[0]
|
location := args[0]
|
||||||
n, err = c.Now(location)
|
f, err = c.Now(location)
|
||||||
cobra.CheckErr(err)
|
cobra.CheckErr(err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isWeb {
|
||||||
|
url := fmt.Sprintf("https://www.yr.no/en/forecast/hourly-table/%.4f,%.4f/?i=0", f.Coordinates.Latitude, f.Coordinates.Longitude)
|
||||||
|
err := browser.OpenURL(url)
|
||||||
|
if err != nil {
|
||||||
|
cobra.CheckErr(err)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
n := f.Forecast[0]
|
||||||
|
|
||||||
if isJson {
|
if isJson {
|
||||||
j, err := json.MarshalIndent(n, "", " ")
|
j, err := json.MarshalIndent(f, "", " ")
|
||||||
cobra.CheckErr(err)
|
cobra.CheckErr(err)
|
||||||
fmt.Printf("%s", j)
|
fmt.Printf("%s", j)
|
||||||
return
|
return
|
||||||
|
|
|
@ -23,6 +23,7 @@ func Execute() {
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.PersistentFlags().Bool(flags.JSON, false, "Result in JSON")
|
rootCmd.PersistentFlags().Bool(flags.JSON, false, "Result in JSON")
|
||||||
rootCmd.PersistentFlags().Bool(flags.UTC, false, "Result times in UTC")
|
rootCmd.PersistentFlags().Bool(flags.UTC, false, "Result times in UTC")
|
||||||
|
rootCmd.PersistentFlags().Bool(flags.WEB, false, "Open result in browser")
|
||||||
rootCmd.PersistentFlags().Float64P(flags.LON, "x", 0, "Longitude coordinate")
|
rootCmd.PersistentFlags().Float64P(flags.LON, "x", 0, "Longitude coordinate")
|
||||||
rootCmd.PersistentFlags().Float64P(flags.LAT, "y", 0, "Latitude coordinate")
|
rootCmd.PersistentFlags().Float64P(flags.LAT, "y", 0, "Latitude coordinate")
|
||||||
}
|
}
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -3,13 +3,14 @@ module git.sr.ht/~timharek/yr-go
|
||||||
go 1.23.1
|
go 1.23.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/charmbracelet/lipgloss v0.13.0
|
||||||
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
||||||
github.com/spf13/cobra v1.8.1
|
github.com/spf13/cobra v1.8.1
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/charmbracelet/lipgloss v0.13.0 // indirect
|
|
||||||
github.com/charmbracelet/x/ansi v0.1.4 // indirect
|
github.com/charmbracelet/x/ansi v0.1.4 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
|
3
go.sum
3
go.sum
|
@ -25,6 +25,8 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ
|
||||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||||
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||||
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
@ -41,6 +43,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
|
3
justfile
3
justfile
|
@ -12,3 +12,6 @@ test:
|
||||||
|
|
||||||
tidy:
|
tidy:
|
||||||
go mod tidy
|
go mod tidy
|
||||||
|
|
||||||
|
vet:
|
||||||
|
go vet ./...
|
||||||
|
|
27
yr/yr.go
27
yr/yr.go
|
@ -73,7 +73,12 @@ type Forecast struct {
|
||||||
Wind wind `json:"wind"` // In m/s
|
Wind wind `json:"wind"` // In m/s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Now(q string) (*Forecast, error) {
|
type ForecastResult struct {
|
||||||
|
Coordinates nominatim.Coordinates `json:"coordinates"`
|
||||||
|
Forecast []Forecast `json:"forecast"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Now(q string) (*ForecastResult, error) {
|
||||||
coords, err := c.nom.Lookup(q)
|
coords, err := c.nom.Lookup(q)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -85,18 +90,18 @@ func (c *Client) Now(q string) (*Forecast, error) {
|
||||||
}, &coords.Location)
|
}, &coords.Location)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) NowCoords(coords *nominatim.Coordinates, location *string) (*Forecast, error) {
|
func (c *Client) NowCoords(coords *nominatim.Coordinates, location *string) (*ForecastResult, error) {
|
||||||
forecasts, err := c.ForecastCoords(coords, location)
|
result, err := c.ForecastCoords(coords, location)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
now := forecasts[0]
|
result.Forecast = result.Forecast[0:]
|
||||||
|
|
||||||
return &now, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Forecast(q string) ([]Forecast, error) {
|
func (c *Client) Forecast(q string) (*ForecastResult, error) {
|
||||||
coords, err := c.nom.Lookup(q)
|
coords, err := c.nom.Lookup(q)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -108,7 +113,7 @@ func (c *Client) Forecast(q string) ([]Forecast, error) {
|
||||||
}, &coords.Location)
|
}, &coords.Location)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ForecastCoords(coords *nominatim.Coordinates, location *string) ([]Forecast, error) {
|
func (c *Client) ForecastCoords(coords *nominatim.Coordinates, location *string) (*ForecastResult, error) {
|
||||||
f, err := c.met.Forecast(coords.Latitude, coords.Longitude, nil)
|
f, err := c.met.Forecast(coords.Latitude, coords.Longitude, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -168,7 +173,13 @@ func (c *Client) ForecastCoords(coords *nominatim.Coordinates, location *string)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return forecasts, nil
|
return &ForecastResult{
|
||||||
|
Coordinates: nominatim.Coordinates{
|
||||||
|
Longitude: coords.Longitude,
|
||||||
|
Latitude: coords.Latitude,
|
||||||
|
},
|
||||||
|
Forecast: forecasts,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortTimeSeries(a, b met.Timeseries) int {
|
func sortTimeSeries(a, b met.Timeseries) int {
|
||||||
|
|
Loading…
Reference in a new issue