Show completions for current scope in autocomplete

Add the TextMate "completions" preferences available as "editor.completions"
and add all completions matching the current scope of the cursor position
when building the autocomplete word list.

Closes #676
This commit is contained in:
Kevin Sawicki
2013-08-06 18:15:54 -07:00
parent bc9e32a3cf
commit 7d58008ed3
7 changed files with 42 additions and 13 deletions

View File

@@ -1,3 +1,4 @@
* Improved: Autocomplete now includes CSS property names and values
* Improved: Settings GUI is now a pane item
* Added: Support package filtering in Settings GUI
* Added: Dynamically load all config options in the Settings GUI

View File

@@ -31,6 +31,7 @@ describe "TextMateScopeSelector", ->
it "matches negation", ->
expect(new TextMateScopeSelector('a - c').matches(['a', 'b'])).toBeTruthy()
expect(new TextMateScopeSelector('a - c').matches(['a'])).toBeTruthy()
expect(new TextMateScopeSelector('-c').matches(['b'])).toBeTruthy()
expect(new TextMateScopeSelector('-c').matches(['c', 'b'])).toBeFalsy()
expect(new TextMateScopeSelector('a-b').matches(['a', 'b'])).toBeFalsy()
@@ -70,7 +71,8 @@ describe "TextMateScopeSelector", ->
expect(new TextMateScopeSelector('a b c').toCssSelector()).toBe '.a .b .c'
expect(new TextMateScopeSelector('a.b.c').toCssSelector()).toBe '.a.b.c'
expect(new TextMateScopeSelector('*').toCssSelector()).toBe '*'
expect(new TextMateScopeSelector('a - b').toCssSelector()).toBe '.a :not(.b)'
expect(new TextMateScopeSelector('a - b').toCssSelector()).toBe '.a:not(.b)'
expect(new TextMateScopeSelector('a & b').toCssSelector()).toBe '.a .b'
expect(new TextMateScopeSelector('a & -b').toCssSelector()).toBe '.a:not(.b)'
expect(new TextMateScopeSelector('a | b').toCssSelector()).toBe '.a .b'
expect(new TextMateScopeSelector('a - (b.c d)').toCssSelector()).toBe '.a :not(.b.c .d)'
expect(new TextMateScopeSelector('a - (b.c d)').toCssSelector()).toBe '.a:not(.b.c .d)'

View File

@@ -5,6 +5,7 @@ Specificity = require 'specificity'
fsUtils = require 'fs-utils'
EventEmitter = require 'event-emitter'
NullGrammar = require 'null-grammar'
TextMateScopeSelector = require 'text-mate-scope-selector'
### Internal ###
@@ -131,12 +132,6 @@ class Syntax
element[0]
cssSelectorFromScopeSelector: (scopeSelector) ->
scopeSelector.split(', ').map((commaFragment) ->
commaFragment.split(' ').map((spaceFragment) ->
spaceFragment.split('.').map((dotFragment) ->
'.' + dotFragment.replace(/\+/g, '\\+')
).join('')
).join(' ')
).join(', ')
new TextMateScopeSelector(scopeSelector).toCssSelector()
_.extend(Syntax.prototype, EventEmitter)

View File

@@ -102,8 +102,9 @@ class TextMatePackage extends Package
selector = syntax.cssSelectorFromScopeSelector(scope) if scope?
@scopedProperties.push({selector, properties})
for {selector, properties} in @scopedProperties
syntax.addProperties(@path, selector, properties)
if @isActive()
for {selector, properties} in @scopedProperties
syntax.addProperties(@path, selector, properties)
loadScopedProperties: (callback) ->
scopedProperties = []
@@ -159,5 +160,6 @@ class TextMatePackage extends Package
increaseIndentPattern: textMateSettings.increaseIndentPattern
decreaseIndentPattern: textMateSettings.decreaseIndentPattern
foldEndPattern: textMateSettings.foldingStopMarker
completions: textMateSettings.completions
)
{ editor: editorProperties } if _.size(editorProperties) > 0

View File

@@ -65,7 +65,11 @@ class AndMatcher
matches: (scopes) -> @left.matches(scopes) and @right.matches(scopes)
toCssSelector: -> "#{@left.toCssSelector()} #{@right.toCssSelector()}"
toCssSelector: ->
if @right instanceof NegateMatcher
"#{@left.toCssSelector()}#{@right.toCssSelector()}"
else
"#{@left.toCssSelector()} #{@right.toCssSelector()}"
class NegateMatcher
constructor: (@matcher) ->

View File

@@ -1,5 +1,6 @@
$ = require 'jquery'
{$$} = require 'space-pen'
_ = require 'underscore'
Range = require 'range'
SelectList = require 'select-list'
@@ -59,10 +60,17 @@ class AutocompleteView extends SelectList
false
getCompletionsForCursorScope: ->
cursorScope = @editor.scopesForBufferPosition(@editor.getCursorBufferPosition())
completions = syntax.propertiesForScope(cursorScope, 'editor.completions')
completions = completions.map (properties) -> _.valueForKeyPath(properties, 'editor.completions')
_.uniq(_.flatten(completions))
buildWordList: ->
wordHash = {}
matches = @currentBuffer.getText().match(@wordRegex)
wordHash[word] ?= true for word in (matches or [])
wordHash[word] ?= true for word in matches ? []
wordHash[word] ?= true for word in @getCompletionsForCursorScope()
@wordList = Object.keys(wordHash).sort (word1, word2) ->
word1 = word1.toLowerCase()

View File

@@ -437,3 +437,20 @@ describe "AutocompleteView", ->
editor.insertText('t')
autocomplete.attach()
expect(autocomplete.list.prop('scrollWidth')).toBe autocomplete.list.width()
it "includes completions for the scope's completion preferences", ->
atom.activatePackage('css-tmbundle', sync: true)
cssEditor = new Editor(editSession: project.open('css.css'))
autocomplete = new AutocompleteView(cssEditor)
cssEditor.attachToDom()
cssEditor.moveCursorToEndOfLine()
cssEditor.insertText(' out')
cssEditor.moveCursorToEndOfLine()
autocomplete.attach()
expect(autocomplete.list.find('li').length).toBe 4
expect(autocomplete.list.find('li:eq(0)')).toHaveText 'outline'
expect(autocomplete.list.find('li:eq(1)')).toHaveText 'outline-color'
expect(autocomplete.list.find('li:eq(2)')).toHaveText 'outline-style'
expect(autocomplete.list.find('li:eq(3)')).toHaveText 'outline-width'