-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathTernHints.js
162 lines (129 loc) · 5.42 KB
/
TernHints.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/**
* Ternific Copyright (c) 2014 Miguel Castillo.
*
* Licensed under MIT
*/
define(function (require /*, exports, module*/) {
"use strict";
var CodeHintManager = brackets.getModule("editor/CodeHintManager");
var EventDispatcher = brackets.getModule("utils/EventDispatcher");
var hintTransform = require("HintTransform");
var hintHelper = require("HintHelper");
function TernHints(ternProvider) {
this.ternProvider = ternProvider;
this._selectedIndex = 0;
this._newSession = false;
this._transformed = null;
this._token = null;
this._cm = null;
this._sortBy = hintTransform.sort.byMatch;
this.events = {};
EventDispatcher.makeEventDispatcher(this.events);
}
TernHints.prototype.setSort = function(sortType) {
if (!hintTransform.sort.hasOwnProperty(sortType)) {
return;
}
this._sortBy = sortType;
if (this.hints) {
this._transformed = hintTransform(this.hints, this._sortBy);
this.events.trigger("hints", this._transformed.tokens, this._transformed.html);
}
};
/**
* Utility function that helps determine if the the parameter _char
* is one that we can start or continue hinting on. There are some
* characters that are not hintable.
*/
TernHints.prototype.hasHints = function (editor, implicitChar) {
var cm = editor._codeMirror;
if (implicitChar && !hintHelper.maybeIdentifier(implicitChar)) {
delete this._cm;
return false;
}
this._token = cm.getTokenAt(cm.getCursor());
var hintable = hintHelper.hintable(this._token);
if (hintable) {
this._cm = cm;
this._newSession = true;
}
return hintable;
};
TernHints.prototype.getHints = function (implicitChar) {
var _self = this,
newSession = this._newSession,
token = this._cm.getTokenAt(this._cm.getCursor());
if (newSession) {
_self._codeHintList = CodeHintManager._getCodeHintList();
// Let's highjack the CodeHint selectedIndex :)
Object.defineProperty(_self._codeHintList, "selectedIndex", {
enumerable: true,
get: function() {
return _self._selectedIndex;
},
set: function(newValue) {
_self._selectedIndex = newValue;
_self.events.trigger("highlight", _self._transformed.tokens[newValue]);
}
});
}
else {
// Condition to make we are providing hints for characters we know are valid
if (implicitChar !== null && hintHelper.maybeIdentifier(implicitChar) === false) {
return null;
}
else if (!implicitChar && !token.type && token.string.trim() === "") {
return null;
}
}
// New session is important because we want to get everything we can from
// tern that contains implicitChar. This is really useful for discoverability
// of what's available when a hinting session if first started.
this._newSession = false;
return this.ternProvider.query(this._cm, {
caseInsensitive: true,
type: "completions",
types: true,
docs: true,
urls: true,
filter: !newSession
}).then(function (result) {
// Result will be null when tern queries are being cancelled because there
// are too many requests coming in and the ones that can be ignored, will
// be cancelled. What will be ignored are those that should never get processed by
// tern. For example, a user types one character and then type 2 other characters
// really fast... The one character in the middle will not need to be processed
// because the user has already typed another character that will generate a fresh
// list of hints. So, that request will get cancelled to avoid extra processing of
// something that's already stale.
if (result === null) {
return {
hints: []
};
}
var hints = {
text: _self._cm.getDoc().getRange(result.start, result.end),
result: result
};
_self.hints = hints;
_self._transformed = hintTransform(hints, _self._sortBy);
_self.events.trigger("hints", _self._transformed.tokens, _self._transformed.html);
return {
hints: _self._transformed.hints,
match: null, // Prevent CodeHintManager from formatting results
selectInitial: true
};
});
};
TernHints.prototype.insertHint = function () {
var hints = this.hints,
hint = this._transformed.tokens[this._selectedIndex];
this._cm.getDoc().replaceRange(hint.name, hints.result.start, hints.result.end);
// Return false to indicate that another hinting session is not needed
return false;
};
TernHints.prototype.insertHintOnTab = function () {
return true;
};
return TernHints;
});