2 if (typeof exports
== "object" && typeof module
== "object") // CommonJS
3 mod(require("../../lib/codemirror"));
4 else if (typeof define
== "function" && define
.amd
) // AMD
5 define(["../../lib/codemirror"], mod
);
6 else // Plain browser env
8 })(function(CodeMirror
) {
9 var Pos
= CodeMirror
.Pos
;
11 function forEach(arr
, f
) {
12 for (var i
= 0, e
= arr
.length
; i
< e
; ++i
) f(arr
[i
]);
15 function arrayContains(arr
, item
) {
16 if (!Array
.prototype.indexOf
) {
19 if (arr
[i
] === item
) {
25 return arr
.indexOf(item
) != -1;
28 function scriptHint(editor
, keywords
, getToken
, options
) {
29 // Find the token at the cursor
30 var cur
= editor
.getCursor(), token
= getToken(editor
, cur
), tprop
= token
;
31 if (/\b(?:string|comment)\b/.test(token
.type
)) return;
32 token
.state
= CodeMirror
.innerMode(editor
.getMode(), token
.state
).state
;
34 // If it's not a 'word-style' token, ignore the token.
35 if (!/^[\w$_]*$/.test(token
.string
)) {
36 token
= tprop
= {start
: cur
.ch
, end
: cur
.ch
, string
: "", state
: token
.state
,
37 type
: token
.string
== "." ? "property" : null};
39 // If it is a property, find out what it is a property of.
40 while (tprop
.type
== "property") {
41 tprop
= getToken(editor
, Pos(cur
.line
, tprop
.start
));
42 if (tprop
.string
!= ".") return;
43 tprop
= getToken(editor
, Pos(cur
.line
, tprop
.start
));
44 if (!context
) var context
= [];
47 return {list
: getCompletions(token
, context
, keywords
, options
),
48 from: Pos(cur
.line
, token
.start
),
49 to
: Pos(cur
.line
, token
.end
)};
52 function javascriptHint(editor
, options
) {
53 return scriptHint(editor
, javascriptKeywords
,
54 function (e
, cur
) {return e
.getTokenAt(cur
);},
57 CodeMirror
.registerHelper("hint", "javascript", javascriptHint
);
59 function getCoffeeScriptToken(editor
, cur
) {
60 // This getToken, it is for coffeescript, imitates the behavior of
61 // getTokenAt method in javascript.js, that is, returning "property"
62 // type and treat "." as indepenent token.
63 var token
= editor
.getTokenAt(cur
);
64 if (cur
.ch
== token
.start
+ 1 && token
.string
.charAt(0) == '.') {
65 token
.end
= token
.start
;
67 token
.type
= "property";
69 else if (/^\.[\w$_]*$/.test(token
.string
)) {
70 token
.type
= "property";
72 token
.string
= token
.string
.replace(/\./, '');
77 function coffeescriptHint(editor
, options
) {
78 return scriptHint(editor
, coffeescriptKeywords
, getCoffeeScriptToken
, options
);
80 CodeMirror
.registerHelper("hint", "coffeescript", coffeescriptHint
);
82 var stringProps
= ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
83 "toUpperCase toLowerCase split concat match replace search").split(" ");
84 var arrayProps
= ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
85 "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
86 var funcProps
= "prototype apply call bind".split(" ");
87 var javascriptKeywords
= ("break case catch continue debugger default delete do else false finally for function " +
88 "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
89 var coffeescriptKeywords
= ("and break catch class continue delete do else extends false finally for " +
90 "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
92 function getCompletions(token
, context
, keywords
, options
) {
93 var found
= [], start
= token
.string
;
94 function maybeAdd(str
) {
95 if (str
.lastIndexOf(start
, 0) == 0 && !arrayContains(found
, str
)) found
.push(str
);
97 function gatherCompletions(obj
) {
98 if (typeof obj
== "string") forEach(stringProps
, maybeAdd
);
99 else if (obj
instanceof Array
) forEach(arrayProps
, maybeAdd
);
100 else if (obj
instanceof Function
) forEach(funcProps
, maybeAdd
);
101 for (var name
in obj
) maybeAdd(name
);
104 if (context
&& context
.length
) {
105 // If this is a property, see if it belongs to some object we can
106 // find in the current environment.
107 var obj
= context
.pop(), base
;
108 if (obj
.type
&& obj
.type
.indexOf("variable") === 0) {
109 if (options
&& options
.additionalContext
)
110 base
= options
.additionalContext
[obj
.string
];
111 base
= base
|| window
[obj
.string
];
112 } else if (obj
.type
== "string") {
114 } else if (obj
.type
== "atom") {
116 } else if (obj
.type
== "function") {
117 if (window
.jQuery
!= null && (obj
.string
== '$' || obj
.string
== 'jQuery') &&
118 (typeof window
.jQuery
== 'function'))
119 base
= window
.jQuery();
120 else if (window
._
!= null && (obj
.string
== '_') && (typeof window
._
== 'function'))
123 while (base
!= null && context
.length
)
124 base
= base
[context
.pop().string
];
125 if (base
!= null) gatherCompletions(base
);
127 // If not, just look in the window object and any local scope
128 // (reading into JS mode internals to get at the local and global variables)
129 for (var v
= token
.state
.localVars
; v
; v
= v
.next
) maybeAdd(v
.name
);
130 for (var v
= token
.state
.globalVars
; v
; v
= v
.next
) maybeAdd(v
.name
);
131 gatherCompletions(window
);
132 forEach(keywords
, maybeAdd
);