Improve tmux statusline: sort rigs by activity and add visual grouping (#337)
* Improve tmux statusline: sort rigs by activity and add visual grouping - Sort rigs by running state, then polecat count, then operational state - Add visual grouping with | separators between state groups - Show process state with icons (🟢 both running, 🟡 one running, 🅿️ parked, 🛑 docked, ⚫ idle) - Display polecat counts for active rigs - Improve icon spacing: 2 spaces after Park emoji, 1 space for others * Fix golangci-lint warnings - Check error return from os.Setenv - Check error return from lock.Unlock - Mark intentionally unused parameters with _ --------- Co-authored-by: joshuavial <git@codewithjv.com>
This commit is contained in:
@@ -182,10 +182,12 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track per-rig status for LED indicators
|
// Track per-rig status for LED indicators and sorting
|
||||||
type rigStatus struct {
|
type rigStatus struct {
|
||||||
hasWitness bool
|
hasWitness bool
|
||||||
hasRefinery bool
|
hasRefinery bool
|
||||||
|
polecatCount int
|
||||||
|
opState string // "OPERATIONAL", "PARKED", or "DOCKED"
|
||||||
}
|
}
|
||||||
rigStatuses := make(map[string]*rigStatus)
|
rigStatuses := make(map[string]*rigStatus)
|
||||||
|
|
||||||
@@ -212,10 +214,21 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
rigStatuses[agent.Rig].hasRefinery = true
|
rigStatuses[agent.Rig].hasRefinery = true
|
||||||
case AgentPolecat:
|
case AgentPolecat:
|
||||||
polecatCount++
|
polecatCount++
|
||||||
|
rigStatuses[agent.Rig].polecatCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get operational state for each rig
|
||||||
|
for rigName, status := range rigStatuses {
|
||||||
|
opState, _ := getRigOperationalState(townRoot, rigName)
|
||||||
|
if opState == "PARKED" || opState == "DOCKED" {
|
||||||
|
status.opState = opState
|
||||||
|
} else {
|
||||||
|
status.opState = "OPERATIONAL"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Build status
|
// Build status
|
||||||
var parts []string
|
var parts []string
|
||||||
parts = append(parts, fmt.Sprintf("%d 😺", polecatCount))
|
parts = append(parts, fmt.Sprintf("%d 😺", polecatCount))
|
||||||
@@ -223,30 +236,96 @@ func runMayorStatusLine(t *tmux.Tmux) error {
|
|||||||
// Build rig status display with LED indicators
|
// Build rig status display with LED indicators
|
||||||
// 🟢 = both witness and refinery running (fully active)
|
// 🟢 = both witness and refinery running (fully active)
|
||||||
// 🟡 = one of witness/refinery running (partially active)
|
// 🟡 = one of witness/refinery running (partially active)
|
||||||
// ⚫ = neither running (inactive)
|
// 🅿️ = parked (nothing running, intentionally paused)
|
||||||
var rigParts []string
|
// 🛑 = docked (nothing running, global shutdown)
|
||||||
var rigNames []string
|
// ⚫ = operational but nothing running (unexpected state)
|
||||||
for rigName := range rigStatuses {
|
|
||||||
rigNames = append(rigNames, rigName)
|
|
||||||
}
|
|
||||||
sort.Strings(rigNames)
|
|
||||||
|
|
||||||
for _, rigName := range rigNames {
|
// Create sortable rig list
|
||||||
status := rigStatuses[rigName]
|
type rigInfo struct {
|
||||||
|
name string
|
||||||
|
status *rigStatus
|
||||||
|
}
|
||||||
|
var rigs []rigInfo
|
||||||
|
for rigName, status := range rigStatuses {
|
||||||
|
rigs = append(rigs, rigInfo{name: rigName, status: status})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by: 1) running state, 2) polecat count (desc), 3) operational state, 4) alphabetical
|
||||||
|
sort.Slice(rigs, func(i, j int) bool {
|
||||||
|
isRunningI := rigs[i].status.hasWitness || rigs[i].status.hasRefinery
|
||||||
|
isRunningJ := rigs[j].status.hasWitness || rigs[j].status.hasRefinery
|
||||||
|
|
||||||
|
// Primary sort: running rigs before non-running rigs
|
||||||
|
if isRunningI != isRunningJ {
|
||||||
|
return isRunningI
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secondary sort: polecat count (descending)
|
||||||
|
if rigs[i].status.polecatCount != rigs[j].status.polecatCount {
|
||||||
|
return rigs[i].status.polecatCount > rigs[j].status.polecatCount
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tertiary sort: operational state (for non-running rigs: OPERATIONAL < PARKED < DOCKED)
|
||||||
|
stateOrder := map[string]int{"OPERATIONAL": 0, "PARKED": 1, "DOCKED": 2}
|
||||||
|
stateI := stateOrder[rigs[i].status.opState]
|
||||||
|
stateJ := stateOrder[rigs[j].status.opState]
|
||||||
|
if stateI != stateJ {
|
||||||
|
return stateI < stateJ
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quaternary sort: alphabetical
|
||||||
|
return rigs[i].name < rigs[j].name
|
||||||
|
})
|
||||||
|
|
||||||
|
// Build display with group separators
|
||||||
|
var rigParts []string
|
||||||
|
var lastGroup string
|
||||||
|
for _, rig := range rigs {
|
||||||
|
isRunning := rig.status.hasWitness || rig.status.hasRefinery
|
||||||
|
var currentGroup string
|
||||||
|
if isRunning {
|
||||||
|
currentGroup = "running"
|
||||||
|
} else {
|
||||||
|
currentGroup = "idle-" + rig.status.opState
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add separator when group changes (running -> non-running, or different opStates within non-running)
|
||||||
|
if lastGroup != "" && lastGroup != currentGroup {
|
||||||
|
rigParts = append(rigParts, "|")
|
||||||
|
}
|
||||||
|
lastGroup = currentGroup
|
||||||
|
|
||||||
|
status := rig.status
|
||||||
var led string
|
var led string
|
||||||
|
|
||||||
// Check if rig is parked or docked
|
// Check if processes are running first (regardless of operational state)
|
||||||
opState, _ := getRigOperationalState(townRoot, rigName)
|
if status.hasWitness && status.hasRefinery {
|
||||||
if opState == "PARKED" || opState == "DOCKED" {
|
|
||||||
led = "⏸️" // Parked/docked - intentionally offline
|
|
||||||
} else if status.hasWitness && status.hasRefinery {
|
|
||||||
led = "🟢" // Both running - fully active
|
led = "🟢" // Both running - fully active
|
||||||
} else if status.hasWitness || status.hasRefinery {
|
} else if status.hasWitness || status.hasRefinery {
|
||||||
led = "🟡" // One running - partially active
|
led = "🟡" // One running - partially active
|
||||||
} else {
|
} else {
|
||||||
led = "⚫" // Neither running - inactive
|
// Nothing running - show operational state
|
||||||
|
switch status.opState {
|
||||||
|
case "PARKED":
|
||||||
|
led = "🅿️" // Parked - intentionally paused
|
||||||
|
case "DOCKED":
|
||||||
|
led = "🛑" // Docked - global shutdown
|
||||||
|
default:
|
||||||
|
led = "⚫" // Operational but nothing running
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rigParts = append(rigParts, led+rigName)
|
|
||||||
|
// Show polecat count if > 0
|
||||||
|
// All icons get 1 space, Park gets 2
|
||||||
|
space := " "
|
||||||
|
if led == "🅿️" {
|
||||||
|
space = " "
|
||||||
|
}
|
||||||
|
display := led + space + rig.name
|
||||||
|
if status.polecatCount > 0 {
|
||||||
|
display += fmt.Sprintf("(%d)", status.polecatCount)
|
||||||
|
}
|
||||||
|
rigParts = append(rigParts, display)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rigParts) > 0 {
|
if len(rigParts) > 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user