diff --git a/textview.go b/textview.go index 0d30be3..6cc5c91 100644 --- a/textview.go +++ b/textview.go @@ -136,6 +136,9 @@ type TextView struct { // The index of the first line shown in the text view. lineOffset int + // The maximum number of liens the text view will hold (set to 0 for no limit) + maxLines int + // If set to true, the text view will always remain at the end of the content. trackEnd bool @@ -203,6 +206,7 @@ func NewTextView() *TextView { textColor: Styles.PrimaryTextColor, regions: false, dynamicColors: false, + maxLines: 0, } } @@ -389,6 +393,23 @@ func (t *TextView) SetHighlightedFunc(handler func(added, removed, remaining []s return t } +func (t *TextView) clipBuffer() { + if t.maxLines > 0 { + lenbuf := len(t.buffer) + if lenbuf > t.maxLines { + t.buffer = t.buffer[lenbuf-t.maxLines:] + } + } +} + +// SetMaxLines establishes the maximum amount of lines the text view will hold +// before discarding older data from the buffer +func (t *TextView) SetMaxLines(maxLines int) *TextView { + t.maxLines = maxLines + t.clipBuffer() + return t +} + // ScrollTo scrolls to the specified row and column (both starting with 0). func (t *TextView) ScrollTo(row, column int) *TextView { t.Lock() @@ -722,6 +743,8 @@ func (t *TextView) write(p []byte) (n int, err error) { } } + t.clipBuffer() + // Reset the index. t.index = nil diff --git a/textview_test.go b/textview_test.go index eff18c0..5d435a5 100644 --- a/textview_test.go +++ b/textview_test.go @@ -3,6 +3,7 @@ package cview import ( "bytes" "fmt" + "strings" "testing" ) @@ -195,6 +196,48 @@ func BenchmarkTextViewDraw(b *testing.B) { } } +func TestTextViewMaxLines(t *testing.T) { + tv := NewTextView() + + // append 100 lines with no limit set: + for i := 0; i < 100; i++ { + tv.Write([]byte(fmt.Sprintf("L%d\n", i))) + } + + // retrieve the total text and see we have the 100 lines: + count := strings.Count(tv.GetText(true), "\n") + if count != 100 { + t.Fatalf("Expected 100 lines, got %d", count) + } + + // now set the maximum lines to 20, this should clip the buffer: + tv.SetMaxLines(20) + // verify buffer was clipped: + count = len(strings.Split(tv.GetText(true), "\n")) + if count != 20 { + t.Fatalf("Expected 20 lines, got %d", count) + } + + // append 100 more lines: + for i := 100; i < 200; i++ { + tv.Write([]byte(fmt.Sprintf("L%d\n", i))) + } + + // Sice max lines is set to 20, we should still get 20 lines: + txt := tv.GetText(true) + lines := strings.Split(txt, "\n") + count = len(lines) + if count != 20 { + t.Fatalf("Expected 20 lines, got %d", count) + } + + // and those 20 lines should be the last ones: + if lines[0] != "L181" { + t.Fatalf("Expected to get L181, got %s", lines[0]) + } + +} + func generateTestCases() []*textViewTestCase { var cases []*textViewTestCase for i := 0; i < 2; i++ {