Move stuff again, just because
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
c99cf3faf9
commit
787166df3a
@ -1,27 +0,0 @@
|
|||||||
package editor
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// !General Constants
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const (
|
|
||||||
KiloVersion = "0.0.1"
|
|
||||||
KiloTabStop = 4
|
|
||||||
KiloQuitTimes = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// !Constants representing input keys
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
const (
|
|
||||||
keyUp = "ARROW_UP"
|
|
||||||
keyDown = "ARROW_DOWN"
|
|
||||||
keyLeft = "ARROW_LEFT"
|
|
||||||
keyRight = "ARROW_RIGHT"
|
|
||||||
keyPageUp = "PAGE_UP"
|
|
||||||
keyPageDown = "PAGE_DOWN"
|
|
||||||
keyHome = "HOME"
|
|
||||||
keyEnd = "END"
|
|
||||||
keyDelete = "DELETE"
|
|
||||||
)
|
|
4
gilo.go
4
gilo.go
@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
"os"
|
"os"
|
||||||
"timshome.page/gilo/editor"
|
"timshome.page/gilo/internal/editor"
|
||||||
"timshome.page/gilo/internal/terminal"
|
"timshome.page/gilo/internal/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ func main() {
|
|||||||
oldState := terminal.RawOn()
|
oldState := terminal.RawOn()
|
||||||
defer cleanup(oldState)
|
defer cleanup(oldState)
|
||||||
|
|
||||||
e := editor.New()
|
e := editor.NewEditor()
|
||||||
|
|
||||||
// If there is an argument passed, open it as a file to edit
|
// If there is an argument passed, open it as a file to edit
|
||||||
if len(os.Args) >= 2 && os.Args[1] != "" {
|
if len(os.Args) >= 2 && os.Args[1] != "" {
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
package editor
|
package document
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"timshome.page/gilo/internal/buffer"
|
|
||||||
"timshome.page/gilo/internal/gilo"
|
"timshome.page/gilo/internal/gilo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Document struct {
|
type Document struct {
|
||||||
dirty bool
|
dirty bool
|
||||||
filename string
|
Filename string
|
||||||
rows []*Row
|
rows []*Row
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +30,7 @@ func (d *Document) Open(filename string) {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
d.filename = filename
|
d.Filename = filename
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
scanner.Split(bufio.ScanLines)
|
scanner.Split(bufio.ScanLines)
|
||||||
|
|
||||||
@ -43,11 +42,11 @@ func (d *Document) Open(filename string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) Save() int {
|
func (d *Document) Save() int {
|
||||||
if d.filename == "" {
|
if d.Filename == "" {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
file, err := os.OpenFile(d.filename, os.O_RDWR|os.O_CREATE, 0644)
|
file, err := os.OpenFile(d.Filename, os.O_RDWR|os.O_CREATE, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to open/create file for saving")
|
panic("failed to open/create file for saving")
|
||||||
}
|
}
|
||||||
@ -89,7 +88,7 @@ func (d *Document) AppendRow(s string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) ToString() string {
|
func (d *Document) ToString() string {
|
||||||
buf := buffer.NewBuffer()
|
buf := gilo.NewBuffer()
|
||||||
|
|
||||||
for _, row := range d.rows {
|
for _, row := range d.rows {
|
||||||
buf.Append(row.toString())
|
buf.Append(row.toString())
|
||||||
@ -105,10 +104,14 @@ func (d *Document) RowCount() int {
|
|||||||
|
|
||||||
func (d *Document) InsertChar(at *gilo.Point, ch rune) {
|
func (d *Document) InsertChar(at *gilo.Point, ch rune) {
|
||||||
d.rows[at.Y].insertRune(ch, at.X)
|
d.rows[at.Y].insertRune(ch, at.X)
|
||||||
|
|
||||||
|
d.dirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) DelChar(at *gilo.Point) {
|
func (d *Document) DelChar(at *gilo.Point) {
|
||||||
d.rows[at.Y].deleteRune(at.X)
|
d.rows[at.Y].deleteRune(at.X)
|
||||||
|
|
||||||
|
d.dirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) IsDirty() bool {
|
func (d *Document) IsDirty() bool {
|
@ -1,4 +1,4 @@
|
|||||||
package editor
|
package document
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
@ -1,7 +1,8 @@
|
|||||||
package editor
|
package document
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
"timshome.page/gilo/internal/gilo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Row struct {
|
type Row struct {
|
||||||
@ -29,6 +30,10 @@ func (r *Row) RenderSize() int {
|
|||||||
return len(r.render)
|
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) {
|
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
|
||||||
@ -75,7 +80,7 @@ func (r *Row) deleteRune(at int) {
|
|||||||
|
|
||||||
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(" ", gilo.TabSize)
|
||||||
|
|
||||||
str := strings.ReplaceAll(string(r.chars), "\t", replacement)
|
str := strings.ReplaceAll(string(r.chars), "\t", replacement)
|
||||||
for _, ch := range str {
|
for _, ch := range str {
|
||||||
@ -87,13 +92,13 @@ 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) (renderX int) {
|
||||||
renderX := 0
|
renderX = 0
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
for ; i < cursorX; i++ {
|
for ; i < cursorX; i++ {
|
||||||
if r.chars[i] == '\t' {
|
if r.chars[i] == '\t' {
|
||||||
renderX += (KiloTabStop - 1) - (renderX % KiloTabStop)
|
renderX += (gilo.TabSize - 1) - (renderX % gilo.TabSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderX += 1
|
renderX += 1
|
@ -1,4 +1,4 @@
|
|||||||
package editor
|
package document
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"timshome.page/gilo/internal/buffer"
|
"timshome.page/gilo/internal/gilo"
|
||||||
"timshome.page/gilo/internal/terminal"
|
"timshome.page/gilo/internal/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ import (
|
|||||||
func (e *editor) RefreshScreen() {
|
func (e *editor) RefreshScreen() {
|
||||||
e.scroll()
|
e.scroll()
|
||||||
|
|
||||||
ab := buffer.NewBuffer()
|
ab := gilo.NewBuffer()
|
||||||
|
|
||||||
ab.Append(terminal.HideCursor)
|
ab.Append(terminal.HideCursor)
|
||||||
ab.Append(terminal.ResetCursor)
|
ab.Append(terminal.ResetCursor)
|
||||||
@ -36,7 +36,7 @@ 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.Row(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 {
|
||||||
@ -56,7 +56,7 @@ func (e *editor) scroll() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) drawRows(ab *buffer.Buffer) {
|
func (e *editor) drawRows(ab *gilo.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
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ func (e *editor) drawRows(ab *buffer.Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rowLen := e.document.Row(fileRow).RenderSize() - e.offset.X
|
rowLen := e.document.Row(fileRow).RenderSize() - e.offset.X
|
||||||
outputRow := truncate(string(e.document.Row(fileRow).render[e.offset.X:]), rowLen)
|
outputRow := truncate(e.document.Row(fileRow).Render(e.offset), rowLen)
|
||||||
ab.Append(outputRow)
|
ab.Append(outputRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,9 +82,9 @@ func (e *editor) drawRows(ab *buffer.Buffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) drawPlaceholderRow(y int, ab *buffer.Buffer) {
|
func (e *editor) drawPlaceholderRow(y int, ab *gilo.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", gilo.Version)
|
||||||
if len(welcome) > e.screen.Cols {
|
if len(welcome) > e.screen.Cols {
|
||||||
welcome = truncate(welcome, e.screen.Cols)
|
welcome = truncate(welcome, e.screen.Cols)
|
||||||
}
|
}
|
||||||
@ -106,17 +106,17 @@ func (e *editor) drawPlaceholderRow(y int, ab *buffer.Buffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) drawStatusBar(ab *buffer.Buffer) {
|
func (e *editor) drawStatusBar(ab *gilo.Buffer) {
|
||||||
cols := e.screen.Cols
|
cols := e.screen.Cols
|
||||||
|
|
||||||
ab.Append(terminal.InvertColor)
|
ab.Append(terminal.InvertColor)
|
||||||
|
|
||||||
fileName := "[No Name]"
|
fileName := "[No Name]"
|
||||||
if e.document.filename != "" {
|
if e.document.Filename != "" {
|
||||||
fileName = e.document.filename
|
fileName = e.document.Filename
|
||||||
}
|
}
|
||||||
modified := ""
|
modified := ""
|
||||||
if e.document.dirty {
|
if e.document.IsDirty() {
|
||||||
modified = "(modified)"
|
modified = "(modified)"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ func (e *editor) drawStatusBar(ab *buffer.Buffer) {
|
|||||||
ab.Append(terminal.ResetColor)
|
ab.Append(terminal.ResetColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) drawMessageBar(ab *buffer.Buffer) {
|
func (e *editor) drawMessageBar(ab *gilo.Buffer) {
|
||||||
ab.Append("\r\n")
|
ab.Append("\r\n")
|
||||||
ab.Append(terminal.ClearLine)
|
ab.Append(terminal.ClearLine)
|
||||||
|
|
@ -4,6 +4,7 @@ package editor
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
doc "timshome.page/gilo/internal/editor/document"
|
||||||
"timshome.page/gilo/internal/gilo"
|
"timshome.page/gilo/internal/gilo"
|
||||||
"timshome.page/gilo/internal/terminal"
|
"timshome.page/gilo/internal/terminal"
|
||||||
)
|
)
|
||||||
@ -21,13 +22,13 @@ type editor struct {
|
|||||||
screen *terminal.Screen
|
screen *terminal.Screen
|
||||||
cursor *gilo.Point
|
cursor *gilo.Point
|
||||||
offset *gilo.Point
|
offset *gilo.Point
|
||||||
document *Document
|
document *doc.Document
|
||||||
status *statusMsg
|
status *statusMsg
|
||||||
quitTimes uint8
|
quitTimes uint8
|
||||||
renderX int
|
renderX int
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *editor {
|
func NewEditor() *editor {
|
||||||
screen := terminal.Size()
|
screen := terminal.Size()
|
||||||
|
|
||||||
// Subtract rows for status bar and message bar/prompt
|
// Subtract rows for status bar and message bar/prompt
|
||||||
@ -35,7 +36,7 @@ func New() *editor {
|
|||||||
|
|
||||||
cursor := gilo.DefaultPoint()
|
cursor := gilo.DefaultPoint()
|
||||||
offset := gilo.DefaultPoint()
|
offset := gilo.DefaultPoint()
|
||||||
document := NewDocument()
|
document := doc.NewDocument()
|
||||||
status := &statusMsg{
|
status := &statusMsg{
|
||||||
"",
|
"",
|
||||||
time.Now(),
|
time.Now(),
|
||||||
@ -47,7 +48,7 @@ func New() *editor {
|
|||||||
offset,
|
offset,
|
||||||
document,
|
document,
|
||||||
status,
|
status,
|
||||||
KiloQuitTimes,
|
gilo.QuitTimes,
|
||||||
0,
|
0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,9 +85,8 @@ func (e *editor) insertChar(ch rune) {
|
|||||||
e.document.AppendRow("")
|
e.document.AppendRow("")
|
||||||
}
|
}
|
||||||
|
|
||||||
e.document.Row(e.cursor.Y).insertRune(ch, e.cursor.X)
|
e.document.InsertChar(e.cursor, ch)
|
||||||
e.cursor.X += 1
|
e.cursor.X += 1
|
||||||
e.document.dirty = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) delChar() {
|
func (e *editor) delChar() {
|
||||||
@ -95,9 +95,10 @@ func (e *editor) delChar() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if e.cursor.X > 0 {
|
if e.cursor.X > 0 {
|
||||||
e.document.Row(e.cursor.Y).deleteRune(e.cursor.X - 1)
|
at := e.cursor
|
||||||
|
at.X -= 1
|
||||||
|
e.document.DelChar(at)
|
||||||
|
|
||||||
e.cursor.X -= 1
|
e.cursor.X -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
e.document.dirty = true
|
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ package editor
|
|||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestNew(t *testing.T) {
|
func TestNew(t *testing.T) {
|
||||||
e := New()
|
e := NewEditor()
|
||||||
|
|
||||||
if e == nil {
|
if e == nil {
|
||||||
t.Errorf("Failed to create editor")
|
t.Errorf("Failed to create editor")
|
||||||
@ -11,7 +11,7 @@ func TestNew(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInsertChar(t *testing.T) {
|
func TestInsertChar(t *testing.T) {
|
||||||
e := New()
|
e := NewEditor()
|
||||||
e.insertChar('q')
|
e.insertChar('q')
|
||||||
|
|
||||||
if e.document.RowCount() != 1 {
|
if e.document.RowCount() != 1 {
|
@ -1,17 +1,35 @@
|
|||||||
package editor
|
package editor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"timshome.page/gilo/internal/editor/document"
|
||||||
|
"timshome.page/gilo/internal/gilo"
|
||||||
"timshome.page/gilo/internal/key"
|
"timshome.page/gilo/internal/key"
|
||||||
"timshome.page/gilo/internal/terminal"
|
"timshome.page/gilo/internal/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// !Constants representing input keys
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
keyUp = "ARROW_UP"
|
||||||
|
keyDown = "ARROW_DOWN"
|
||||||
|
keyLeft = "ARROW_LEFT"
|
||||||
|
keyRight = "ARROW_RIGHT"
|
||||||
|
keyPageUp = "PAGE_UP"
|
||||||
|
keyPageDown = "PAGE_DOWN"
|
||||||
|
keyHome = "HOME"
|
||||||
|
keyEnd = "END"
|
||||||
|
keyDelete = "DELETE"
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine what to do with an individual character of input
|
* Determine what to do with an individual character of input
|
||||||
*/
|
*/
|
||||||
func (e *editor) processKeypressChar(ch rune) bool {
|
func (e *editor) processKeypressChar(ch rune) bool {
|
||||||
switch ch {
|
switch ch {
|
||||||
case key.Ctrl('q'):
|
case key.Ctrl('q'):
|
||||||
if e.document.dirty && e.quitTimes > 0 {
|
if e.document.IsDirty() && e.quitTimes > 0 {
|
||||||
e.SetStatusMessage("WARNING!!! File has unsaved changes. Press Ctrl-Q %d more tiems to quite.", e.quitTimes)
|
e.SetStatusMessage("WARNING!!! File has unsaved changes. Press Ctrl-Q %d more tiems to quite.", e.quitTimes)
|
||||||
e.quitTimes -= 1
|
e.quitTimes -= 1
|
||||||
|
|
||||||
@ -50,8 +68,8 @@ func (e *editor) processKeypressChar(ch rune) bool {
|
|||||||
// Clear the quit message and restart the
|
// Clear the quit message and restart the
|
||||||
// confirmation count if confirmation is not
|
// confirmation count if confirmation is not
|
||||||
// completed
|
// completed
|
||||||
if e.quitTimes != KiloQuitTimes {
|
if e.quitTimes != gilo.QuitTimes {
|
||||||
e.quitTimes = KiloQuitTimes
|
e.quitTimes = gilo.QuitTimes
|
||||||
e.SetStatusMessage("")
|
e.SetStatusMessage("")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +99,7 @@ func (e *editor) processKeypressStr(key string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *editor) moveCursor(key string) {
|
func (e *editor) moveCursor(key string) {
|
||||||
var row *Row
|
var row *document.Row
|
||||||
if e.cursor.Y >= e.document.RowCount() {
|
if e.cursor.Y >= e.document.RowCount() {
|
||||||
row = nil
|
row = nil
|
||||||
} else {
|
} else {
|
@ -24,7 +24,7 @@ var cursorTests = []moveCursor{
|
|||||||
|
|
||||||
func TestMoveCursor(t *testing.T) {
|
func TestMoveCursor(t *testing.T) {
|
||||||
for _, test := range cursorTests {
|
for _, test := range cursorTests {
|
||||||
e := New()
|
e := NewEditor()
|
||||||
|
|
||||||
if test.withFile {
|
if test.withFile {
|
||||||
e.Open("editor.go")
|
e.Open("editor.go")
|
@ -1,4 +1,4 @@
|
|||||||
package buffer
|
package gilo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@ -1,4 +1,4 @@
|
|||||||
package buffer
|
package gilo
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
11
internal/gilo/constants.go
Normal file
11
internal/gilo/constants.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package gilo
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// !General Constants
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
Version = "0.0.1"
|
||||||
|
TabSize = 4
|
||||||
|
QuitTimes = 3
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user