Skip to content
This repository was archived by the owner on Sep 8, 2020. It is now read-only.

Commit 992be7a

Browse files
committed
support autocomplte-plus for directives
1 parent 0f63633 commit 992be7a

File tree

5 files changed

+190
-3
lines changed

5 files changed

+190
-3
lines changed

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ angular.module($3).controller('$1Ctrl', $1Ctrl);
436436
* @name $2
437437
* @description
438438
* $3
439-
*
439+
*
440440
*/
441441
```
442442

‎completions.json

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"directives": [
3+
"ng-app",
4+
"ng-bind",
5+
"ng-bind-html",
6+
"ng-bind-template",
7+
"ng-blur",
8+
"ng-change",
9+
"ng-checked",
10+
"ng-class",
11+
"ng-class-even",
12+
"ng-class-odd",
13+
"ng-click",
14+
"ng-cloak",
15+
"ng-controller",
16+
"ng-copy",
17+
"ng-csp",
18+
"ng-cut",
19+
"ng-dblclick",
20+
"ng-disabled",
21+
"ng-focus",
22+
"ng-form",
23+
"ng-hide",
24+
"ng-href",
25+
"ng-if",
26+
"ng-include",
27+
"ng-init",
28+
"ng-keydown",
29+
"ng-keypress",
30+
"ng-keyup",
31+
"ng-list",
32+
"ng-model",
33+
"ng-model-options",
34+
"ng-mousedown",
35+
"ng-mouseenter",
36+
"ng-mouseleave",
37+
"ng-mousemove",
38+
"ng-mouseover",
39+
"ng-mouseup",
40+
"ng-non-bindable",
41+
"ng-open",
42+
"ng-paste",
43+
"ng-pluralize",
44+
"ng-readonly",
45+
"ng-repeat",
46+
"ng-repeat-start",
47+
"ng-repeat-end",
48+
"ng-selected",
49+
"ng-src",
50+
"ng-srcset",
51+
"ng-style",
52+
"ng-submit",
53+
"ng-switch",
54+
"ng-options",
55+
"ng-switch-when",
56+
"ng-switch-default",
57+
"ng-transclude",
58+
"ng-view",
59+
"ng-messages",
60+
"ng-message",
61+
"ng-swipe-left",
62+
"ng-swipe-right"
63+
],
64+
"attributes": [
65+
"ng-valid",
66+
"ng-invalid",
67+
"ng-pristine",
68+
"ng-dirty",
69+
"ng-show",
70+
"ng-required",
71+
"ng-minlength",
72+
"ng-maxlength",
73+
"ng-pattern",
74+
"ng-true-value",
75+
"ng-false-value",
76+
"ng-value",
77+
"ng-trim"
78+
]
79+
}

‎lib/angularjs.coffee

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
provider = require './provider'
2+
13
module.exports =
2-
activate: (state) ->
4+
activate: ->
35

4-
deactivate: ->
6+
getProvider: -> provider

‎lib/provider.coffee

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# ref https://github.com/atom/autocomplete-html/blob/master/lib/provider.coffee
2+
3+
COMPLETIONS = require '../completions.json'
4+
5+
attributePattern = /\s+([a-zA-Z][-a-zA-Z]*)\s*=\s*$/
6+
7+
module.exports =
8+
selector: '.source.js, .text.html'
9+
disableForSelector: '.source.js .comment, .text.html .comment'
10+
filterSuggestions: true
11+
completions: COMPLETIONS
12+
13+
getSuggestions: (request) ->
14+
if @isJavaScript(request)
15+
console.log('is js');
16+
[]
17+
else if @isHtml(request)
18+
if @isAttributeStart(request)
19+
@getAttributeNameCompletions(request)
20+
else if @isTagStart(request)
21+
@getTagNameCompletions(request)
22+
else
23+
[]
24+
25+
isJavaScript: ({ scopeDescriptor }) ->
26+
for scope in scopeDescriptor.getScopesArray()
27+
return true if scope.startsWith('source') and scope.endsWith('.js')
28+
return false
29+
30+
isHtml: ({ scopeDescriptor }) ->
31+
for scope in scopeDescriptor.getScopesArray()
32+
return true if scope.endsWith('.html')
33+
return false
34+
35+
isAttributeStart: ({prefix, scopeDescriptor, bufferPosition, editor}) ->
36+
scopes = scopeDescriptor.getScopesArray()
37+
return @hasTagScope(scopes) if not @getPreviousAttribute(editor, bufferPosition) and prefix and not prefix.trim()
38+
39+
previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)]
40+
previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
41+
previousScopesArray = previousScopes.getScopesArray()
42+
43+
return true if previousScopesArray.indexOf('entity.other.attribute-name.html') isnt -1
44+
return false unless @hasTagScope(scopes)
45+
46+
# autocomplete here: <tag |>
47+
# not here: <tag >|
48+
scopes.indexOf('punctuation.definition.tag.end.html') isnt -1 and
49+
previousScopesArray.indexOf('punctuation.definition.tag.end.html') is -1
50+
51+
isTagStart: ({ prefix, scopeDescriptor, bufferPosition, editor }) ->
52+
return @hasTagScope(scopeDescriptor.getScopesArray()) if prefix.trim() and prefix.indexOf('<') is -1
53+
54+
# autocomplete-plus's default prefix setting does not capture <. Manually check for it.
55+
prefix = editor.getTextInRange([[bufferPosition.row, bufferPosition.column - 1], bufferPosition])
56+
57+
scopes = scopeDescriptor.getScopesArray()
58+
59+
# Don't autocomplete in embedded languages
60+
prefix is '<' and scopes[0] is 'text.html.basic' and scopes.length is 1
61+
62+
hasTagScope: (scopes) ->
63+
for scope in scopes
64+
return true if scope.startsWith('meta.tag.') and scope.endsWith('.html')
65+
return false
66+
67+
hasStringScope: (scopes) ->
68+
scopes.indexOf('string.quoted.double.html') isnt -1 or
69+
scopes.indexOf('string.quoted.single.html') isnt -1
70+
71+
getAttributeNameCompletions: ({prefix, editor, bufferPosition}) ->
72+
completions = []
73+
cantidates = @completions.directives.concat @completions.attributes
74+
for idx, attribute of cantidates when not prefix.trim() or firstCharsEqual(attribute, prefix)
75+
completions.push({ text: attribute, type: 'attribute' })
76+
completions
77+
78+
getTagNameCompletions: ({ prefix, editor, bufferPosition }) ->
79+
# autocomplete-plus's default prefix setting does not capture <. Manually check for it.
80+
ignorePrefix = editor.getTextInRange([[bufferPosition.row, bufferPosition.column - 1], bufferPosition]) is '<'
81+
82+
completions = []
83+
for idx, tag of @completions.directives when ignorePrefix or firstCharsEqual(tag, prefix)
84+
completions.push({ text: tag, type: 'tag' })
85+
completions
86+
87+
getPreviousAttribute: (editor, bufferPosition) ->
88+
# Remove everything until the opening quote (if we're in a string)
89+
quoteIndex = bufferPosition.column - 1 # Don't start at the end of the line
90+
while quoteIndex
91+
scopes = editor.scopeDescriptorForBufferPosition([bufferPosition.row, quoteIndex])
92+
scopesArray = scopes.getScopesArray()
93+
break if not @hasStringScope(scopesArray) or scopesArray.indexOf('punctuation.definition.string.begin.html') isnt -1
94+
quoteIndex--
95+
96+
attributePattern.exec(editor.getTextInRange([[bufferPosition.row, 0], [bufferPosition.row, quoteIndex]]))?[1]
97+
98+
firstCharsEqual = (str1, str2) ->
99+
str1[0].toLowerCase() is str2[0].toLowerCase()

‎package.json

+7
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,12 @@
1515
"engines": {
1616
"atom": ">=0.174.0 <2.0.0"
1717
},
18+
"providedServices": {
19+
"autocomplete.provider": {
20+
"versions": {
21+
"2.0.0": "getProvider"
22+
}
23+
}
24+
},
1825
"dependencies": {}
1926
}

0 commit comments

Comments
 (0)