100 lines
2.0 KiB
Go
100 lines
2.0 KiB
Go
package buffer
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"unicode"
|
||
|
|
"unicode/utf8"
|
||
|
|
|
||
|
|
"code.chimeric.al/dwrz/wen/internal/editor/buffer/glyph"
|
||
|
|
"code.chimeric.al/dwrz/wen/internal/editor/buffer/line"
|
||
|
|
)
|
||
|
|
|
||
|
|
func (b *Buffer) Backspace() {
|
||
|
|
var cl = b.CursorLine()
|
||
|
|
|
||
|
|
switch {
|
||
|
|
// Don't do anything at the beginning of the buffer.
|
||
|
|
case b.cursor.line == 0 && b.cursor.index == 0:
|
||
|
|
|
||
|
|
// Delete empty lines.
|
||
|
|
case cl.Length() == 0:
|
||
|
|
b.lines = append(
|
||
|
|
b.lines[:b.cursor.line],
|
||
|
|
b.lines[b.cursor.line+1:]...,
|
||
|
|
)
|
||
|
|
|
||
|
|
b.CursorUp()
|
||
|
|
b.CursorEnd()
|
||
|
|
|
||
|
|
// Append to the previous line.
|
||
|
|
case b.cursor.line != 0 && b.cursor.index == 0:
|
||
|
|
index := b.cursor.line
|
||
|
|
|
||
|
|
b.CursorUp()
|
||
|
|
b.CursorEnd()
|
||
|
|
|
||
|
|
b.lines[index-1].Append(cl.String())
|
||
|
|
|
||
|
|
b.lines = append(
|
||
|
|
b.lines[:index],
|
||
|
|
b.lines[index+1:]...,
|
||
|
|
)
|
||
|
|
|
||
|
|
// Delete a rune.
|
||
|
|
default:
|
||
|
|
b.CursorLeft()
|
||
|
|
b.CursorLine().DeleteRune(b.cursor.index)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (b *Buffer) Insert(r rune) {
|
||
|
|
switch {
|
||
|
|
case r == '\n' || r == '\r':
|
||
|
|
b.Newline()
|
||
|
|
|
||
|
|
case r == '\t':
|
||
|
|
b.CursorLine().Insert(b.cursor.index, r)
|
||
|
|
b.cursor.index += utf8.RuneLen(r)
|
||
|
|
b.cursor.glyph += glyph.Width(r)
|
||
|
|
|
||
|
|
// Ignore all other non-printable characters.
|
||
|
|
case !unicode.IsPrint(r):
|
||
|
|
return
|
||
|
|
|
||
|
|
default:
|
||
|
|
b.CursorLine().Insert(b.cursor.index, r)
|
||
|
|
b.cursor.index += utf8.RuneLen(r)
|
||
|
|
b.cursor.glyph += glyph.Width(r)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// At the start of a line, create a new line above.
|
||
|
|
// At the end of the line, create a new line below.
|
||
|
|
// In the middle of a line, any remaining runes go to the next line.
|
||
|
|
// TODO: using the cursor index will probably break with marks.
|
||
|
|
func (b *Buffer) Newline() {
|
||
|
|
var cl = b.CursorLine()
|
||
|
|
|
||
|
|
switch {
|
||
|
|
case b.cursor.index == 0:
|
||
|
|
b.lines = append(
|
||
|
|
b.lines[:b.cursor.line+1],
|
||
|
|
b.lines[b.cursor.line:]...,
|
||
|
|
)
|
||
|
|
b.lines[b.cursor.line] = line.New("")
|
||
|
|
|
||
|
|
default:
|
||
|
|
text := cl.String()
|
||
|
|
rest := line.New(text[b.cursor.index:])
|
||
|
|
|
||
|
|
b.lines = append(
|
||
|
|
b.lines[:b.cursor.line+1],
|
||
|
|
b.lines[b.cursor.line:]...,
|
||
|
|
)
|
||
|
|
b.lines[b.cursor.line] = line.New(text[:b.cursor.index])
|
||
|
|
b.lines[b.cursor.line+1] = rest
|
||
|
|
}
|
||
|
|
|
||
|
|
b.CursorDown()
|
||
|
|
b.CursorHome()
|
||
|
|
}
|