More moving stuff around
This commit is contained in:
parent
1cc35c95a7
commit
c99cf3faf9
@ -5,25 +5,26 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"timshome.page/gilo/internal/buffer"
|
"timshome.page/gilo/internal/buffer"
|
||||||
|
"timshome.page/gilo/internal/gilo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type document struct {
|
type Document struct {
|
||||||
dirty bool
|
dirty bool
|
||||||
filename string
|
filename string
|
||||||
rows []*row
|
rows []*Row
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDocument() *document {
|
func NewDocument() *Document {
|
||||||
var rows []*row
|
var rows []*Row
|
||||||
|
|
||||||
return &document{
|
return &Document{
|
||||||
false,
|
false,
|
||||||
"",
|
"",
|
||||||
rows,
|
rows,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *document) open(filename string) {
|
func (d *Document) Open(filename string) {
|
||||||
file, err := os.Open(filename)
|
file, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to open file")
|
log.Fatalf("failed to open file")
|
||||||
@ -35,13 +36,13 @@ func (d *document) open(filename string) {
|
|||||||
scanner.Split(bufio.ScanLines)
|
scanner.Split(bufio.ScanLines)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
d.appendRow(scanner.Text())
|
d.AppendRow(scanner.Text())
|
||||||
}
|
}
|
||||||
|
|
||||||
d.dirty = false
|
d.dirty = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *document) save() int {
|
func (d *Document) Save() int {
|
||||||
if d.filename == "" {
|
if d.filename == "" {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -52,7 +53,7 @@ func (d *document) save() int {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
fileStr := d.toString()
|
fileStr := d.ToString()
|
||||||
fileLen := len(fileStr)
|
fileLen := len(fileStr)
|
||||||
|
|
||||||
err = file.Truncate(int64(fileLen))
|
err = file.Truncate(int64(fileLen))
|
||||||
@ -63,7 +64,7 @@ func (d *document) save() int {
|
|||||||
size, err := file.WriteString(fileStr)
|
size, err := file.WriteString(fileStr)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to save document to file")
|
panic("failed to save Document to file")
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileLen == size {
|
if fileLen == size {
|
||||||
@ -75,7 +76,11 @@ func (d *document) save() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *document) appendRow(s string) {
|
func (d *Document) Row(at int) *Row {
|
||||||
|
return d.rows[at]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Document) AppendRow(s string) {
|
||||||
newRow := newRow(s)
|
newRow := newRow(s)
|
||||||
newRow.update()
|
newRow.update()
|
||||||
d.rows = append(d.rows, newRow)
|
d.rows = append(d.rows, newRow)
|
||||||
@ -83,7 +88,7 @@ func (d *document) appendRow(s string) {
|
|||||||
d.dirty = true
|
d.dirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *document) toString() string {
|
func (d *Document) ToString() string {
|
||||||
buf := buffer.NewBuffer()
|
buf := buffer.NewBuffer()
|
||||||
|
|
||||||
for _, row := range d.rows {
|
for _, row := range d.rows {
|
||||||
@ -94,6 +99,18 @@ func (d *document) toString() string {
|
|||||||
return buf.ToString()
|
return buf.ToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *document) rowCount() int {
|
func (d *Document) RowCount() int {
|
||||||
return len(d.rows)
|
return len(d.rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Document) InsertChar(at *gilo.Point, ch rune) {
|
||||||
|
d.rows[at.Y].insertRune(ch, at.X)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Document) DelChar(at *gilo.Point) {
|
||||||
|
d.rows[at.Y].deleteRune(at.X)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Document) IsDirty() bool {
|
||||||
|
return d.dirty
|
||||||
|
}
|
||||||
|
@ -3,30 +3,30 @@ package editor
|
|||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestNewDocument(t *testing.T) {
|
func TestNewDocument(t *testing.T) {
|
||||||
d := newDocument()
|
d := NewDocument()
|
||||||
|
|
||||||
if d == nil {
|
if d == nil {
|
||||||
t.Errorf("Failed to create document")
|
t.Errorf("Failed to create Document")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAppendRow(t *testing.T) {
|
func TestAppendRow(t *testing.T) {
|
||||||
d := newDocument()
|
d := NewDocument()
|
||||||
d.appendRow("Test Row")
|
d.AppendRow("Test Row")
|
||||||
|
|
||||||
got := len(d.rows)
|
got := len(d.rows)
|
||||||
want := 1
|
want := 1
|
||||||
|
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf("Failed to add a row to the document")
|
t.Errorf("Failed to add a row to the Document")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRowCount(t *testing.T) {
|
func TestRowCount(t *testing.T) {
|
||||||
d := newDocument()
|
d := NewDocument()
|
||||||
d.appendRow("Test Row")
|
d.AppendRow("Test Row")
|
||||||
|
|
||||||
got := d.rowCount()
|
got := d.RowCount()
|
||||||
want := 1
|
want := 1
|
||||||
|
|
||||||
if got != want {
|
if got != want {
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"timshome.page/gilo/internal/buffer"
|
"timshome.page/gilo/internal/buffer"
|
||||||
"timshome.page/gilo/terminal"
|
"timshome.page/gilo/internal/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -25,7 +25,7 @@ func (e *editor) RefreshScreen() {
|
|||||||
e.drawStatusBar(ab)
|
e.drawStatusBar(ab)
|
||||||
e.drawMessageBar(ab)
|
e.drawMessageBar(ab)
|
||||||
|
|
||||||
ab.Append(terminal.MoveCursor(e.renderX-e.offset.x, e.cursor.y-e.offset.y))
|
ab.Append(terminal.MoveCursor(e.renderX-e.offset.X, e.cursor.Y-e.offset.Y))
|
||||||
|
|
||||||
ab.Append(terminal.ShowCursor)
|
ab.Append(terminal.ShowCursor)
|
||||||
|
|
||||||
@ -35,46 +35,46 @@ func (e *editor) RefreshScreen() {
|
|||||||
func (e *editor) scroll() {
|
func (e *editor) scroll() {
|
||||||
e.renderX = 0
|
e.renderX = 0
|
||||||
|
|
||||||
if e.cursor.y < e.document.rowCount() {
|
if e.cursor.Y < e.document.RowCount() {
|
||||||
e.renderX = e.document.rows[e.cursor.y].cursorXToRenderX(e.cursor.x)
|
e.renderX = e.document.Row(e.cursor.Y).cursorXToRenderX(e.cursor.X)
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.cursor.y < e.offset.y {
|
if e.cursor.Y < e.offset.Y {
|
||||||
e.offset.y = e.cursor.y
|
e.offset.Y = e.cursor.Y
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.cursor.y >= e.offset.y+e.screen.Rows {
|
if e.cursor.Y >= e.offset.Y+e.screen.Rows {
|
||||||
e.offset.y = e.cursor.y - e.screen.Rows + 1
|
e.offset.Y = e.cursor.Y - e.screen.Rows + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.renderX < e.offset.x {
|
if e.renderX < e.offset.X {
|
||||||
e.offset.x = e.renderX
|
e.offset.X = e.renderX
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.renderX >= e.offset.x+e.screen.Cols {
|
if e.renderX >= e.offset.X+e.screen.Cols {
|
||||||
e.offset.x = e.renderX - e.screen.Cols
|
e.offset.X = e.renderX - e.screen.Cols
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) drawRows(ab *buffer.Buffer) {
|
func (e *editor) drawRows(ab *buffer.Buffer) {
|
||||||
for y := 0; y < e.screen.Rows; y++ {
|
for y := 0; y < e.screen.Rows; y++ {
|
||||||
fileRow := y + e.offset.y
|
fileRow := y + e.offset.Y
|
||||||
|
|
||||||
if fileRow >= e.document.rowCount() {
|
if fileRow >= e.document.RowCount() {
|
||||||
e.drawPlaceholderRow(y, ab)
|
e.drawPlaceholderRow(y, ab)
|
||||||
} else {
|
} else {
|
||||||
rawRow := e.document.rows[fileRow]
|
rawRow := e.document.Row(fileRow)
|
||||||
|
|
||||||
// If the column offset is greater than the length of the row,
|
// If the column offset is greater than the length of the row,
|
||||||
// just display an empty row
|
// just display an empty row
|
||||||
if e.offset.x > rawRow.size() {
|
if e.offset.X > rawRow.Size() {
|
||||||
ab.Append("")
|
ab.Append("")
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
rowLen := e.document.rows[fileRow].rSize() - e.offset.x
|
rowLen := e.document.Row(fileRow).RenderSize() - e.offset.X
|
||||||
outputRow := truncate(string(e.document.rows[fileRow].render[e.offset.x:]), rowLen)
|
outputRow := truncate(string(e.document.Row(fileRow).render[e.offset.X:]), rowLen)
|
||||||
ab.Append(outputRow)
|
ab.Append(outputRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ func (e *editor) drawRows(ab *buffer.Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) drawPlaceholderRow(y int, ab *buffer.Buffer) {
|
func (e *editor) drawPlaceholderRow(y int, ab *buffer.Buffer) {
|
||||||
if e.document.rowCount() == 0 && y == e.screen.Rows/3 {
|
if e.document.RowCount() == 0 && y == e.screen.Rows/3 {
|
||||||
welcome := fmt.Sprintf("Gilo editor -- version %s", KiloVersion)
|
welcome := fmt.Sprintf("Gilo editor -- version %s", KiloVersion)
|
||||||
if len(welcome) > e.screen.Cols {
|
if len(welcome) > e.screen.Cols {
|
||||||
welcome = truncate(welcome, e.screen.Cols)
|
welcome = truncate(welcome, e.screen.Cols)
|
||||||
@ -120,7 +120,7 @@ func (e *editor) drawStatusBar(ab *buffer.Buffer) {
|
|||||||
modified = "(modified)"
|
modified = "(modified)"
|
||||||
}
|
}
|
||||||
|
|
||||||
leftStatus := fmt.Sprintf("%.20s - %d lines %s", fileName, e.document.rowCount(), modified)
|
leftStatus := fmt.Sprintf("%.20s - %d lines %s", fileName, e.document.RowCount(), modified)
|
||||||
length := len(leftStatus)
|
length := len(leftStatus)
|
||||||
if length > cols {
|
if length > cols {
|
||||||
leftStatus = truncate(leftStatus, cols)
|
leftStatus = truncate(leftStatus, cols)
|
||||||
@ -131,7 +131,7 @@ func (e *editor) drawStatusBar(ab *buffer.Buffer) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rightStatus := fmt.Sprintf("%d/%d", e.cursor.y+1, e.document.rowCount())
|
rightStatus := fmt.Sprintf("%d/%d", e.cursor.Y+1, e.document.RowCount())
|
||||||
rlength := len(rightStatus)
|
rlength := len(rightStatus)
|
||||||
statusLength := length + rlength
|
statusLength := length + rlength
|
||||||
|
|
||||||
|
@ -4,18 +4,14 @@ package editor
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
"timshome.page/gilo/terminal"
|
"timshome.page/gilo/internal/gilo"
|
||||||
|
"timshome.page/gilo/internal/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// !Editor
|
// !Editor
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
type point struct {
|
|
||||||
x int
|
|
||||||
y int
|
|
||||||
}
|
|
||||||
|
|
||||||
type statusMsg struct {
|
type statusMsg struct {
|
||||||
message string
|
message string
|
||||||
created time.Time
|
created time.Time
|
||||||
@ -23,9 +19,9 @@ type statusMsg struct {
|
|||||||
|
|
||||||
type editor struct {
|
type editor struct {
|
||||||
screen *terminal.Screen
|
screen *terminal.Screen
|
||||||
cursor *point
|
cursor *gilo.Point
|
||||||
offset *point
|
offset *gilo.Point
|
||||||
document *document
|
document *Document
|
||||||
status *statusMsg
|
status *statusMsg
|
||||||
quitTimes uint8
|
quitTimes uint8
|
||||||
renderX int
|
renderX int
|
||||||
@ -37,9 +33,9 @@ func New() *editor {
|
|||||||
// Subtract rows for status bar and message bar/prompt
|
// Subtract rows for status bar and message bar/prompt
|
||||||
screen.Rows -= 2
|
screen.Rows -= 2
|
||||||
|
|
||||||
cursor := &point{0, 0}
|
cursor := gilo.DefaultPoint()
|
||||||
offset := &point{0, 0}
|
offset := gilo.DefaultPoint()
|
||||||
document := newDocument()
|
document := NewDocument()
|
||||||
status := &statusMsg{
|
status := &statusMsg{
|
||||||
"",
|
"",
|
||||||
time.Now(),
|
time.Now(),
|
||||||
@ -57,11 +53,11 @@ func New() *editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) Open(filename string) {
|
func (e *editor) Open(filename string) {
|
||||||
e.document.open(filename)
|
e.document.Open(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) Save() {
|
func (e *editor) Save() {
|
||||||
size := e.document.save()
|
size := e.document.Save()
|
||||||
|
|
||||||
if size > 0 {
|
if size > 0 {
|
||||||
e.SetStatusMessage("%d bytes written to disk", size)
|
e.SetStatusMessage("%d bytes written to disk", size)
|
||||||
@ -84,23 +80,23 @@ func (e *editor) ProcessKeypress() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) insertChar(ch rune) {
|
func (e *editor) insertChar(ch rune) {
|
||||||
if e.cursor.y == e.document.rowCount() {
|
if e.cursor.Y == e.document.RowCount() {
|
||||||
e.document.appendRow("")
|
e.document.AppendRow("")
|
||||||
}
|
}
|
||||||
|
|
||||||
e.document.rows[e.cursor.y].insertRune(ch, e.cursor.x)
|
e.document.Row(e.cursor.Y).insertRune(ch, e.cursor.X)
|
||||||
e.cursor.x += 1
|
e.cursor.X += 1
|
||||||
e.document.dirty = true
|
e.document.dirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) delChar() {
|
func (e *editor) delChar() {
|
||||||
if e.cursor.y == e.document.rowCount() {
|
if e.cursor.Y == e.document.RowCount() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.cursor.x > 0 {
|
if e.cursor.X > 0 {
|
||||||
e.document.rows[e.cursor.y].deleteRune(e.cursor.x - 1)
|
e.document.Row(e.cursor.Y).deleteRune(e.cursor.X - 1)
|
||||||
e.cursor.x -= 1
|
e.cursor.X -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
e.document.dirty = true
|
e.document.dirty = true
|
||||||
|
@ -14,12 +14,12 @@ func TestInsertChar(t *testing.T) {
|
|||||||
e := New()
|
e := New()
|
||||||
e.insertChar('q')
|
e.insertChar('q')
|
||||||
|
|
||||||
if e.document.rowCount() != 1 {
|
if e.document.RowCount() != 1 {
|
||||||
t.Errorf("A row was not created when the character was inserted")
|
t.Errorf("A row was not created when the character was inserted")
|
||||||
}
|
}
|
||||||
|
|
||||||
row := e.document.rows[0]
|
row := e.document.Row(0)
|
||||||
if row.size() != 1 {
|
if row.Size() != 1 {
|
||||||
t.Errorf("Failed to add character to row. Row: %v", row)
|
t.Errorf("Failed to add character to row. Row: %v", row)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package editor
|
package editor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"timshome.page/gilo/key"
|
"timshome.page/gilo/internal/key"
|
||||||
"timshome.page/gilo/terminal"
|
"timshome.page/gilo/internal/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,71 +81,71 @@ func (e *editor) processKeypressStr(key string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) moveCursor(key string) {
|
func (e *editor) moveCursor(key string) {
|
||||||
var row *row
|
var row *Row
|
||||||
if e.cursor.y >= e.document.rowCount() {
|
if e.cursor.Y >= e.document.RowCount() {
|
||||||
row = nil
|
row = nil
|
||||||
} else {
|
} else {
|
||||||
row = e.document.rows[e.cursor.y]
|
row = e.document.Row(e.cursor.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch key {
|
switch key {
|
||||||
case keyLeft:
|
case keyLeft:
|
||||||
if e.cursor.x != 0 {
|
if e.cursor.X != 0 {
|
||||||
e.cursor.x -= 1
|
e.cursor.X -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move from beginning of current row to end of previous row
|
// Move from beginning of current row to end of previous row
|
||||||
if e.cursor.y > 0 {
|
if e.cursor.Y > 0 {
|
||||||
e.cursor.y -= 1
|
e.cursor.Y -= 1
|
||||||
e.cursor.x = e.document.rows[e.cursor.y].size()
|
e.cursor.X = e.document.Row(e.cursor.Y).Size()
|
||||||
}
|
}
|
||||||
case keyRight:
|
case keyRight:
|
||||||
if row != nil && e.cursor.x < row.size() {
|
if row != nil && e.cursor.X < row.Size() {
|
||||||
e.cursor.x += 1
|
e.cursor.X += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move from end of current line to beginning of next line
|
// Move from end of current line to beginning of next line
|
||||||
if row != nil && e.cursor.x == row.size() && e.cursor.y < e.document.rowCount()-1 {
|
if row != nil && e.cursor.X == row.Size() && e.cursor.Y < e.document.RowCount()-1 {
|
||||||
e.cursor.y += 1
|
e.cursor.Y += 1
|
||||||
e.cursor.x = 0
|
e.cursor.X = 0
|
||||||
}
|
}
|
||||||
case keyUp:
|
case keyUp:
|
||||||
if e.cursor.y != 0 {
|
if e.cursor.Y != 0 {
|
||||||
e.cursor.y -= 1
|
e.cursor.Y -= 1
|
||||||
}
|
}
|
||||||
case keyDown:
|
case keyDown:
|
||||||
if e.cursor.y < e.document.rowCount() {
|
if e.cursor.Y < e.document.RowCount() {
|
||||||
e.cursor.y += 1
|
e.cursor.Y += 1
|
||||||
}
|
}
|
||||||
case keyPageUp:
|
case keyPageUp:
|
||||||
if e.cursor.y > e.screen.Rows {
|
if e.cursor.Y > e.screen.Rows {
|
||||||
e.cursor.y -= e.screen.Rows
|
e.cursor.Y -= e.screen.Rows
|
||||||
} else {
|
} else {
|
||||||
e.cursor.y = 0
|
e.cursor.Y = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
case keyPageDown:
|
case keyPageDown:
|
||||||
if e.cursor.y+e.screen.Rows > e.document.rowCount() {
|
if e.cursor.Y+e.screen.Rows > e.document.RowCount() {
|
||||||
e.cursor.y += e.screen.Rows
|
e.cursor.Y += e.screen.Rows
|
||||||
} else {
|
} else {
|
||||||
e.cursor.y = e.document.rowCount() - 1
|
e.cursor.Y = e.document.RowCount() - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
case keyHome:
|
case keyHome:
|
||||||
e.cursor.x = 0
|
e.cursor.X = 0
|
||||||
case keyEnd:
|
case keyEnd:
|
||||||
if row != nil {
|
if row != nil {
|
||||||
e.cursor.x = row.size()
|
e.cursor.X = row.Size()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.cursor.y < e.document.rowCount() {
|
if e.cursor.Y < e.document.RowCount() {
|
||||||
row = e.document.rows[e.cursor.y]
|
row = e.document.Row(e.cursor.Y)
|
||||||
rowLen := row.size()
|
rowLen := row.Size()
|
||||||
|
|
||||||
// Snap to the end of a shorter line from a longer one
|
// Snap to the end of a shorter line from a longer one
|
||||||
if e.cursor.x > rowLen {
|
if e.cursor.X > rowLen {
|
||||||
e.cursor.x = rowLen
|
e.cursor.X = rowLen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,24 @@ package editor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"timshome.page/gilo/key"
|
"timshome.page/gilo/internal/gilo"
|
||||||
|
"timshome.page/gilo/internal/key"
|
||||||
)
|
)
|
||||||
|
|
||||||
type moveCursor struct {
|
type moveCursor struct {
|
||||||
keys []string
|
keys []string
|
||||||
withFile bool
|
withFile bool
|
||||||
cursor *point
|
cursor *gilo.Point
|
||||||
}
|
}
|
||||||
|
|
||||||
var cursorTests = []moveCursor{
|
var cursorTests = []moveCursor{
|
||||||
{[]string{string(rune(key.Esc))}, false, &point{0, 0}},
|
{[]string{string(rune(key.Esc))}, false, gilo.DefaultPoint()},
|
||||||
{[]string{keyRight}, true, &point{1, 0}},
|
{[]string{keyRight}, true, gilo.NewPoint(1, 0)},
|
||||||
{[]string{keyDown, keyEnd}, true, &point{14, 1}},
|
{[]string{keyDown, keyEnd}, true, gilo.NewPoint(14, 1)},
|
||||||
{[]string{keyEnd, keyHome}, true, &point{0, 0}},
|
{[]string{keyEnd, keyHome}, true, gilo.DefaultPoint()},
|
||||||
{[]string{keyRight, keyLeft}, true, &point{0, 0}},
|
{[]string{keyRight, keyLeft}, true, gilo.DefaultPoint()},
|
||||||
{[]string{keyDown, keyUp}, true, &point{0, 0}},
|
{[]string{keyDown, keyUp}, true, gilo.DefaultPoint()},
|
||||||
// {[]string{keyPageUp}, true, &point{0, 0}},
|
// {[]string{keyPageUp}, true, gilo.DefaultPoint()},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMoveCursor(t *testing.T) {
|
func TestMoveCursor(t *testing.T) {
|
||||||
@ -35,7 +36,7 @@ func TestMoveCursor(t *testing.T) {
|
|||||||
want := test.cursor
|
want := test.cursor
|
||||||
got := e.cursor
|
got := e.cursor
|
||||||
|
|
||||||
if got.x != want.x || got.y != want.y {
|
if got.X != want.X || got.Y != want.Y {
|
||||||
t.Errorf("Output %v not equal to expected %v for input %q", got, want, test.keys)
|
t.Errorf("Output %v not equal to expected %v for input %q", got, want, test.keys)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type row struct {
|
type Row struct {
|
||||||
chars []rune
|
chars []rune
|
||||||
render []rune
|
render []rune
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRow(s string) *row {
|
func newRow(s string) *Row {
|
||||||
var chars []rune
|
var chars []rune
|
||||||
var render []rune
|
var render []rune
|
||||||
|
|
||||||
@ -18,21 +18,21 @@ func newRow(s string) *row {
|
|||||||
render = append(render, ch)
|
render = append(render, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &row{chars, render}
|
return &Row{chars, render}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *row) size() int {
|
func (r *Row) Size() int {
|
||||||
return len(r.chars)
|
return len(r.chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *row) rSize() int {
|
func (r *Row) RenderSize() int {
|
||||||
return len(r.render)
|
return len(r.render)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *row) insertRune(ch rune, at int) {
|
func (r *Row) insertRune(ch rune, at int) {
|
||||||
// If insertion index is invalid, just
|
// If insertion index is invalid, just
|
||||||
// append the rune to the end of the array
|
// append the rune to the end of the array
|
||||||
if at < 0 || at >= r.size() {
|
if at < 0 || at >= r.Size() {
|
||||||
r.chars = append(r.chars, ch)
|
r.chars = append(r.chars, ch)
|
||||||
r.update()
|
r.update()
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ func (r *row) insertRune(ch rune, at int) {
|
|||||||
|
|
||||||
// Split the character array at the insertion point
|
// Split the character array at the insertion point
|
||||||
start := r.chars[0:at]
|
start := r.chars[0:at]
|
||||||
end := r.chars[at:r.size()]
|
end := r.chars[at:r.Size()]
|
||||||
|
|
||||||
// Splice it back together
|
// Splice it back together
|
||||||
newSlice = append(newSlice, start...)
|
newSlice = append(newSlice, start...)
|
||||||
@ -54,8 +54,8 @@ func (r *row) insertRune(ch rune, at int) {
|
|||||||
r.update()
|
r.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *row) deleteRune(at int) {
|
func (r *Row) deleteRune(at int) {
|
||||||
if at < 0 || at >= r.size() {
|
if at < 0 || at >= r.Size() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ func (r *row) deleteRune(at int) {
|
|||||||
|
|
||||||
// Split the character array at the insertion point
|
// Split the character array at the insertion point
|
||||||
start := r.chars[0:at]
|
start := r.chars[0:at]
|
||||||
end := r.chars[at+1 : r.size()] // Skip the index in question
|
end := r.chars[at+1 : r.Size()] // Skip the index in question
|
||||||
|
|
||||||
// Splice it back together
|
// Splice it back together
|
||||||
newSlice = append(newSlice, start...)
|
newSlice = append(newSlice, start...)
|
||||||
@ -73,7 +73,7 @@ func (r *row) deleteRune(at int) {
|
|||||||
r.update()
|
r.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *row) update() {
|
func (r *Row) update() {
|
||||||
r.render = r.render[:0]
|
r.render = r.render[:0]
|
||||||
replacement := strings.Repeat(" ", KiloTabStop)
|
replacement := strings.Repeat(" ", KiloTabStop)
|
||||||
|
|
||||||
@ -83,11 +83,11 @@ func (r *row) update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *row) toString() string {
|
func (r *Row) toString() string {
|
||||||
return string(r.chars)
|
return string(r.chars)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *row) cursorXToRenderX(cursorX int) int {
|
func (r *Row) cursorXToRenderX(cursorX int) int {
|
||||||
renderX := 0
|
renderX := 0
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ func TestRowSize(t *testing.T) {
|
|||||||
str := "abcdefg"
|
str := "abcdefg"
|
||||||
row := newRow(str)
|
row := newRow(str)
|
||||||
|
|
||||||
got := row.size()
|
got := row.Size()
|
||||||
want := 7
|
want := 7
|
||||||
|
|
||||||
if got != want {
|
if got != want {
|
||||||
@ -31,7 +31,7 @@ func TestRenderSize(t *testing.T) {
|
|||||||
row := newRow(str)
|
row := newRow(str)
|
||||||
row.update()
|
row.update()
|
||||||
|
|
||||||
got := row.rSize()
|
got := row.RenderSize()
|
||||||
want := 11
|
want := 11
|
||||||
|
|
||||||
if got != want {
|
if got != want {
|
||||||
@ -58,8 +58,8 @@ func TestInsertRune(t *testing.T) {
|
|||||||
row := newRow(test.initial)
|
row := newRow(test.initial)
|
||||||
row.insertRune(test.ch, test.at)
|
row.insertRune(test.ch, test.at)
|
||||||
|
|
||||||
if row.size() != 5 {
|
if row.Size() != 5 {
|
||||||
t.Errorf("Row size after inserting rune at index [%d] is %d, should be %d", test.at, row.size(), 5)
|
t.Errorf("Row size after inserting rune at index [%d] is %d, should be %d", test.at, row.Size(), 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
got := row.toString()
|
got := row.toString()
|
||||||
|
2
gilo.go
2
gilo.go
@ -5,7 +5,7 @@ import (
|
|||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
"os"
|
"os"
|
||||||
"timshome.page/gilo/editor"
|
"timshome.page/gilo/editor"
|
||||||
"timshome.page/gilo/terminal"
|
"timshome.page/gilo/internal/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cleanup(oldState *term.State) {
|
func cleanup(oldState *term.State) {
|
||||||
|
14
internal/gilo/shared.go
Normal file
14
internal/gilo/shared.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package gilo
|
||||||
|
|
||||||
|
type Point struct {
|
||||||
|
X int
|
||||||
|
Y int
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultPoint() *Point {
|
||||||
|
return &Point{0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPoint(x, y int) *Point {
|
||||||
|
return &Point{x, y}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user