1
0

model.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package editor
  2. import (
  3. "moose/internal/buffer"
  4. "strings"
  5. "unicode/utf8"
  6. "charm.land/bubbles/v2/viewport"
  7. tea "charm.land/bubbletea/v2"
  8. )
  9. type Model struct {
  10. Buffer buffer.Buffer
  11. CommandBuffer buffer.Buffer
  12. Viewport viewport.Model
  13. Actions []Action
  14. Width int
  15. Height int
  16. }
  17. func NewModel() Model {
  18. initialBuf := buffer.Buffer{
  19. Rope: nil,
  20. CM: buffer.CursorManager{
  21. Cursors: []buffer.Cursor{{Offset: 0, Goal: 0}},
  22. PrimaryIdx: 0,
  23. },
  24. }
  25. vp := viewport.New()
  26. vp.MouseWheelEnabled = false
  27. model := Model{
  28. Buffer: initialBuf,
  29. Viewport: vp,
  30. Actions: DefaultActions(),
  31. }
  32. model.Viewport.SetContent(model.renderedContent())
  33. return model
  34. }
  35. func (m Model) Init() tea.Cmd {
  36. return nil
  37. }
  38. func (m Model) View() tea.View {
  39. v := tea.NewView(m.Viewport.View())
  40. v.AltScreen = true
  41. v.MouseMode = tea.MouseModeCellMotion
  42. return v
  43. }
  44. func (m Model) renderedContent() string {
  45. content := []byte(m.Buffer.String())
  46. cursorMap := make(map[int]bool)
  47. for _, cur := range m.Buffer.CM.Cursors {
  48. offset := cur.Offset
  49. if offset < 0 {
  50. offset = 0
  51. }
  52. if offset > len(content) {
  53. offset = len(content)
  54. }
  55. cursorMap[offset] = true
  56. }
  57. var out strings.Builder
  58. out.Grow(len(content) + len(cursorMap))
  59. for i := 0; i < len(content); {
  60. r, size := utf8.DecodeRune(content[i:])
  61. if r == utf8.RuneError && size == 1 {
  62. if cursorMap[i] {
  63. out.WriteRune('█')
  64. i++
  65. continue
  66. }
  67. out.WriteByte(content[i])
  68. i++
  69. continue
  70. }
  71. if cursorMap[i] {
  72. out.WriteRune('█')
  73. if r == '\n' {
  74. out.WriteRune('\n')
  75. }
  76. i += size
  77. continue
  78. }
  79. out.WriteRune(r)
  80. i += size
  81. }
  82. if cursorMap[len(content)] {
  83. out.WriteRune('█')
  84. }
  85. return out.String()
  86. }