Move file-specific logic to a document struct
All checks were successful
timw4mail/gilo/pipeline/head This commit looks good
All checks were successful
timw4mail/gilo/pipeline/head This commit looks good
This commit is contained in:
parent
d831bd4f83
commit
1d4c8f99c0
46
editor/buffer.go
Normal file
46
editor/buffer.go
Normal 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
47
editor/document.go
Normal 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
35
editor/document_test.go
Normal 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)
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
@ -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
|
||||
|
@ -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)
|
||||
// }
|
||||
// }
|
||||
//}
|
Loading…
Reference in New Issue
Block a user