1
0
Fork 0

Move file-specific logic to a document struct
timw4mail/gilo/pipeline/head This commit looks good Details

This commit is contained in:
Timothy Warren 2021-04-01 12:02:17 -04:00
parent d831bd4f83
commit 1d4c8f99c0
6 changed files with 169 additions and 109 deletions

46
editor/buffer.go Normal file
View File

@ -0,0 +1,46 @@
package editor
import (
"fmt"
"strings"
)
// ----------------------------------------------------------------------------
// !Output Buffer
// ----------------------------------------------------------------------------
type buffer struct {
buf *strings.Builder
}
func newBuffer() *buffer {
var buf strings.Builder
b := new(buffer)
b.buf = &buf
return b
}
func (b *buffer) appendRune(r rune) int {
size, _ := b.buf.WriteRune(r)
return size
}
func (b *buffer) append(s string) int {
size, _ := b.buf.WriteString(s)
return size
}
func (b *buffer) appendLn(s string) int {
str := fmt.Sprintf("%s\r\n", s)
size, _ := b.buf.WriteString(str)
return size
}
func (b *buffer) toString() string {
return b.buf.String()
}

47
editor/document.go Normal file
View File

@ -0,0 +1,47 @@
package editor
import (
"bufio"
"log"
"os"
)
type document struct {
filename string
rows []*row
}
func newDocument() *document {
var rows []*row
return &document{
"",
rows,
}
}
func (d *document) open(filename string) {
file, err := os.Open(filename)
if err != nil {
log.Fatalf("failed to open file")
}
defer file.Close()
d.filename = filename
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
d.appendRow(scanner.Text())
}
}
func (d *document) appendRow(s string) {
newRow := newRow(s)
newRow.update()
d.rows = append(d.rows, newRow)
}
func (d *document) rowCount() int {
return len(d.rows)
}

35
editor/document_test.go Normal file
View File

@ -0,0 +1,35 @@
package editor
import "testing"
func TestNewDocument(t *testing.T) {
d := newDocument()
if d == nil {
t.Errorf("Failed to create document")
}
}
func TestAppendRow(t *testing.T) {
d := newDocument()
d.appendRow("Test Row")
got := len(d.rows)
want := 1
if got != want {
t.Errorf("Failed to add a row to the document")
}
}
func TestRowCount(t *testing.T) {
d := newDocument()
d.appendRow("Test Row")
got := d.rowCount()
want := 1
if got != want {
t.Errorf("Expected %d rows, got %d rows", want, got)
}
}

View File

@ -32,8 +32,8 @@ func (e *editor) RefreshScreen() {
func (e *editor) scroll() {
e.renderX = 0
if e.cursor.y < e.rowCount() {
e.renderX = e.rows[e.cursor.y].cursorXToRenderX(e.cursor.x)
if e.cursor.y < e.document.rowCount() {
e.renderX = e.document.rows[e.cursor.y].cursorXToRenderX(e.cursor.x)
}
if e.cursor.y < e.offset.y {
@ -57,10 +57,10 @@ func (e *editor) drawRows(ab *buffer) {
for y :=0; y < e.screen.Rows; y++ {
fileRow := y + e.offset.y
if fileRow >= e.rowCount() {
if fileRow >= e.document.rowCount() {
e.drawPlaceholderRow(y, ab)
} else {
rawRow := e.rows[fileRow]
rawRow := e.document.rows[fileRow]
// If the column offset is greater than the length of the row,
// just display an empty row
@ -70,8 +70,8 @@ func (e *editor) drawRows(ab *buffer) {
continue
}
rowLen := e.rows[fileRow].rSize() - e.offset.x
outputRow := truncateString(string(e.rows[fileRow].render[e.offset.x:]), rowLen)
rowLen := e.document.rows[fileRow].rSize() - e.offset.x
outputRow := truncateString(string(e.document.rows[fileRow].render[e.offset.x:]), rowLen)
ab.append(outputRow)
}
@ -81,7 +81,7 @@ func (e *editor) drawRows(ab *buffer) {
}
func (e *editor) drawPlaceholderRow(y int, ab *buffer) {
if e.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)
if len(welcome) > e.screen.Cols {
welcome = truncateString(welcome, e.screen.Cols)
@ -112,43 +112,3 @@ func (e *editor) drawStatusBar(ab *buffer) {
ab.append(terminal.ResetColor)
}
// ----------------------------------------------------------------------------
// !Output Buffer
// ----------------------------------------------------------------------------
type buffer struct {
buf *strings.Builder
}
func newBuffer() *buffer {
var buf strings.Builder
b := new(buffer)
b.buf = &buf
return b
}
func (b *buffer) appendRune(r rune) int {
size, _ := b.buf.WriteRune(r)
return size
}
func (b *buffer) append(s string) int {
size, _ := b.buf.WriteString(s)
return size
}
func (b *buffer) appendLn(s string) int {
str := fmt.Sprintf("%s\r\n", s)
size, _ := b.buf.WriteString(str)
return size
}
func (b *buffer) toString() string {
return b.buf.String()
}

View File

@ -1,9 +1,6 @@
package editor
import (
"bufio"
"log"
"os"
"timshome.page/gilo/terminal"
)
@ -20,8 +17,8 @@ type editor struct {
screen *terminal.Screen
cursor *point
offset *point
document *document
renderX int
rows []*row
}
func New() *editor {
@ -32,30 +29,19 @@ func New() *editor {
cursor := &point { 0, 0 }
offset := &point { 0, 0 }
var rows []*row
document := newDocument()
return &editor{
screen,
cursor,
offset,
document,
0,
rows,
}
}
func (e *editor) Open(filename string) {
file, err := os.Open(filename)
if err != nil {
log.Fatalf("failed to open file")
}
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
e.appendRow(scanner.Text())
}
e.document.open(filename)
}
func (e *editor) ProcessKeypress() bool {
@ -92,10 +78,10 @@ func (e *editor) ProcessKeypress() bool {
func (e *editor) moveCursor (key string) {
var row *row
if e.cursor.y >= len(e.rows) {
if e.cursor.y >= e.document.rowCount() {
row = nil
} else {
row = e.rows[e.cursor.y]
row = e.document.rows[e.cursor.y]
}
switch key {
@ -107,7 +93,7 @@ func (e *editor) moveCursor (key string) {
// Move from beginning of current row to end of previous row
if e.cursor.y > 0 {
e.cursor.y -= 1
e.cursor.x = e.rows[e.cursor.y].size()
e.cursor.x = e.document.rows[e.cursor.y].size()
}
case keyRight:
if row != nil && e.cursor.x < row.size() {
@ -115,7 +101,7 @@ func (e *editor) moveCursor (key string) {
}
// Move from end of current line to beginning of next line
if row != nil && e.cursor.x == row.size() && e.cursor.y < len(e.rows) - 1 {
if row != nil && e.cursor.x == row.size() && e.cursor.y < e.document.rowCount() - 1 {
e.cursor.y += 1
e.cursor.x = 0
}
@ -124,7 +110,7 @@ func (e *editor) moveCursor (key string) {
e.cursor.y -= 1
}
case keyDown:
if e.cursor.y < (len(e.rows) - 1) {
if e.cursor.y < (e.document.rowCount() - 1) {
e.cursor.y += 1
}
case keyPageUp:
@ -135,10 +121,10 @@ func (e *editor) moveCursor (key string) {
}
case keyPageDown:
if e.cursor.y + e.screen.Rows > len(e.rows) {
if e.cursor.y + e.screen.Rows > e.document.rowCount() {
e.cursor.y += e.screen.Rows
} else {
e.cursor.y = len(e.rows) - 1
e.cursor.y = e.document.rowCount() - 1
}
case keyHome:
@ -149,10 +135,8 @@ func (e *editor) moveCursor (key string) {
}
}
if e.cursor.y > len(e.rows) {
row = nil
} else {
row = e.rows[e.cursor.y]
if e.cursor.y < e.document.rowCount() {
row = e.document.rows[e.cursor.y]
rowLen := row.size()
// Snap to the end of a shorter line from a longer one
@ -162,16 +146,6 @@ func (e *editor) moveCursor (key string) {
}
}
func (e *editor) appendRow(s string) {
newRow := newRow(s)
newRow.update()
e.rows = append(e.rows, newRow)
}
func (e *editor) rowCount() int {
return len(e.rows)
}
// Convert the raw ANSI escape sequences to the type of key input
func parseEscapeSequence () string {
var runes []rune

View File

@ -10,26 +10,24 @@ func TestNew(t *testing.T) {
}
}
func TestAppendRow(t *testing.T) {
e := New()
e.appendRow("Test Row")
got := len(e.rows)
want := 1
if got != want {
t.Errorf("Failed to add a row to the editor")
}
}
func TestRowCount(t *testing.T) {
e := New()
e.appendRow("Test Row")
got := e.rowCount()
want := 1
if got != want {
t.Errorf("Expected %d rows, got %d rows", want, got)
}
}
//type moveCursor struct {
// key string
// editor *editor
//}
//
//var cursorTests = []moveCursor{
// {"\x1b", New()},
//}
//
//func TestMoveCursor(t *testing.T) {
// for _, test := range cursorTests {
// e := New()
// e.moveCursor(test.key)
// want := test.editor
// got := e
//
// if got != want {
// t.Errorf("Output %v not equal to expected %v for input %q", got, want, test.key)
// }
// }
//}