Initial patterm project
This commit is contained in:
70
internal/app/tabbar.go
Normal file
70
internal/app/tabbar.go
Normal file
@@ -0,0 +1,70 @@
|
||||
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())
|
||||
}
|
||||
Reference in New Issue
Block a user