summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--commands/account/clear.go4
-rw-r--r--commands/account/connection.go12
-rw-r--r--commands/account/search.go11
-rw-r--r--commands/msg/toggle-threads.go2
-rw-r--r--commands/msgview/toggle-key-passthrough.go7
-rw-r--r--commands/next-tab.go1
-rw-r--r--lib/statusline/state.go133
-rw-r--r--widgets/account.go41
-rw-r--r--widgets/aerc.go14
-rw-r--r--widgets/status.go16
10 files changed, 196 insertions, 45 deletions
diff --git a/commands/account/clear.go b/commands/account/clear.go
index 259a9de..64e7012 100644
--- a/commands/account/clear.go
+++ b/commands/account/clear.go
@@ -3,6 +3,7 @@ package account
import (
"errors"
+ "git.sr.ht/~rjarry/aerc/lib/statusline"
"git.sr.ht/~rjarry/aerc/widgets"
)
@@ -30,6 +31,7 @@ func (Clear) Execute(aerc *widgets.Aerc, args []string) error {
return errors.New("Cannot perform action. Messages still loading")
}
store.ApplyClear()
- aerc.ClearExtraStatus()
+ acct.SetStatus(statusline.SearchFilterClear())
+
return nil
}
diff --git a/commands/account/connection.go b/commands/account/connection.go
index a87993b..52b569c 100644
--- a/commands/account/connection.go
+++ b/commands/account/connection.go
@@ -3,6 +3,7 @@ package account
import (
"errors"
+ "git.sr.ht/~rjarry/aerc/lib/statusline"
"git.sr.ht/~rjarry/aerc/widgets"
"git.sr.ht/~rjarry/aerc/worker/types"
)
@@ -26,12 +27,15 @@ func (Connection) Execute(aerc *widgets.Aerc, args []string) error {
if acct == nil {
return errors.New("No account selected")
}
+ cb := func(msg types.WorkerMessage) {
+ acct.SetStatus(statusline.ConnectionActivity(""))
+ }
if args[0] == "connect" {
- acct.Worker().PostAction(&types.Connect{}, nil)
- acct.SetStatus("Connecting...")
+ acct.Worker().PostAction(&types.Connect{}, cb)
+ acct.SetStatus(statusline.ConnectionActivity("Connecting..."))
} else {
- acct.Worker().PostAction(&types.Disconnect{}, nil)
- acct.SetStatus("Disconnecting...")
+ acct.Worker().PostAction(&types.Disconnect{}, cb)
+ acct.SetStatus(statusline.ConnectionActivity("Disconnecting..."))
}
return nil
}
diff --git a/commands/account/search.go b/commands/account/search.go
index 86d9dea..eeee7bd 100644
--- a/commands/account/search.go
+++ b/commands/account/search.go
@@ -2,8 +2,9 @@ package account
import (
"errors"
- "fmt"
+ "strings"
+ "git.sr.ht/~rjarry/aerc/lib/statusline"
"git.sr.ht/~rjarry/aerc/widgets"
)
@@ -33,16 +34,16 @@ func (SearchFilter) Execute(aerc *widgets.Aerc, args []string) error {
var cb func([]uint32)
if args[0] == "filter" {
- aerc.SetExtraStatus("Filtering...")
+ acct.SetStatus(statusline.FilterActivity("Filtering..."), statusline.Search(""))
cb = func(uids []uint32) {
- aerc.SetExtraStatus(fmt.Sprintf("%s", args))
+ acct.SetStatus(statusline.FilterResult(strings.Join(args, " ")))
acct.Logger().Printf("Filter results: %v", uids)
store.ApplyFilter(uids)
}
} else {
- aerc.SetExtraStatus("Searching...")
+ acct.SetStatus(statusline.Search("Searching..."))
cb = func(uids []uint32) {
- aerc.SetExtraStatus(fmt.Sprintf("%s", args))
+ acct.SetStatus(statusline.Search(strings.Join(args, " ")))
acct.Logger().Printf("Search results: %v", uids)
store.ApplySearch(uids)
// TODO: Remove when stores have multiple OnUpdate handlers
diff --git a/commands/msg/toggle-threads.go b/commands/msg/toggle-threads.go
index e93cb42..79d515c 100644
--- a/commands/msg/toggle-threads.go
+++ b/commands/msg/toggle-threads.go
@@ -3,6 +3,7 @@ package msg
import (
"errors"
+ "git.sr.ht/~rjarry/aerc/lib/statusline"
"git.sr.ht/~rjarry/aerc/widgets"
)
@@ -34,6 +35,7 @@ func (ToggleThreads) Execute(aerc *widgets.Aerc, args []string) error {
return err
}
store.SetBuildThreads(!store.BuildThreads())
+ acct.SetStatus(statusline.Threading(store.BuildThreads()))
acct.Messages().Invalidate()
return nil
}
diff --git a/commands/msgview/toggle-key-passthrough.go b/commands/msgview/toggle-key-passthrough.go
index 6cd575b..1ac370e 100644
--- a/commands/msgview/toggle-key-passthrough.go
+++ b/commands/msgview/toggle-key-passthrough.go
@@ -3,6 +3,7 @@ package msgview
import (
"errors"
+ "git.sr.ht/~rjarry/aerc/lib/statusline"
"git.sr.ht/~rjarry/aerc/widgets"
)
@@ -26,10 +27,8 @@ func (ToggleKeyPassthrough) Execute(aerc *widgets.Aerc, args []string) error {
}
mv, _ := aerc.SelectedTab().(*widgets.MessageViewer)
keyPassthroughEnabled := mv.ToggleKeyPassthrough()
- if keyPassthroughEnabled {
- aerc.SetExtraStatus("[passthrough]")
- } else {
- aerc.ClearExtraStatus()
+ if acct := mv.SelectedAccount(); acct != nil {
+ acct.SetStatus(statusline.Passthrough(keyPassthroughEnabled))
}
return nil
}
diff --git a/commands/next-tab.go b/commands/next-tab.go
index 9d6a09b..854353f 100644
--- a/commands/next-tab.go
+++ b/commands/next-tab.go
@@ -42,6 +42,7 @@ func (NextPrevTab) Execute(aerc *widgets.Aerc, args []string) error {
aerc.NextTab()
}
}
+ aerc.UpdateStatus()
return nil
}
diff --git a/lib/statusline/state.go b/lib/statusline/state.go
new file mode 100644
index 0000000..30029c1
--- /dev/null
+++ b/lib/statusline/state.go
@@ -0,0 +1,133 @@
+package statusline
+
+import (
+ "fmt"
+ "strings"
+)
+
+type State struct {
+ Name string
+ Multiple bool
+ Separator string
+
+ Connection string
+ ConnActivity string
+ Connected bool
+
+ Search string
+ Filter string
+ FilterActivity string
+
+ Threading string
+ Passthrough string
+}
+
+func NewState(name string, multipleAccts bool, sep string) *State {
+ return &State{Name: name, Multiple: multipleAccts, Separator: sep}
+}
+
+func (s *State) String() string {
+ var line []string
+ if s.Connection != "" || s.ConnActivity != "" {
+ conn := s.Connection
+ if s.ConnActivity != "" {
+ conn = s.ConnActivity
+ }
+ if s.Multiple {
+ line = append(line, fmt.Sprintf("[%s] %s", s.Name, conn))
+ } else {
+ line = append(line, conn)
+ }
+ }
+ if s.Connected {
+ if s.FilterActivity != "" {
+ line = append(line, s.FilterActivity)
+ } else {
+ if s.Filter != "" {
+ line = append(line, s.Filter)
+ }
+ }
+ if s.Search != "" {
+ line = append(line, s.Search)
+ }
+ if s.Threading != "" {
+ line = append(line, s.Threading)
+ }
+ if s.Passthrough != "" {
+ line = append(line, s.Passthrough)
+ }
+ }
+ return strings.Join(line, s.Separator)
+}
+
+type SetStateFunc func(s *State)
+
+func Connected(state bool) SetStateFunc {
+ return func(s *State) {
+ s.ConnActivity = ""
+ s.Connected = state
+ if state {
+ s.Connection = "Connected"
+ } else {
+ s.Connection = "Disconnected"
+ }
+ }
+}
+
+func ConnectionActivity(desc string) SetStateFunc {
+ return func(s *State) {
+ s.ConnActivity = desc
+ }
+}
+
+func SearchFilterClear() SetStateFunc {
+ return func(s *State) {
+ s.Search = ""
+ s.FilterActivity = ""
+ s.Filter = ""
+ }
+}
+
+func FilterActivity(str string) SetStateFunc {
+ return func(s *State) {
+ s.FilterActivity = str
+ }
+}
+
+func FilterResult(str string) SetStateFunc {
+ return func(s *State) {
+ s.FilterActivity = ""
+ s.Filter = concatFilters(s.Filter, str)
+ }
+}
+
+func concatFilters(existing, next string) string {
+ if existing == "" {
+ return next
+ }
+ return fmt.Sprintf("%s && %s", existing, next)
+}
+
+func Search(desc string) SetStateFunc {
+ return func(s *State) {
+ s.Search = desc
+ }
+}
+
+func Threading(on bool) SetStateFunc {
+ return func(s *State) {
+ s.Threading = ""
+ if on {
+ s.Threading = "threading"
+ }
+ }
+}
+
+func Passthrough(on bool) SetStateFunc {
+ return func(s *State) {
+ s.Passthrough = ""
+ if on {
+ s.Passthrough = "passthrough"
+ }
+ }
+}
diff --git a/widgets/account.go b/widgets/account.go
index 87a8cef..647a3ae 100644
--- a/widgets/account.go
+++ b/widgets/account.go
@@ -4,12 +4,14 @@ import (
"errors"
"fmt"
"log"
+ "time"
"github.com/gdamore/tcell/v2"
"git.sr.ht/~rjarry/aerc/config"
"git.sr.ht/~rjarry/aerc/lib"
"git.sr.ht/~rjarry/aerc/lib/sort"
+ "git.sr.ht/~rjarry/aerc/lib/statusline"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker"
@@ -29,6 +31,7 @@ type AccountView struct {
logger *log.Logger
msglist *MessageList
worker *types.Worker
+ state *statusline.State
}
func (acct *AccountView) UiConfig() config.UIConfig {
@@ -55,6 +58,7 @@ func NewAccountView(aerc *Aerc, conf *config.AercConfig, acct *config.AccountCon
conf: conf,
host: host,
logger: logger,
+ state: statusline.NewState(acct.Name, len(conf.Accounts) > 1, " | "),
}
view.grid = ui.NewGrid().Rows([]ui.GridSpec{
@@ -86,7 +90,7 @@ func NewAccountView(aerc *Aerc, conf *config.AercConfig, acct *config.AccountCon
worker.PostAction(&types.Configure{Config: acct}, nil)
worker.PostAction(&types.Connect{}, nil)
- host.SetStatus("Connecting...")
+ view.SetStatus(statusline.ConnectionActivity("Connecting..."))
return view, nil
}
@@ -105,8 +109,22 @@ func (acct *AccountView) Tick() bool {
}
}
-func (acct *AccountView) SetStatus(msg string) {
- acct.host.SetStatus(msg)
+func (acct *AccountView) SetStatus(setters ...statusline.SetStateFunc) {
+ for _, fn := range setters {
+ fn(acct.state)
+ }
+}
+
+func (acct *AccountView) UpdateStatus() {
+ acct.host.SetStatus(acct.state.String())
+}
+
+func (acct *AccountView) PushStatus(status string, expiry time.Duration) {
+ acct.aerc.PushStatus(fmt.Sprintf("%s: %v", acct.acct.Name, status), expiry)
+}
+
+func (acct *AccountView) PushError(err error) {
+ acct.aerc.PushError(fmt.Sprintf("%s: %v", acct.acct.Name, err))
}
func (acct *AccountView) AccountConfig() *config.AccountConfig {
@@ -140,6 +158,7 @@ func (acct *AccountView) Invalidate() {
}
func (acct *AccountView) Draw(ctx *ui.Context) {
+ acct.UpdateStatus()
acct.grid.Draw(ctx)
}
@@ -203,7 +222,7 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
case *types.Done:
switch msg.InResponseTo().(type) {
case *types.Connect, *types.Reconnect:
- acct.host.SetStatus("Listing mailboxes...")
+ acct.SetStatus(statusline.ConnectionActivity("Listing mailboxes..."))
acct.logger.Println("Listing mailboxes...")
acct.dirlist.UpdateList(func(dirs []string) {
var dir string
@@ -221,13 +240,13 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
}
acct.msglist.SetInitDone()
acct.logger.Println("Connected.")
- acct.host.SetStatus("Connected.")
+ acct.SetStatus(statusline.Connected(true))
})
case *types.Disconnect:
acct.dirlist.UpdateList(nil)
acct.msglist.SetStore(nil)
acct.logger.Println("Disconnected.")
- acct.host.SetStatus("Disconnected.")
+ acct.SetStatus(statusline.Connected(false))
case *types.OpenDirectory:
if store, ok := acct.dirlist.SelectedMsgStore(); ok {
// If we've opened this dir before, we can re-render it from
@@ -289,14 +308,14 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
case *types.LabelList:
acct.labels = msg.Labels
case *types.ConnError:
- acct.logger.Printf("connection error: %v", msg.Error)
- acct.host.SetStatus("Disconnected.")
- acct.aerc.PushError(fmt.Sprintf("%v", msg.Error))
+ acct.logger.Printf("connection error: [%s] %v", acct.acct.Name, msg.Error)
+ acct.SetStatus(statusline.Connected(false))
+ acct.PushError(msg.Error)
acct.msglist.SetStore(nil)
acct.worker.PostAction(&types.Reconnect{}, nil)
case *types.Error:
acct.logger.Printf("%v", msg.Error)
- acct.aerc.PushError(fmt.Sprintf("%v", msg.Error))
+ acct.PushError(msg.Error)
}
}
@@ -306,7 +325,7 @@ func (acct *AccountView) getSortCriteria() []*types.SortCriterion {
}
criteria, err := sort.GetSortCriteria(acct.UiConfig().Sort)
if err != nil {
- acct.aerc.PushError(" ui.sort: " + err.Error())
+ acct.PushError(fmt.Errorf("ui sort: %v", err))
return nil
}
return criteria
diff --git a/widgets/aerc.go b/widgets/aerc.go
index 3a8f47f..a8b23fe 100644
--- a/widgets/aerc.go
+++ b/widgets/aerc.go
@@ -337,6 +337,7 @@ func (aerc *Aerc) NumTabs() int {
func (aerc *Aerc) NewTab(clickable ui.Drawable, name string) *ui.Tab {
tab := aerc.tabs.Add(clickable, name)
aerc.tabs.Select(len(aerc.tabs.Tabs) - 1)
+ aerc.UpdateStatus()
return tab
}
@@ -400,17 +401,20 @@ func (aerc *Aerc) SelectPreviousTab() bool {
return aerc.tabs.SelectPrevious()
}
-// TODO: Use per-account status lines, but a global ex line
func (aerc *Aerc) SetStatus(status string) *StatusMessage {
return aerc.statusline.Set(status)
}
-func (aerc *Aerc) SetExtraStatus(status string) {
- aerc.statusline.SetExtra(status)
+func (aerc *Aerc) UpdateStatus() {
+ if acct := aerc.SelectedAccount(); acct != nil {
+ acct.UpdateStatus()
+ } else {
+ aerc.ClearStatus()
+ }
}
-func (aerc *Aerc) ClearExtraStatus() {
- aerc.statusline.ClearExtra()
+func (aerc *Aerc) ClearStatus() {
+ aerc.statusline.Set("")
}
func (aerc *Aerc) SetError(status string) *StatusMessage {
diff --git a/widgets/status.go b/widgets/status.go
index 960f244..c70d215 100644
--- a/widgets/status.go
+++ b/widgets/status.go
@@ -14,7 +14,6 @@ type StatusLine struct {
ui.Invalidatable
stack []*StatusMessage
fallback StatusMessage
- extra string
aerc *Aerc
uiConfig config.UIConfig
}
@@ -30,7 +29,6 @@ func NewStatusLine(uiConfig config.UIConfig) *StatusLine {
style: uiConfig.GetStyle(config.STYLE_STATUSLINE_DEFAULT),
message: "Idle",
},
- extra: "",
uiConfig: uiConfig,
}
}
@@ -51,11 +49,7 @@ func (status *StatusLine) Draw(ctx *ui.Context) {
pendingKeys += string(pendingKey.Rune)
}
}
- text := line.message
- if status.extra != "" {
- text += " " + status.extra
- }
- message := runewidth.FillRight(text, ctx.Width()-len(pendingKeys)-5)
+ message := runewidth.FillRight(line.message, ctx.Width()-len(pendingKeys)-5)
ctx.Printf(0, 0, line.style, "%s%s", message, pendingKeys)
}
@@ -109,14 +103,6 @@ func (status *StatusLine) PushSuccess(text string) *StatusMessage {
return msg
}
-func (status *StatusLine) SetExtra(text string) {
- status.extra = text
-}
-
-func (status *StatusLine) ClearExtra() {
- status.extra = ""
-}
-
func (status *StatusLine) Expire() {
status.stack = nil
}