1
0

buffer.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. package buffer
  2. import (
  3. "slices"
  4. "unicode/utf8"
  5. "github.com/zyedidia/rope"
  6. )
  7. type BufferManager struct {
  8. Buffers []Buffer
  9. CurrentIdx int
  10. PaletteBuffer Buffer
  11. }
  12. func (bm *BufferManager) Current() *Buffer {
  13. return &bm.Buffers[bm.CurrentIdx]
  14. }
  15. type Buffer struct {
  16. Rope *rope.Node
  17. LI *LineIndex
  18. CM CursorManager
  19. Path string
  20. TopLine int
  21. }
  22. func NewBuffer() Buffer {
  23. return Buffer{
  24. Rope: rope.New([]byte{}),
  25. LI: NewLineIndex(),
  26. CM: CursorManager{
  27. Cursors: []Cursor{{Offset: 0, Goal: 0}},
  28. PrimaryIdx: 0,
  29. },
  30. }
  31. }
  32. func (buf *Buffer) ensureRope() {
  33. if buf.Rope == nil {
  34. buf.Rope = rope.New([]byte{})
  35. }
  36. if buf.LI == nil {
  37. buf.LI = NewLineIndexFromRope(buf.Rope)
  38. }
  39. }
  40. func (buf *Buffer) Insert(content rune) {
  41. buf.ensureRope()
  42. buf.CM.DeduplicateAndSort()
  43. delta := 0
  44. data := []byte(string(content))
  45. shift := len(data)
  46. for i := range buf.CM.Cursors {
  47. cur := &buf.CM.Cursors[i]
  48. pos := cur.Offset + delta
  49. if pos < 0 {
  50. pos = 0
  51. }
  52. if pos > buf.Rope.Len() {
  53. pos = buf.Rope.Len()
  54. }
  55. buf.Rope.Insert(pos, data)
  56. buf.LI.InsertAt(pos, data)
  57. cur.Offset = pos + shift
  58. _, goal := LineCol(buf, cur.Offset)
  59. cur.Goal = goal
  60. delta += shift
  61. }
  62. }
  63. func (buf *Buffer) Paste(content string) {
  64. for _, r := range content {
  65. buf.Insert(r)
  66. }
  67. }
  68. func (buf *Buffer) Delete() {
  69. buf.ensureRope()
  70. buf.CM.DeduplicateAndSort()
  71. delta := 0
  72. for i := range buf.CM.Cursors {
  73. cur := &buf.CM.Cursors[i]
  74. pos := cur.Offset + delta
  75. if pos <= 0 {
  76. cur.Offset = 0
  77. continue
  78. }
  79. if pos > buf.Rope.Len() {
  80. pos = buf.Rope.Len()
  81. }
  82. left := buf.Rope.Slice(0, pos)
  83. _, size := utf8.DecodeLastRune(left)
  84. if size <= 0 {
  85. size = 1
  86. }
  87. start := pos - size
  88. if start < 0 {
  89. start = 0
  90. }
  91. buf.Rope.Remove(start, pos)
  92. buf.LI.RemoveAt(start, pos)
  93. deleted := pos - start
  94. delta -= deleted
  95. cur.Offset = start
  96. _, goal := LineCol(buf, cur.Offset)
  97. cur.Goal = goal
  98. }
  99. buf.CM.DeduplicateAndSort()
  100. }
  101. func (buf *Buffer) Clear() {
  102. buf.ensureRope()
  103. primaryCursor := &Cursor{
  104. Offset: 0,
  105. Goal: 0,
  106. }
  107. buf.CM.Cursors = buf.CM.Cursors[:0]
  108. buf.CM.Cursors = append(buf.CM.Cursors, *primaryCursor)
  109. buf.CM.PrimaryIdx = 0
  110. buf.Rope.Remove(0, buf.Rope.Len())
  111. buf.LI = NewLineIndex()
  112. }
  113. func (buf *Buffer) MoveHoriz(dir int) {
  114. buf.ensureRope()
  115. for i := range buf.CM.Cursors {
  116. cur := &buf.CM.Cursors[i]
  117. switch {
  118. case dir < 0:
  119. cur.Offset = prevRuneStart(buf.Rope, cur.Offset)
  120. case dir > 0:
  121. cur.Offset = nextRuneEnd(buf.Rope, cur.Offset)
  122. }
  123. _, goal := LineCol(buf, cur.Offset)
  124. cur.Goal = goal
  125. }
  126. buf.CM.DeduplicateAndSort()
  127. }
  128. func (buf *Buffer) MoveVert(dir int) {
  129. buf.ensureRope()
  130. for i := range buf.CM.Cursors {
  131. cur := &buf.CM.Cursors[i]
  132. line, _ := LineCol(buf, cur.Offset)
  133. targetLine := line + dir
  134. if targetLine < 0 || targetLine >= LineCount(buf) {
  135. continue
  136. }
  137. lineStart := OffsetForLine(buf, targetLine)
  138. lineEnd := lineContentEnd(buf, targetLine)
  139. lineLen := runeCount(buf.Rope, lineStart, lineEnd)
  140. goal := cur.Goal
  141. if goal > lineLen {
  142. goal = lineLen
  143. }
  144. cur.Offset = OffsetForLineCol(buf, targetLine, goal)
  145. }
  146. buf.CM.DeduplicateAndSort()
  147. }
  148. func (buf *Buffer) AddCursorVert(dir int) {
  149. buf.ensureRope()
  150. var newCursors []Cursor
  151. for i := range buf.CM.Cursors {
  152. cur := &buf.CM.Cursors[i]
  153. line, _ := LineCol(buf, cur.Offset)
  154. targetLine := line + dir
  155. if targetLine < 0 || targetLine >= LineCount(buf) {
  156. continue
  157. }
  158. lineStart := OffsetForLine(buf, targetLine)
  159. lineEnd := lineContentEnd(buf, targetLine)
  160. lineLen := runeCount(buf.Rope, lineStart, lineEnd)
  161. goal := cur.Goal
  162. if goal > lineLen {
  163. goal = lineLen
  164. }
  165. newCursors = append(newCursors, Cursor{
  166. Offset: OffsetForLineCol(buf, targetLine, goal),
  167. Goal: goal,
  168. })
  169. }
  170. buf.CM.Cursors = slices.Concat(buf.CM.Cursors, newCursors)
  171. buf.CM.DeduplicateAndSort()
  172. }
  173. func (buf *Buffer) ScrollToShow(line, maxHeight int) {
  174. if maxHeight <= 0 {
  175. return
  176. }
  177. if line < buf.TopLine {
  178. buf.TopLine = line
  179. } else if line >= buf.TopLine+maxHeight {
  180. buf.TopLine = line - maxHeight + 1
  181. }
  182. if buf.TopLine < 0 {
  183. buf.TopLine = 0
  184. }
  185. }
  186. func (buf *Buffer) ClearCursors() {
  187. primaryCursor := &Cursor{
  188. Offset: buf.CM.Cursors[buf.CM.PrimaryIdx].Offset,
  189. Goal: buf.CM.Cursors[buf.CM.PrimaryIdx].Goal,
  190. }
  191. buf.CM.Cursors = buf.CM.Cursors[:0]
  192. buf.CM.Cursors = append(buf.CM.Cursors, *primaryCursor)
  193. buf.CM.PrimaryIdx = 0
  194. }
  195. func LineCount(buf *Buffer) int {
  196. return buf.LI.Count()
  197. }
  198. func LineCol(buf *Buffer, offset int) (line, col int) {
  199. offset = normalizeOffset(buf.Rope, offset)
  200. if offset < 0 {
  201. offset = 0
  202. }
  203. if offset > buf.Rope.Len() {
  204. offset = buf.Rope.Len()
  205. }
  206. line = buf.LI.LineForOffset(offset)
  207. lineStart := buf.LI.OffsetForLine(line)
  208. col = runeCount(buf.Rope, lineStart, offset)
  209. return
  210. }
  211. func OffsetForLine(buf *Buffer, targetLine int) int {
  212. if targetLine <= 0 {
  213. return 0
  214. }
  215. if targetLine >= buf.LI.Count() {
  216. return buf.Rope.Len()
  217. }
  218. return buf.LI.OffsetForLine(targetLine)
  219. }
  220. func OffsetForLineCol(buf *Buffer, line int, col int) int {
  221. if col <= 0 {
  222. return OffsetForLine(buf, line)
  223. }
  224. start := OffsetForLine(buf, line)
  225. end := lineContentEnd(buf, line)
  226. i := start
  227. for n := 0; i < end && n < col; n++ {
  228. _, size := utf8.DecodeRune(buf.Rope.Slice(i, end))
  229. if size <= 0 {
  230. size = 1
  231. }
  232. i += size
  233. }
  234. if i > end {
  235. return end
  236. }
  237. return i
  238. }
  239. func LineText(buf *Buffer, line int) string {
  240. start := OffsetForLine(buf, line)
  241. end := lineContentEnd(buf, line)
  242. if end < start {
  243. end = start
  244. }
  245. return string(buf.Rope.Slice(start, end))
  246. }
  247. func lineContentEnd(buf *Buffer, line int) int {
  248. nextStart := OffsetForLine(buf, line+1)
  249. if nextStart > 0 && nextStart <= buf.Rope.Len() && buf.Rope.At(nextStart-1) == '\n' {
  250. return nextStart - 1
  251. }
  252. return nextStart
  253. }
  254. func runeCount(r *rope.Node, start, end int) int {
  255. if start < 0 {
  256. start = 0
  257. }
  258. if end < start {
  259. end = start
  260. }
  261. if end > r.Len() {
  262. end = r.Len()
  263. }
  264. return utf8.RuneCount(r.Slice(start, end))
  265. }
  266. func normalizeOffset(r *rope.Node, offset int) int {
  267. if offset < 0 {
  268. return 0
  269. }
  270. if offset > r.Len() {
  271. return r.Len()
  272. }
  273. for offset > 0 && offset < r.Len() && !utf8.RuneStart(r.At(offset)) {
  274. offset--
  275. }
  276. return offset
  277. }
  278. func prevRuneStart(r *rope.Node, offset int) int {
  279. offset = normalizeOffset(r, offset)
  280. if offset <= 0 {
  281. return 0
  282. }
  283. left := r.Slice(0, offset)
  284. _, size := utf8.DecodeLastRune(left)
  285. if size <= 0 {
  286. size = 1
  287. }
  288. start := offset - size
  289. if start < 0 {
  290. start = 0
  291. }
  292. return start
  293. }
  294. func nextRuneEnd(r *rope.Node, offset int) int {
  295. offset = normalizeOffset(r, offset)
  296. if offset >= r.Len() {
  297. return r.Len()
  298. }
  299. _, size := utf8.DecodeRune(r.Slice(offset, r.Len()))
  300. if size <= 0 {
  301. size = 1
  302. }
  303. end := offset + size
  304. if end > r.Len() {
  305. end = r.Len()
  306. }
  307. return end
  308. }
  309. func RuneAt(buf *Buffer, offset int) rune {
  310. if buf.Rope == nil || offset < 0 || offset >= buf.Rope.Len() {
  311. return ' '
  312. }
  313. r, size := utf8.DecodeRune(buf.Rope.Slice(offset, buf.Rope.Len()))
  314. if size <= 0 || r == '\n' || r == '\t' {
  315. return ' '
  316. }
  317. return r
  318. }
  319. func (buf Buffer) String() string {
  320. if buf.Rope == nil {
  321. return ""
  322. }
  323. return string(buf.Rope.Value())
  324. }