diff --git a/cmd/aerc/main.go b/cmd/aerc/main.go index 420d7a8..e33f158 100644 --- a/cmd/aerc/main.go +++ b/cmd/aerc/main.go @@ -5,8 +5,6 @@ import ( "git.sr.ht/~sircmpwn/aerc2/config" "git.sr.ht/~sircmpwn/aerc2/ui" - "git.sr.ht/~sircmpwn/aerc2/worker" - "git.sr.ht/~sircmpwn/aerc2/worker/types" ) func main() { @@ -19,27 +17,15 @@ func main() { panic(err) } defer _ui.Close() - var workers []worker.Worker for _, account := range conf.Accounts { - work, err := worker.NewWorker(account.Source) + tab, err := ui.NewAccountTab(&account) if err != nil { panic(err) } - go work.Run() - work.PostAction(types.Configure{Config: account}) - workers = append(workers, work) - // TODO: Give tabs ownership over their workers - _ui.AddTab(ui.NewAccountTab(&account, &work)) + _ui.AddTab(tab) } for !_ui.Exit { - activity := false - for _, worker := range workers { - if msg := worker.GetMessage(); msg != nil { - activity = true - } - } - activity = _ui.Tick() || activity - if !activity { + if !_ui.Tick() { time.Sleep(100 * time.Millisecond) } } diff --git a/ui/account.go b/ui/account.go index 9c16cc5..50f41e4 100644 --- a/ui/account.go +++ b/ui/account.go @@ -1,25 +1,35 @@ package ui import ( + "fmt" + tb "github.com/nsf/termbox-go" "git.sr.ht/~sircmpwn/aerc2/config" "git.sr.ht/~sircmpwn/aerc2/worker" + "git.sr.ht/~sircmpwn/aerc2/worker/types" ) type AccountTab struct { Config *config.AccountConfig - Worker *worker.Worker + Worker worker.Worker Parent *UIState counter int + log []string } -func NewAccountTab(conf *config.AccountConfig, work *worker.Worker) *AccountTab { +func NewAccountTab(conf *config.AccountConfig) (*AccountTab, error) { + work, err := worker.NewWorker(conf.Source) + if err != nil { + return nil, err + } + go work.Run() + work.PostAction(types.Configure{Config: conf}) return &AccountTab{ Config: conf, Worker: work, - } + }, nil } func (acc *AccountTab) Name() string { @@ -32,13 +42,26 @@ func (acc *AccountTab) SetParent(parent *UIState) { func (acc *AccountTab) Render(at Geometry) { cell := tb.Cell{ + Ch: ' ', Fg: tb.ColorDefault, Bg: tb.ColorDefault, } - TPrintf(&at, cell, "%s %d", acc.Name(), acc.counter) + TFill(at, cell) + TPrintf(&at, cell, "%s %d\n", acc.Name(), acc.counter) + for _, str := range acc.log { + TPrintf(&at, cell, "%s\n", str) + } acc.counter++ if acc.counter%10000 == 0 { acc.counter = 0 } acc.Parent.InvalidateFrom(acc) } + +func (acc *AccountTab) GetChannel() chan types.WorkerMessage { + return acc.Worker.GetMessages() +} + +func (acc *AccountTab) HandleMessage(msg types.WorkerMessage) { + acc.log = append(acc.log, fmt.Sprintf("<- %T", msg)) +} diff --git a/ui/helpers.go b/ui/helpers.go index 0b8789e..f2b2adf 100644 --- a/ui/helpers.go +++ b/ui/helpers.go @@ -9,13 +9,33 @@ import ( func TPrintf(geo *Geometry, ref tb.Cell, format string, a ...interface{}) { str := fmt.Sprintf(format, a...) _geo := *geo + newline := func() { + // TODO: Abort when out of room? + geo.Col = _geo.Col + geo.Row++ + } for _, ch := range str { - tb.SetCell(geo.Col, geo.Row, ch, ref.Fg, ref.Bg) - geo.Col++ - if geo.Col == _geo.Col+geo.Width { - // TODO: Abort when out of room? + switch ch { + case '\n': + newline() + case '\r': geo.Col = _geo.Col - geo.Row++ + default: + tb.SetCell(geo.Col, geo.Row, ch, ref.Fg, ref.Bg) + geo.Col++ + if geo.Col == _geo.Col+geo.Width { + newline() + } } } } + +func TFill(geo Geometry, ref tb.Cell) { + _geo := geo + for ; geo.Row < geo.Height; geo.Row++ { + for ; geo.Col < geo.Width; geo.Col++ { + tb.SetCell(geo.Col, geo.Row, ref.Ch, ref.Fg, ref.Bg) + } + geo.Col = _geo.Col + } +} diff --git a/ui/types.go b/ui/types.go index 14a91c3..5437642 100644 --- a/ui/types.go +++ b/ui/types.go @@ -4,20 +4,19 @@ import ( tb "github.com/nsf/termbox-go" "git.sr.ht/~sircmpwn/aerc2/config" + "git.sr.ht/~sircmpwn/aerc2/worker/types" ) const ( Valid = 0 InvalidateTabList = 1 << iota InvalidateTabView - InvalidateSidebar InvalidateStatusBar ) const ( InvalidateAll = InvalidateTabList | InvalidateTabView | - InvalidateSidebar | InvalidateStatusBar ) @@ -34,6 +33,16 @@ type AercTab interface { SetParent(parent *UIState) } +type WorkerListener interface { + GetChannel() chan types.WorkerMessage + HandleMessage(msg types.WorkerMessage) +} + +type wrappedMessage struct { + msg types.WorkerMessage + listener WorkerListener +} + type UIState struct { Config *config.AercConfig Exit bool @@ -57,4 +66,6 @@ type UIState struct { } tbEvents chan tb.Event + // Aggregate channel for all worker messages + workerEvents chan wrappedMessage } diff --git a/ui/ui.go b/ui/ui.go index f01af08..db31696 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -11,7 +11,8 @@ func Initialize(conf *config.AercConfig) (*UIState, error) { Config: conf, InvalidPanes: InvalidateAll, - tbEvents: make(chan tb.Event, 10), + tbEvents: make(chan tb.Event, 10), + workerEvents: make(chan wrappedMessage), } if err := tb.Init(); err != nil { return nil, err @@ -33,6 +34,16 @@ func (state *UIState) Close() { func (state *UIState) AddTab(tab AercTab) { tab.SetParent(state) state.Tabs = append(state.Tabs, tab) + if listener, ok := tab.(WorkerListener); ok { + go (func() { + for msg := range listener.GetChannel() { + state.workerEvents <- wrappedMessage{ + msg: msg, + listener: listener, + } + } + })() + } } func (state *UIState) Invalidate(what uint) { @@ -67,6 +78,8 @@ func (state *UIState) Tick() bool { case tb.EventResize: state.Invalidate(InvalidateAll) } + case msg := <-state.workerEvents: + msg.listener.HandleMessage(msg.msg) default: // no-op break diff --git a/worker/imap/worker.go b/worker/imap/worker.go index 14e4004..080927d 100644 --- a/worker/imap/worker.go +++ b/worker/imap/worker.go @@ -18,13 +18,8 @@ func NewIMAPWorker() *IMAPWorker { } } -func (w *IMAPWorker) GetMessage() types.WorkerMessage { - select { - case msg := <-w.messages: - return msg - default: - return nil - } +func (w *IMAPWorker) GetMessages() chan types.WorkerMessage { + return w.messages } func (w *IMAPWorker) PostAction(msg types.WorkerMessage) { diff --git a/worker/types/messages.go b/worker/types/messages.go index 845bb86..a4d8ddb 100644 --- a/worker/types/messages.go +++ b/worker/types/messages.go @@ -33,7 +33,7 @@ type Ping struct { type Configure struct { Message - Config config.AccountConfig + Config *config.AccountConfig } type Connect struct { diff --git a/worker/worker.go b/worker/worker.go index da7928e..c8ec622 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -9,7 +9,7 @@ import ( ) type Worker interface { - GetMessage() types.WorkerMessage + GetMessages() chan types.WorkerMessage PostAction(types.WorkerMessage) Run() }