editor.go

  1package repl
  2
  3import (
  4	"github.com/charmbracelet/bubbles/key"
  5	tea "github.com/charmbracelet/bubbletea"
  6	"github.com/kujtimiihoxha/termai/internal/app"
  7	"github.com/kujtimiihoxha/termai/internal/tui/layout"
  8	"github.com/kujtimiihoxha/vimtea"
  9)
 10
 11type EditorCmp interface {
 12	tea.Model
 13	layout.Focusable
 14	layout.Sizeable
 15	layout.Bordered
 16}
 17
 18type editorCmp struct {
 19	app        *app.App
 20	editor     vimtea.Editor
 21	editorMode vimtea.EditorMode
 22	sessionID  string
 23	focused    bool
 24	width      int
 25	height     int
 26}
 27
 28type localKeyMap struct {
 29	SendMessage  key.Binding
 30	SendMessageI key.Binding
 31}
 32
 33var keyMap = localKeyMap{
 34	SendMessage: key.NewBinding(
 35		key.WithKeys("enter"),
 36		key.WithHelp("enter", "send message normal mode"),
 37	),
 38	SendMessageI: key.NewBinding(
 39		key.WithKeys("ctrl+s"),
 40		key.WithHelp("ctrl+s", "send message insert mode"),
 41	),
 42}
 43
 44func (m *editorCmp) Init() tea.Cmd {
 45	return m.editor.Init()
 46}
 47
 48func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 49	switch msg := msg.(type) {
 50	case vimtea.EditorModeMsg:
 51		m.editorMode = msg.Mode
 52	case SelectedSessionMsg:
 53		if msg.SessionID != m.sessionID {
 54			m.sessionID = msg.SessionID
 55		}
 56	}
 57	if m.IsFocused() {
 58		switch msg := msg.(type) {
 59		case tea.KeyMsg:
 60			switch {
 61			case key.Matches(msg, keyMap.SendMessage):
 62				if m.editorMode == vimtea.ModeNormal {
 63					return m, m.Send()
 64				}
 65			case key.Matches(msg, keyMap.SendMessageI):
 66				if m.editorMode == vimtea.ModeInsert {
 67					return m, m.Send()
 68				}
 69			}
 70		}
 71		u, cmd := m.editor.Update(msg)
 72		m.editor = u.(vimtea.Editor)
 73		return m, cmd
 74	}
 75	return m, nil
 76}
 77
 78// Blur implements EditorCmp.
 79func (m *editorCmp) Blur() tea.Cmd {
 80	m.focused = false
 81	return nil
 82}
 83
 84// BorderText implements EditorCmp.
 85func (m *editorCmp) BorderText() map[layout.BorderPosition]string {
 86	return map[layout.BorderPosition]string{
 87		layout.TopLeftBorder: "New Message",
 88	}
 89}
 90
 91// Focus implements EditorCmp.
 92func (m *editorCmp) Focus() tea.Cmd {
 93	m.focused = true
 94	return m.editor.Tick()
 95}
 96
 97// GetSize implements EditorCmp.
 98func (m *editorCmp) GetSize() (int, int) {
 99	return m.width, m.height
100}
101
102// IsFocused implements EditorCmp.
103func (m *editorCmp) IsFocused() bool {
104	return m.focused
105}
106
107// SetSize implements EditorCmp.
108func (m *editorCmp) SetSize(width int, height int) {
109	m.width = width
110	m.height = height
111	m.editor.SetSize(width, height)
112}
113
114func (m *editorCmp) Send() tea.Cmd {
115	return func() tea.Msg {
116		// TODO: Send message
117		return nil
118	}
119}
120
121func (m *editorCmp) View() string {
122	return m.editor.View()
123}
124
125func NewEditorCmp(app *app.App) EditorCmp {
126	return &editorCmp{
127		app:    app,
128		editor: vimtea.NewEditor(),
129	}
130}