buffer.go 8.0 KB

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