diff --git a/internal/action/command.go b/internal/action/command.go index d676cfadf8..e60d60ad6c 100644 --- a/internal/action/command.go +++ b/internal/action/command.go @@ -587,7 +587,7 @@ func doSetGlobalOptionNative(option string, nativeValue any) error { for _, b := range buffer.OpenBuffers { b.UpdateRules() } - } else if option == "infobar" || option == "keymenu" { + } else if option == "infobar" || option == "keymenu" || option == "tabalways" { Tabs.Resize() } else if option == "mouse" { if !nativeValue.(bool) { diff --git a/internal/action/tab.go b/internal/action/tab.go index fa991f3e9a..e1672a9332 100644 --- a/internal/action/tab.go +++ b/internal/action/tab.go @@ -26,7 +26,7 @@ func NewTabList(bufs []*buffer.Buffer) *TabList { iOffset := config.GetInfoBarOffset() tl := new(TabList) tl.List = make([]*Tab, len(bufs)) - if len(bufs) > 1 { + if tabBarVisible(len(bufs)) { for i, b := range bufs { tl.List[i] = NewTabFromBuffer(0, 1, w, h-1-iOffset, b) } @@ -75,15 +75,22 @@ func (t *TabList) RemoveTab(id uint64) { } } +// tabBarVisible reports whether the tab bar should be drawn. It is normally +// only shown when more than one tab is open, but the tabalways option forces +// it to always be visible +func tabBarVisible(numTabs int) bool { + return numTabs > 1 || config.GetGlobalOption("tabalways").(bool) +} + // Resize resizes all elements within the tab list -// One thing to note is that when there is only 1 tab -// the tab bar should not be drawn so resizing must take +// One thing to note is that when the tab bar is hidden (only 1 tab open and +// tabalways off) the panes occupy the full height, so resizing must take // that into account func (t *TabList) Resize() { w, h := screen.Screen.Size() iOffset := config.GetInfoBarOffset() InfoBar.Resize(w, h-1) - if len(t.List) > 1 { + if tabBarVisible(len(t.List)) { for _, p := range t.List { p.Y = 1 p.Node.Resize(w, h-1-iOffset) @@ -107,7 +114,7 @@ func (t *TabList) HandleEvent(event tcell.Event) { mx, my := e.Position() switch e.Buttons() { case tcell.Button1: - if my == t.Y && len(t.List) > 1 { + if my == t.Y && tabBarVisible(len(t.List)) { if mx == 0 { t.Scroll(-4) } else if mx == t.Width-1 { @@ -127,12 +134,12 @@ func (t *TabList) HandleEvent(event tcell.Event) { return } case tcell.WheelUp: - if my == t.Y && len(t.List) > 1 { + if my == t.Y && tabBarVisible(len(t.List)) { t.Scroll(4) return } case tcell.WheelDown: - if my == t.Y && len(t.List) > 1 { + if my == t.Y && tabBarVisible(len(t.List)) { t.Scroll(-4) return } @@ -144,7 +151,7 @@ func (t *TabList) HandleEvent(event tcell.Event) { // Display updates the names and then displays the tab bar func (t *TabList) Display() { t.UpdateNames() - if len(t.List) > 1 { + if tabBarVisible(len(t.List)) { t.TabWindow.Display() } } diff --git a/internal/config/settings.go b/internal/config/settings.go index 26f1cc8d81..45f6b3aad6 100644 --- a/internal/config/settings.go +++ b/internal/config/settings.go @@ -129,6 +129,7 @@ var DefaultGlobalOnlySettings = map[string]any{ "savehistory": true, "scrollbarchar": "|", "sucmd": "sudo", + "tabalways": false, "tabhighlight": false, "tabreverse": true, "xterm": false, diff --git a/runtime/help/options.md b/runtime/help/options.md index 4d086698b7..542089425b 100644 --- a/runtime/help/options.md +++ b/runtime/help/options.md @@ -462,6 +462,10 @@ Here are the available options: default value: `true` +* `tabalways`: always shows the tab bar, even when only one tab is open. + + default value: `false` + * `tabhighlight`: inverts the tab characters' (filename, save indicator, etc) colors with respect to the tab bar. @@ -628,6 +632,7 @@ so that you can see what the formatting should look like. "statusline": true, "sucmd": "sudo", "syntax": true, + "tabalways": false, "tabhighlight": true, "tabmovement": false, "tabreverse": false,