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() }