render.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package editor
  2. import (
  3. "strings"
  4. "moose/internal/buffer"
  5. "github.com/gdamore/tcell/v3/color"
  6. )
  7. func (m Model) Render() {
  8. sWidth, sHeight := m.Screen.Size()
  9. maxHeight := sHeight - 2 // TODO: saturating sub?
  10. bLen := len(m.BM.Buffers)
  11. bufWidth := sWidth / bLen
  12. for i := range m.BM.Buffers {
  13. buf := &m.BM.Buffers[i]
  14. primary := buf.CM.Cursors[buf.CM.PrimaryIdx]
  15. curLine, _ := buffer.LineCol(buf, primary.Offset)
  16. buf.ScrollToShow(curLine, maxHeight)
  17. startOffset := buffer.OffsetForLine(buf, buf.TopLine)
  18. endOffset := buf.Rope.Len()
  19. if endLine := buf.TopLine + maxHeight; endLine < buffer.LineCount(buf) {
  20. endOffset = buffer.OffsetForLine(buf, endLine)
  21. }
  22. visible := string(buf.Rope.Slice(startOffset, endOffset))
  23. table := strings.SplitAfter(visible, "\n")
  24. for j, line := range table {
  25. if j + 1 > maxHeight { break }
  26. r := []rune(line)
  27. if len(r) + 1 > bufWidth {
  28. r = r[:bufWidth]
  29. }
  30. m.Screen.PutStrStyled(bufWidth*i, j, string(r), m.Style)
  31. }
  32. if i == m.BM.CurrentIdx || m.Mode == ModePalette {
  33. for _, cur := range buf.CM.Cursors {
  34. line, col := buffer.LineCol(buf, cur.Offset)
  35. screenLine := line - buf.TopLine
  36. if screenLine < 0 || screenLine + 1 > maxHeight { continue }
  37. if col + 1 > bufWidth { continue }
  38. if m.Mode == ModeWrite {
  39. m.Screen.SetContent(bufWidth * i + col, screenLine, ' ', nil, m.Style.Reverse(true))
  40. } else {
  41. m.Screen.SetContent(bufWidth * i + col, screenLine, ' ', nil, m.Style.Reverse(true).Foreground(color.Gray))
  42. }
  43. }
  44. }
  45. }
  46. for col := 0; col < sWidth; col++ {
  47. m.Screen.SetContent(col, maxHeight, ' ', nil, m.Style.Reverse(true))
  48. }
  49. modeStr := m.Mode.String()
  50. if m.Mode == ModePalette {
  51. if strings.HasPrefix(m.BM.PaletteBuffer.String(), "/") {
  52. modeStr = "command"
  53. } else if strings.HasPrefix(m.BM.PaletteBuffer.String(), "?") {
  54. modeStr = "find"
  55. } else if strings.HasPrefix(m.BM.PaletteBuffer.String(), "=") {
  56. modeStr = "replace"
  57. }
  58. }
  59. m.Screen.PutStrStyled(sWidth - (len(modeStr) + 1), maxHeight, strings.ToUpper(modeStr), m.Style.Reverse(true))
  60. if m.Mode == ModePalette {
  61. m.Screen.PutStrStyled(0, maxHeight + 1, m.BM.PaletteBuffer.String(), m.Style)
  62. for _, cur := range m.BM.PaletteBuffer.CM.Cursors {
  63. line, col := buffer.LineCol(&m.BM.PaletteBuffer, cur.Offset)
  64. if line + maxHeight != maxHeight { continue }
  65. if col + 1 > sWidth { continue }
  66. m.Screen.SetContent(col, maxHeight + 1, ' ', nil, m.Style.Reverse(true))
  67. }
  68. } else if strings.HasPrefix(m.BM.PaletteBuffer.String(), "moose.info:") {
  69. m.Screen.PutStrStyled(0, maxHeight + 1, string([]rune(m.BM.PaletteBuffer.String())[11:]), m.Style.Foreground(color.LightGray))
  70. } else if strings.HasPrefix(m.BM.PaletteBuffer.String(), "moose.warn:") {
  71. m.Screen.PutStrStyled(0, maxHeight + 1, string([]rune(m.BM.PaletteBuffer.String())[11:]), m.Style.Foreground(color.Orange))
  72. } else if strings.HasPrefix(m.BM.PaletteBuffer.String(), "moose.error:") {
  73. m.Screen.PutStrStyled(0, maxHeight + 1, string([]rune(m.BM.PaletteBuffer.String())[12:]), m.Style.Foreground(color.Red))
  74. }
  75. }