Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions pkg/gocui/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,17 @@ func (g *Gui) SetView(name string, x0, y0, x1, y1 int, overlaps byte) (*View, er
newViewCursorX, newOriginX := updatedCursorAndOrigin(0, v.InnerWidth(), cursorX)
newViewCursorY, newOriginY := updatedCursorAndOrigin(0, v.InnerHeight(), cursorY)

contentWidth := v.TextArea.GetContentWidth()
usableWidth := v.InnerWidth() - 1
maxOriginX := contentWidth - usableWidth
if maxOriginX < 0 {
maxOriginX = 0
}
if newOriginX > maxOriginX {
newOriginX = maxOriginX
newViewCursorX = cursorX - newOriginX
}

v.SetCursor(newViewCursorX, newViewCursorY)
v.SetOrigin(newOriginX, newOriginY)
}
Expand Down
8 changes: 8 additions & 0 deletions pkg/gocui/text_area.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,14 @@ func (self *TextArea) GetUnwrappedContent() string {
return self.content
}

func (self *TextArea) GetContentWidth() int {
if len(self.cells) == 0 {
return 0
}
last := self.cells[len(self.cells)-1]
return last.x + last.width
}

func (self *TextArea) ToggleOverwrite() {
self.overwrite = !self.overwrite
}
Expand Down
11 changes: 11 additions & 0 deletions pkg/gocui/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -1722,6 +1722,17 @@ func (v *View) RenderTextArea() {
newViewCursorX, newOriginX := updatedCursorAndOrigin(prevOriginX, width, cursorX)
newViewCursorY, newOriginY := updatedCursorAndOrigin(prevOriginY, height, cursorY)

contentWidth := v.TextArea.GetContentWidth()
usableWidth := width - 1
maxOriginX := contentWidth - usableWidth
if maxOriginX < 0 {
maxOriginX = 0
}
if newOriginX > maxOriginX {
newOriginX = maxOriginX
newViewCursorX = cursorX - newOriginX
}

v.SetCursor(newViewCursorX, newViewCursorY)
v.SetOrigin(newOriginX, newOriginY)
}
Expand Down
34 changes: 34 additions & 0 deletions pkg/gocui/view_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,40 @@ func TestUpdatedCursorAndOrigin(t *testing.T) {
}
}

func TestRenderTextAreaClampsScrollOffset(t *testing.T) {
// View with inner width 10: x0=0, x1=11 → Width=12, InnerWidth=10
v := NewView("name", 0, 0, 11, 0, OutputNormal)
v.Editable = true

// Type 15 characters to overflow the viewport
for i := 0; i < 15; i++ {
v.TextArea.TypeCharacter("a")
}
// Cursor is at position 15, content width is 15
cursorX, _ := v.TextArea.GetCursorXY()
assert.Equal(t, 15, cursorX)

// Simulate scrolling: set origin so viewport shows positions 6-15
v.SetOrigin(6, 0)
v.RenderTextArea()
originX, _ := v.Origin()
assert.Equal(t, 6, originX)

// Now delete 11 characters so content is only 4 chars wide
for i := 0; i < 11; i++ {
v.TextArea.BackSpaceChar()
}
// Cursor is at position 4, content width is 4
cursorX, _ = v.TextArea.GetCursorXY()
assert.Equal(t, 4, cursorX)
assert.Equal(t, 4, v.TextArea.GetContentWidth())

// After rendering, origin should be clamped to 0 since content (4) < viewport (10)
v.RenderTextArea()
originX, _ = v.Origin()
assert.Equal(t, 0, originX, "origin should be clamped to 0 when content is narrower than viewport")
}

func TestAutoRenderingHyperlinks(t *testing.T) {
v := NewView("name", 0, 0, 10, 10, OutputNormal)
v.AutoRenderHyperLinks = true
Expand Down