From 7d58008ed3ec5517ff193625155bf0c6f121c340 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 6 Aug 2013 18:15:54 -0700 Subject: [PATCH] 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 --- CHANGELOG.md | 1 + spec/app/text-mate-scope-selector-spec.coffee | 6 ++++-- src/app/syntax.coffee | 9 ++------- src/app/text-mate-package.coffee | 6 ++++-- .../text-mate-scope-selector-matchers.coffee | 6 +++++- .../autocomplete/lib/autocomplete-view.coffee | 10 +++++++++- .../autocomplete/spec/autocomplete-spec.coffee | 17 +++++++++++++++++ 7 files changed, 42 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40385c19c..187be08e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/spec/app/text-mate-scope-selector-spec.coffee b/spec/app/text-mate-scope-selector-spec.coffee index 392c22b77..82ad293d2 100644 --- a/spec/app/text-mate-scope-selector-spec.coffee +++ b/spec/app/text-mate-scope-selector-spec.coffee @@ -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)' diff --git a/src/app/syntax.coffee b/src/app/syntax.coffee index 4e9817e16..30d2be92a 100644 --- a/src/app/syntax.coffee +++ b/src/app/syntax.coffee @@ -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) diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index 18792fac8..b715e1583 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -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 diff --git a/src/app/text-mate-scope-selector-matchers.coffee b/src/app/text-mate-scope-selector-matchers.coffee index da475bdc5..59839ac4b 100644 --- a/src/app/text-mate-scope-selector-matchers.coffee +++ b/src/app/text-mate-scope-selector-matchers.coffee @@ -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) -> diff --git a/src/packages/autocomplete/lib/autocomplete-view.coffee b/src/packages/autocomplete/lib/autocomplete-view.coffee index 239c938f6..f74ca66f0 100644 --- a/src/packages/autocomplete/lib/autocomplete-view.coffee +++ b/src/packages/autocomplete/lib/autocomplete-view.coffee @@ -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() diff --git a/src/packages/autocomplete/spec/autocomplete-spec.coffee b/src/packages/autocomplete/spec/autocomplete-spec.coffee index dc500ba95..6380e67af 100644 --- a/src/packages/autocomplete/spec/autocomplete-spec.coffee +++ b/src/packages/autocomplete/spec/autocomplete-spec.coffee @@ -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'