Initial waybar plugin framework for go

Signed-off-by: Jim Ramsay <i.am@jimramsay.com>
This commit is contained in:
Jim Ramsay 2022-07-29 23:41:51 -04:00
parent 1abd54534b
commit d76d56b393
7 changed files with 217 additions and 1 deletions

View file

@ -1,2 +1,44 @@
# gowaybarplug
Go framework for
Go framework for custom [Waybar](https://github.com/Alexays/Waybar) plugins
# Usage
First build a plugin that reports some interesting status:
```go
package main
import (
"time"
waybar "github.com/lack/gowaybarplug"
)
main() {
updater := waybar.NewUpdater()
for {
status := waybar.Status{
Text: "Some text",
Toolbar: "Other text",
}
// Obviously do something more interesting than just static text in the status...
updater.Status <- &status
time.Sleep(15 * time.Second)
}
}
```
Then add it to your ~/.config/waybar/config:
```json
{
// ... Other waybar config
"custom/mything": {
"format": "{} {icon}",
"return-type": "json",
"exec": "/path/to/my/new/plugin"
// etc
}
}
```

12
go.mod Normal file
View file

@ -0,0 +1,12 @@
module github.com/lack/gowaybarplug
go 1.18
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.4.0 // indirect
github.com/stretchr/testify v1.8.0 // indirect
github.com/xorcare/pointer v1.1.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

17
go.sum Normal file
View file

@ -0,0 +1,17 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/xorcare/pointer v1.1.0 h1:sFwXOhRF8QZ0tyVZrtxWGIoVZNEmRzBCaFWdONPQIUM=
github.com/xorcare/pointer v1.1.0/go.mod h1:6KLhkOh6YbuvZkT4YbxIbR/wzLBjyMxOiNzZhJTor2Y=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

31
status.go Normal file
View file

@ -0,0 +1,31 @@
package gowaybarplug
import (
"encoding/json"
"fmt"
)
// Status represents the json structure expected from waybar custom plugins.
// See waybar-custom(5) for more details.
type Status struct {
// Text is usually the label, represented by {} in a waybar format
Text string `json:"text"`
// Tooltip appears when you mouse-hover over the custom entry
Tooltip string `json:"tooltip,omitempty"`
// Class is a list of css classes that will be added to the waybat entry
Class []string `json:"class,omitempty"`
// Percentage can be added to format strings via the {percent} format string, but can also affect which icon is set in {icon} if the config specifies format-icons as an array.
Percentage *int `json:"percentage,omitempty"`
// Alt os the key used to look up the {icon} of format-icons is specified as a map.
Alt string `json:"alt,omitempty"`
}
// String renders the Status as a json string
func (s *Status) String() string {
b, err := json.Marshal(s)
if err != nil {
// Fake json error reporting
return fmt.Sprintf(`"text": "Marshal error", "tooltip": "Marshal error: %s"}`, err.Error())
}
return string(b)
}

30
status_test.go Normal file
View file

@ -0,0 +1,30 @@
package gowaybarplug
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/xorcare/pointer"
)
func TestString(t *testing.T) {
tests := []struct {
input Status
output string
}{{
input: Status{},
output: `{"text":""}`,
}, {
input: Status{
Text: "a",
Tooltip: "b",
Class: []string{"c1", "c2"},
Percentage: pointer.Int(42),
Alt: "d",
},
output: `{"text":"a","tooltip":"b","class":["c1","c2"],"percentage":42,"alt":"d"}`,
}}
for _, test := range tests {
assert.Equal(t, test.input.String(), test.output)
}
}

41
updater.go Normal file
View file

@ -0,0 +1,41 @@
package gowaybarplug
import (
"fmt"
"io"
"os"
)
// Updater runs a goroutine that accepts Status updates in a channel and ptints them to stdout.
type Updater struct {
// Status is the main Status reporting channel. Every Status submitted here will be sent to stdout.
Status chan *Status
last string
writer io.Writer
}
// Create a new Updater and start the receiver thread
func NewUpdater() *Updater {
u := Updater{
Status: make(chan *Status, 10),
writer: os.Stdout,
}
go u.run()
return &u
}
func (u *Updater) run() {
for s := range u.Status {
next := s.String()
if next != u.last {
u.last = next
fmt.Fprintln(u.writer, next)
}
}
}
func (u *Updater) OutputTo(writer io.Writer) *Updater {
u.writer = writer
return u
}

43
updater_test.go Normal file
View file

@ -0,0 +1,43 @@
package gowaybarplug
import (
"bytes"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
type ChBuf struct {
Ch chan bool
Buff bytes.Buffer
}
func NewChBuf() *ChBuf {
return &ChBuf{
Ch: make(chan bool, 100),
}
}
func (c *ChBuf) Write(data []byte) (int, error) {
n, err := c.Buff.Write(data)
c.Ch <- err == nil
return n, err
}
func (c *ChBuf) WaitForBuffer(deadline time.Duration) {
select {
case <-c.Ch:
case <-time.After(deadline):
}
}
func TestNewUpdater(t *testing.T) {
buff := NewChBuf()
u := NewUpdater().OutputTo(buff)
u.Ch <- &Status{Text: "test"}
buff.WaitForBuffer(2 * time.Second)
result, err := buff.Buff.ReadString('\n')
assert.NoError(t, err)
assert.Equal(t, result, "{\"text\":\"test\"}\n")
}