func addRestartHandlers(o bar.Output, restartFn func()) bar.Segments {
	in := toSegments(o)
	var out bar.Segments
	for _, s := range in {
		out = append(out, s.Clone().OnClick(func(e bar.Event) {
			if isRestartableClick(e) {
				restartFn()
			}
		}))
	}
	return out
}
addRestartHandlers replaces all click handlers with a function
that restarts the module. This is used on the last output of
the wrapped module after the original finishes.
package core
import (
	"sync"
	"time"
	"barista.run/bar"
	"barista.run/base/notifier"
	l "barista.run/logging"
	"barista.run/timing"
)
type Module struct {
	original  bar.Module
	replayCh  <-chan struct{}
	replayFn  func()
	restartCh <-chan struct{}
	restartFn func()
}
func NewModule(original bar.Module) *Module {
	m := &Module{original: original}
	m.replayFn, m.replayCh = notifier.New()
	m.restartFn, m.restartCh = notifier.New()
	l.Attach(original, m, "~core")
	l.Register(m, "replayCh")
	l.Register(m, "restartCh")
	return m
}
func (m *Module) Stream(sink bar.Sink) {
	for {
		m.runLoop(sink)
	}
}
func (m *Module) runLoop(realSink bar.Sink) {
	started := false
	finished := false
	var refreshFn func()
	if r, ok := m.original.(bar.RefresherModule); ok {
		refreshFn = r.Refresh
	}
	timedSink := newTimedSink(realSink, refreshFn)
	l.Attach(m.original, timedSink, "~internal-sink")
	outputCh := make(chan bar.Output)
	innerSink := func(o bar.Output) { outputCh <- o }
	doneCh := make(chan struct{})
	go func(m bar.Module, innerSink bar.Sink, doneCh chan<- struct{}) {
		l.Fine("%s started", l.ID(m))
		m.Stream(innerSink)
		l.Fine("%s finished", l.ID(m))
		doneCh <- struct{}{}
	}(m.original, innerSink, doneCh)
	var out bar.Output
	for {
		select {
		case out = <-outputCh:
			started = true
			timedSink.Output(out, true)
		case <-doneCh:
			finished = true
			timedSink.Stop()
			out = toSegments(out)
			l.Fine("%s: set restart handlers", l.ID(m))
			timedSink.Output(addRestartHandlers(out, m.restartFn), false)
		case <-m.replayCh:
			if started {
				l.Fine("%s: replay last output", l.ID(m))
				timedSink.Output(out, true)
			}
		case <-m.restartCh:
			if finished {
				l.Fine("%s restarted", l.ID(m.original))
				timedSink.Output(stripErrors(out, l.ID(m)), false)
				return  
			}
		}
	}
}
func (m *Module) Replay() {
	m.replayFn()
}
func isRestartableClick(e bar.Event) bool {
	return e.Button == bar.ButtonLeft ||
		e.Button == bar.ButtonRight ||
		e.Button == bar.ButtonMiddle
}
func stripErrors(o bar.Output, logCtx string) bar.Segments {
	in := toSegments(o)
	var out bar.Segments
	for _, s := range in {
		if s.GetError() == nil {
			out = append(out, s)
		}
	}
	if len(in) != len(out) {
		l.Fine("%s removed %d error segments from output",
			logCtx, len(in)-len(out))
	}
	return out
}