diff --git a/main.go b/main.go index 8b3fdb3..ea8c810 100755 --- a/main.go +++ b/main.go @@ -48,6 +48,10 @@ type Cmd struct { Stderr io.ReadCloser } +type Line struct { + StartIndex, EndIndex uint64 +} + var _ engine.Game = &program{} type program struct { @@ -62,6 +66,7 @@ type program struct { gridMesh *meshes.Mesh gridMat *materials.Material + Lines []Line textBuf *ring.Buffer[byte] textBufMutex sync.Mutex @@ -128,6 +133,7 @@ func main() { imguiInfo: nmageimgui.NewImGUI(), FontSize: 40, + Lines: make([]Line, defaultTextBufSize), textBuf: ring.NewBuffer[byte](defaultTextBufSize), cursorCharIndex: 0, @@ -294,7 +300,6 @@ func (p *program) MainUpdate() { p.cursorCharIndex = p.cmdBufLen } - // var a, b uint64 if mouseWheelYNorm := -int64(input.GetMouseWheelYNorm()); mouseWheelYNorm != 0 { var newPosNewLines int64 @@ -304,10 +309,6 @@ func (p *program) MainUpdate() { newPosNewLines, _ = findNLinesIndexIterator(p.textBuf.Iterator(), p.scrollPos, p.scrollSpd*mouseWheelYNorm, p.CellCountX) } - // a = p.textBuf.AbsIndex(uint64(p.scrollPos)) - // b = p.textBuf.AbsIndex(uint64(newPosNewLines)) - // fmt.Printf("was at absIndex %d (char=%d); Now at absIndex %d (char=%d)\n", a, p.textBuf.Get(a), b, p.textBuf.Get(b)) - // assert.T(p.textBuf.Get(uint64(newPosNewLines)) != '\n', fmt.Sprintf("Original AbsIndex %d; New line at AbsIndex %d\n", a, b)) p.scrollPos = clamp(newPosNewLines, 0, p.textBuf.Len) } @@ -619,7 +620,9 @@ func (p *program) HandleReturn() { } // @Todo We need to parse ansi codes as data is coming in to update the drawing settings (e.g. color) - p.WriteToTextBuf(buf[:readBytes]) + b := buf[:readBytes] + p.ParseLines(b) + p.WriteToTextBuf(b) // println("Read:", string(buf[:readBytes])) } }() @@ -652,6 +655,10 @@ func (p *program) HandleReturn() { }() } +func (p *program) ParseLines(b []byte) { + +} + func (p *program) ClearActiveCmd() { if p.activeCmd == nil { @@ -922,7 +929,10 @@ func findNLinesIndexIterator(it ring.Iterator[byte], startIndex, n, charsPerLine } else { // @Todo this has wrong behavior when dealing with wrapped lines because we don't know what X position to be in - // after going up a line. Are we in the middle of the line? + // after going up a line. Are we in the middle of the line? The only way to know is to draw from the start of this paragraph + // till the start index, which will allows us to get accurate information on wrapping. + // + // But this is bad if the paragraph is too big, so we should break paragraphs after a certain size for !done || bytesToKeep > 0 { read, done = it.PrevN(buf[bytesToKeep:], 4) @@ -940,10 +950,6 @@ func findNLinesIndexIterator(it ring.Iterator[byte], startIndex, n, charsPerLine // If this is true we covered one line if charsSeenThisLine == charsPerLine || r == '\n' { - if r == '\n' { - fmt.Printf("Found \\n at index %d\n", it.Curr) - } - charsSeenThisLine = 0 newSize = int64(size) newIndex = startIndex - bytesSeen + newSize diff --git a/ring/ring.go b/ring/ring.go index c29fdd9..08383b5 100755 --- a/ring/ring.go +++ b/ring/ring.go @@ -9,11 +9,16 @@ type Buffer[T any] struct { Start int64 Len int64 Cap int64 + + // WrittenElements is the total number of elements written to the buffer over its lifetime. + // Can be bigger than Cap + WrittenElements uint64 } func (b *Buffer[T]) Write(x ...T) { inLen := int64(len(x)) + b.WrittenElements += uint64(inLen) for len(x) > 0 { @@ -44,40 +49,6 @@ func (b *Buffer[T]) IsFull() bool { return b.Len == b.Cap } -//Insert inserts the given elements starting at the provided index. -// -//Note: Insert is a no-op if the buffer is full or doesn't have enough place for the elements -func (b *Buffer[T]) Insert(index uint64, x ...T) { - - delta := int64(len(x)) - newLen := b.Len + delta - if newLen > b.Cap { - return - } - - copy(b.Data[b.Start+int64(index)+delta:], b.Data[index:]) - copy(b.Data[index:], x) - b.Len = newLen -} - -//DeleteN removes 'n' elements starting at the provided index. -// -//Note DeleteN is a no-op if Len==0 or if buffer is full with start>0 -func (b *Buffer[T]) DeleteN(delStartIndex, n uint64) { - - if b.Len == 0 { - return - } - - if b.Len == b.Cap && b.Start > 0 { - return - } - - relStartIndex := b.Start + int64(delStartIndex) - copy(b.Data[relStartIndex:], b.Data[relStartIndex+int64(n):]) - b.Len = clamp(b.Len-int64(n), 0, b.Cap) -} - func clamp[T constraints.Ordered](x, min, max T) T { if x < min { diff --git a/ring/ring_test.go b/ring/ring_test.go index 05cc09e..32c6a76 100755 --- a/ring/ring_test.go +++ b/ring/ring_test.go @@ -45,50 +45,29 @@ func TestRing(t *testing.T) { b.Write('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i') CheckArr(t, []rune{'i', 'f', 'g', 'h'}, b.Data) - // Input starting in the middle and having to loop back + // Input starting in the middle and having to loop back and WrittenElements b2 := ring.NewBuffer[int](4) + Check(t, 0, b2.WrittenElements) + b2.Write(1, 2, 3) + Check(t, 3, b2.WrittenElements) b2.Write(4, 5) + Check(t, 5, b2.WrittenElements) CheckArr(t, []int{5, 2, 3, 4}, b2.Data) b2.Write(6) + Check(t, 6, b2.WrittenElements) CheckArr(t, []int{5, 6, 3, 4}, b2.Data) b2.Write(7) + Check(t, 7, b2.WrittenElements) CheckArr(t, []int{5, 6, 7, 4}, b2.Data) b2.Write(8) + Check(t, 8, b2.WrittenElements) CheckArr(t, []int{5, 6, 7, 8}, b2.Data) - // Insert - b2 = ring.NewBuffer[int](4) - b2.Write(1, 2) - - b2.Insert(0, 3) - CheckArr(t, []int{3, 1, 2, 0}, b2.Data) - - b2.Insert(3, 4) - CheckArr(t, []int{3, 1, 2, 4}, b2.Data) - - b2.Insert(2, 5, 6) - CheckArr(t, []int{3, 1, 2, 4}, b2.Data) - - // Delete - b2 = ring.NewBuffer[int](4) - b2.Write(1, 2, 3, 4) - - b2.DeleteN(0, 4) - Check(t, 0, b2.Start) - Check(t, 0, b2.Len) - CheckArr(t, []int{1, 2, 3, 4}, b2.Data) - - b2.Write(5, 6, 7, 8) - Check(t, 4, b2.Len) - b2.DeleteN(2, 1) - Check(t, 3, b2.Len) - CheckArr(t, []int{5, 6, 8, 8}, b2.Data) - // ViewsFromTo b2 = ring.NewBuffer[int](4)