feat(cli): add -display and NEFERBAR_DISPLAY to pick the Wayland socket, and clear connect errors
- commit
- c4a6bed4cdeebf100b3d848aec8a90d941547e2a
- author
- brice · · 2026-10-05 14:15 UTC
- parent
- ec57f2f
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
4 files · +55 -19
M README.md +3 -1
| @@ -15,7 +15,9 @@ go build -o neferbar ./cmd/neferbar | |||
| 15 | 15 | ./neferbar -config examples/config.toml | |
| 16 | 16 | ``` | |
| 17 | 17 | ||
| 18 | - | Flags: `-config <file>`, `-pprof <loopback addr>`, `-memstats <interval>`. | |
| 18 | + | Flags: `-config <file>`, `-display <socket>`, `-pprof <loopback addr>`, `-memstats <interval>`. | |
| 19 | + | ||
| 20 | + | The Wayland socket comes from `-display`, then `$NEFERBAR_DISPLAY`, then `$WAYLAND_DISPLAY`, then `wayland-0`. A relative name lives in `$XDG_RUNTIME_DIR`; an absolute path is used as is. | |
| 19 | 21 | ||
| 20 | 22 | ## Configuration | |
| 21 | 23 | ||
| @@ -15,7 +15,9 @@ go build -o neferbar ./cmd/neferbar | |||||
| 15 | ./neferbar -config examples/config.toml | 15 | ./neferbar -config examples/config.toml | ||
| 16 | ``` | 16 | ``` | ||
| 17 | 17 | ||||
| 18 | - | Flags: `-config <file>`, `-pprof <loopback addr>`, `-memstats <interval>`. | 18 | + | Flags: `-config <file>`, `-display <socket>`, `-pprof <loopback addr>`, `-memstats <interval>`. |
| 19 | + | ||||
| 20 | + | The Wayland socket comes from `-display`, then `$NEFERBAR_DISPLAY`, then `$WAYLAND_DISPLAY`, then `wayland-0`. A relative name lives in `$XDG_RUNTIME_DIR`; an absolute path is used as is. | |||
| 19 | 21 | ||||
| 20 | ## Configuration | 22 | ## Configuration | ||
| 21 | 23 | ||||
M cmd/neferbar/main.go +6 -8
| @@ -21,6 +21,7 @@ import ( | |||
| 21 | 21 | ||
| 22 | 22 | func main() { | |
| 23 | 23 | cfgPath := flag.String("config", "", "config file (default: $XDG_CONFIG_HOME/neferbar/config.toml)") | |
| 24 | + | display := flag.String("display", os.Getenv("NEFERBAR_DISPLAY"), "Wayland socket name or absolute path (default: $NEFERBAR_DISPLAY, then $WAYLAND_DISPLAY)") | |
| 24 | 25 | pprofAddr := flag.String("pprof", "", "serve pprof on this loopback address, e.g. localhost:6060") | |
| 25 | 26 | memStats := flag.Duration("memstats", 0, "log allocation counters at this interval (0: off)") | |
| 26 | 27 | flag.Parse() | |
| @@ -28,13 +29,13 @@ func main() { | |||
| 28 | 29 | log := slog.New(slog.NewTextHandler(os.Stderr, nil)) | |
| 29 | 30 | ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) | |
| 30 | 31 | defer stop() | |
| 31 | - | if err := run(ctx, log, *cfgPath, *pprofAddr, *memStats); err != nil { | |
| 32 | - | log.Error("neferbar", "err", err) | |
| 32 | + | if err := run(ctx, log, *cfgPath, *display, *pprofAddr, *memStats); err != nil { | |
| 33 | + | fmt.Fprintf(os.Stderr, "neferbar: %v\n", err) | |
| 33 | 34 | os.Exit(1) | |
| 34 | 35 | } | |
| 35 | 36 | } | |
| 36 | 37 | ||
| 37 | - | func run(ctx context.Context, log *slog.Logger, cfgPath, pprofAddr string, memStats time.Duration) error { | |
| 38 | + | func run(ctx context.Context, log *slog.Logger, cfgPath, display, pprofAddr string, memStats time.Duration) error { | |
| 38 | 39 | explicit := cfgPath != "" | |
| 39 | 40 | if !explicit { | |
| 40 | 41 | cfgPath = config.DefaultPath() | |
| @@ -48,17 +49,14 @@ func run(ctx context.Context, log *slog.Logger, cfgPath, pprofAddr string, memSt | |||
| 48 | 49 | return err | |
| 49 | 50 | } | |
| 50 | 51 | } | |
| 51 | - | b, err := bar.New(cfg, log) | |
| 52 | + | b, err := bar.New(cfg, log, display) | |
| 52 | 53 | if err != nil { | |
| 53 | 54 | return err | |
| 54 | 55 | } | |
| 55 | 56 | if memStats > 0 { | |
| 56 | 57 | go logMemStats(ctx, log, memStats) | |
| 57 | 58 | } | |
| 58 | - | err = b.Run(ctx) | |
| 59 | - | log.Info("stats", "presented", b.Stats.Presented, "rebuilds", b.Stats.Rebuilds, | |
| 60 | - | "recreated", b.Stats.Recreated, "no_slot", b.Stats.NoSlot, "dirty", b.Stats.Dirty, "module_wakes", b.Stats.ModuleWake) | |
| 61 | - | return err | |
| 59 | + | return b.Run(ctx) | |
| 62 | 60 | } | |
| 63 | 61 | ||
| 64 | 62 | // servePprof serves the pprof handlers on a loopback address only. | |
| @@ -21,6 +21,7 @@ import ( | |||||
| 21 | 21 | ||||
| 22 | func main() { | 22 | func main() { | ||
| 23 | cfgPath := flag.String("config", "", "config file (default: $XDG_CONFIG_HOME/neferbar/config.toml)") | 23 | cfgPath := flag.String("config", "", "config file (default: $XDG_CONFIG_HOME/neferbar/config.toml)") | ||
| 24 | + | display := flag.String("display", os.Getenv("NEFERBAR_DISPLAY"), "Wayland socket name or absolute path (default: $NEFERBAR_DISPLAY, then $WAYLAND_DISPLAY)") | |||
| 24 | pprofAddr := flag.String("pprof", "", "serve pprof on this loopback address, e.g. localhost:6060") | 25 | pprofAddr := flag.String("pprof", "", "serve pprof on this loopback address, e.g. localhost:6060") | ||
| 25 | memStats := flag.Duration("memstats", 0, "log allocation counters at this interval (0: off)") | 26 | memStats := flag.Duration("memstats", 0, "log allocation counters at this interval (0: off)") | ||
| 26 | flag.Parse() | 27 | flag.Parse() | ||
| @@ -28,13 +29,13 @@ func main() { | |||||
| 28 | log := slog.New(slog.NewTextHandler(os.Stderr, nil)) | 29 | log := slog.New(slog.NewTextHandler(os.Stderr, nil)) | ||
| 29 | ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) | 30 | ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) | ||
| 30 | defer stop() | 31 | defer stop() | ||
| 31 | - | if err := run(ctx, log, *cfgPath, *pprofAddr, *memStats); err != nil { | 32 | + | if err := run(ctx, log, *cfgPath, *display, *pprofAddr, *memStats); err != nil { |
| 32 | - | log.Error("neferbar", "err", err) | 33 | + | fmt.Fprintf(os.Stderr, "neferbar: %v\n", err) |
| 33 | os.Exit(1) | 34 | os.Exit(1) | ||
| 34 | } | 35 | } | ||
| 35 | } | 36 | } | ||
| 36 | 37 | ||||
| 37 | - | func run(ctx context.Context, log *slog.Logger, cfgPath, pprofAddr string, memStats time.Duration) error { | 38 | + | func run(ctx context.Context, log *slog.Logger, cfgPath, display, pprofAddr string, memStats time.Duration) error { |
| 38 | explicit := cfgPath != "" | 39 | explicit := cfgPath != "" | ||
| 39 | if !explicit { | 40 | if !explicit { | ||
| 40 | cfgPath = config.DefaultPath() | 41 | cfgPath = config.DefaultPath() | ||
| @@ -48,17 +49,14 @@ func run(ctx context.Context, log *slog.Logger, cfgPath, pprofAddr string, memSt | |||||
| 48 | return err | 49 | return err | ||
| 49 | } | 50 | } | ||
| 50 | } | 51 | } | ||
| 51 | - | b, err := bar.New(cfg, log) | 52 | + | b, err := bar.New(cfg, log, display) |
| 52 | if err != nil { | 53 | if err != nil { | ||
| 53 | return err | 54 | return err | ||
| 54 | } | 55 | } | ||
| 55 | if memStats > 0 { | 56 | if memStats > 0 { | ||
| 56 | go logMemStats(ctx, log, memStats) | 57 | go logMemStats(ctx, log, memStats) | ||
| 57 | } | 58 | } | ||
| 58 | - | err = b.Run(ctx) | 59 | + | return b.Run(ctx) |
| 59 | - | log.Info("stats", "presented", b.Stats.Presented, "rebuilds", b.Stats.Rebuilds, | |||
| 60 | - | "recreated", b.Stats.Recreated, "no_slot", b.Stats.NoSlot, "dirty", b.Stats.Dirty, "module_wakes", b.Stats.ModuleWake) | |||
| 61 | - | return err | |||
| 62 | } | 60 | } | ||
| 63 | 61 | ||||
| 64 | // servePprof serves the pprof handlers on a loopback address only. | 62 | // servePprof serves the pprof handlers on a loopback address only. | ||
M internal/bar/bar.go +44 -8
| @@ -13,7 +13,9 @@ import ( | |||
| 13 | 13 | "fmt" | |
| 14 | 14 | "log/slog" | |
| 15 | 15 | "math" | |
| 16 | + | "os" | |
| 16 | 17 | "path/filepath" | |
| 18 | + | "syscall" | |
| 17 | 19 | ||
| 18 | 20 | "github.com/bnema/neferclient" | |
| 19 | 21 | ||
| @@ -40,9 +42,10 @@ type Stats struct { | |||
| 40 | 42 | ||
| 41 | 43 | // Bar is the running application. | |
| 42 | 44 | type Bar struct { | |
| 43 | - | cfg config.Config | |
| 44 | - | log *slog.Logger | |
| 45 | - | fg, bg [3]uint8 | |
| 45 | + | cfg config.Config | |
| 46 | + | log *slog.Logger | |
| 47 | + | display string | |
| 48 | + | fg, bg [3]uint8 | |
| 46 | 49 | ||
| 47 | 50 | conn *neferclient.Conn | |
| 48 | 51 | surf *neferclient.Surface | |
| @@ -76,8 +79,9 @@ type Bar struct { | |||
| 76 | 79 | } | |
| 77 | 80 | ||
| 78 | 81 | // New builds a bar from a validated config. | |
| 79 | - | func New(cfg config.Config, log *slog.Logger) (*Bar, error) { | |
| 80 | - | b := &Bar{cfg: cfg, log: log, modCh: make(chan struct{}, 1)} | |
| 82 | + | // display names the Wayland socket; empty uses $WAYLAND_DISPLAY. | |
| 83 | + | func New(cfg config.Config, log *slog.Logger, display string) (*Bar, error) { | |
| 84 | + | b := &Bar{cfg: cfg, log: log, display: display, modCh: make(chan struct{}, 1)} | |
| 81 | 85 | var err error | |
| 82 | 86 | if b.fg, err = config.ParseColor(cfg.Bar.Foreground); err != nil { | |
| 83 | 87 | return nil, err | |
| @@ -104,11 +108,15 @@ func New(cfg config.Config, log *slog.Logger) (*Bar, error) { | |||
| 104 | 108 | // Run connects to the compositor and serves until ctx ends or the surface is | |
| 105 | 109 | // closed. It returns the first fatal error. | |
| 106 | 110 | func (b *Bar) Run(ctx context.Context) (err error) { | |
| 107 | - | b.conn, err = neferclient.Connect(ctx, "") | |
| 111 | + | b.conn, err = neferclient.Connect(ctx, b.display) | |
| 108 | 112 | if err != nil { | |
| 109 | - | return fmt.Errorf("connect: %w", err) | |
| 113 | + | return connectError(b.display, err) | |
| 110 | 114 | } | |
| 111 | - | defer func() { err = errors.Join(err, b.shutdown()) }() | |
| 115 | + | defer func() { | |
| 116 | + | err = errors.Join(err, b.shutdown()) | |
| 117 | + | b.log.Info("stats", "presented", b.Stats.Presented, "rebuilds", b.Stats.Rebuilds, | |
| 118 | + | "recreated", b.Stats.Recreated, "no_slot", b.Stats.NoSlot, "dirty", b.Stats.Dirty, "module_wakes", b.Stats.ModuleWake) | |
| 119 | + | }() | |
| 112 | 120 | if err = b.createSurface(estimateHeight(b.cfg.Bar.Size * b.cfg.Bar.Scale)); err != nil { | |
| 113 | 121 | return err | |
| 114 | 122 | } | |
| @@ -138,6 +146,34 @@ func (b *Bar) Run(ctx context.Context) (err error) { | |||
| 138 | 146 | return nil | |
| 139 | 147 | } | |
| 140 | 148 | ||
| 149 | + | // socketPath mirrors how neferclient resolves the socket, for error messages. | |
| 150 | + | func socketPath(display string) string { | |
| 151 | + | if display == "" { | |
| 152 | + | display = os.Getenv("WAYLAND_DISPLAY") | |
| 153 | + | } | |
| 154 | + | if display == "" { | |
| 155 | + | display = "wayland-0" | |
| 156 | + | } | |
| 157 | + | if filepath.IsAbs(display) { | |
| 158 | + | return display | |
| 159 | + | } | |
| 160 | + | return filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), display) | |
| 161 | + | } | |
| 162 | + | ||
| 163 | + | // connectError turns a failed dial into one actionable sentence. | |
| 164 | + | func connectError(display string, err error) error { | |
| 165 | + | path := socketPath(display) | |
| 166 | + | switch { | |
| 167 | + | case errors.Is(err, os.ErrNotExist): | |
| 168 | + | return fmt.Errorf("no Wayland socket at %s: is the compositor running? Set WAYLAND_DISPLAY, NEFERBAR_DISPLAY or -display", path) | |
| 169 | + | case errors.Is(err, syscall.ECONNREFUSED): | |
| 170 | + | return fmt.Errorf("the Wayland socket %s exists but refuses connections: stale socket or compositor not ready", path) | |
| 171 | + | case errors.Is(err, os.ErrPermission): | |
| 172 | + | return fmt.Errorf("not allowed to open the Wayland socket %s", path) | |
| 173 | + | } | |
| 174 | + | return err | |
| 175 | + | } | |
| 176 | + | ||
| 141 | 177 | // estimateHeight is the first request, before the real cell height is known. | |
| 142 | 178 | func estimateHeight(px float64) int32 { return int32(math.Ceil(px * 1.5)) } | |
| 143 | 179 | ||
| @@ -13,7 +13,9 @@ import ( | |||||
| 13 | "fmt" | 13 | "fmt" | ||
| 14 | "log/slog" | 14 | "log/slog" | ||
| 15 | "math" | 15 | "math" | ||
| 16 | + | "os" | |||
| 16 | "path/filepath" | 17 | "path/filepath" | ||
| 18 | + | "syscall" | |||
| 17 | 19 | ||||
| 18 | "github.com/bnema/neferclient" | 20 | "github.com/bnema/neferclient" | ||
| 19 | 21 | ||||
| @@ -40,9 +42,10 @@ type Stats struct { | |||||
| 40 | 42 | ||||
| 41 | // Bar is the running application. | 43 | // Bar is the running application. | ||
| 42 | type Bar struct { | 44 | type Bar struct { | ||
| 43 | - | cfg config.Config | 45 | + | cfg config.Config |
| 44 | - | log *slog.Logger | 46 | + | log *slog.Logger |
| 45 | - | fg, bg [3]uint8 | 47 | + | display string |
| 48 | + | fg, bg [3]uint8 | |||
| 46 | 49 | ||||
| 47 | conn *neferclient.Conn | 50 | conn *neferclient.Conn | ||
| 48 | surf *neferclient.Surface | 51 | surf *neferclient.Surface | ||
| @@ -76,8 +79,9 @@ type Bar struct { | |||||
| 76 | } | 79 | } | ||
| 77 | 80 | ||||
| 78 | // New builds a bar from a validated config. | 81 | // New builds a bar from a validated config. | ||
| 79 | - | func New(cfg config.Config, log *slog.Logger) (*Bar, error) { | 82 | + | // display names the Wayland socket; empty uses $WAYLAND_DISPLAY. |
| 80 | - | b := &Bar{cfg: cfg, log: log, modCh: make(chan struct{}, 1)} | 83 | + | func New(cfg config.Config, log *slog.Logger, display string) (*Bar, error) { |
| 84 | + | b := &Bar{cfg: cfg, log: log, display: display, modCh: make(chan struct{}, 1)} | |||
| 81 | var err error | 85 | var err error | ||
| 82 | if b.fg, err = config.ParseColor(cfg.Bar.Foreground); err != nil { | 86 | if b.fg, err = config.ParseColor(cfg.Bar.Foreground); err != nil { | ||
| 83 | return nil, err | 87 | return nil, err | ||
| @@ -104,11 +108,15 @@ func New(cfg config.Config, log *slog.Logger) (*Bar, error) { | |||||
| 104 | // Run connects to the compositor and serves until ctx ends or the surface is | 108 | // Run connects to the compositor and serves until ctx ends or the surface is | ||
| 105 | // closed. It returns the first fatal error. | 109 | // closed. It returns the first fatal error. | ||
| 106 | func (b *Bar) Run(ctx context.Context) (err error) { | 110 | func (b *Bar) Run(ctx context.Context) (err error) { | ||
| 107 | - | b.conn, err = neferclient.Connect(ctx, "") | 111 | + | b.conn, err = neferclient.Connect(ctx, b.display) |
| 108 | if err != nil { | 112 | if err != nil { | ||
| 109 | - | return fmt.Errorf("connect: %w", err) | 113 | + | return connectError(b.display, err) |
| 110 | } | 114 | } | ||
| 111 | - | defer func() { err = errors.Join(err, b.shutdown()) }() | 115 | + | defer func() { |
| 116 | + | err = errors.Join(err, b.shutdown()) | |||
| 117 | + | b.log.Info("stats", "presented", b.Stats.Presented, "rebuilds", b.Stats.Rebuilds, | |||
| 118 | + | "recreated", b.Stats.Recreated, "no_slot", b.Stats.NoSlot, "dirty", b.Stats.Dirty, "module_wakes", b.Stats.ModuleWake) | |||
| 119 | + | }() | |||
| 112 | if err = b.createSurface(estimateHeight(b.cfg.Bar.Size * b.cfg.Bar.Scale)); err != nil { | 120 | if err = b.createSurface(estimateHeight(b.cfg.Bar.Size * b.cfg.Bar.Scale)); err != nil { | ||
| 113 | return err | 121 | return err | ||
| 114 | } | 122 | } | ||
| @@ -138,6 +146,34 @@ func (b *Bar) Run(ctx context.Context) (err error) { | |||||
| 138 | return nil | 146 | return nil | ||
| 139 | } | 147 | } | ||
| 140 | 148 | ||||
| 149 | + | // socketPath mirrors how neferclient resolves the socket, for error messages. | |||
| 150 | + | func socketPath(display string) string { | |||
| 151 | + | if display == "" { | |||
| 152 | + | display = os.Getenv("WAYLAND_DISPLAY") | |||
| 153 | + | } | |||
| 154 | + | if display == "" { | |||
| 155 | + | display = "wayland-0" | |||
| 156 | + | } | |||
| 157 | + | if filepath.IsAbs(display) { | |||
| 158 | + | return display | |||
| 159 | + | } | |||
| 160 | + | return filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), display) | |||
| 161 | + | } | |||
| 162 | + | ||||
| 163 | + | // connectError turns a failed dial into one actionable sentence. | |||
| 164 | + | func connectError(display string, err error) error { | |||
| 165 | + | path := socketPath(display) | |||
| 166 | + | switch { | |||
| 167 | + | case errors.Is(err, os.ErrNotExist): | |||
| 168 | + | return fmt.Errorf("no Wayland socket at %s: is the compositor running? Set WAYLAND_DISPLAY, NEFERBAR_DISPLAY or -display", path) | |||
| 169 | + | case errors.Is(err, syscall.ECONNREFUSED): | |||
| 170 | + | return fmt.Errorf("the Wayland socket %s exists but refuses connections: stale socket or compositor not ready", path) | |||
| 171 | + | case errors.Is(err, os.ErrPermission): | |||
| 172 | + | return fmt.Errorf("not allowed to open the Wayland socket %s", path) | |||
| 173 | + | } | |||
| 174 | + | return err | |||
| 175 | + | } | |||
| 176 | + | ||||
| 141 | // estimateHeight is the first request, before the real cell height is known. | 177 | // estimateHeight is the first request, before the real cell height is known. | ||
| 142 | func estimateHeight(px float64) int32 { return int32(math.Ceil(px * 1.5)) } | 178 | func estimateHeight(px float64) int32 { return int32(math.Ceil(px * 1.5)) } | ||
| 143 | 179 | ||||
M scripts/headless.sh +2 -2
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | # Run neferbar against a nested headless NeferWL with a clean environment. | |
| 3 | 3 | # usage: scripts/headless.sh <config> <seconds> [neferbar args...] | |
| 4 | 4 | # env: SIZE=WxH (output size), SCALE=1.5 (output scale), OUT=dir (screenshots), | |
| 5 | - | # NEFERBAR=binary, LOGLINES=n (compositor log lines to show). | |
| 5 | + | # DISPLAY_VAR=NEFERBAR_DISPLAY (pass the socket that way), NEFERBAR=binary, LOGLINES=n (compositor log lines to show). | |
| 6 | 6 | set -eu | |
| 7 | 7 | cfg=$1; secs=$2; shift 2 | |
| 8 | 8 | out=${OUT:-/tmp/neferbar-shots} | |
| @@ -24,6 +24,6 @@ for _ in $(seq 100); do | |||
| 24 | 24 | done | |
| 25 | 25 | [ -n "${sock:-}" ] || { echo "no compositor socket"; cat "$root/neferwl.log"; exit 1; } | |
| 26 | 26 | set +e | |
| 27 | - | timeout "$secs" "${clean[@]}" WAYLAND_DISPLAY="$sock" "${NEFERBAR:-/tmp/neferbar}" -config "$cfg" "$@" | |
| 27 | + | timeout "$secs" "${clean[@]}" "${DISPLAY_VAR:-WAYLAND_DISPLAY}=$sock" "${NEFERBAR:-/tmp/neferbar}" -config "$cfg" "$@" | |
| 28 | 28 | echo "neferbar exit: $?" | |
| 29 | 29 | echo "--- compositor log"; grep -v "not a conformant" "$root/neferwl.log" | tail -"${LOGLINES:-8}"; cp "$root/neferwl.log" /tmp/neferwl-last.log | |
| @@ -2,7 +2,7 @@ | |||||
| 2 | # Run neferbar against a nested headless NeferWL with a clean environment. | 2 | # Run neferbar against a nested headless NeferWL with a clean environment. | ||
| 3 | # usage: scripts/headless.sh <config> <seconds> [neferbar args...] | 3 | # usage: scripts/headless.sh <config> <seconds> [neferbar args...] | ||
| 4 | # env: SIZE=WxH (output size), SCALE=1.5 (output scale), OUT=dir (screenshots), | 4 | # env: SIZE=WxH (output size), SCALE=1.5 (output scale), OUT=dir (screenshots), | ||
| 5 | - | # NEFERBAR=binary, LOGLINES=n (compositor log lines to show). | 5 | + | # DISPLAY_VAR=NEFERBAR_DISPLAY (pass the socket that way), NEFERBAR=binary, LOGLINES=n (compositor log lines to show). |
| 6 | set -eu | 6 | set -eu | ||
| 7 | cfg=$1; secs=$2; shift 2 | 7 | cfg=$1; secs=$2; shift 2 | ||
| 8 | out=${OUT:-/tmp/neferbar-shots} | 8 | out=${OUT:-/tmp/neferbar-shots} | ||
| @@ -24,6 +24,6 @@ for _ in $(seq 100); do | |||||
| 24 | done | 24 | done | ||
| 25 | [ -n "${sock:-}" ] || { echo "no compositor socket"; cat "$root/neferwl.log"; exit 1; } | 25 | [ -n "${sock:-}" ] || { echo "no compositor socket"; cat "$root/neferwl.log"; exit 1; } | ||
| 26 | set +e | 26 | set +e | ||
| 27 | - | timeout "$secs" "${clean[@]}" WAYLAND_DISPLAY="$sock" "${NEFERBAR:-/tmp/neferbar}" -config "$cfg" "$@" | 27 | + | timeout "$secs" "${clean[@]}" "${DISPLAY_VAR:-WAYLAND_DISPLAY}=$sock" "${NEFERBAR:-/tmp/neferbar}" -config "$cfg" "$@" |
| 28 | echo "neferbar exit: $?" | 28 | echo "neferbar exit: $?" | ||
| 29 | echo "--- compositor log"; grep -v "not a conformant" "$root/neferwl.log" | tail -"${LOGLINES:-8}"; cp "$root/neferwl.log" /tmp/neferwl-last.log | 29 | echo "--- compositor log"; grep -v "not a conformant" "$root/neferwl.log" | tail -"${LOGLINES:-8}"; cp "$root/neferwl.log" /tmp/neferwl-last.log | ||