71 lines
1.4 KiB
Go
71 lines
1.4 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
const tabBarRows = 1
|
|
|
|
// drawTabBar renders SPEC §4's top tab bar at row 1. Tabs are top-level
|
|
// children (ParentID == ""); the focused tab is highlighted. The PTY
|
|
// region begins at row 2.
|
|
func (st *uiState) drawTabBar() {
|
|
st.mu.Lock()
|
|
palOpen := st.palette != nil
|
|
focus := st.focusedID
|
|
st.mu.Unlock()
|
|
if palOpen {
|
|
return
|
|
}
|
|
layout := st.layoutSnapshot()
|
|
width := int(layout.childCols())
|
|
|
|
var sessions []*Child
|
|
for _, c := range st.sess.Children() {
|
|
if c.ParentID == "" && c.Status() == StatusRunning {
|
|
sessions = append(sessions, c)
|
|
}
|
|
}
|
|
|
|
var b strings.Builder
|
|
b.WriteString("\x1b[1;1H")
|
|
cur := 0
|
|
for _, c := range sessions {
|
|
label := c.Name
|
|
seg := " " + label + " "
|
|
if cur+len(seg) > width-2 {
|
|
break
|
|
}
|
|
if c.ID == focus {
|
|
b.WriteString("\x1b[7m")
|
|
} else {
|
|
b.WriteString("\x1b[2m")
|
|
}
|
|
b.WriteString(seg)
|
|
b.WriteString("\x1b[0m")
|
|
cur += len(seg)
|
|
}
|
|
// "+" hint at end.
|
|
hint := "+"
|
|
if cur > 0 {
|
|
hint = " +"
|
|
}
|
|
if cur+len(hint) <= width {
|
|
b.WriteString("\x1b[2m")
|
|
b.WriteString(hint)
|
|
b.WriteString("\x1b[0m")
|
|
cur += len(hint)
|
|
}
|
|
// Fill the rest of the tab-bar row so stale chars don't linger.
|
|
if width-cur > 0 {
|
|
b.WriteString(strings.Repeat(" ", width-cur))
|
|
}
|
|
|
|
st.outMu.Lock()
|
|
defer st.outMu.Unlock()
|
|
// Save cursor, paint, restore.
|
|
fmt.Fprintf(os.Stdout, "\x1b7%s\x1b8", b.String())
|
|
}
|