summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordelitako <delitako@delitako.xyz>2024-01-25 22:50:14 -0600
committerRobin Jarry <robin@jarry.cc>2024-01-26 20:27:08 +0100
commit936d519a67301bd78a4d737dc47234e3769e639f (patch)
tree701dc21c0551d4f020cb1c339ba0270c1525c2a7
parent58585e0a8e264f7a5500b3f24b0b319d59f36882 (diff)
downloadaerc-936d519a67301bd78a4d737dc47234e3769e639f.tar.gz
aerc-936d519a67301bd78a4d737dc47234e3769e639f.zip
tabs: optimize switching by offsets
I imagine no sane user requires aerc to correctly handle commands like `:next-tab 1000000000`, but I tried anyway and it froze aerc while also eating up many GBs of system memory. This behavior is not ideal, so I improved it. This commit adds functions for selecting a tab at an offset from the currently-selected tab and changes the next-tab, prev-tab, and change-tab commands to use these functions instead of looping. Signed-off-by: delitako <delitako@delitako.xyz> Tested-by: Thomas Böhler <witcher@wiredspace.de> Reviewed-by: Thomas Böhler <witcher@wiredspace.de> Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r--app/aerc.go4
-rw-r--r--app/app.go1
-rw-r--r--commands/ct.go16
-rw-r--r--commands/next-tab.go15
-rw-r--r--lib/ui/tab.go12
5 files changed, 30 insertions, 18 deletions
diff --git a/app/aerc.go b/app/aerc.go
index c7307540..31d3a44b 100644
--- a/app/aerc.go
+++ b/app/aerc.go
@@ -525,6 +525,10 @@ func (aerc *Aerc) SelectTabIndex(index int) bool {
return ok
}
+func (aerc *Aerc) SelectTabAtOffset(offset int) {
+ aerc.tabs.SelectOffset(offset)
+}
+
func (aerc *Aerc) TabNames() []string {
return aerc.tabs.Names()
}
diff --git a/app/app.go b/app/app.go
index ea4e4d26..ca9c59bb 100644
--- a/app/app.go
+++ b/app/app.go
@@ -55,6 +55,7 @@ func SelectPreviousTab() bool { return aerc.SelectPrev
func SelectedTab() *ui.Tab { return aerc.SelectedTab() }
func SelectedTabContent() ui.Drawable { return aerc.SelectedTabContent() }
func SelectTabIndex(index int) bool { return aerc.SelectTabIndex(index) }
+func SelectTabAtOffset(offset int) { aerc.SelectTabAtOffset(offset) }
func RemoveTab(tab ui.Drawable, closeContent bool) { aerc.RemoveTab(tab, closeContent) }
func NewTab(clickable ui.Drawable, name string) *ui.Tab { return aerc.NewTab(clickable, name) }
func ReplaceTab(tabSrc ui.Drawable, tabTarget ui.Drawable, name string, closeSrc bool) {
diff --git a/commands/ct.go b/commands/ct.go
index 1f99c6a5..4f908fcf 100644
--- a/commands/ct.go
+++ b/commands/ct.go
@@ -37,20 +37,12 @@ func (c ChangeTab) Execute(args []string) error {
} else {
n, err := strconv.Atoi(c.Tab)
if err == nil {
- switch {
- case strings.HasPrefix(c.Tab, "+"):
- for ; n > 0; n-- {
- app.NextTab()
- }
- case strings.HasPrefix(c.Tab, "-"):
- for ; n < 0; n++ {
- app.PrevTab()
- }
- default:
+ if strings.HasPrefix(c.Tab, "+") || strings.HasPrefix(c.Tab, "-") {
+ app.SelectTabAtOffset(n)
+ } else {
ok := app.SelectTabIndex(n)
if !ok {
- return errors.New(
- "No tab with that index")
+ return errors.New("No tab with that index")
}
}
} else {
diff --git a/commands/next-tab.go b/commands/next-tab.go
index adab95ae..12f659c9 100644
--- a/commands/next-tab.go
+++ b/commands/next-tab.go
@@ -21,13 +21,16 @@ func (NextPrevTab) Aliases() []string {
}
func (np NextPrevTab) Execute(args []string) error {
- for n := 0; n < np.Offset; n++ {
- if args[0] == "prev-tab" {
- app.PrevTab()
- } else {
- app.NextTab()
- }
+ if np.Offset <= 0 {
+ return nil
}
+
+ offset := np.Offset
+ if args[0] == "prev-tab" {
+ offset *= -1
+ }
+
+ app.SelectTabAtOffset(offset)
app.UpdateStatus()
return nil
}
diff --git a/lib/ui/tab.go b/lib/ui/tab.go
index 43b6e14f..f5e89064 100644
--- a/lib/ui/tab.go
+++ b/lib/ui/tab.go
@@ -209,6 +209,18 @@ func (tabs *Tabs) SelectPrevious() bool {
return tabs.selectPriv(index)
}
+func (tabs *Tabs) SelectOffset(offset int) {
+ tabs.m.Lock()
+ tabCount := len(tabs.tabs)
+ newIndex := (tabs.curIndex + offset) % tabCount
+ if newIndex < 0 {
+ // Handle negative offsets correctly
+ newIndex += tabCount
+ }
+ tabs.selectPriv(newIndex)
+ tabs.m.Unlock()
+}
+
func (tabs *Tabs) MoveTab(to int, relative bool) {
tabs.m.Lock()
tabs.moveTabPriv(to, relative)