mirror of
https://github.com/bloeys/nterm.git
synced 2025-12-29 14:38:19 +00:00
Remove insert/delete from ring+track total written elements to ring
This commit is contained in:
28
main.go
28
main.go
@ -48,6 +48,10 @@ type Cmd struct {
|
|||||||
Stderr io.ReadCloser
|
Stderr io.ReadCloser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Line struct {
|
||||||
|
StartIndex, EndIndex uint64
|
||||||
|
}
|
||||||
|
|
||||||
var _ engine.Game = &program{}
|
var _ engine.Game = &program{}
|
||||||
|
|
||||||
type program struct {
|
type program struct {
|
||||||
@ -62,6 +66,7 @@ type program struct {
|
|||||||
gridMesh *meshes.Mesh
|
gridMesh *meshes.Mesh
|
||||||
gridMat *materials.Material
|
gridMat *materials.Material
|
||||||
|
|
||||||
|
Lines []Line
|
||||||
textBuf *ring.Buffer[byte]
|
textBuf *ring.Buffer[byte]
|
||||||
textBufMutex sync.Mutex
|
textBufMutex sync.Mutex
|
||||||
|
|
||||||
@ -128,6 +133,7 @@ func main() {
|
|||||||
imguiInfo: nmageimgui.NewImGUI(),
|
imguiInfo: nmageimgui.NewImGUI(),
|
||||||
FontSize: 40,
|
FontSize: 40,
|
||||||
|
|
||||||
|
Lines: make([]Line, defaultTextBufSize),
|
||||||
textBuf: ring.NewBuffer[byte](defaultTextBufSize),
|
textBuf: ring.NewBuffer[byte](defaultTextBufSize),
|
||||||
|
|
||||||
cursorCharIndex: 0,
|
cursorCharIndex: 0,
|
||||||
@ -294,7 +300,6 @@ func (p *program) MainUpdate() {
|
|||||||
p.cursorCharIndex = p.cmdBufLen
|
p.cursorCharIndex = p.cmdBufLen
|
||||||
}
|
}
|
||||||
|
|
||||||
// var a, b uint64
|
|
||||||
if mouseWheelYNorm := -int64(input.GetMouseWheelYNorm()); mouseWheelYNorm != 0 {
|
if mouseWheelYNorm := -int64(input.GetMouseWheelYNorm()); mouseWheelYNorm != 0 {
|
||||||
|
|
||||||
var newPosNewLines int64
|
var newPosNewLines int64
|
||||||
@ -304,10 +309,6 @@ func (p *program) MainUpdate() {
|
|||||||
newPosNewLines, _ = findNLinesIndexIterator(p.textBuf.Iterator(), p.scrollPos, p.scrollSpd*mouseWheelYNorm, p.CellCountX)
|
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)
|
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)
|
// @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]))
|
// println("Read:", string(buf[:readBytes]))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -652,6 +655,10 @@ func (p *program) HandleReturn() {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *program) ParseLines(b []byte) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (p *program) ClearActiveCmd() {
|
func (p *program) ClearActiveCmd() {
|
||||||
|
|
||||||
if p.activeCmd == nil {
|
if p.activeCmd == nil {
|
||||||
@ -922,7 +929,10 @@ func findNLinesIndexIterator(it ring.Iterator[byte], startIndex, n, charsPerLine
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
// @Todo this has wrong behavior when dealing with wrapped lines because we don't know what X position to be in
|
// @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 {
|
for !done || bytesToKeep > 0 {
|
||||||
|
|
||||||
read, done = it.PrevN(buf[bytesToKeep:], 4)
|
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 this is true we covered one line
|
||||||
if charsSeenThisLine == charsPerLine || r == '\n' {
|
if charsSeenThisLine == charsPerLine || r == '\n' {
|
||||||
|
|
||||||
if r == '\n' {
|
|
||||||
fmt.Printf("Found \\n at index %d\n", it.Curr)
|
|
||||||
}
|
|
||||||
|
|
||||||
charsSeenThisLine = 0
|
charsSeenThisLine = 0
|
||||||
newSize = int64(size)
|
newSize = int64(size)
|
||||||
newIndex = startIndex - bytesSeen + newSize
|
newIndex = startIndex - bytesSeen + newSize
|
||||||
|
|||||||
39
ring/ring.go
39
ring/ring.go
@ -9,11 +9,16 @@ type Buffer[T any] struct {
|
|||||||
Start int64
|
Start int64
|
||||||
Len int64
|
Len int64
|
||||||
Cap 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) {
|
func (b *Buffer[T]) Write(x ...T) {
|
||||||
|
|
||||||
inLen := int64(len(x))
|
inLen := int64(len(x))
|
||||||
|
b.WrittenElements += uint64(inLen)
|
||||||
|
|
||||||
for len(x) > 0 {
|
for len(x) > 0 {
|
||||||
|
|
||||||
@ -44,40 +49,6 @@ func (b *Buffer[T]) IsFull() bool {
|
|||||||
return b.Len == b.Cap
|
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 {
|
func clamp[T constraints.Ordered](x, min, max T) T {
|
||||||
|
|
||||||
if x < min {
|
if x < min {
|
||||||
|
|||||||
@ -45,50 +45,29 @@ func TestRing(t *testing.T) {
|
|||||||
b.Write('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')
|
b.Write('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')
|
||||||
CheckArr(t, []rune{'i', 'f', 'g', 'h'}, b.Data)
|
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)
|
b2 := ring.NewBuffer[int](4)
|
||||||
|
Check(t, 0, b2.WrittenElements)
|
||||||
|
|
||||||
b2.Write(1, 2, 3)
|
b2.Write(1, 2, 3)
|
||||||
|
Check(t, 3, b2.WrittenElements)
|
||||||
|
|
||||||
b2.Write(4, 5)
|
b2.Write(4, 5)
|
||||||
|
Check(t, 5, b2.WrittenElements)
|
||||||
CheckArr(t, []int{5, 2, 3, 4}, b2.Data)
|
CheckArr(t, []int{5, 2, 3, 4}, b2.Data)
|
||||||
|
|
||||||
b2.Write(6)
|
b2.Write(6)
|
||||||
|
Check(t, 6, b2.WrittenElements)
|
||||||
CheckArr(t, []int{5, 6, 3, 4}, b2.Data)
|
CheckArr(t, []int{5, 6, 3, 4}, b2.Data)
|
||||||
|
|
||||||
b2.Write(7)
|
b2.Write(7)
|
||||||
|
Check(t, 7, b2.WrittenElements)
|
||||||
CheckArr(t, []int{5, 6, 7, 4}, b2.Data)
|
CheckArr(t, []int{5, 6, 7, 4}, b2.Data)
|
||||||
|
|
||||||
b2.Write(8)
|
b2.Write(8)
|
||||||
|
Check(t, 8, b2.WrittenElements)
|
||||||
CheckArr(t, []int{5, 6, 7, 8}, b2.Data)
|
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
|
// ViewsFromTo
|
||||||
b2 = ring.NewBuffer[int](4)
|
b2 = ring.NewBuffer[int](4)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user