@@ -162,9 +162,7 @@ func (m *editorCmp) send() tea.Cmd {
164func (m *editorCmp) repositionCompletions() tea.Msg {
164func (m *editorCmp) repositionCompletions() tea.Msg {
165− cur := m.textarea.Cursor()
165+ x, y := m.completionsPosition()
166− x := cur.X + m.x // adjust for padding
167− y := cur.Y + m.y + 1
168 return completions.RepositionCompletionsMsg{X: x, Y: y}
166 return completions.RepositionCompletionsMsg{X: x, Y: y}
@@ -191,32 +189,37 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
191 return m, nil
189 return m, nil
193 if item, ok := msg.Value.(FileCompletionItem); ok {
191 if item, ok := msg.Value.(FileCompletionItem); ok {
192+ word := m.textarea.Word()
194 // If the selected item is a file, insert its path into the textarea
193 // If the selected item is a file, insert its path into the textarea
195 value := m.textarea.Value()
194 value := m.textarea.Value()
196− value = value[:m.completionsStartIndex]
195+ value = value[:m.completionsStartIndex] + // Remove the current query
197− value += item.Path
196+ item.Path + // Insert the file path
197+ value[m.completionsStartIndex+len(word):] // Append the rest of the value
198+ // XXX: This will always move the cursor to the end of the textarea.
198 m.textarea.SetValue(value)
199 m.textarea.SetValue(value)
200+ m.textarea.MoveToEnd()
199 if !msg.Insert {
201 if !msg.Insert {
200 m.isCompletionsOpen = false
202 m.isCompletionsOpen = false
201 m.currentQuery = ""
203 m.currentQuery = ""
202 m.completionsStartIndex = 0
204 m.completionsStartIndex = 0
206 case openEditorMsg:
207 case openEditorMsg:
207 m.textarea.SetValue(msg.Text)
208 m.textarea.SetValue(msg.Text)
208 m.textarea.MoveToEnd()
209 m.textarea.MoveToEnd()
209 case tea.KeyPressMsg:
210 case tea.KeyPressMsg:
211+ cur := m.textarea.Cursor()
212+ curIdx := m.textarea.Width()*cur.Y + cur.X
211 // Completions
214 // Completions
212 case msg.String() == "/" && !m.isCompletionsOpen &&
215 case msg.String() == "/" && !m.isCompletionsOpen &&
213− // only show if beginning of prompt, or if previous char is a space:
216+ // only show if beginning of prompt, or if previous char is a space or newline:
214− (len(m.textarea.Value()) == 0 || m.textarea.Value()[len(m.textarea.Value())-1] == ' '):
217+ (len(m.textarea.Value()) == 0 || unicode.IsSpace(rune(m.textarea.Value()[len(m.textarea.Value())-1]))):
215 m.isCompletionsOpen = true
218 m.isCompletionsOpen = true
216 m.currentQuery = ""
219 m.currentQuery = ""
217− m.completionsStartIndex = len(m.textarea.Value())
220+ m.completionsStartIndex = curIdx
218 cmds = append(cmds, m.startCompletions)
221 cmds = append(cmds, m.startCompletions)
219− case m.isCompletionsOpen && m.textarea.Cursor().X <= m.completionsStartIndex:
222+ case m.isCompletionsOpen && curIdx <= m.completionsStartIndex:
220 cmds = append(cmds, util.CmdHandler(completions.CloseCompletionsMsg{}))
223 cmds = append(cmds, util.CmdHandler(completions.CloseCompletionsMsg{}))
222 if key.Matches(msg, DeleteKeyMaps.AttachmentDeleteMode) {
225 if key.Matches(msg, DeleteKeyMaps.AttachmentDeleteMode) {
@@ -253,6 +256,7 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
254 if key.Matches(msg, m.keyMap.Newline) {
257 if key.Matches(msg, m.keyMap.Newline) {
255 m.textarea.InsertRune('\n')
258 m.textarea.InsertRune('\n')
259+ cmds = append(cmds, util.CmdHandler(completions.CloseCompletionsMsg{}))
257 // Handle Enter key
261 // Handle Enter key
258 if m.textarea.Focused() && key.Matches(msg, m.keyMap.SendMessage) {
262 if m.textarea.Focused() && key.Matches(msg, m.keyMap.SendMessage) {
@@ -284,12 +288,18 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
284 // XXX: wont' work if editing in the middle of the field.
288 // XXX: wont' work if editing in the middle of the field.
285 m.completionsStartIndex = strings.LastIndex(m.textarea.Value(), word)
289 m.completionsStartIndex = strings.LastIndex(m.textarea.Value(), word)
286 m.currentQuery = word[1:]
290 m.currentQuery = word[1:]
291+ x, y := m.completionsPosition()
292+ x -= len(m.currentQuery)
287 m.isCompletionsOpen = true
293 m.isCompletionsOpen = true
288− cmds = append(cmds, util.CmdHandler(completions.FilterCompletionsMsg{
295+ util.CmdHandler(completions.FilterCompletionsMsg{
289− Query: m.currentQuery,
296+ Query: m.currentQuery,
290− Reopen: m.isCompletionsOpen,
297+ Reopen: m.isCompletionsOpen,
302+ } else if m.isCompletionsOpen {
293 m.isCompletionsOpen = false
303 m.isCompletionsOpen = false
294 m.currentQuery = ""
304 m.currentQuery = ""
295 m.completionsStartIndex = 0
305 m.completionsStartIndex = 0
@@ -302,6 +312,16 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
302 return m, tea.Batch(cmds...)
312 return m, tea.Batch(cmds...)
315+func (m *editorCmp) completionsPosition() (int, int) {
316+ cur := m.textarea.Cursor()
318+ return m.x, m.y + 1 // adjust for padding
321+ y := cur.Y + m.y + 1 // adjust for padding
305func (m *editorCmp) Cursor() *tea.Cursor {
325func (m *editorCmp) Cursor() *tea.Cursor {
306 cursor := m.textarea.Cursor()
326 cursor := m.textarea.Cursor()
307 if cursor != nil {
327 if cursor != nil {
@@ -382,9 +402,7 @@ func (m *editorCmp) startCompletions() tea.Msg {
385− cur := m.textarea.Cursor()
405+ x, y := m.completionsPosition()
386− x := cur.X + m.x // adjust for padding
387− y := cur.Y + m.y + 1
388 return completions.OpenCompletionsMsg{
406 return completions.OpenCompletionsMsg{
389 Completions: completionItems,
407 Completions: completionItems,