mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-30 06:37:14 +09:00
Comments and style for rope
This commit is contained in:
10
buffer.go
10
buffer.go
@@ -20,7 +20,7 @@ type Buffer struct {
|
|||||||
// This is the text stored everytime the buffer is saved to check if the buffer is modified
|
// This is the text stored everytime the buffer is saved to check if the buffer is modified
|
||||||
savedText string
|
savedText string
|
||||||
|
|
||||||
// Provide efficient and easy access to text and lines so the rope toString does not
|
// Provide efficient and easy access to text and lines so the rope String does not
|
||||||
// need to be constantly recalculated
|
// need to be constantly recalculated
|
||||||
// These variables are updated in the update() function
|
// These variables are updated in the update() function
|
||||||
text string
|
text string
|
||||||
@@ -30,7 +30,7 @@ type Buffer struct {
|
|||||||
// NewBuffer creates a new buffer from `txt` with path and name `path`
|
// NewBuffer creates a new buffer from `txt` with path and name `path`
|
||||||
func NewBuffer(txt, path string) *Buffer {
|
func NewBuffer(txt, path string) *Buffer {
|
||||||
b := new(Buffer)
|
b := new(Buffer)
|
||||||
b.r = newRope(txt)
|
b.r = NewRope(txt)
|
||||||
b.path = path
|
b.path = path
|
||||||
b.name = path
|
b.name = path
|
||||||
b.savedText = txt
|
b.savedText = txt
|
||||||
@@ -42,7 +42,7 @@ func NewBuffer(txt, path string) *Buffer {
|
|||||||
|
|
||||||
// Update fetches the string from the rope and updates the `text` and `lines` in the buffer
|
// Update fetches the string from the rope and updates the `text` and `lines` in the buffer
|
||||||
func (b *Buffer) Update() {
|
func (b *Buffer) Update() {
|
||||||
b.text = b.r.toString()
|
b.text = b.r.String()
|
||||||
b.lines = strings.Split(b.text, "\n")
|
b.lines = strings.Split(b.text, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,13 +60,13 @@ func (b *Buffer) SaveAs(filename string) error {
|
|||||||
|
|
||||||
// Insert a string into the rope
|
// Insert a string into the rope
|
||||||
func (b *Buffer) Insert(idx int, value string) {
|
func (b *Buffer) Insert(idx int, value string) {
|
||||||
b.r.insert(idx, value)
|
b.r.Insert(idx, value)
|
||||||
b.Update()
|
b.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a slice of the rope from start to end (exclusive)
|
// Remove a slice of the rope from start to end (exclusive)
|
||||||
func (b *Buffer) Remove(start, end int) {
|
func (b *Buffer) Remove(start, end int) {
|
||||||
b.r.remove(start, end)
|
b.r.Remove(start, end)
|
||||||
b.Update()
|
b.Update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
65
rope.go
65
rope.go
@@ -1,31 +1,35 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "fmt"
|
|
||||||
"math"
|
"math"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ropeSplitLength = 1000
|
// RopeSplitLength defines how large can a string be before it is split into two nodes
|
||||||
ropeJoinLength = 500
|
RopeSplitLength = 1000
|
||||||
ropeRebalanceRatio = 1.2
|
// RopeJoinLength defines how short can a string be before it is joined
|
||||||
|
RopeJoinLength = 500
|
||||||
|
// RopeRebalanceRatio = 1.2
|
||||||
)
|
)
|
||||||
|
|
||||||
func min(a, b int) int {
|
// Min takes the min of two ints
|
||||||
|
func Min(a, b int) int {
|
||||||
if a > b {
|
if a > b {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func max(a, b int) int {
|
// Max takes the max of two ints
|
||||||
|
func Max(a, b int) int {
|
||||||
if a > b {
|
if a > b {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Rope is a data structure for efficiently manipulating large strings
|
||||||
type Rope struct {
|
type Rope struct {
|
||||||
left *Rope
|
left *Rope
|
||||||
right *Rope
|
right *Rope
|
||||||
@@ -35,28 +39,30 @@ type Rope struct {
|
|||||||
len int
|
len int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRope(str string) *Rope {
|
// NewRope returns a new rope from a given string
|
||||||
|
func NewRope(str string) *Rope {
|
||||||
r := new(Rope)
|
r := new(Rope)
|
||||||
r.value = str
|
r.value = str
|
||||||
r.valueNil = false
|
r.valueNil = false
|
||||||
r.len = utf8.RuneCountInString(r.value)
|
r.len = utf8.RuneCountInString(r.value)
|
||||||
|
|
||||||
r.adjust()
|
r.Adjust()
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rope) adjust() {
|
// Adjust modifies the rope so it is more balanced
|
||||||
|
func (r *Rope) Adjust() {
|
||||||
if !r.valueNil {
|
if !r.valueNil {
|
||||||
if r.len > ropeSplitLength {
|
if r.len > RopeSplitLength {
|
||||||
divide := int(math.Floor(float64(r.len) / 2))
|
divide := int(math.Floor(float64(r.len) / 2))
|
||||||
r.left = newRope(r.value[:divide])
|
r.left = NewRope(r.value[:divide])
|
||||||
r.right = newRope(r.value[divide:])
|
r.right = NewRope(r.value[divide:])
|
||||||
r.valueNil = true
|
r.valueNil = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if r.len < ropeJoinLength {
|
if r.len < RopeJoinLength {
|
||||||
r.value = r.left.toString() + r.right.toString()
|
r.value = r.left.String() + r.right.String()
|
||||||
r.valueNil = false
|
r.valueNil = false
|
||||||
r.left = nil
|
r.left = nil
|
||||||
r.right = nil
|
r.right = nil
|
||||||
@@ -64,36 +70,39 @@ func (r *Rope) adjust() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rope) toString() string {
|
// String returns the string representation of the rope
|
||||||
|
func (r *Rope) String() string {
|
||||||
if !r.valueNil {
|
if !r.valueNil {
|
||||||
return r.value
|
return r.value
|
||||||
}
|
}
|
||||||
return r.left.toString() + r.right.toString()
|
return r.left.String() + r.right.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rope) remove(start, end int) {
|
// Remove deletes a slice of the rope from start the to end (exclusive)
|
||||||
|
func (r *Rope) Remove(start, end int) {
|
||||||
if !r.valueNil {
|
if !r.valueNil {
|
||||||
r.value = string(append([]rune(r.value)[:start], []rune(r.value)[end:]...))
|
r.value = string(append([]rune(r.value)[:start], []rune(r.value)[end:]...))
|
||||||
r.valueNil = false
|
r.valueNil = false
|
||||||
r.len = utf8.RuneCountInString(r.value)
|
r.len = utf8.RuneCountInString(r.value)
|
||||||
} else {
|
} else {
|
||||||
leftStart := min(start, r.left.len)
|
leftStart := Min(start, r.left.len)
|
||||||
leftEnd := min(end, r.left.len)
|
leftEnd := Min(end, r.left.len)
|
||||||
rightStart := max(0, min(start-r.left.len, r.right.len))
|
rightStart := Max(0, Min(start-r.left.len, r.right.len))
|
||||||
rightEnd := max(0, min(end-r.left.len, r.right.len))
|
rightEnd := Max(0, Min(end-r.left.len, r.right.len))
|
||||||
if leftStart < r.left.len {
|
if leftStart < r.left.len {
|
||||||
r.left.remove(leftStart, leftEnd)
|
r.left.Remove(leftStart, leftEnd)
|
||||||
}
|
}
|
||||||
if rightEnd > 0 {
|
if rightEnd > 0 {
|
||||||
r.right.remove(rightStart, rightEnd)
|
r.right.Remove(rightStart, rightEnd)
|
||||||
}
|
}
|
||||||
r.len = r.left.len + r.right.len
|
r.len = r.left.len + r.right.len
|
||||||
}
|
}
|
||||||
|
|
||||||
r.adjust()
|
r.Adjust()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rope) insert(pos int, value string) {
|
// Insert inserts a string into the rope at a specified position
|
||||||
|
func (r *Rope) Insert(pos int, value string) {
|
||||||
if !r.valueNil {
|
if !r.valueNil {
|
||||||
first := append([]rune(r.value)[:pos], []rune(value)...)
|
first := append([]rune(r.value)[:pos], []rune(value)...)
|
||||||
r.value = string(append(first, []rune(r.value)[pos:]...))
|
r.value = string(append(first, []rune(r.value)[pos:]...))
|
||||||
@@ -101,12 +110,12 @@ func (r *Rope) insert(pos int, value string) {
|
|||||||
r.len = utf8.RuneCountInString(r.value)
|
r.len = utf8.RuneCountInString(r.value)
|
||||||
} else {
|
} else {
|
||||||
if pos < r.left.len {
|
if pos < r.left.len {
|
||||||
r.left.insert(pos, value)
|
r.left.Insert(pos, value)
|
||||||
r.len = r.left.len + r.right.len
|
r.len = r.left.len + r.right.len
|
||||||
} else {
|
} else {
|
||||||
r.right.insert(pos-r.left.len, value)
|
r.right.Insert(pos-r.left.len, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.adjust()
|
r.Adjust()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user