From cc098d05ef59c1229bf17be53ff6afe0f28d6eeb Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Fri, 18 Mar 2016 21:25:45 -0400 Subject: [PATCH] Comments and style for rope --- buffer.go | 10 ++++----- rope.go | 65 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/buffer.go b/buffer.go index 770b2660..4a091930 100644 --- a/buffer.go +++ b/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 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 // These variables are updated in the update() function text string @@ -30,7 +30,7 @@ type Buffer struct { // NewBuffer creates a new buffer from `txt` with path and name `path` func NewBuffer(txt, path string) *Buffer { b := new(Buffer) - b.r = newRope(txt) + b.r = NewRope(txt) b.path = path b.name = path 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 func (b *Buffer) Update() { - b.text = b.r.toString() + b.text = b.r.String() b.lines = strings.Split(b.text, "\n") } @@ -60,13 +60,13 @@ func (b *Buffer) SaveAs(filename string) error { // Insert a string into the rope func (b *Buffer) Insert(idx int, value string) { - b.r.insert(idx, value) + b.r.Insert(idx, value) b.Update() } // Remove a slice of the rope from start to end (exclusive) func (b *Buffer) Remove(start, end int) { - b.r.remove(start, end) + b.r.Remove(start, end) b.Update() } diff --git a/rope.go b/rope.go index 29980289..ad653983 100644 --- a/rope.go +++ b/rope.go @@ -1,31 +1,35 @@ package main import ( - // "fmt" "math" "unicode/utf8" ) const ( - ropeSplitLength = 1000 - ropeJoinLength = 500 - ropeRebalanceRatio = 1.2 + // RopeSplitLength defines how large can a string be before it is split into two nodes + RopeSplitLength = 1000 + // 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 { return b } return a } -func max(a, b int) int { +// Max takes the max of two ints +func Max(a, b int) int { if a > b { return a } return b } +// A Rope is a data structure for efficiently manipulating large strings type Rope struct { left *Rope right *Rope @@ -35,28 +39,30 @@ type Rope struct { 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.value = str r.valueNil = false r.len = utf8.RuneCountInString(r.value) - r.adjust() + r.Adjust() return r } -func (r *Rope) adjust() { +// Adjust modifies the rope so it is more balanced +func (r *Rope) Adjust() { if !r.valueNil { - if r.len > ropeSplitLength { + if r.len > RopeSplitLength { divide := int(math.Floor(float64(r.len) / 2)) - r.left = newRope(r.value[:divide]) - r.right = newRope(r.value[divide:]) + r.left = NewRope(r.value[:divide]) + r.right = NewRope(r.value[divide:]) r.valueNil = true } } else { - if r.len < ropeJoinLength { - r.value = r.left.toString() + r.right.toString() + if r.len < RopeJoinLength { + r.value = r.left.String() + r.right.String() r.valueNil = false r.left = 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 { 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 { r.value = string(append([]rune(r.value)[:start], []rune(r.value)[end:]...)) r.valueNil = false r.len = utf8.RuneCountInString(r.value) } else { - leftStart := min(start, r.left.len) - leftEnd := min(end, r.left.len) - rightStart := max(0, min(start-r.left.len, r.right.len)) - rightEnd := max(0, min(end-r.left.len, r.right.len)) + leftStart := Min(start, r.left.len) + leftEnd := Min(end, r.left.len) + rightStart := Max(0, Min(start-r.left.len, r.right.len)) + rightEnd := Max(0, Min(end-r.left.len, r.right.len)) if leftStart < r.left.len { - r.left.remove(leftStart, leftEnd) + r.left.Remove(leftStart, leftEnd) } if rightEnd > 0 { - r.right.remove(rightStart, rightEnd) + r.right.Remove(rightStart, rightEnd) } 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 { first := append([]rune(r.value)[:pos], []rune(value)...) 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) } else { if pos < r.left.len { - r.left.insert(pos, value) + r.left.Insert(pos, value) r.len = r.left.len + r.right.len } else { - r.right.insert(pos-r.left.len, value) + r.right.Insert(pos-r.left.len, value) } } - r.adjust() + r.Adjust() }