When insertion of text during autocomplete results in no matches, automatically select current match and insert the inserted text after it

This commit is contained in:
Corey Johnson & Nathan Sobo 2012-04-19 12:03:47 -06:00
parent 99621acdd7
commit 66f7373b3d
2 changed files with 51 additions and 19 deletions

View File

@ -190,23 +190,39 @@ describe "Autocomplete", ->
expect(autocomplete.buildWordList).not.toHaveBeenCalled()
describe "when the change was not caused by autocomplete", ->
it "rebuilds the match list based on the new prefix and suffix", ->
editor.buffer.insert([10, 0] ,"t")
editor.setCursorBufferPosition [10, 0]
editor.trigger "autocomplete:toggle"
expect($(document).find('#autocomplete')).toExist()
describe "when the change produces a prefix that still has matches in the word list", ->
it "rebuilds the match list based on the new prefix and suffix", ->
editor.buffer.insert([10, 0] ,"t")
editor.setCursorBufferPosition [10, 0]
editor.trigger "autocomplete:toggle"
expect($(document).find('#autocomplete')).toExist()
editor.insertText('c')
editor.insertText('c')
expect($(document).find('#autocomplete')).toExist()
expect($(document).find('#autocomplete')).toExist()
expect(editor.lineForBufferRow(10)).toBe "current"
expect(editor.getCursorBufferPosition()).toEqual [10,6]
expect(editor.getSelection().getBufferRange()).toEqual [[10,1], [10,6]]
expect(editor.lineForBufferRow(10)).toBe "current"
expect(editor.getCursorBufferPosition()).toEqual [10,6]
expect(editor.getSelection().getBufferRange()).toEqual [[10,1], [10,6]]
expect(autocomplete.matchesList.find('li').length).toBe 2
expect(autocomplete.matchesList.find('li:eq(0)')).toHaveText('current')
expect(autocomplete.matchesList.find('li:eq(1)')).toHaveText('concat')
expect(autocomplete.matchesList.find('li').length).toBe 2
expect(autocomplete.matchesList.find('li:eq(0)')).toHaveText('current')
expect(autocomplete.matchesList.find('li:eq(1)')).toHaveText('concat')
describe "when the change produces a prefix that has no matches in the word list", ->
it "accepts the selected match and appends the change after it", ->
editor.buffer.insert([10, 0] ,"c")
editor.setCursorBufferPosition [10, 1]
editor.trigger "autocomplete:toggle"
expect($(document).find('#autocomplete')).toExist()
editor.insertText(' ')
expect(editor.lineForBufferRow(10)).toBe "current "
expect(editor.getCursorBufferPosition()).toEqual [10,8]
expect(editor.getSelection().getBufferRange()).toEqual [[10,8], [10,8]]
expect($(document).find('#autocomplete')).not.toExist()
describe "when editor's buffer is assigned a new buffer", ->
it 'creates and uses a new word list based on new buffer', ->

View File

@ -37,7 +37,7 @@ class Autocomplete extends View
@currentBuffer = buffer
@buildWordList()
@currentBuffer.on 'change.autocomplete', => @bufferChanged()
@currentBuffer.on 'change.autocomplete', (e) => @bufferChanged(e)
cancel: ->
@detach()
@ -86,13 +86,27 @@ class Autocomplete extends View
nextIndex = (@currentMatchIndex + 1) % @matches.length
@selectMatch(nextIndex)
bufferChanged: ->
@buildMatchList() if @parent()[0] and not @isAutocompleting
bufferChanged: (e) ->
if @parent()[0] and not @isAutocompleting
selectedMatch = @selectedMatch()
@buildMatchList()
if @matches.length == 0
@detach()
@currentBuffer.undo()
@completeUsingMatch(selectedMatch)
@editor.getSelection().clearSelection()
@editor.insertText(e.newText)
return
@buildWordList() unless @isAutocompleting
buildMatchList: ->
selection = @editor.getSelection()
{prefix, suffix} = @prefixAndSuffixOfSelection(selection)
if (prefix.length + suffix.length) == 0
@matches = []
return
currentWord = prefix + @editor.getSelectedText() + suffix
@matches = (match for match in @wordMatches(prefix, suffix) when match[0] != currentWord)
@ -121,10 +135,12 @@ class Autocomplete extends View
@currentMatchIndex = index
@matchesList.find("li").removeClass "selected"
@matchesList.find("li:eq(#{index})").addClass "selected"
@completeUsingMatch(index)
@completeUsingMatch(@selectedMatch())
completeUsingMatch: (matchIndex) ->
match = @matches[matchIndex]
selectedMatch: ->
@matches[@currentMatchIndex]
completeUsingMatch: (match) ->
selection = @editor.getSelection()
startPosition = selection.getBufferRange().start
@isAutocompleting = true