From f8fd7251e46c525ceec130357564e4ed69048fff Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 17 Apr 2012 17:22:51 -0700 Subject: [PATCH] Add 'move-down' event to autocomplete --- spec/app/autocomplete-spec.coffee | 54 ++++++++++++++++++++----------- src/app/autocomplete.coffee | 20 +++++++----- 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/spec/app/autocomplete-spec.coffee b/spec/app/autocomplete-spec.coffee index 4f216422d..adc1c21bb 100644 --- a/spec/app/autocomplete-spec.coffee +++ b/spec/app/autocomplete-spec.coffee @@ -18,16 +18,16 @@ describe "Autocomplete", -> describe 'autocomplete:toggle event', -> it 'shows autocomplete view', -> expect($(document).find('#autocomplete')).not.toExist() - editor.trigger "autocomplete:toggle" + autocomplete.trigger "autocomplete:toggle" expect($(document).find('#autocomplete')).toExist() - editor.trigger "autocomplete:toggle" + autocomplete.trigger "autocomplete:toggle" expect($(document).find('#autocomplete')).not.toExist() describe "when no text is selected", -> it 'autocompletes word when there is only a prefix', -> editor.buffer.insert([10,0] ,"extra:s:extra") editor.setCursorBufferPosition([10,7]) - editor.trigger "autocomplete:toggle" + autocomplete.trigger "autocomplete:toggle" expect(editor.lineForBufferRow(10)).toBe "extra:sort:extra" expect(editor.getCursorBufferPosition()).toEqual [10,10] @@ -36,7 +36,7 @@ describe "Autocomplete", -> it 'autocompletes word when there is only a suffix', -> editor.buffer.insert([10,0] ,"extra:e:extra") editor.setCursorBufferPosition([10,6]) - editor.trigger "autocomplete:toggle" + autocomplete.trigger "autocomplete:toggle" expect(editor.lineForBufferRow(10)).toBe "extra:while:extra" expect(editor.getCursorBufferPosition()).toEqual [10,10] @@ -45,7 +45,7 @@ describe "Autocomplete", -> it 'autocompletes word when there is a prefix and suffix', -> editor.buffer.insert([8,43] ,"q") editor.setCursorBufferPosition([8,44]) - editor.trigger "autocomplete:toggle" + autocomplete.trigger "autocomplete:toggle" expect(editor.lineForBufferRow(8)).toBe " return sort(left).concat(pivot).concat(quicksort(right));" expect(editor.getCursorBufferPosition()).toEqual [8,48] @@ -55,7 +55,7 @@ describe "Autocomplete", -> it 'autocompletes word when there is only a prefix', -> editor.buffer.insert([10,0] ,"extra:sort:extra") editor.setSelectionBufferRange [[10,7], [10,10]] - editor.trigger "autocomplete:toggle" + autocomplete.trigger "autocomplete:toggle" expect(editor.lineForBufferRow(10)).toBe "extra:shift:extra" expect(editor.getCursorBufferPosition()).toEqual [10,11] @@ -64,7 +64,7 @@ describe "Autocomplete", -> it 'autocompletes word when there is only a suffix', -> editor.buffer.insert([10,0] ,"extra:current:extra") editor.setSelectionBufferRange [[10,6],[10,12]] - editor.trigger "autocomplete:toggle" + autocomplete.trigger "autocomplete:toggle" expect(editor.lineForBufferRow(10)).toBe "extra:quicksort:extra" expect(editor.getCursorBufferPosition()).toEqual [10,14] @@ -72,12 +72,28 @@ describe "Autocomplete", -> it 'autocompletes word when there is a prefix and suffix', -> editor.setSelectionBufferRange [[5,7],[5,12]] - editor.trigger "autocomplete:toggle" + autocomplete.trigger "autocomplete:toggle" expect(editor.lineForBufferRow(5)).toBe " concat = items.shift();" expect(editor.getCursorBufferPosition()).toEqual [5,11] expect(editor.getSelection().getBufferRange()).toEqual [[5,7], [5,11]] + describe 'move-down event', -> + it 'replaces selection with next match', -> + editor.buffer.insert([10,0] ,"extra:s:extra") + editor.setCursorBufferPosition([10,7]) + autocomplete.trigger "autocomplete:toggle" + + autocomplete.trigger "move-down" + expect(editor.lineForBufferRow(10)).toBe "extra:shift:extra" + expect(autocomplete.find('li:eq(0)')).not.toHaveClass('selected') + expect(autocomplete.find('li:eq(1)')).toHaveClass('selected') + + autocomplete.trigger "move-down" + expect(editor.lineForBufferRow(10)).toBe "extra:sort:extra" + expect(autocomplete.find('li:eq(0)')).toHaveClass('selected') + expect(autocomplete.find('li:eq(1)')).not.toHaveClass('selected') + describe 'when changes are made to the buffer', -> it 'updates word list', -> spyOn(autocomplete, 'buildWordList') @@ -105,6 +121,15 @@ describe "Autocomplete", -> expect(autocomplete.buildWordList).not.toHaveBeenCalled() + describe 'when autocomplete changes buffer', -> + it 'does not rebuild the word list', -> + editor.buffer.insert([10,0] ,"extra:s:extra") + + spyOn(autocomplete, 'buildWordList') + editor.setCursorBufferPosition([10,7]) + autocomplete.trigger "autocomplete:toggle" + expect(autocomplete.buildWordList).not.toHaveBeenCalled() + describe '.wordMatches(prefix, suffix)', -> it 'returns wordMatches on buffer starting with given prefix and ending with given suffix', -> wordMatches = autocomplete.wordMatches("s", "").map (match) -> match[0] @@ -146,15 +171,6 @@ describe "Autocomplete", -> it "selects the first match and replaces the seleced text with it", -> expect(autocomplete.matchesList.find('li').length).toBe 2 expect(autocomplete.matchesList.find('li:eq(0)')).toHaveClass('selected') - expect(autocomplete.matchesList.find('li:eq(1)')).not.toHaveText('selected') + expect(autocomplete.matchesList.find('li:eq(1)')).not.toHaveClass('selected') - expect(editor.lineForBufferRow(10)).toBe "extra:sort:extra" - - describe 'when autocomplete changes buffer', -> - it 'does not rebuild the word list', -> - editor.buffer.insert([10,0] ,"extra:s:extra") - - spyOn(autocomplete, 'buildWordList') - editor.setCursorBufferPosition([10,7]) - editor.trigger "autocomplete:toggle" - expect(autocomplete.buildWordList).not.toHaveBeenCalled() \ No newline at end of file + expect(editor.lineForBufferRow(10)).toBe "extra:sort:extra" \ No newline at end of file diff --git a/src/app/autocomplete.coffee b/src/app/autocomplete.coffee index 09aa26de8..f4485d5b7 100644 --- a/src/app/autocomplete.coffee +++ b/src/app/autocomplete.coffee @@ -14,11 +14,13 @@ class Autocomplete extends View wordList: null wordRegex: /\w+/g matches: null + currentMatchIndex: null isAutocompleting: false initialize: (@editor) -> requireStylesheet 'autocomplete.css' - @editor.on 'autocomplete:toggle', => @toggle() + @on 'autocomplete:toggle', => @toggle() + @on 'move-down', => @nextMatch() @editor.on 'buffer-path-change', => @setCurrentBuffer(@editor.buffer) @setCurrentBuffer(@editor.buffer) @@ -31,9 +33,8 @@ class Autocomplete extends View @currentBuffer.on 'change.autocomplete', => @buildWordList() unless @isAutocompleting - toggle: -> - if @parent()[0] then @hide() else @show() + if @parent()[0] then @remove() else @show() show: -> @buildMatchList() @@ -44,8 +45,9 @@ class Autocomplete extends View @css {left: left, top: top + @editor.lineHeight} $(document.body).append(this) - hide: -> - @remove() + nextMatch: -> + nextIndex = (@currentMatchIndex + 1) % @matches.length + @selectMatch(nextIndex) buildMatchList: -> selection = @editor.getSelection() @@ -60,17 +62,19 @@ class Autocomplete extends View else @matchesList.append($$ -> @li "No matches found") + buildWordList: () -> + @wordList = _.unique(@currentBuffer.getText().match(@wordRegex)) + wordMatches: (prefix, suffix) -> regex = new RegExp("^#{prefix}(.+)#{suffix}$", "i") regex.exec(word) for word in @wordList when regex.test(word) selectMatch: (index) -> + @currentMatchIndex = index + @matchesList.find("li").removeClass "selected" @matchesList.find("li:eq(#{index})").addClass "selected" @completeUsingMatch(index) - buildWordList: () -> - @wordList = _.unique(@currentBuffer.getText().match(@wordRegex)) - completeUsingMatch: (matchIndex) -> match = @matches[matchIndex] selection = @editor.getSelection()