summaryrefslogtreecommitdiff
path: root/bspc/bspc.go
diff options
context:
space:
mode:
Diffstat (limited to 'bspc/bspc.go')
-rw-r--r--bspc/bspc.go133
1 files changed, 133 insertions, 0 deletions
diff --git a/bspc/bspc.go b/bspc/bspc.go
new file mode 100644
index 0000000..568919e
--- /dev/null
+++ b/bspc/bspc.go
@@ -0,0 +1,133 @@
+package bspc
+
+import (
+ "io"
+ "bufio"
+ "strings"
+ "os/exec"
+ "encoding/json"
+
+ "hhvn.uk/hbspbar/common"
+)
+
+type State struct {
+ Monitors []*Monitor
+}
+
+type Monitor struct {
+ ID int
+ Rectangle *Rect
+ Desktops []*Desktop
+}
+
+type Rect struct {
+ X int
+ Y int
+ Width int
+ Height int
+}
+
+type Desktop struct {
+ Name string
+ Layout string
+}
+
+func LoadState() (*State, error) {
+ cmd := exec.Command("bspc", "wm", "-d")
+
+ out, err := cmd.StdoutPipe()
+ if err != nil {
+ return nil, common.Perror("cmd.StdoutPipe", err)
+ }
+
+ if err = cmd.Start(); err != nil {
+ return nil, common.Perror("cmd.Start", err)
+ }
+
+ data, err := io.ReadAll(out)
+ if err != nil {
+ return nil, common.Perror("io.ReadAll", err)
+ }
+
+ if err = cmd.Wait(); err != nil {
+ return nil, common.Perror("cmd.Wait", err)
+ }
+
+ var state State
+ err = json.Unmarshal(data, &state)
+ if err != nil {
+ return nil, common.Perror("json.Unmarshal", err)
+ }
+
+ return &state, nil
+}
+
+type Subscriber struct {
+ cmd *exec.Cmd
+ pipe io.ReadCloser
+ scanner *bufio.Scanner
+}
+
+func Subscribe() (*Subscriber, error) {
+ cmd := exec.Command("bspc", "subscribe", "all")
+
+ pipe, err := cmd.StdoutPipe()
+ if err != nil {
+ return nil, common.Perror("cmd.StdoutPipe", err)
+ }
+
+ if err = cmd.Start(); err != nil {
+ return nil, common.Perror("cmd.Start", err)
+ }
+
+ var ret Subscriber
+ ret.cmd = cmd
+ ret.pipe = pipe
+ ret.scanner = bufio.NewScanner(ret.pipe)
+
+ return &ret, nil
+}
+
+type Event struct {
+ Name string
+ Tokens []string
+}
+
+func (s *Subscriber) GetLine() (string, error) {
+ if s.scanner.Scan() {
+ return s.scanner.Text(), nil
+ }
+
+ if err := s.scanner.Err(); err != nil {
+ return "", common.Perror("scanner.Err", err)
+ }
+
+ return "", nil
+}
+
+func (s *Subscriber) Get() (*Event, error) {
+ var line string
+ var err error
+ for {
+ line, err = s.GetLine()
+ if line[0] != 'W' { break }
+ }
+
+ if err != nil { return nil, err }
+ if line == "" { return nil, nil }
+
+ name, tokens, found := strings.Cut(line, " ")
+
+ var event Event
+ event.Name = name
+ event.Tokens = strings.Split(tokens, " ")
+
+ // We do not found. Shut up, compiler.
+ found = !found
+
+ return &event, nil
+}
+
+func (s *Subscriber) Close() error {
+ return s.cmd.Wait()
+}