Auto-complete matches can be fuzzy-filtered. Typing non-word characters confirms the match automatically.

Extract fuzzyFilter function into a file that is shared between file finder and autocompleter. Fix jQuery.fn.preempt to pass its arguments to the event handler.
This commit is contained in:
Nathan Sobo
2012-04-19 18:17:08 -06:00
parent cdd824960e
commit 0024cf89de
5 changed files with 98 additions and 31 deletions

View File

@@ -3,6 +3,7 @@ $ = require 'jquery'
_ = require 'underscore'
Range = require 'range'
Editor = require 'editor'
fuzzyFilter = require 'fuzzy-filter'
module.exports =
class Autocomplete extends View
@@ -37,6 +38,9 @@ class Autocomplete extends View
@on 'autocomplete:confirm', => @confirm()
@on 'autocomplete:cancel', => @cancel()
@miniEditor.buffer.on 'change', =>
@filterMatchList() if @parent()[0]
@miniEditor.preempt 'move-up', =>
@selectPreviousMatch()
false
@@ -45,6 +49,13 @@ class Autocomplete extends View
@selectNextMatch()
false
@miniEditor.preempt 'textInput', (e) =>
text = e.originalEvent.data
unless text.match(@wordRegex)
@confirm()
@editor.insertText(text)
false
setCurrentBuffer: (buffer) ->
@currentBuffer?.off '.autocomplete'
@currentBuffer = buffer
@@ -71,7 +82,6 @@ class Autocomplete extends View
@originalSelectedText = @editor.getSelectedText()
@originalSelectionBufferRange = @editor.getSelection().getBufferRange()
@buildMatchList()
@selectMatchAtIndex(0) if @matches.length > 0
cursorScreenPosition = @editor.getCursorScreenPosition()
{left, top} = @editor.pixelOffsetForScreenPosition(cursorScreenPosition)
@@ -83,6 +93,7 @@ class Autocomplete extends View
@editor.off(".autocomplete")
@editor.focus()
super
@miniEditor.buffer.setText('')
selectPreviousMatch: ->
previousIndex = @currentMatchIndex - 1
@@ -108,20 +119,27 @@ class Autocomplete extends View
buildMatchList: ->
selection = @editor.getSelection()
{prefix, suffix} = @prefixAndSuffixOfSelection(selection)
if (prefix.length + suffix.length) == 0
if (prefix.length + suffix.length) > 0
currentWord = prefix + @editor.getSelectedText() + suffix
@matches = (match for match in @wordMatches(prefix, suffix) when match.word != currentWord)
else
@matches = []
return
@renderMatchList()
currentWord = prefix + @editor.getSelectedText() + suffix
@matches = (match for match in @wordMatches(prefix, suffix) when match.word != currentWord)
filterMatchList: ->
@matches = fuzzyFilter(@matches, @miniEditor.buffer.getText(), key: 'word')
@renderMatchList()
renderMatchList: ->
@matchesList.empty()
if @matches.length > 0
@matchesList.append($$ -> @li match.word) for match in @matches
else
@matchesList.append($$ -> @li "No matches found")
@selectMatchAtIndex(0) if @matches.length > 0
buildWordList: () ->
@wordList = _.unique(@currentBuffer.getText().match(@wordRegex))

View File

@@ -1,6 +1,7 @@
$ = require 'jquery'
{View} = require 'space-pen'
stringScore = require 'stringscore'
fuzzyFilter = require 'fuzzy-filter'
Editor = require 'editor'
module.exports =
@@ -58,19 +59,7 @@ class FileFinder extends View
.addClass('selected')
findMatches: (query) ->
if not query
paths = @paths
else
scoredPaths = ({path, score: stringScore(path, query)} for path in @paths)
scoredPaths.sort (a, b) ->
if a.score > b.score then -1
else if a.score < b.score then 1
else 0
window.x = scoredPaths
paths = (pathAndScore.path for pathAndScore in scoredPaths when pathAndScore.score > 0)
paths.slice 0, @maxResults
fuzzyFilter(@paths, query, maxResults: @maxResults)
remove: ->
$('#panes .editor.active').focus()