This commit is contained in:
parent
de99ca3429
commit
b4da3d53fd
5
Makefile
5
Makefile
|
@ -19,9 +19,10 @@ all: bspwm bspc
|
||||||
|
|
||||||
VPATH=src
|
VPATH=src
|
||||||
|
|
||||||
bspwm:
|
bspwm: cmd/bspwm src/**/*
|
||||||
|
go build -o bspwm ./cmd/bspwm
|
||||||
|
|
||||||
bspc: cmd/bspc src
|
bspc: cmd/bspc src/**/*
|
||||||
go build -o bspc ./cmd/bspc
|
go build -o bspc ./cmd/bspc
|
||||||
|
|
||||||
xephyr:
|
xephyr:
|
||||||
|
|
|
@ -10,7 +10,12 @@ import (
|
||||||
func main() {
|
func main() {
|
||||||
s, err := sock.Client("")
|
s, err := sock.Client("")
|
||||||
errExit(err)
|
errExit(err)
|
||||||
resp, err := s.Send(os.Args[1:]...)
|
o := os.Args[1:]
|
||||||
|
if len(o) == 0 {
|
||||||
|
fmt.Println("no arguments given.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := s.Send(o...)
|
||||||
errExit(err)
|
errExit(err)
|
||||||
fmt.Print(resp)
|
fmt.Print(resp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,40 +2,56 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"tuxpa.in/t/wm/src/bsp"
|
||||||
"tuxpa.in/t/wm/src/handler"
|
"tuxpa.in/t/wm/src/handler"
|
||||||
|
"tuxpa.in/t/wm/src/handler/domains"
|
||||||
"tuxpa.in/t/wm/src/sock"
|
"tuxpa.in/t/wm/src/sock"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// create socket
|
||||||
ln, err := sock.Server("./bspwm.sock")
|
ln, err := sock.Server("./bspwm.sock")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
defer ln.Close()
|
defer ln.Close()
|
||||||
log.Printf("starting bspwm")
|
log.Printf("starting bspwm")
|
||||||
|
|
||||||
ctx, stop := signal.NotifyContext(context.Background(),
|
ctx, stop := signal.NotifyContext(context.Background(),
|
||||||
os.Interrupt,
|
os.Interrupt,
|
||||||
syscall.SIGTERM,
|
syscall.SIGTERM,
|
||||||
syscall.SIGQUIT)
|
syscall.SIGQUIT,
|
||||||
|
syscall.SIGINT,
|
||||||
|
)
|
||||||
defer stop()
|
defer stop()
|
||||||
|
// initialize WM state
|
||||||
h := &handler.Handler{}
|
w := bsp.NewWM()
|
||||||
|
// create a wm manager
|
||||||
|
xwm := bsp.NewXWM(w, ln.X11())
|
||||||
|
// install the handler
|
||||||
|
h := &handler.Handler{
|
||||||
|
XWM: xwm,
|
||||||
|
}
|
||||||
|
handler.AddDomain[domains.Todo](h, "node")
|
||||||
|
handler.AddDomain[domains.Todo](h, "desktop")
|
||||||
|
handler.AddDomain[domains.Todo](h, "monitor")
|
||||||
|
handler.AddDomain[domains.Todo](h, "wm")
|
||||||
|
handler.AddDomain[domains.Todo](h, "rule")
|
||||||
|
handler.AddDomain[domains.Todo](h, "config")
|
||||||
|
handler.AddDomain[domains.Todo](h, "subscribe")
|
||||||
|
handler.AddDomain[domains.Todo](h, "quit")
|
||||||
|
handler.AddDomain[domains.Query](h, "query")
|
||||||
|
handler.AddDomain[domains.Echo](h, "echo")
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case m := <-ln.Msg():
|
case m := <-ln.Msg():
|
||||||
log.Printf("got cmd: %s", m.Args())
|
|
||||||
h.Run(m)
|
h.Run(m)
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
fmt.Println()
|
log.Println("bspwm shutting down...")
|
||||||
log.Printf("bspwm shutting down...")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
go.mod
19
go.mod
|
@ -2,19 +2,10 @@ module tuxpa.in/t/wm
|
||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
require github.com/alecthomas/kong v0.7.1
|
replace github.com/jezek/xgb v1.1.0 => ./xgb
|
||||||
|
|
||||||
require github.com/jezek/xgb v1.1.0 // indirect
|
replace github.com/jezek/xgbutil v0.0.0-20230603163917-04188eb39cf0 => ./xgbutil
|
||||||
|
|
||||||
require (
|
require github.com/jezek/xgb v1.1.0
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
require github.com/jezek/xgbutil v0.0.0-20230603163917-04188eb39cf0
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
|
||||||
modernc.org/libc v1.21.2 // indirect
|
|
||||||
modernc.org/mathutil v1.5.0 // indirect
|
|
||||||
modernc.org/memory v1.4.0 // indirect
|
|
||||||
modernc.org/xau v1.0.13 // indirect
|
|
||||||
modernc.org/xcb v1.0.13
|
|
||||||
modernc.org/xdmcp v1.0.14 // indirect
|
|
||||||
)
|
|
||||||
|
|
29
go.sum
29
go.sum
|
@ -1,27 +1,2 @@
|
||||||
github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0=
|
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ=
|
||||||
github.com/alecthomas/kong v0.7.1 h1:azoTh0IOfwlAX3qN9sHWTxACE2oV8Bg2gAwBsMwDQY4=
|
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0=
|
||||||
github.com/alecthomas/kong v0.7.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
|
|
||||||
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
|
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
|
||||||
github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk=
|
|
||||||
github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
|
|
||||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
|
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
modernc.org/libc v1.21.2 h1:V053DgNSpAY+IPrO3XlWqrFKUiQqHyPqG4dsx42Ulck=
|
|
||||||
modernc.org/libc v1.21.2/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
|
|
||||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
|
||||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
|
||||||
modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
|
|
||||||
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
|
||||||
modernc.org/xau v1.0.13 h1:AEYsSsJFSmkfhSwV6/dx6GoHt02BnZLmMcRT1O8EUOo=
|
|
||||||
modernc.org/xau v1.0.13/go.mod h1:5ORRqBKlhiUXwoVdM0+ZPy8plvcq0OPOdEgTWyeokhk=
|
|
||||||
modernc.org/xcb v1.0.13 h1:SIMh1yKsKjkfT/qAxcxSv/W+mRe4RnPzp+XewnD4rS4=
|
|
||||||
modernc.org/xcb v1.0.13/go.mod h1:M5m1dSVaHvBUf5XUg5Y/b1DZdJs6NK7pYLqsQ+d0swU=
|
|
||||||
modernc.org/xdmcp v1.0.14 h1:hRCxbYfl75rvOdCmVCPLBRCedClOPjpHiq+tOBzGS3Q=
|
|
||||||
modernc.org/xdmcp v1.0.14/go.mod h1:TDsH3iMey1HJ3tMCePfTy4dIX6hL/MIVnGREX97nCrE=
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package bsp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/jezek/xgbutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
type XWM struct {
|
||||||
|
w *WM
|
||||||
|
x *xgbutil.XUtil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewXWM(w *WM, x *xgbutil.XUtil) *XWM {
|
||||||
|
xwm := &XWM{
|
||||||
|
w: w,
|
||||||
|
x: x,
|
||||||
|
}
|
||||||
|
return xwm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xwm *XWM) Start(ctx context.Context) error {
|
||||||
|
for {
|
||||||
|
err := xwm.run(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (xwm *XWM) run(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
package bsp
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package bsp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WM struct {
|
||||||
|
Desktops []*Desktop
|
||||||
|
Monitors []*Monitor
|
||||||
|
|
||||||
|
mu sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type Desktop struct {
|
||||||
|
Name string
|
||||||
|
Monitor *Monitor
|
||||||
|
}
|
||||||
|
|
||||||
|
type Monitor struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WM) Mutate(fn func() error) {
|
||||||
|
w.mu.Lock()
|
||||||
|
defer w.mu.Unlock()
|
||||||
|
if fn != nil {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WM) View(fn func() error) {
|
||||||
|
w.mu.RLock()
|
||||||
|
defer w.mu.RUnlock()
|
||||||
|
if fn != nil {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WM) AddDesktop(name string) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWM() *WM {
|
||||||
|
w := &WM{}
|
||||||
|
return w
|
||||||
|
}
|
|
@ -22,7 +22,14 @@ type ErrMissingArguments struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ErrMissingArguments) Error() string {
|
func (m *ErrMissingArguments) Error() string {
|
||||||
return `Missing Arguments`
|
return `Missing arguments`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrNoCommandsGiven struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ErrNoCommandsGiven) Error() string {
|
||||||
|
return `No commands given`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrTODO struct {
|
type ErrTODO struct {
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"tuxpa.in/t/wm/src/bsp"
|
||||||
|
"tuxpa.in/t/wm/src/sock"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Domain interface {
|
||||||
|
DomainRunner
|
||||||
|
DomainState
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainRunner interface {
|
||||||
|
Run(*sock.Msg) ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainState interface {
|
||||||
|
SetXWM(*bsp.XWM)
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package domains
|
||||||
|
|
||||||
|
import "tuxpa.in/t/wm/src/bsp"
|
||||||
|
|
||||||
|
type inject struct {
|
||||||
|
xwm
|
||||||
|
}
|
||||||
|
|
||||||
|
type xwm struct {
|
||||||
|
XWM *bsp.XWM
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x xwm) SetXWM(z *bsp.XWM) {
|
||||||
|
x.XWM = z
|
||||||
|
}
|
|
@ -8,9 +8,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Echo struct {
|
type Echo struct {
|
||||||
|
inject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Echo) Run(msg *sock.Msg) ([]byte, error) {
|
func (n Echo) Run(msg *sock.Msg) ([]byte, error) {
|
||||||
if !msg.HasNext() {
|
if !msg.HasNext() {
|
||||||
return nil, &copies.ErrMissingArguments{}
|
return nil, &copies.ErrMissingArguments{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,10 @@ package domains
|
||||||
import "tuxpa.in/t/wm/src/copies"
|
import "tuxpa.in/t/wm/src/copies"
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
|
inject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) Run(args ...string) error {
|
func (n Node) Run(args ...string) error {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return &copies.ErrMissingArguments{}
|
return &copies.ErrMissingArguments{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,78 @@
|
||||||
package domains
|
package domains
|
||||||
|
|
||||||
import "tuxpa.in/t/wm/src/copies"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"tuxpa.in/t/wm/src/copies"
|
||||||
|
"tuxpa.in/t/wm/src/sock"
|
||||||
|
)
|
||||||
|
|
||||||
type Query struct {
|
type Query struct {
|
||||||
|
Command string
|
||||||
|
|
||||||
|
UseNames bool
|
||||||
|
|
||||||
|
inject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Query) Run(args ...string) error {
|
func (n Query) Run(msg *sock.Msg) ([]byte, error) {
|
||||||
if len(args) == 0 {
|
if !msg.HasNext() {
|
||||||
return &copies.ErrMissingArguments{}
|
return nil, &copies.ErrMissingArguments{}
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
ok, err := n.parse(msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch n.Command {
|
||||||
|
case "desktops":
|
||||||
|
return n.desktops(msg)
|
||||||
|
default:
|
||||||
|
return nil, &copies.ErrTODO{}
|
||||||
}
|
}
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
func (n *Query) desktops(msg *sock.Msg) ([]byte, error) {
|
||||||
|
o := new(bytes.Buffer)
|
||||||
|
o.WriteString("hi there")
|
||||||
|
return o.Bytes(), nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Query) parse(msg *sock.Msg) (bool, error) {
|
||||||
|
if !msg.HasNext() {
|
||||||
|
return false, &copies.ErrMissingArguments{}
|
||||||
|
}
|
||||||
|
arg := msg.Next()
|
||||||
|
switch arg {
|
||||||
|
case "--desktop", "-d":
|
||||||
|
case "--desktops", "-D":
|
||||||
|
return n.readCommand(msg, "desktops")
|
||||||
|
case "--monitor", "-m":
|
||||||
|
case "--monitors", "-M":
|
||||||
|
return n.readCommand(msg, "monitors")
|
||||||
|
case "--names":
|
||||||
|
n.UseNames = true
|
||||||
|
case "--node", "-n":
|
||||||
|
case "--nodes", "-N":
|
||||||
|
return n.readCommand(msg, "nodes")
|
||||||
|
case "--tree", "-T":
|
||||||
|
return n.readCommand(msg, "tree")
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf(`unknown option: '%s'`, arg)
|
||||||
|
}
|
||||||
|
return msg.HasNext(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Query) readCommand(msg *sock.Msg, c string) (bool, error) {
|
||||||
|
if n.Command == "" {
|
||||||
|
n.Command = c
|
||||||
|
return msg.HasNext(), nil
|
||||||
|
}
|
||||||
|
return false, fmt.Errorf("multiple commands given")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package domains
|
||||||
|
|
||||||
|
import (
|
||||||
|
"tuxpa.in/t/wm/src/copies"
|
||||||
|
"tuxpa.in/t/wm/src/sock"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Todo struct {
|
||||||
|
inject
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n Todo) Run(msg *sock.Msg) ([]byte, error) {
|
||||||
|
return nil, &copies.ErrTODO{}
|
||||||
|
}
|
|
@ -3,12 +3,29 @@ package handler
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"tuxpa.in/t/wm/src/bsp"
|
||||||
"tuxpa.in/t/wm/src/copies"
|
"tuxpa.in/t/wm/src/copies"
|
||||||
"tuxpa.in/t/wm/src/handler/domains"
|
|
||||||
"tuxpa.in/t/wm/src/sock"
|
"tuxpa.in/t/wm/src/sock"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
|
XWM *bsp.XWM
|
||||||
|
|
||||||
|
domains map[string]func() Domain
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddDomain[T any, PT interface {
|
||||||
|
Domain
|
||||||
|
*T
|
||||||
|
}](h *Handler, name string) {
|
||||||
|
if h.domains == nil {
|
||||||
|
h.domains = map[string]func() Domain{}
|
||||||
|
}
|
||||||
|
h.domains[name] = func() Domain {
|
||||||
|
domain := PT(new(T))
|
||||||
|
domain.SetXWM(h.XWM)
|
||||||
|
return domain
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) Run(msg *sock.Msg) {
|
func (h *Handler) Run(msg *sock.Msg) {
|
||||||
|
@ -28,26 +45,15 @@ func (h *Handler) run(msg *sock.Msg) ([]byte, error) {
|
||||||
return nil, &copies.ErrMissingArguments{}
|
return nil, &copies.ErrMissingArguments{}
|
||||||
}
|
}
|
||||||
cmd := msg.Next()
|
cmd := msg.Next()
|
||||||
switch cmd {
|
d, ok := h.domains[cmd]
|
||||||
case "node",
|
if !ok {
|
||||||
"desktop",
|
|
||||||
"monitor",
|
|
||||||
"query",
|
|
||||||
"wm",
|
|
||||||
"rule",
|
|
||||||
"config",
|
|
||||||
"subscribe",
|
|
||||||
"quit":
|
|
||||||
return nil, &copies.ErrTODO{Kind: "domain", Name: cmd}
|
|
||||||
case "echo":
|
|
||||||
return h.runDomain(cmd, msg, (&domains.Echo{}).Run)
|
|
||||||
default:
|
|
||||||
return nil, &copies.ErrUnknownDomainOrCommand{Str: cmd}
|
return nil, &copies.ErrUnknownDomainOrCommand{Str: cmd}
|
||||||
}
|
}
|
||||||
|
return h.runDomain(cmd, msg, d())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) runDomain(name string, msg *sock.Msg, fn func(*sock.Msg) ([]byte, error)) ([]byte, error) {
|
func (h *Handler) runDomain(name string, msg *sock.Msg, d DomainRunner) ([]byte, error) {
|
||||||
str, err := fn(msg)
|
str, err := d.Run(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s: %w", name, err)
|
return nil, fmt.Errorf("%s: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ func (m *Msg) Peek() string {
|
||||||
return m.Get(0)
|
return m.Get(0)
|
||||||
}
|
}
|
||||||
func (m *Msg) Next() string {
|
func (m *Msg) Next() string {
|
||||||
if m.Has(m.cur) {
|
if m.Has(0) {
|
||||||
m.cur = m.cur + 1
|
m.cur = m.cur + 1
|
||||||
return m.args[m.cur-1]
|
return m.args[m.cur-1]
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/jezek/xgb"
|
"github.com/jezek/xgbutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SockListener struct {
|
type SockListener struct {
|
||||||
xgb *xgb.Conn
|
xgb *xgbutil.XUtil
|
||||||
l *net.UnixListener
|
l *net.UnixListener
|
||||||
|
|
||||||
ch chan *Msg
|
ch chan *Msg
|
||||||
|
@ -19,24 +20,32 @@ type SockListener struct {
|
||||||
func (s *SockListener) Msg() <-chan *Msg {
|
func (s *SockListener) Msg() <-chan *Msg {
|
||||||
return s.ch
|
return s.ch
|
||||||
}
|
}
|
||||||
func Server(path string) (*SockListener, error) {
|
func (s *SockListener) X11() *xgbutil.XUtil {
|
||||||
s := &SockListener{}
|
return s.xgb
|
||||||
s.ch = make(chan *Msg, 1)
|
}
|
||||||
xc, err := xgb.NewConnDisplay("")
|
func getUnixAddr(xc *xgbutil.XUtil, path string) *net.UnixAddr {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
s.xgb = xc
|
|
||||||
if path == "" {
|
if path == "" {
|
||||||
path = os.Getenv(SOCKET_ENV_VAR)
|
path = os.Getenv(SOCKET_ENV_VAR)
|
||||||
}
|
}
|
||||||
if path == "" {
|
if path == "" {
|
||||||
path = fmt.Sprintf(SOCKET_PATH_TPL, "", xc.DisplayNumber, xc.DefaultScreen)
|
path = fmt.Sprintf(SOCKET_PATH_TPL, "", xc.Conn().DisplayNumber, xc.Conn().DefaultScreen)
|
||||||
}
|
}
|
||||||
addr, err := net.ResolveUnixAddr("unix", path)
|
addr, err := net.ResolveUnixAddr("unix", path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func Server(path string) (*SockListener, error) {
|
||||||
|
s := &SockListener{}
|
||||||
|
s.ch = make(chan *Msg, 1)
|
||||||
|
xc, err := xgbutil.NewConn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
s.xgb = xc
|
||||||
|
addr := getUnixAddr(xc, path)
|
||||||
conn, err := net.ListenUnix("unix", addr)
|
conn, err := net.ListenUnix("unix", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -59,7 +68,8 @@ func Server(path string) (*SockListener, error) {
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
func (s *SockListener) Close() error {
|
func (s *SockListener) Close() error {
|
||||||
return s.l.Close()
|
err := s.l.Close()
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
func (s *SockListener) acceptConn(c *net.UnixConn) error {
|
func (s *SockListener) acceptConn(c *net.UnixConn) error {
|
||||||
msg := &Msg{}
|
msg := &Msg{}
|
||||||
|
@ -71,7 +81,9 @@ func (s *SockListener) acceptConn(c *net.UnixConn) error {
|
||||||
bts = bts[:n]
|
bts = bts[:n]
|
||||||
splt := bytes.Split(bts, []byte{0})
|
splt := bytes.Split(bts, []byte{0})
|
||||||
for _, v := range splt {
|
for _, v := range splt {
|
||||||
msg.args = append(msg.args, string(v))
|
if len(strings.TrimSpace(string(v))) > 0 {
|
||||||
|
msg.args = append(msg.args, string(v))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
msg.c = c
|
msg.c = c
|
||||||
s.ch <- msg
|
s.ch <- msg
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit a57abb570aeba12f867c58afe22ce49ac5db4872
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 04188eb39cf0fa005f5b3aec48faa82541748b79
|
Loading…
Reference in New Issue