diff --git a/internal/tui/components/fuzzyselect/mentions.go b/internal/tui/components/fuzzyselect/mentions.go index dbd3a4219..51f42b918 100644 --- a/internal/tui/components/fuzzyselect/mentions.go +++ b/internal/tui/components/fuzzyselect/mentions.go @@ -49,7 +49,7 @@ func (src *UserMentionSource) ExtractContext(input string, cursorPos tea.Positio } if userStart >= len(runes)+1 || - (userStart > 0 && userStart < len(runes) && src.WithAtSymbol && runes[userStart-1] != '@') { + (userStart > 0 && userStart <= len(runes) && src.WithAtSymbol && runes[userStart-1] != '@') { return Context{} } diff --git a/internal/tui/components/fuzzyselect/source_test.go b/internal/tui/components/fuzzyselect/source_test.go index ab764ca18..d01da8c29 100644 --- a/internal/tui/components/fuzzyselect/source_test.go +++ b/internal/tui/components/fuzzyselect/source_test.go @@ -238,6 +238,41 @@ func TestUserMentionSource(t *testing.T) { require.Equal(t, tea.Position{X: 12}, newCursor) } +func TestUserMentionSourceCursorBetweenBoundaries(t *testing.T) { + testCases := []struct { + name string + input string + cursorPos tea.Position + }{ + { + name: "cursor between two trailing spaces", + input: "hello ", + cursorPos: tea.Position{X: 6}, + }, + { + name: "cursor before the only char, which is a boundary", + input: " ", + cursorPos: tea.Position{X: 0}, + }, + { + name: "cursor between a space and a trailing punctuation mark", + input: "hello @octo .", + cursorPos: tea.Position{X: 12}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for _, withAt := range []bool{true, false} { + source := UserMentionSource{WithAtSymbol: withAt} + require.NotPanics(t, func() { + source.ExtractContext(tc.input, tc.cursorPos) + }) + } + }) + } +} + func TestUserMentionSourceWithoutAtSymbol(t *testing.T) { source := UserMentionSource{WithAtSymbol: false} require.Equal(