@@ -721,41 +721,51 @@ func (s SessionList) renderSessionRow(sess data.Session, selected bool, hidden b
721721 relTime := RelativeTime (sess .LastActiveAt )
722722 turns := strconv .Itoa (sess .TurnCount ) + "t"
723723
724- // Attention dot — 2 chars (dot + space).
724+ // ── Row layout ─────────────────────────────────────────────────────
725+ // [indent 0|2][selector 2][att 2][host 2][plan 2][work 2] summary …
726+ //
727+ // The selector merges cursor pointer and multi-select check into one
728+ // 2-char column, saving 2 chars vs the old separate columns. Combined
729+ // with the reduced tree indent (2 vs 4), the prefix is 4 chars shorter
730+ // than before.
731+
732+ // Selector: combines cursor pointer and multi-select check into 2 chars.
733+ isChecked := s .IsSelected (sess .ID )
734+ var selector string
735+ switch {
736+ case isChecked && selected :
737+ selector = styles .IconCheck () + " "
738+ case isChecked :
739+ selector = styles .IconCheck () + " "
740+ case selected :
741+ selector = " " + styles .IconPointer ()
742+ default :
743+ selector = " "
744+ }
745+
746+ // Status dots — each is a fixed 2 chars (icon + space) for alignment.
725747 attDot := s .attentionDot (sess .ID , selected )
726748
727- // Host type icon — 2 chars (icon + space) if set, else empty.
728- hostIcon := styles .IconHostType (sess .HostType )
729- hostDotW := 0
730- if hostIcon != "" {
731- hostIcon += " "
732- hostDotW = 2
749+ hostDot := styles .IconHostType (sess .HostType )
750+ if hostDot != "" {
751+ hostDot += " "
752+ } else {
753+ hostDot = " "
733754 }
734755
735- // Plan dot — 2 chars (dot + space) if plan exists, else 2 spaces.
736756 plnDot := s .planDot (sess .ID , selected )
737-
738- // Work status dot — 2 chars (icon + space) if work status known, else 2 spaces.
739757 wrkDot := s .workStatusDot (sess .ID , selected )
740758
741759 // In tree mode, indent sessions under their folder.
742760 indent := ""
743761 if s .treeMode {
744- indent = " "
745- w -= 4
746- }
747-
748- indicator := " "
749- if selected {
750- indicator = styles .IconPointer () + " "
751- }
752- // Show check mark for multi-selected sessions.
753- checkMark := " "
754- if s .IsSelected (sess .ID ) {
755- checkMark = styles .IconCheck () + " "
762+ indent = " "
763+ w -= 2
756764 }
757765
766+ const selectorW = 2
758767 const dotW = 2 // attention dot + space
768+ const hostDotW = 2 // host icon + space (always reserved)
759769 const planDotW = 2 // plan dot + space
760770 const wrkDotW = 2 // work status dot + space
761771 const timeW = 9
@@ -764,18 +774,9 @@ func (s SessionList) renderSessionRow(sess data.Session, selected bool, hidden b
764774
765775 // Very narrow terminal: summary + time only.
766776 if w < 50 {
767- summaryW := max (10 , w - 2 - dotW - hostDotW - planDotW - wrkDotW - 2 - timeW - spacing )
768- line := indent + checkMark + indicator + attDot + hostIcon + plnDot + wrkDot + PadRight (summary , summaryW ) + " " + PadLeft (relTime , timeW )
769- if selected {
770- return styles .SelectedStyle .Render (PadToWidth (line , s .width ))
771- }
772- if hidden {
773- return styles .HiddenStyle .Render (PadToWidth (line , s .width ))
774- }
775- if favorited {
776- return styles .FavoritedStyle .Render (PadToWidth (line , s .width ))
777- }
778- return lipgloss .NewStyle ().Render (PadToWidth (line , s .width ))
777+ summaryW := max (10 , w - selectorW - dotW - hostDotW - planDotW - wrkDotW - timeW - spacing )
778+ line := indent + selector + attDot + hostDot + plnDot + wrkDot + PadRight (summary , summaryW ) + " " + PadLeft (relTime , timeW )
779+ return s .applyRowStyle (line , selected , hidden , favorited )
779780 }
780781
781782 // Show folder/repo columns at wider terminals.
@@ -787,7 +788,7 @@ func (s SessionList) renderSessionRow(sess data.Session, selected bool, hidden b
787788 folderW = 18
788789 }
789790
790- summaryW := w - 2 - dotW - hostDotW - planDotW - wrkDotW - 2 - timeW - turnsW - 2 * spacing
791+ summaryW := w - selectorW - dotW - hostDotW - planDotW - wrkDotW - timeW - turnsW - 2 * spacing
791792 if folderW > 0 {
792793 summaryW -= folderW + spacing
793794 }
@@ -800,10 +801,9 @@ func (s SessionList) renderSessionRow(sess data.Session, selected bool, hidden b
800801
801802 var b strings.Builder
802803 b .WriteString (indent )
803- b .WriteString (checkMark )
804- b .WriteString (indicator )
804+ b .WriteString (selector )
805805 b .WriteString (attDot )
806- b .WriteString (hostIcon )
806+ b .WriteString (hostDot )
807807 b .WriteString (plnDot )
808808 b .WriteString (wrkDot )
809809 b .WriteString (PadRight (summary , summaryW ))
@@ -824,18 +824,22 @@ func (s SessionList) renderSessionRow(sess data.Session, selected bool, hidden b
824824 b .WriteString (" " )
825825 b .WriteString (PadLeft (turns , turnsW ))
826826
827- line := b .String ()
827+ return s .applyRowStyle (b .String (), selected , hidden , favorited )
828+ }
828829
830+ // applyRowStyle renders a row line with the appropriate style based on state.
831+ func (s SessionList ) applyRowStyle (line string , selected , hidden , favorited bool ) string {
832+ padded := PadToWidth (line , s .width )
829833 if selected {
830- return styles .SelectedStyle .Render (PadToWidth ( line , s . width ) )
834+ return styles .SelectedStyle .Render (padded )
831835 }
832836 if hidden {
833- return styles .HiddenStyle .Render (PadToWidth ( line , s . width ) )
837+ return styles .HiddenStyle .Render (padded )
834838 }
835839 if favorited {
836- return styles .FavoritedStyle .Render (PadToWidth ( line , s . width ) )
840+ return styles .FavoritedStyle .Render (padded )
837841 }
838- return lipgloss .NewStyle ().Render (PadToWidth ( line , s . width ) )
842+ return lipgloss .NewStyle ().Render (padded )
839843}
840844
841845// renderDot returns a styled 2-character string (icon + space). When selected
0 commit comments