hbspbar

[WIP] bspwm status bar
git clone git://hhvn.uk/hbspbar
git clone https://hhvn.uk/hbspbar
Log | Files | Refs

commit 2e3b351c355bd241de4aa4f2bdafd633ccef6eac
Author: hhvn <dev@hhvn.uk>
Date:   Fri,  4 Aug 2023 23:02:50 +0100

Implement bspc wrappers

Diffstat:
Abspc/bspc.go | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acommon/common.go | 14++++++++++++++
Ago.mod | 8++++++++
Ago.sum | 4++++
Amain.go | 44++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 203 insertions(+), 0 deletions(-)

diff --git a/bspc/bspc.go 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() +} diff --git a/common/common.go b/common/common.go @@ -0,0 +1,14 @@ +package common + +import ( + "os" + "fmt" +) + +func Perror(function string, err error) error { + return fmt.Errorf("%s(): %w", function, err) +} + +func Error(format string, a ... any) (int, error) { + return fmt.Fprintf(os.Stderr, format, a) +} diff --git a/go.mod b/go.mod @@ -0,0 +1,8 @@ +module hhvn.uk/hbspbar + +go 1.20 + +require ( + github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc // indirect + github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 // indirect +) diff --git a/go.sum b/go.sum @@ -0,0 +1,4 @@ +github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc h1:7D+Bh06CRPCJO3gr2F7h1sriovOZ8BMhca2Rg85c2nk= +github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 h1:O/r2Sj+8QcMF7V5IcmiE2sMFV2q3J47BEirxbXJAdzA= +github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k= diff --git a/main.go b/main.go @@ -0,0 +1,44 @@ +package main + +import ( + "fmt" + + "hhvn.uk/hbspbar/common" + "hhvn.uk/hbspbar/bspc" + "hhvn.uk/hbspbar/bar" + + /* + "github.com/BurntSushi/xgb" + "github.com/BurntSushi/xgb/xproto" + */ +) + +func main() { + state, err := bspc.LoadState() + if (err != nil) { + common.Error("Couldn't load bspwm state: %s", err) + return + } + + events, err := bspc.Subscribe() + if (err != nil) { + common.Error("Couldn't subscribe to bspwm: %s", err) + return + } + defer events.Close() + + fmt.Println(state.Monitors[0].ID) + + for { + event, err := events.Get() + + if err != nil { + common.Error("Couldn't read event: %s", err) + return + } + + if event != nil { + fmt.Printf("Event: %v %v\n", event.Name, event.Tokens) + } + } +}