fix: added gutter fix and basic scroll
All checks were successful
Run Test Suite / test (push) Successful in 15s

Scrolling is pretty useless, but nice touch
This commit is contained in:
Hayden Hargreaves 2026-04-05 00:16:19 -07:00
parent a5ff18e1de
commit 58082afdd2
3 changed files with 86 additions and 67 deletions

View File

@ -23,11 +23,13 @@ func main() {
prog = program.NewProgramBuilder(). prog = program.NewProgramBuilder().
EmptyProgram(). EmptyProgram().
WithOpt(tea.WithAltScreen()). WithOpt(tea.WithAltScreen()).
WithOpt(tea.WithMouseCellMotion()).
Build() Build()
} else { } else {
prog = program.NewProgramBuilder(). prog = program.NewProgramBuilder().
FileProgram(args[0]). FileProgram(args[0]).
WithOpt(tea.WithAltScreen()). WithOpt(tea.WithAltScreen()).
WithOpt(tea.WithMouseCellMotion()).
Build() Build()
} }

View File

@ -1,83 +1,95 @@
package editor package editor
import ( import (
"git.gophernest.net/azpect/TextEditor/internal/core" "git.gophernest.net/azpect/TextEditor/internal/core"
tea "github.com/charmbracelet/bubbletea" "git.gophernest.net/azpect/TextEditor/internal/motion"
tea "github.com/charmbracelet/bubbletea"
) )
// Model.Update: Handles BubbleTea messages including window resizes and key // Model.Update: Handles BubbleTea messages including window resizes and key
// presses. Routes input to the handler and adjusts scroll after updates. // presses. Routes input to the handler and adjusts scroll after updates.
func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd var cmd tea.Cmd
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.WindowSizeMsg: case tea.WindowSizeMsg:
m.termHeight = msg.Height m.termHeight = msg.Height
m.termWidth = msg.Width m.termWidth = msg.Width
// TODO: Implement a layout method that handles this // TODO: Implement a layout method that handles this
// //
// func (m *Model) layoutWindows() { // func (m *Model) layoutWindows() {
// if len(m.windows) == 0 { // if len(m.windows) == 0 {
// return // return
// } // }
// //
// if len(m.windows) == 1 { // if len(m.windows) == 1 {
// // Single window - full screen // // Single window - full screen
// m.windows[0].Width = m.termWidth // m.windows[0].Width = m.termWidth
// m.windows[0].Height = m.termHeight // m.windows[0].Height = m.termHeight
// return // return
// } // }
// //
// // Multiple windows - distribute space // // Multiple windows - distribute space
// // This is where you'd implement split layout logic // // This is where you'd implement split layout logic
// // For example, horizontal split: // // For example, horizontal split:
// halfHeight := m.termHeight / 2 // halfHeight := m.termHeight / 2
// for i, win := range m.windows { // for i, win := range m.windows {
// win.Width = m.termWidth // win.Width = m.termWidth
// if i < len(m.windows)-1 { // if i < len(m.windows)-1 {
// win.Height = halfHeight // win.Height = halfHeight
// } else { // } else {
// // Last window gets remainder // // Last window gets remainder
// win.Height = m.termHeight - (halfHeight * (len(m.windows) - 1)) // win.Height = m.termHeight - (halfHeight * (len(m.windows) - 1))
// } // }
// } // }
// } // }
for i := range m.windows { for i := range m.windows {
m.windows[i].Height = msg.Height m.windows[i].Height = msg.Height
m.windows[i].Width = msg.Width m.windows[i].Width = msg.Width
} }
case tea.KeyMsg: // TODO: This is not great, totally temporary. But I don't like vim's handling, so this is up to me
// TODO: This needs to be removed, but for now its required for the tests. case tea.MouseMsg:
// Ctrl+C always quits regardless of mode switch msg.Button {
if msg.Type == tea.KeyCtrlC { case tea.MouseButtonWheelUp:
return m, tea.Quit scrollAction := motion.ScrollUpPage{Divisor: 4} // Quarter page
} cmd = scrollAction.Execute(m)
case tea.MouseButtonWheelDown:
scrollAction := motion.ScrollDownPage{Divisor: 4} // Quarter page
cmd = scrollAction.Execute(m)
}
// TODO: This is not great case tea.KeyMsg:
// TODO: Any vim action should exit also // TODO: This needs to be removed, but for now its required for the tests.
// Simple override for command output mode for now // Ctrl+C always quits regardless of mode
if m.Mode() == core.CommandOutputMode { if msg.Type == tea.KeyCtrlC {
// TODO: Implement g/G/d/u return m, tea.Quit
switch msg.String() { }
case "enter":
m.SetMode(core.NormalMode)
m.SetCommandOutput(&core.CommandOutput{})
case "j":
m.CommandOutput().ScrollDown(m.termHeight)
case "k":
m.CommandOutput().ScrollUp()
}
} else {
cmd = m.input.Handle(m, msg.String())
}
}
// Keep cursor in view after any update // TODO: This is not great
win := m.ActiveWindow() // TODO: Any vim action should exit also
win.AdjustScroll() // Simple override for command output mode for now
if m.Mode() == core.CommandOutputMode {
// TODO: Implement g/G/d/u
switch msg.String() {
case "enter":
m.SetMode(core.NormalMode)
m.SetCommandOutput(&core.CommandOutput{})
case "j":
m.CommandOutput().ScrollDown(m.termHeight)
case "k":
m.CommandOutput().ScrollUp()
}
} else {
cmd = m.input.Handle(m, msg.String())
}
}
return m, cmd // Keep cursor in view after any update
win := m.ActiveWindow()
win.AdjustScroll()
return m, cmd
} }

View File

@ -2,6 +2,7 @@ package editor
import ( import (
"fmt" "fmt"
"strconv"
"strings" "strings"
"git.gophernest.net/azpect/TextEditor/internal/core" "git.gophernest.net/azpect/TextEditor/internal/core"
@ -22,6 +23,10 @@ func (m Model) View() string {
styles := m.Styles() styles := m.Styles()
options := win.Options options := win.Options
// Adjust gutter to fit line len
maxLineLen := len(strconv.Itoa(win.Buffer.LineCount()))
options.GutterSize = max(options.GutterSize, maxLineLen+2)
// Draw window // Draw window
view := viewWindow(win, styles, options, m.Mode()) view := viewWindow(win, styles, options, m.Mode())