model.go 1.4 KB

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