Optimization for buffer text

We no longer store a string representation of the buffer and instead
directly access it through the rope
This commit is contained in:
Zachary Yedidia 2016-05-04 12:43:17 -04:00
parent c163aaa895
commit f6dc983823
5 changed files with 24 additions and 25 deletions

View file

@ -373,7 +373,7 @@ func (v *View) SelectDown() bool {
// SelectLeft selects the character to the left of the cursor
func (v *View) SelectLeft() bool {
loc := v.cursor.Loc()
count := Count(v.buf.text) - 1
count := v.buf.Len() - 1
if loc > count {
loc = count
}
@ -388,7 +388,7 @@ func (v *View) SelectLeft() bool {
// SelectRight selects the character to the right of the cursor
func (v *View) SelectRight() bool {
loc := v.cursor.Loc()
count := Count(v.buf.text) - 1
count := v.buf.Len() - 1
if loc > count {
loc = count
}
@ -465,7 +465,7 @@ func (v *View) CursorStart() bool {
// CursorEnd moves the cursor to the end of the buffer
func (v *View) CursorEnd() bool {
v.cursor.SetLoc(len(v.buf.text))
v.cursor.SetLoc(v.buf.Len())
return true
}
@ -487,7 +487,7 @@ func (v *View) SelectToEnd() bool {
v.cursor.origSelection[0] = loc
}
v.CursorEnd()
v.cursor.SelectTo(len(v.buf.text))
v.cursor.SelectTo(v.buf.Len())
return true
}
@ -570,7 +570,7 @@ func (v *View) Delete() bool {
v.cursor.ResetSelection()
} else {
loc := v.cursor.Loc()
if loc < len(v.buf.text) {
if loc < v.buf.Len() {
v.eh.Remove(loc, loc+1)
}
}

View file

@ -27,7 +27,6 @@ type Buffer struct {
// Provide efficient and easy access to text and lines so the rope String does not
// need to be constantly recalculated
// These variables are updated in the update() function
text string
lines []string
// Syntax highlighting rules
@ -60,14 +59,17 @@ func (b *Buffer) UpdateRules() {
b.rules, b.filetype = GetRules(b)
}
func (b *Buffer) String() string {
text := ""
if b.r.Len() != 0 {
text = b.r.String()
}
return text
}
// Update fetches the string from the rope and updates the `text` and `lines` in the buffer
func (b *Buffer) Update() {
if b.r.Len() == 0 {
b.text = ""
} else {
b.text = b.r.String()
}
b.lines = strings.Split(b.text, "\n")
b.lines = strings.Split(b.String(), "\n")
}
// Save saves the buffer to its default path
@ -78,7 +80,7 @@ func (b *Buffer) Save() error {
// SaveAs saves the buffer to a specified path (filename), creating the file if it does not exist
func (b *Buffer) SaveAs(filename string) error {
b.UpdateRules()
data := []byte(b.text)
data := []byte(b.String())
err := ioutil.WriteFile(filename, data, 0644)
if err == nil {
b.savedText = md5.Sum(data)
@ -93,17 +95,13 @@ func (b *Buffer) IsDirty() bool {
return false
}
if b.netInsertions == 0 {
isDirty := b.savedText != md5.Sum([]byte(b.text))
isDirty := b.savedText != md5.Sum([]byte(b.String()))
b.dirtySinceLastCheck = isDirty
return isDirty
}
return true
}
func (b *Buffer) Lines() []string {
return strings.Split(b.text, "\n")
}
// Insert a string into the rope
func (b *Buffer) Insert(idx int, value string) {
b.dirtySinceLastCheck = true
@ -123,7 +121,7 @@ func (b *Buffer) Remove(start, end int) string {
if end > b.Len() {
end = b.Len()
}
removed := b.text[start:end]
removed := b.r.Report(start+1, end-start)
// The rope implenentation I am using wants indicies starting at 1 instead of 0
start++
end++

View file

@ -141,7 +141,7 @@ func HandleCommand(input string, view *View) {
found := false
for {
match := regex.FindStringIndex(view.buf.text)
match := regex.FindStringIndex(view.buf.String())
if match == nil {
break
}

View file

@ -102,9 +102,9 @@ func (c *Cursor) DeleteSelection() {
// GetSelection returns the cursor's selection
func (c *Cursor) GetSelection() string {
if c.curSelection[0] > c.curSelection[1] {
return string([]rune(c.v.buf.text)[c.curSelection[1]:c.curSelection[0]])
return c.v.buf.r.Report(c.curSelection[1]+1, c.curSelection[0]-c.curSelection[1])
}
return string([]rune(c.v.buf.text)[c.curSelection[0]:c.curSelection[1]])
return c.v.buf.r.Report(c.curSelection[0]+1, c.curSelection[1]-c.curSelection[0])
}
// SelectLine selects the current line

View file

@ -72,11 +72,12 @@ func Search(searchStr string, v *View, down bool) {
}
var str string
var charPos int
text := v.buf.String()
if down {
str = v.buf.text[searchStart:]
str = text[searchStart:]
charPos = searchStart
} else {
str = v.buf.text[:searchStart]
str = text[:searchStart]
}
r, err := regexp.Compile(searchStr)
if err != nil {
@ -86,7 +87,7 @@ func Search(searchStr string, v *View, down bool) {
var match []int
if matches == nil {
// Search the entire buffer now
matches = r.FindAllStringIndex(v.buf.text, -1)
matches = r.FindAllStringIndex(text, -1)
charPos = 0
if matches == nil {
v.cursor.ResetSelection()