@@ -113,8 +113,9 @@ type Model struct {
113113 actionStack []StagedAction
114114
115115 // Rename mode
116- renameMode bool
117- renameInput textinput.Model
116+ renameMode bool
117+ renameInput textinput.Model
118+ renameOriginal string // original branch name shown as label
118119
119120 // Help overlay
120121 showHelp bool
@@ -701,7 +702,9 @@ func (m *Model) startRename() {
701702 }
702703
703704 m .renameMode = true
705+ m .renameOriginal = node .Ref .Branch
704706 m .renameInput .SetValue (node .Ref .Branch )
707+ m .renameInput .Prompt = ""
705708 m .renameInput .Focus ()
706709 m .renameInput .CursorEnd ()
707710}
@@ -830,7 +833,7 @@ func (m Model) nodeLineCount(idx int) int {
830833}
831834
832835func (m Model ) contentViewHeight () int {
833- reserved := 1 // status line
836+ reserved := 3 // post-scroll newline + context line + status bar
834837 if shared .ShouldShowHeader (m .width , m .height ) {
835838 reserved += shared .HeaderHeight
836839 }
@@ -983,55 +986,51 @@ func (m Model) View() string {
983986 shared .RenderHeader (& out , m .buildHeaderConfig (), m .width , m .height )
984987 }
985988
989+ // Build the scrollable branch list content
986990 var b strings.Builder
987-
988- // Branch list — all nodes rendered with shared renderer, annotations for pending actions
989991 for i := 0 ; i < len (m .nodes ); i ++ {
990992 nodeData := toNodeData (m .nodes [i ], i )
991993 isFocused := i == m .cursor
992994 annotation := nodeAnnotation (m .nodes [i ], i )
993995 shared .RenderNode (& b , nodeData , isFocused , m .width , annotation )
994996 }
995-
996- // Trunk
997997 shared .RenderTrunk (& b , m .trunk .Branch )
998998
999- // Rename input line (if in rename mode)
1000- if m .renameMode {
1001- b .WriteString ("\n " )
1002- b .WriteString (renameBadge .Render ("Rename: " ))
1003- b .WriteString (m .renameInput .View ())
1004- b .WriteString ("\n " )
1005- }
1006-
1007- // Transient status message
1008- if m .statusMessage != "" {
1009- b .WriteString ("\n " )
1010- if m .statusIsError {
1011- b .WriteString (transientErrorStyle .Render ("✗ " + m .statusMessage ))
1012- } else {
1013- b .WriteString (transientInfoStyle .Render (m .statusMessage ))
1014- }
1015- b .WriteString ("\n " )
1016- }
1017-
1018- content := b .String ()
999+ // Count fixed bottom lines (always visible, not scrollable).
1000+ // The bottom section always has 2 lines: one for contextual info
1001+ // (rename prompt or error, blank when neither) and one for the status bar.
1002+ bottomLines := 2 // post-scroll newline + context line + status bar
10191003
1020- // Scrolling
1021- reservedLines := 0
1004+ // Scrolling — reserve space for header and fixed bottom
1005+ reservedLines := bottomLines
10221006 if showHeader {
1023- reservedLines = shared .HeaderHeight
1007+ reservedLines + = shared .HeaderHeight
10241008 }
1025- viewHeight := m .height - reservedLines - 1 // -1 for status line
1009+ viewHeight := m .height - reservedLines
10261010 if viewHeight < 1 {
10271011 viewHeight = 1
10281012 }
10291013
1030- out .WriteString (shared .ApplyScrollToContent (content , m .scrollOffset , viewHeight ))
1014+ out .WriteString (shared .ApplyScrollToContent (b . String () , m .scrollOffset , viewHeight ))
10311015 out .WriteString ("\n " )
10321016
1033- // Status line at the bottom
1034- out .WriteString (renderStatusLine (m .nodes , m .width ))
1017+ // Second-to-bottom: error/status message line (always present, blank when empty)
1018+ if m .statusMessage != "" {
1019+ if m .statusIsError {
1020+ out .WriteString (transientErrorStyle .Render ("✗ " + m .statusMessage ))
1021+ } else {
1022+ out .WriteString (transientInfoStyle .Render (m .statusMessage ))
1023+ }
1024+ }
1025+
1026+ // Bottom line: rename prompt (when active) or status bar
1027+ out .WriteString ("\n " )
1028+ if m .renameMode {
1029+ out .WriteString (renameBadge .Render (fmt .Sprintf ("Rename: %s → " , m .renameOriginal )))
1030+ out .WriteString (m .renameInput .View ())
1031+ } else {
1032+ out .WriteString (renderStatusLine (m .nodes , m .width ))
1033+ }
10351034
10361035 return out .String ()
10371036}
@@ -1079,12 +1078,12 @@ func (m Model) buildHeaderConfig() shared.HeaderConfig {
10791078 ShortcutColumns : 2 ,
10801079 Shortcuts : []shared.ShortcutEntry {
10811080 // Left column // Right column
1082- {Key : "↑↓" , Desc : "select branch" }, {Key : "x" , Desc : "drop" , Disabled : structureDisabled },
1083- {Key : "f" , Desc : "view files" }, {Key : "r" , Desc : "rename" , Disabled : structureDisabled },
1084- {Key : "c" , Desc : "view commits" }, {Key : "u" , Desc : "fold up" , Disabled : structureDisabled },
1085- {Key : "?" , Desc : "help" }, {Key : "d" , Desc : "fold down" , Disabled : structureDisabled },
1086- {Key : "q/esc" , Desc : "quit" }, {Key : "shift+↑↓" , Desc : "reorder" , Disabled : reorderDisabled },
1087- {Key : "^S" , Desc : "apply changes" }, {Key : "z" , Desc : "undo" },
1081+ {Key : "↑↓" , Desc : "select branch" }, {Key : "x" , Desc : "drop" , Disabled : structureDisabled },
1082+ {Key : "f" , Desc : "view files" }, {Key : "r" , Desc : "rename" , Disabled : structureDisabled },
1083+ {Key : "c" , Desc : "view commits" }, {Key : "u" , Desc : "fold up" , Disabled : structureDisabled },
1084+ {Key : "?" , Desc : "help" }, {Key : "d" , Desc : "fold down" , Disabled : structureDisabled },
1085+ {Key : "q/esc" , Desc : "quit" }, {Key : "shift+↑↓" , Desc : "reorder" , Disabled : reorderDisabled },
1086+ {Key : "^S" , Desc : "apply changes" }, {Key : "z" , Desc : "undo" },
10881087 },
10891088 }
10901089}
0 commit comments