1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
package wcswidth
import (
"fmt"
)
var _ = fmt.Print
type current_cell struct {
head, tail, width int
}
type forward_iterator struct {
width_iter *WCWidthIterator
current_cell current_cell
cell_num, pos int
}
type reverse_iterator struct {
cells []string
pos int
}
func (self *forward_iterator) reset() {
self.width_iter.Reset()
self.current_cell = current_cell{}
self.pos = 0
self.cell_num = 0
}
type CellIterator struct {
text, current string
forward_iter forward_iterator
reverse_iter reverse_iterator
}
func NewCellIterator(text string) *CellIterator {
ans := &CellIterator{text: text}
ans.forward_iter.width_iter = CreateWCWidthIterator()
return ans
}
func (self *CellIterator) GotoStart() *CellIterator {
self.forward_iter.reset()
self.reverse_iter.pos = -1
self.current = ""
return self
}
func (self *CellIterator) GotoEnd() *CellIterator {
self.current = ""
self.reverse_iter.pos = len(self.reverse_iter.cells)
self.forward_iter.pos = len(self.text)
self.forward_iter.cell_num = len(self.text) + 1
return self
}
func (self *CellIterator) Current() string { return self.current }
func (self *CellIterator) forward_one_rune() bool {
for self.forward_iter.pos < len(self.text) {
rune_count_before := self.forward_iter.width_iter.rune_count
self.forward_iter.width_iter.ParseByte(self.text[self.forward_iter.pos])
self.forward_iter.pos++
if self.forward_iter.width_iter.rune_count != rune_count_before {
return true
}
}
return false
}
func (self *CellIterator) Forward() (has_more bool) {
if self.reverse_iter.cells != nil {
if self.reverse_iter.pos < len(self.reverse_iter.cells) {
self.reverse_iter.pos++
}
if self.reverse_iter.pos >= len(self.reverse_iter.cells) {
self.current = ""
return false
}
self.current = self.reverse_iter.cells[self.reverse_iter.pos]
return true
}
fi := &self.forward_iter
cc := &fi.current_cell
for {
width_before := fi.width_iter.current_width
pos_before := fi.pos
if !self.forward_one_rune() {
break
}
change_in_width := fi.width_iter.current_width - width_before
cc.tail = fi.pos
if cc.width > 0 && change_in_width > 0 {
self.current = self.text[cc.head:pos_before]
cc.width = change_in_width
cc.head = pos_before
fi.cell_num++
return true
}
cc.width += change_in_width
}
if cc.tail > cc.head {
self.current = self.text[cc.head:cc.tail]
cc.head = fi.pos
cc.tail = fi.pos
cc.width = 0
fi.cell_num++
return true
}
self.current = ""
return false
}
func (self *CellIterator) Backward() (has_more bool) {
ri := &self.reverse_iter
if ri.cells == nil {
current_cell_num := self.forward_iter.cell_num
cells := make([]string, 0, len(self.text))
self.GotoStart()
for self.Forward() {
cells = append(cells, self.current)
}
ri.pos = min(max(-1, current_cell_num-1), len(cells))
ri.cells = cells
}
if ri.pos > -1 {
ri.pos--
}
if ri.pos < 0 {
self.current = ""
return false
}
self.current = ri.cells[ri.pos]
return true
}
|