summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2018-01-10 22:41:15 -0500
committerDrew DeVault <sir@cmpwn.com>2018-01-10 22:41:15 -0500
commit77a0f68758905faa74407499ff92c90929e27989 (patch)
tree44edc8d2de572deff60330f609aecab56aa4dea7
parentdb1b2cd53f5dc7bfbfb6ee54ad0bb0882ea2cc03 (diff)
downloadaerc-77a0f68758905faa74407499ff92c90929e27989.zip
Make termbox event loop async
-rw-r--r--cmd/aerc/main.go11
-rw-r--r--ui/account.go41
-rw-r--r--ui/helpers.go21
-rw-r--r--ui/render.go53
-rw-r--r--ui/types.go18
5 files changed, 126 insertions, 18 deletions
diff --git a/cmd/aerc/main.go b/cmd/aerc/main.go
index 4adf11e..9da7b3e 100644
--- a/cmd/aerc/main.go
+++ b/cmd/aerc/main.go
@@ -14,6 +14,11 @@ func main() {
if err != nil {
panic(err)
}
+ _ui, err := ui.Initialize(conf)
+ if err != nil {
+ panic(err)
+ }
+ defer _ui.Close()
var workers []worker.Worker
for _, account := range conf.Accounts {
work, err := worker.NewWorker(account.Source)
@@ -23,12 +28,8 @@ func main() {
go work.Run()
work.PostAction(types.Configure{Config: account})
workers = append(workers, work)
+ _ui.AddTab(ui.NewAccountTab(&account, &work))
}
- _ui, err := ui.Initialize(conf)
- if err != nil {
- panic(err)
- }
- defer _ui.Close()
for !_ui.Exit {
activity := false
for _, worker := range workers {
diff --git a/ui/account.go b/ui/account.go
new file mode 100644
index 0000000..0949e52
--- /dev/null
+++ b/ui/account.go
@@ -0,0 +1,41 @@
+package ui
+
+import (
+ tb "github.com/nsf/termbox-go"
+
+ "git.sr.ht/~sircmpwn/aerc2/config"
+ "git.sr.ht/~sircmpwn/aerc2/worker"
+)
+
+type AccountTab struct {
+ Config *config.AccountConfig
+ Worker *worker.Worker
+ Parent *UIState
+}
+
+func NewAccountTab(conf *config.AccountConfig, work *worker.Worker) *AccountTab {
+ return &AccountTab{
+ Config: conf,
+ Worker: work,
+ }
+}
+
+func (acc *AccountTab) Name() string {
+ return acc.Config.Name
+}
+
+func (acc *AccountTab) Invalid() bool {
+ return false
+}
+
+func (acc *AccountTab) SetParent(parent *UIState) {
+ acc.Parent = parent
+}
+
+func (acc *AccountTab) Render(at Geometry) {
+ cell := tb.Cell{
+ Fg: tb.ColorDefault,
+ Bg: tb.ColorDefault,
+ }
+ TPrintf(&at, cell, "%s", acc.Name())
+}
diff --git a/ui/helpers.go b/ui/helpers.go
new file mode 100644
index 0000000..0b8789e
--- /dev/null
+++ b/ui/helpers.go
@@ -0,0 +1,21 @@
+package ui
+
+import (
+ "fmt"
+
+ tb "github.com/nsf/termbox-go"
+)
+
+func TPrintf(geo *Geometry, ref tb.Cell, format string, a ...interface{}) {
+ str := fmt.Sprintf(format, a...)
+ _geo := *geo
+ 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?
+ geo.Col = _geo.Col
+ geo.Row++
+ }
+ }
+}
diff --git a/ui/render.go b/ui/render.go
index bca0cf6..4fedc2c 100644
--- a/ui/render.go
+++ b/ui/render.go
@@ -8,15 +8,21 @@ import (
func Initialize(conf *config.AercConfig) (*UIState, error) {
state := UIState{
+ Config: conf,
InvalidPanes: InvalidateAll,
- Tabs: make([]AercTab, len(conf.Accounts)),
+
+ tbEvents: make(chan tb.Event, 10),
}
- // TODO: Initialize each tab to a mailbox tab
if err := tb.Init(); err != nil {
return nil, err
}
tb.SetInputMode(tb.InputEsc | tb.InputMouse)
tb.SetOutputMode(tb.Output256)
+ go (func() {
+ for !state.Exit {
+ state.tbEvents <- tb.PollEvent()
+ }
+ })()
return &state, nil
}
@@ -24,21 +30,50 @@ func (state *UIState) Close() {
tb.Close()
}
+func (state *UIState) AddTab(tab AercTab) {
+ state.Tabs = append(state.Tabs, tab)
+}
+
func (state *UIState) Invalidate(what uint) {
state.InvalidPanes |= what
}
+func (state *UIState) calcGeometries() {
+ width, height := tb.Size()
+ // TODO: more
+ state.Panes.TabView = Geometry{
+ Row: 0,
+ Col: 0,
+ Width: width,
+ Height: height,
+ }
+}
+
func (state *UIState) Tick() bool {
- switch e := tb.PollEvent(); e.Type {
- case tb.EventKey:
- if e.Key == tb.KeyEsc {
- state.Exit = true
+ select {
+ case event := <-state.tbEvents:
+ switch event.Type {
+ case tb.EventKey:
+ if event.Key == tb.KeyEsc {
+ state.Exit = true
+ }
+ case tb.EventResize:
+ state.Invalidate(InvalidateAll)
}
- case tb.EventResize:
- state.Invalidate(InvalidateAll)
+ default:
+ // no-op
+ break
}
if state.InvalidPanes != 0 {
- // TODO: re-render
+ if state.InvalidPanes&InvalidateAll == InvalidateAll {
+ tb.Clear(tb.ColorDefault, tb.ColorDefault)
+ state.calcGeometries()
+ }
+ if state.InvalidPanes&InvalidateTabs != 0 {
+ tab := state.Tabs[state.SelectedTab]
+ tab.Render(state.Panes.TabView)
+ }
+ tb.Flush()
state.InvalidPanes = 0
}
return true
diff --git a/ui/types.go b/ui/types.go
index a7918b5..588c3b3 100644
--- a/ui/types.go
+++ b/ui/types.go
@@ -1,5 +1,11 @@
package ui
+import (
+ tb "github.com/nsf/termbox-go"
+
+ "git.sr.ht/~sircmpwn/aerc2/config"
+)
+
const (
Valid = 0
InvalidateTabs = 1 << iota
@@ -12,19 +18,21 @@ const (
)
type Geometry struct {
- row int
- col int
- width int
- height int
+ Row int
+ Col int
+ Width int
+ Height int
}
type AercTab interface {
Name() string
Invalid() bool
Render(at Geometry)
+ SetParent(parent *UIState)
}
type UIState struct {
+ Config *config.AercConfig
Exit bool
InvalidPanes uint
@@ -44,4 +52,6 @@ type UIState struct {
Index int
Scroll int
}
+
+ tbEvents chan tb.Event
}