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