Update to chapter 7 step 161 in kilo tutorial
Some checks failed
timw4mail/gilo/pipeline/head There was a failure building this commit
Some checks failed
timw4mail/gilo/pipeline/head There was a failure building this commit
This commit is contained in:
parent
1b9c1744aa
commit
cc99f08747
1468
_code/kilo.c
Normal file
1468
_code/kilo.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,7 +19,7 @@ type statusMsg struct {
|
||||
created time.Time
|
||||
}
|
||||
|
||||
type editor struct {
|
||||
type Editor struct {
|
||||
screen *terminal.Screen
|
||||
cursor *gilo.Point
|
||||
offset *gilo.Point
|
||||
@ -30,7 +30,7 @@ type editor struct {
|
||||
renderX int
|
||||
}
|
||||
|
||||
func NewEditor() *editor {
|
||||
func NewEditor() *Editor {
|
||||
// Subtract rows for status bar and message bar/prompt
|
||||
screen := terminal.Size()
|
||||
screen.Rows -= 2
|
||||
@ -40,7 +40,7 @@ func NewEditor() *editor {
|
||||
time.Now(),
|
||||
}
|
||||
|
||||
return &editor{
|
||||
return &Editor{
|
||||
screen,
|
||||
gilo.DefaultPoint(),
|
||||
gilo.DefaultPoint(),
|
||||
@ -52,24 +52,24 @@ func NewEditor() *editor {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) Open(filename string) {
|
||||
func (e *Editor) Open(filename string) {
|
||||
e.doc.Open(filename)
|
||||
}
|
||||
|
||||
func (e *editor) SetStatusMessage(template string, a ...interface{}) {
|
||||
func (e *Editor) SetStatusMessage(template string, a ...interface{}) {
|
||||
e.status = &statusMsg{
|
||||
fmt.Sprintf(template, a...),
|
||||
time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) ProcessKeypress() bool {
|
||||
func (e *Editor) ProcessKeypress() bool {
|
||||
ch, _ := terminal.ReadKey()
|
||||
|
||||
return e.processKeypressChar(ch)
|
||||
}
|
||||
|
||||
func (e *editor) save() {
|
||||
func (e *Editor) save() {
|
||||
if e.doc.Filename == "" {
|
||||
e.doc.Filename = e.prompt("Save as: %s (ESC to cancel)", nil)
|
||||
if e.doc.Filename == "" {
|
||||
@ -86,7 +86,7 @@ func (e *editor) save() {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) prompt(prompt string, callback func(string, string)) string {
|
||||
func (e *Editor) prompt(prompt string, callback func(string, string)) string {
|
||||
buf := gilo.NewBuffer()
|
||||
|
||||
// Show the prompt message
|
||||
@ -136,7 +136,7 @@ func (e *editor) prompt(prompt string, callback func(string, string)) string {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) insertChar(ch rune) {
|
||||
func (e *Editor) insertChar(ch rune) {
|
||||
if e.cursor.Y == e.doc.RowCount() {
|
||||
e.doc.AppendRow("")
|
||||
}
|
||||
@ -145,7 +145,7 @@ func (e *editor) insertChar(ch rune) {
|
||||
e.cursor.X += 1
|
||||
}
|
||||
|
||||
func (e *editor) delChar() {
|
||||
func (e *Editor) delChar() {
|
||||
if e.cursor.Y == e.doc.RowCount() {
|
||||
return
|
||||
}
|
@ -4,12 +4,14 @@ import (
|
||||
"bufio"
|
||||
"log"
|
||||
"os"
|
||||
"timshome.page/gilo/editor/highlight"
|
||||
"timshome.page/gilo/internal/gilo"
|
||||
)
|
||||
|
||||
type Document struct {
|
||||
dirty bool
|
||||
Filename string
|
||||
Syntax *highlight.Syntax
|
||||
rows []*Row
|
||||
}
|
||||
|
||||
@ -19,6 +21,7 @@ func NewDocument() *Document {
|
||||
return &Document{
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
rows,
|
||||
}
|
||||
}
|
||||
@ -80,7 +83,7 @@ func (d *Document) GetRow(at int) *Row {
|
||||
}
|
||||
|
||||
func (d *Document) AppendRow(s string) {
|
||||
newRow := newRow(s)
|
||||
newRow := newRow(d, s)
|
||||
newRow.update()
|
||||
d.rows = append(d.rows, newRow)
|
||||
|
||||
@ -100,7 +103,7 @@ func (d *Document) InsertRow(at int, s string) {
|
||||
|
||||
// Splice it back together
|
||||
newRows = append(newRows, start...)
|
||||
newRows = append(newRows, newRow(s))
|
||||
newRows = append(newRows, newRow(d, s))
|
||||
newRows = append(newRows, end...)
|
||||
|
||||
d.rows = newRows
|
||||
|
@ -9,12 +9,13 @@ import (
|
||||
)
|
||||
|
||||
type Row struct {
|
||||
parent *Document
|
||||
chars []rune
|
||||
render []rune
|
||||
Hl []int
|
||||
}
|
||||
|
||||
func newRow(s string) *Row {
|
||||
func newRow(parent *Document, s string) *Row {
|
||||
var chars []rune
|
||||
var render []rune
|
||||
|
||||
@ -23,13 +24,14 @@ func newRow(s string) *Row {
|
||||
render = append(render, ch)
|
||||
}
|
||||
|
||||
return &Row{chars, render, []int{}}
|
||||
return &Row{parent, chars, render, []int{}}
|
||||
}
|
||||
|
||||
func (r *Row) Size() int {
|
||||
return len(r.chars)
|
||||
}
|
||||
|
||||
// RenderSize is a convenient equivalent of row->rsize in kilo
|
||||
func (r *Row) RenderSize() int {
|
||||
return len(r.render)
|
||||
}
|
||||
@ -106,11 +108,21 @@ func (r *Row) update() {
|
||||
r.updateSyntax()
|
||||
}
|
||||
|
||||
// updateSyntax is the equivalent of editorUpdateSyntax in kilo
|
||||
func (r *Row) updateSyntax() {
|
||||
i := 0
|
||||
s := r.parent.Syntax
|
||||
prevSep := true
|
||||
|
||||
r.Hl = make([]int, r.RenderSize())
|
||||
for x := range r.Hl {
|
||||
r.Hl[x] = highlight.Normal
|
||||
}
|
||||
|
||||
// Don't bother updating the syntax if there isn't any
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i < r.RenderSize() {
|
||||
ch := r.render[i]
|
||||
@ -120,14 +132,14 @@ func (r *Row) updateSyntax() {
|
||||
prevHl = r.Hl[i-1]
|
||||
}
|
||||
|
||||
if s.Flags&highlight.HighlightNumbers == 1 {
|
||||
if (unicode.IsDigit(ch) && (prevSep || prevHl == highlight.Number)) ||
|
||||
(ch == '.' && prevHl == highlight.Number) {
|
||||
r.Hl[i] = highlight.Number
|
||||
i += 1
|
||||
prevSep = false
|
||||
continue
|
||||
} else {
|
||||
r.Hl[i] = highlight.Normal
|
||||
}
|
||||
}
|
||||
|
||||
prevSep = key.IsSeparator(ch)
|
||||
@ -139,6 +151,7 @@ func (r *Row) toString() string {
|
||||
return string(r.chars)
|
||||
}
|
||||
|
||||
// CursorXToRenderX is the equivalent of editorRowCxToRx in kilo
|
||||
func (r *Row) CursorXToRenderX(cursorX int) (renderX int) {
|
||||
renderX = 0
|
||||
|
||||
@ -153,6 +166,7 @@ func (r *Row) CursorXToRenderX(cursorX int) (renderX int) {
|
||||
return renderX
|
||||
}
|
||||
|
||||
// RenderXtoCursorX is the equivalent of editorRowRxToCx in kilo
|
||||
func (r *Row) RenderXtoCursorX(renderX int) (cursorX int) {
|
||||
currentRenderX := 0
|
||||
cursorX = 0
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
// !Editor Methods
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
func (e *editor) RefreshScreen() {
|
||||
func (e *Editor) RefreshScreen() {
|
||||
e.scroll()
|
||||
|
||||
ab := gilo.NewBuffer()
|
||||
@ -33,7 +33,7 @@ func (e *editor) RefreshScreen() {
|
||||
terminal.Write(ab.ToString())
|
||||
}
|
||||
|
||||
func (e *editor) scroll() {
|
||||
func (e *Editor) scroll() {
|
||||
e.renderX = 0
|
||||
|
||||
if e.cursor.Y < e.doc.RowCount() {
|
||||
@ -57,7 +57,7 @@ func (e *editor) scroll() {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) drawRows(ab *gilo.Buffer) {
|
||||
func (e *Editor) drawRows(ab *gilo.Buffer) {
|
||||
for y := 0; y < e.screen.Rows; y++ {
|
||||
fileRow := y + e.offset.Y
|
||||
|
||||
@ -81,7 +81,7 @@ func (e *editor) drawRows(ab *gilo.Buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) drawFileRow(fileRow int, ab *gilo.Buffer) {
|
||||
func (e *Editor) drawFileRow(fileRow int, ab *gilo.Buffer) {
|
||||
currentColor := terminal.DefaultFGColor
|
||||
row := e.doc.GetRow(fileRow)
|
||||
|
||||
@ -107,7 +107,7 @@ func (e *editor) drawFileRow(fileRow int, ab *gilo.Buffer) {
|
||||
ab.Append(terminal.DefaultFGColor)
|
||||
}
|
||||
|
||||
func (e *editor) drawPlaceholderRow(y int, ab *gilo.Buffer) {
|
||||
func (e *Editor) drawPlaceholderRow(y int, ab *gilo.Buffer) {
|
||||
if e.doc.RowCount() == 0 && y == e.screen.Rows/3 {
|
||||
welcome := fmt.Sprintf("Gilo editor -- version %s", gilo.Version)
|
||||
if len(welcome) > e.screen.Cols {
|
||||
@ -131,7 +131,7 @@ func (e *editor) drawPlaceholderRow(y int, ab *gilo.Buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) drawStatusBar(ab *gilo.Buffer) {
|
||||
func (e *Editor) drawStatusBar(ab *gilo.Buffer) {
|
||||
cols := e.screen.Cols
|
||||
|
||||
ab.Append(terminal.InvertColor)
|
||||
@ -156,7 +156,11 @@ func (e *editor) drawStatusBar(ab *gilo.Buffer) {
|
||||
return
|
||||
}
|
||||
|
||||
rightStatus := fmt.Sprintf("%d/%d", e.cursor.Y+1, e.doc.RowCount())
|
||||
syntaxName := "no filetype"
|
||||
if e.doc.Syntax != nil {
|
||||
syntaxName = e.doc.Syntax.FileType
|
||||
}
|
||||
rightStatus := fmt.Sprintf("%s | %d/%d", syntaxName, e.cursor.Y+1, e.doc.RowCount())
|
||||
rlength := len(rightStatus)
|
||||
statusLength := length + rlength
|
||||
|
||||
@ -182,7 +186,7 @@ func (e *editor) drawStatusBar(ab *gilo.Buffer) {
|
||||
ab.Append(terminal.ResetColor)
|
||||
}
|
||||
|
||||
func (e *editor) drawMessageBar(ab *gilo.Buffer) {
|
||||
func (e *Editor) drawMessageBar(ab *gilo.Buffer) {
|
||||
ab.Append("\r\n")
|
||||
ab.Append(terminal.ClearLine)
|
||||
|
||||
|
@ -8,3 +8,15 @@ const (
|
||||
Number
|
||||
Match
|
||||
)
|
||||
|
||||
const HighlightNumbers = (1 << 0)
|
||||
|
||||
var HLDB = []*Syntax{{
|
||||
"c",
|
||||
[]string{".c", ".h", ".cpp"},
|
||||
HighlightNumbers,
|
||||
}, {
|
||||
"go",
|
||||
[]string{".go"},
|
||||
HighlightNumbers,
|
||||
}}
|
||||
|
7
editor/highlight/syntax.go
Normal file
7
editor/highlight/syntax.go
Normal file
@ -0,0 +1,7 @@
|
||||
package highlight
|
||||
|
||||
type Syntax struct {
|
||||
FileType string
|
||||
FileMatch []string
|
||||
Flags int
|
||||
}
|
@ -26,7 +26,7 @@ const (
|
||||
/**
|
||||
* 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 {
|
||||
case key.Ctrl('q'):
|
||||
if e.doc.IsDirty() && e.quitTimes > 0 {
|
||||
@ -85,7 +85,7 @@ func (e *editor) processKeypressChar(ch rune) bool {
|
||||
/**
|
||||
* Determine what do do with a parsed ANSI escape sequence
|
||||
*/
|
||||
func (e *editor) processKeypressStr(key string) {
|
||||
func (e *Editor) processKeypressStr(key string) {
|
||||
switch key {
|
||||
case keyUp,
|
||||
keyDown,
|
||||
@ -104,7 +104,7 @@ func (e *editor) processKeypressStr(key string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) moveCursor(key string) {
|
||||
func (e *Editor) moveCursor(key string) {
|
||||
var row *document.Row
|
||||
if e.cursor.Y >= e.doc.RowCount() {
|
||||
row = nil
|
||||
|
@ -27,7 +27,7 @@ func TestMoveCursor(t *testing.T) {
|
||||
e := NewEditor()
|
||||
|
||||
if test.withFile {
|
||||
e.Open("editor.go")
|
||||
e.Open("Editor.go")
|
||||
}
|
||||
|
||||
for _, k := range test.keys {
|
||||
|
@ -9,8 +9,8 @@ import (
|
||||
type search struct {
|
||||
cursor *gilo.Point
|
||||
offset *gilo.Point
|
||||
hlLine int
|
||||
hl []int
|
||||
savedhlLine int
|
||||
savedhl []int
|
||||
direction int
|
||||
lastMatch int
|
||||
}
|
||||
@ -19,14 +19,14 @@ func newSearch() *search {
|
||||
return &search{
|
||||
cursor: gilo.DefaultPoint(),
|
||||
offset: gilo.DefaultPoint(),
|
||||
hlLine: -1,
|
||||
hl: []int{},
|
||||
savedhlLine: -1,
|
||||
savedhl: []int{},
|
||||
lastMatch: -1,
|
||||
direction: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) find() {
|
||||
func (e *Editor) find() {
|
||||
e.search.cursor.X = e.cursor.X
|
||||
e.search.cursor.Y = e.cursor.Y
|
||||
e.search.offset.X = e.offset.X
|
||||
@ -44,14 +44,15 @@ func (e *editor) find() {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *editor) findCallback(query string, ch string) {
|
||||
if e.search.hlLine != -1 && e.search.hl != nil {
|
||||
staleRow := e.doc.GetRow(e.search.hlLine)
|
||||
for i, val := range e.search.hl {
|
||||
func (e *Editor) findCallback(query string, ch string) {
|
||||
// If we highlighted a previous match, restore the original highlighting
|
||||
if e.search.savedhlLine != -1 && e.search.savedhl != nil {
|
||||
staleRow := e.doc.GetRow(e.search.savedhlLine)
|
||||
for i, val := range e.search.savedhl {
|
||||
staleRow.Hl[i] = val
|
||||
}
|
||||
e.search.hl = nil
|
||||
e.search.hlLine = -1
|
||||
e.search.savedhl = nil
|
||||
e.search.savedhlLine = -1
|
||||
}
|
||||
|
||||
if ch == string(key.Enter) || ch == string(key.Esc) {
|
||||
@ -97,12 +98,14 @@ func (e *editor) findCallback(query string, ch string) {
|
||||
e.cursor.X = row.RenderXtoCursorX(matchIndex)
|
||||
e.offset.Y = e.doc.RowCount()
|
||||
|
||||
// Update highlighting of search result
|
||||
e.search.hlLine = current
|
||||
e.search.hl = make([]int, row.RenderSize())
|
||||
// Save the current highlighting of where the search result is
|
||||
e.search.savedhlLine = current
|
||||
e.search.savedhl = make([]int, row.RenderSize())
|
||||
for i, val := range row.Hl {
|
||||
e.search.hl[i] = val
|
||||
e.search.savedhl[i] = val
|
||||
}
|
||||
|
||||
// Update highlighting of search result
|
||||
for x := matchIndex; x < matchIndex+len(query); x++ {
|
||||
row.Hl[x] = highlight.Match
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ type Point struct {
|
||||
X int
|
||||
Y int
|
||||
}
|
||||
|
||||
// DefaultPoint creates a Point at 0,0
|
||||
func DefaultPoint() *Point {
|
||||
return &Point{0, 0}
|
||||
|
Loading…
Reference in New Issue
Block a user