package document import ( "strings" "timshome.page/gilo/internal/gilo" ) type Row struct { chars []rune render []rune } func newRow(s string) *Row { var chars []rune var render []rune for _, ch := range s { chars = append(chars, ch) render = append(render, ch) } return &Row{chars, render} } func (r *Row) Size() int { return len(r.chars) } func (r *Row) RenderSize() int { return len(r.render) } func (r *Row) Render(at *gilo.Point) string { return string(r.render[at.X:]) } func (r *Row) insertRune(ch rune, at int) { // If insertion index is invalid, just // append the rune to the end of the array if at < 0 || at >= r.Size() { r.chars = append(r.chars, ch) r.update() return } var newSlice []rune // Split the character array at the insertion point start := r.chars[0:at] end := r.chars[at:r.Size()] // Splice it back together newSlice = append(newSlice, start...) newSlice = append(newSlice, ch) newSlice = append(newSlice, end...) r.chars = newSlice r.update() } func (r *Row) appendString(str string) { for _, ch := range str { r.chars = append(r.chars, ch) } r.update() } func (r *Row) deleteRune(at int) { if at < 0 || at >= r.Size() { return } var newSlice []rune // Split the character array at the insertion point start := r.chars[0:at] end := r.chars[at+1 : r.Size()] // Skip the index in question // Splice it back together newSlice = append(newSlice, start...) newSlice = append(newSlice, end...) r.chars = newSlice r.update() } func (r *Row) update() { r.render = r.render[:0] replacement := strings.Repeat(" ", gilo.TabSize) str := strings.ReplaceAll(string(r.chars), "\t", replacement) for _, ch := range str { r.render = append(r.render, ch) } } func (r *Row) toString() string { return string(r.chars) } func (r *Row) CursorXToRenderX(cursorX int) (renderX int) { renderX = 0 i := 0 for ; i < cursorX; i++ { if r.chars[i] == '\t' { renderX += (gilo.TabSize - 1) - (renderX % gilo.TabSize) } renderX += 1 } return renderX }