##// END OF EJS Templates
remove CamelCasse methods from completer.js
Matthias BUSSONNIER -
Show More
@@ -1,276 +1,276
1 // function completer.
1 // function completer.
2 //
2 //
3 // completer should be a class that take an cell instance
3 // completer should be a class that take an cell instance
4 var IPython = (function (IPython) {
4 var IPython = (function (IPython) {
5 // that will prevent us from misspelling
5 // that will prevent us from misspelling
6 "use strict";
6 "use strict";
7
7
8 // easyier key mapping
8 // easyier key mapping
9 var key = IPython.utils.keycodes;
9 var key = IPython.utils.keycodes;
10
10
11 // what is the common start of all completions
11 // what is the common start of all completions
12
12
13
13
14 function sharedStart(B) {
14 function shared_start(B) {
15 if (B.length == 1) {
15 if (B.length == 1) {
16 return B[0];
16 return B[0];
17 }
17 }
18 var A = new Array();
18 var A = new Array();
19 for (var i = 0; i < B.length; i++) {
19 for (var i = 0; i < B.length; i++) {
20 A.push(B[i].str);
20 A.push(B[i].str);
21 }
21 }
22 if (A.length > 1) {
22 if (A.length > 1) {
23 var tem1, tem2, s;
23 var tem1, tem2, s;
24 A = A.slice(0).sort();
24 A = A.slice(0).sort();
25 tem1 = A[0];
25 tem1 = A[0];
26 s = tem1.length;
26 s = tem1.length;
27 tem2 = A.pop();
27 tem2 = A.pop();
28 while (s && tem2.indexOf(tem1) == -1) {
28 while (s && tem2.indexOf(tem1) == -1) {
29 tem1 = tem1.substring(0, --s);
29 tem1 = tem1.substring(0, --s);
30 }
30 }
31 if (tem1 == "" || tem2.indexOf(tem1) != 0) {
31 if (tem1 == "" || tem2.indexOf(tem1) != 0) {
32 return null;
32 return null;
33 }
33 }
34 return {
34 return {
35 str: tem1,
35 str: tem1,
36 type: "computed",
36 type: "computed",
37 from: B[0].from,
37 from: B[0].from,
38 to: B[0].to
38 to: B[0].to
39 };
39 };
40 }
40 }
41 return null;
41 return null;
42 }
42 }
43
43
44
44
45 var Completer = function (cell) {
45 var Completer = function (cell) {
46 this.editor = cell.code_mirror;
46 this.editor = cell.code_mirror;
47 var that = this;
47 var that = this;
48 $([IPython.events]).on('status_busy.Kernel', function () {
48 $([IPython.events]).on('status_busy.Kernel', function () {
49 that.skip_kernel_completion = true;
49 that.skip_kernel_completion = true;
50 });
50 });
51 $([IPython.events]).on('status_idle.Kernel', function () {
51 $([IPython.events]).on('status_idle.Kernel', function () {
52 that.skip_kernel_completion = false;
52 that.skip_kernel_completion = false;
53 });
53 });
54
54
55
55
56 };
56 };
57
57
58
58
59
59
60 Completer.prototype.startCompletion = function () {
60 Completer.prototype.startCompletion = function () {
61 // call for a 'first' completion, that will set the editor and do some
61 // call for a 'first' completion, that will set the editor and do some
62 // special behaviour like autopicking if only one completion availlable
62 // special behaviour like autopicking if only one completion availlable
63 //
63 //
64 if (this.editor.somethingSelected()) return;
64 if (this.editor.somethingSelected()) return;
65 this.done = false;
65 this.done = false;
66 // use to get focus back on opera
66 // use to get focus back on opera
67 this.carryOnCompletion(true);
67 this.carry_on_completion(true);
68 };
68 };
69
69
70 Completer.prototype.carryOnCompletion = function (ff) {
70 Completer.prototype.carry_on_completion = function (ff) {
71 // Pass true as parameter if you want the commpleter to autopick when
71 // Pass true as parameter if you want the commpleter to autopick when
72 // only one completion. This function is automatically reinvoked at
72 // only one completion. This function is automatically reinvoked at
73 // each keystroke with ff = false
73 // each keystroke with ff = false
74 var cur = this.editor.getCursor();
74 var cur = this.editor.getCursor();
75 var line = this.editor.getLine(cur.line);
75 var line = this.editor.getLine(cur.line);
76 var pre_cursor = this.editor.getRange({
76 var pre_cursor = this.editor.getRange({
77 line: cur.line,
77 line: cur.line,
78 ch: cur.ch - 1
78 ch: cur.ch - 1
79 }, cur);
79 }, cur);
80
80
81 // we need to check that we are still on a word boundary
81 // we need to check that we are still on a word boundary
82 // because while typing the completer is still reinvoking itself
82 // because while typing the completer is still reinvoking itself
83 if (!/[0-9a-z._]/i.test(pre_cursor)) {
83 if (!/[0-9a-z._]/i.test(pre_cursor)) {
84 this.close();
84 this.close();
85 return;
85 return;
86 }
86 }
87
87
88 this.autopick = false;
88 this.autopick = false;
89 if (ff != 'undefined' && ff == true) {
89 if (ff != 'undefined' && ff == true) {
90 this.autopick = true;
90 this.autopick = true;
91 }
91 }
92
92
93 // We want a single cursor position.
93 // We want a single cursor position.
94 if (this.editor.somethingSelected()) return;
94 if (this.editor.somethingSelected()) return;
95
95
96 // one kernel completion came back, finish_completing will be called with the results
96 // one kernel completion came back, finish_completing will be called with the results
97 // we fork here and directly call finish completing if kernel is busy
97 // we fork here and directly call finish completing if kernel is busy
98 if (this.skip_kernel_completion == true) {
98 if (this.skip_kernel_completion == true) {
99 this.finish_completing({
99 this.finish_completing({
100 'matches': [],
100 'matches': [],
101 matched_text: ""
101 matched_text: ""
102 })
102 })
103 } else {
103 } else {
104 var callbacks = {
104 var callbacks = {
105 'complete_reply': $.proxy(this.finish_completing, this)
105 'complete_reply': $.proxy(this.finish_completing, this)
106 };
106 };
107 IPython.notebook.kernel.complete(line, cur.ch, callbacks);
107 IPython.notebook.kernel.complete(line, cur.ch, callbacks);
108 }
108 }
109 };
109 };
110
110
111 Completer.prototype.finish_completing = function (content) {
111 Completer.prototype.finish_completing = function (content) {
112 // let's build a function that wrap all that stuff into what is needed
112 // let's build a function that wrap all that stuff into what is needed
113 // for the new completer:
113 // for the new completer:
114 var matched_text = content.matched_text;
114 var matched_text = content.matched_text;
115 var matches = content.matches;
115 var matches = content.matches;
116
116
117 var cur = this.editor.getCursor();
117 var cur = this.editor.getCursor();
118 var results = CodeMirror.contextHint(this.editor);
118 var results = CodeMirror.contextHint(this.editor);
119
119
120 // append the introspection result, in order, at at the beginning of
120 // append the introspection result, in order, at at the beginning of
121 // the table and compute the replacement range from current cursor
121 // the table and compute the replacement range from current cursor
122 // positon and matched_text length.
122 // positon and matched_text length.
123 for (var i = matches.length - 1; i >= 0; --i) {
123 for (var i = matches.length - 1; i >= 0; --i) {
124 results.unshift({
124 results.unshift({
125 str: matches[i],
125 str: matches[i],
126 type: "introspection",
126 type: "introspection",
127 from: {
127 from: {
128 line: cur.line,
128 line: cur.line,
129 ch: cur.ch - matched_text.length
129 ch: cur.ch - matched_text.length
130 },
130 },
131 to: {
131 to: {
132 line: cur.line,
132 line: cur.line,
133 ch: cur.ch
133 ch: cur.ch
134 }
134 }
135 });
135 });
136 }
136 }
137
137
138 // one the 2 sources results have been merge, deal with it
138 // one the 2 sources results have been merge, deal with it
139 this.raw_result = results;
139 this.raw_result = results;
140
140
141 // if empty result return
141 // if empty result return
142 if (!this.raw_result || !this.raw_result.length) return;
142 if (!this.raw_result || !this.raw_result.length) return;
143
143
144 // When there is only one completion, use it directly.
144 // When there is only one completion, use it directly.
145 if (this.autopick == true && this.raw_result.length == 1) {
145 if (this.autopick == true && this.raw_result.length == 1) {
146 this.insert(this.raw_result[0]);
146 this.insert(this.raw_result[0]);
147 return;
147 return;
148 }
148 }
149
149
150 if (this.raw_result.length == 1) {
150 if (this.raw_result.length == 1) {
151 // test if first and only completion totally matches
151 // test if first and only completion totally matches
152 // what is typed, in this case dismiss
152 // what is typed, in this case dismiss
153 var str = this.raw_result[0].str;
153 var str = this.raw_result[0].str;
154 var pre_cursor = this.editor.getRange({
154 var pre_cursor = this.editor.getRange({
155 line: cur.line,
155 line: cur.line,
156 ch: cur.ch - str.length
156 ch: cur.ch - str.length
157 }, cur);
157 }, cur);
158 if (pre_cursor == str) {
158 if (pre_cursor == str) {
159 this.close();
159 this.close();
160 return;
160 return;
161 }
161 }
162 }
162 }
163
163
164 this.complete = $('<div/>').addClass('completions');
164 this.complete = $('<div/>').addClass('completions');
165 this.complete.attr('id', 'complete');
165 this.complete.attr('id', 'complete');
166
166
167 this.sel = $('<select/>').attr('multiple', 'true').attr('size', Math.min(10, this.raw_result.length));
167 this.sel = $('<select/>').attr('multiple', 'true').attr('size', Math.min(10, this.raw_result.length));
168 var pos = this.editor.cursorCoords();
168 var pos = this.editor.cursorCoords();
169
169
170 // TODO: I propose to remove enough horizontal pixel
170 // TODO: I propose to remove enough horizontal pixel
171 // to align the text later
171 // to align the text later
172 this.complete.css('left', pos.x + 'px');
172 this.complete.css('left', pos.x + 'px');
173 this.complete.css('top', pos.yBot + 'px');
173 this.complete.css('top', pos.yBot + 'px');
174 this.complete.append(this.sel);
174 this.complete.append(this.sel);
175
175
176 $('body').append(this.complete);
176 $('body').append(this.complete);
177 //build the container
177 //build the container
178 var that = this;
178 var that = this;
179 this.sel.dblclick(function () {
179 this.sel.dblclick(function () {
180 that.pick();
180 that.pick();
181 });
181 });
182 this.sel.blur(this.close);
182 this.sel.blur(this.close);
183 this.sel.keydown(function (event) {
183 this.sel.keydown(function (event) {
184 that.keydown(event);
184 that.keydown(event);
185 });
185 });
186
186
187 this.build_gui_list(this.raw_result);
187 this.build_gui_list(this.raw_result);
188
188
189 this.sel.focus();
189 this.sel.focus();
190 // Opera sometimes ignores focusing a freshly created node
190 // Opera sometimes ignores focusing a freshly created node
191 if (window.opera) setTimeout(function () {
191 if (window.opera) setTimeout(function () {
192 if (!this.done) this.sel.focus();
192 if (!this.done) this.sel.focus();
193 }, 100);
193 }, 100);
194 return true;
194 return true;
195 }
195 }
196
196
197 Completer.prototype.insert = function (completion) {
197 Completer.prototype.insert = function (completion) {
198 this.editor.replaceRange(completion.str, completion.from, completion.to);
198 this.editor.replaceRange(completion.str, completion.from, completion.to);
199 }
199 }
200
200
201 Completer.prototype.build_gui_list = function (completions) {
201 Completer.prototype.build_gui_list = function (completions) {
202 // Need to clear the all list
202 // Need to clear the all list
203 for (var i = 0; i < completions.length; ++i) {
203 for (var i = 0; i < completions.length; ++i) {
204 var opt = $('<option/>').text(completions[i].str).addClass(completions[i].type);
204 var opt = $('<option/>').text(completions[i].str).addClass(completions[i].type);
205 this.sel.append(opt);
205 this.sel.append(opt);
206 }
206 }
207 this.sel.children().first().attr('selected', 'true');
207 this.sel.children().first().attr('selected', 'true');
208 }
208 }
209
209
210 Completer.prototype.close = function () {
210 Completer.prototype.close = function () {
211 if (this.done) return;
211 if (this.done) return;
212 this.done = true;
212 this.done = true;
213 $('.completions').remove();
213 $('.completions').remove();
214 }
214 }
215
215
216 Completer.prototype.pick = function () {
216 Completer.prototype.pick = function () {
217 this.insert(this.raw_result[this.sel[0].selectedIndex]);
217 this.insert(this.raw_result[this.sel[0].selectedIndex]);
218 this.close();
218 this.close();
219 var that = this;
219 var that = this;
220 setTimeout(function () {
220 setTimeout(function () {
221 that.editor.focus();
221 that.editor.focus();
222 }, 50);
222 }, 50);
223 }
223 }
224
224
225
225
226 Completer.prototype.keydown = function (event) {
226 Completer.prototype.keydown = function (event) {
227 var code = event.keyCode;
227 var code = event.keyCode;
228 var that = this;
228 var that = this;
229 // Enter
229 // Enter
230 if (code == key.enter) {
230 if (code == key.enter) {
231 CodeMirror.e_stop(event);
231 CodeMirror.e_stop(event);
232 this.pick();
232 this.pick();
233 }
233 }
234 // Escape or backspace
234 // Escape or backspace
235 else if (code == key.esc) {
235 else if (code == key.esc) {
236 CodeMirror.e_stop(event);
236 CodeMirror.e_stop(event);
237 this.close();
237 this.close();
238 this.editor.focus();
238 this.editor.focus();
239 } else if (code == key.space || code == key.backspace) {
239 } else if (code == key.space || code == key.backspace) {
240 this.close();
240 this.close();
241 this.editor.focus();
241 this.editor.focus();
242 } else if (code == key.tab) {
242 } else if (code == key.tab) {
243 //all the fastforwarding operation,
243 //all the fastforwarding operation,
244 //Check that shared start is not null which can append with prefixed completion
244 //Check that shared start is not null which can append with prefixed completion
245 // like %pylab , pylab have no shred start, and ff will result in py<tab><tab>
245 // like %pylab , pylab have no shred start, and ff will result in py<tab><tab>
246 // to erase py
246 // to erase py
247 var sh = sharedStart(this.raw_result);
247 var sh = shared_start(this.raw_result);
248 if (sh) {
248 if (sh) {
249 this.insert(sh);
249 this.insert(sh);
250 }
250 }
251 this.close();
251 this.close();
252 CodeMirror.e_stop(event);
252 CodeMirror.e_stop(event);
253 this.editor.focus();
253 this.editor.focus();
254 //reinvoke self
254 //reinvoke self
255 setTimeout(function () {
255 setTimeout(function () {
256 that.carryOnCompletion();
256 that.carry_on_completion();
257 }, 50);
257 }, 50);
258 } else if (code == key.upArrow || code == key.downArrow) {
258 } else if (code == key.upArrow || code == key.downArrow) {
259 // need to do that to be able to move the arrow
259 // need to do that to be able to move the arrow
260 // when on the first or last line ofo a code cell
260 // when on the first or last line ofo a code cell
261 event.stopPropagation();
261 event.stopPropagation();
262 } else if (code != key.upArrow && code != key.downArrow) {
262 } else if (code != key.upArrow && code != key.downArrow) {
263 this.close();
263 this.close();
264 this.editor.focus();
264 this.editor.focus();
265 //we give focus to the editor immediately and call sell in 50 ms
265 //we give focus to the editor immediately and call sell in 50 ms
266 setTimeout(function () {
266 setTimeout(function () {
267 that.carryOnCompletion();
267 that.carry_on_completion();
268 }, 50);
268 }, 50);
269 }
269 }
270 }
270 }
271
271
272
272
273 IPython.Completer = Completer;
273 IPython.Completer = Completer;
274
274
275 return IPython;
275 return IPython;
276 }(IPython));
276 }(IPython));
General Comments 0
You need to be logged in to leave comments. Login now