File: iter.go

package info (click to toggle)
kitty 0.42.1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 28,564 kB
  • sloc: ansic: 82,787; python: 55,191; objc: 5,122; sh: 1,295; xml: 364; makefile: 143; javascript: 78
file content (138 lines) | stat: -rw-r--r-- 3,094 bytes parent folder | download | duplicates (2)
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
}