diff options
Diffstat (limited to 'bspc')
| -rw-r--r-- | bspc/bspc.go | 133 |
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() +} |