##// END OF EJS Templates
beautify completer.js
Matthias BUSSONNIER -
Show More
@@ -1,7 +1,6 b''
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
5 var IPython = (function(IPython ) {
4 var IPython = (function(IPython) {
6 // that will prevent us from misspelling
5 // that will prevent us from misspelling
7 "use strict";
6 "use strict";
@@ -10,11 +9,14 b' var IPython = (function(IPython ) {'
10 var key = IPython.utils.keycodes;
9 var key = IPython.utils.keycodes;
11
10
12 // what is the common start of all completions
11 // what is the common start of all completions
12
13
13 function sharedStart(B){
14 function sharedStart(B) {
14 if(B.length == 1){return B[0];}
15 if (B.length == 1) {
16 return B[0];
17 }
15 var A = new Array();
18 var A = new Array();
16 for(var i=0; i< B.length; i++)
19 for (var i = 0; i < B.length; i++) {
17 {
18 A.push(B[i].str);
20 A.push(B[i].str);
19 }
21 }
20 if(A.length > 1 ){
22 if (A.length > 1) {
@@ -26,8 +28,11 b' var IPython = (function(IPython ) {'
26 while(s && tem2.indexOf(tem1) == -1){
28 while (s && tem2.indexOf(tem1) == -1) {
27 tem1 = tem1.substring(0, --s);
29 tem1 = tem1.substring(0, --s);
28 }
30 }
29 if (tem1 == "" || tem2.indexOf(tem1) != 0){return null;}
31 if (tem1 == "" || tem2.indexOf(tem1) != 0) {
30 return { str : tem1,
32 return null;
33 }
34 return {
35 str: tem1,
31 type : "computed",
36 type: "computed",
32 from : B[0].from,
37 from: B[0].from,
33 to : B[0].to
38 to: B[0].to
@@ -52,8 +57,7 b' var IPython = (function(IPython ) {'
52
57
53
58
54
59
55 Completer.prototype.startCompletion = function()
60 Completer.prototype.startCompletion = function() {
56 {
57 // 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
58 // special behaviour like autopicking if only one completion availlable
62 // special behaviour like autopicking if only one completion availlable
59 //
63 //
@@ -67,18 +71,24 b' var IPython = (function(IPython ) {'
67 // 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
68 // only one completion. This function is automatically reinvoked at
72 // only one completion. This function is automatically reinvoked at
69 // each keystroke with ff = false
73 // each keystroke with ff = false
70
71 var cur = this.editor.getCursor();
74 var cur = this.editor.getCursor();
72 var line = this.editor.getLine(cur.line);
75 var line = this.editor.getLine(cur.line);
73 var pre_cursor = this.editor.getRange({line:cur.line,ch:cur.ch-1},cur);
76 var pre_cursor = this.editor.getRange({
77 line: cur.line,
78 ch: cur.ch - 1
79 }, cur);
74
80
75 // 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
76 // because while typing the completer is still reinvoking itself
82 // because while typing the completer is still reinvoking itself
77 if(!/[0-9a-z._]/i.test(pre_cursor)){ this.close(); return;}
83 if (!/[0-9a-z._]/i.test(pre_cursor)) {
84 this.close();
85 return;
86 }
78
87
79 this.autopick = false;
88 this.autopick = false;
80 if( ff != 'undefined' && ff==true)
89 if (ff != 'undefined' && ff == true) {
81 { this.autopick=true; }
90 this.autopick = true;
91 }
82
92
83 // We want a single cursor position.
93 // We want a single cursor position.
84 if (this.editor.somethingSelected()) return;
94 if (this.editor.somethingSelected()) return;
@@ -86,9 +96,14 b' var IPython = (function(IPython ) {'
86 // 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
87 // 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
88 if (this.skip_kernel_completion == true){
98 if (this.skip_kernel_completion == true) {
89 this.finish_completing({'matches' :[], matched_text : ""})
99 this.finish_completing({
100 'matches': [],
101 matched_text: ""
102 })
90 } else {
103 } else {
91 var callbacks = {'complete_reply': $.proxy(this.finish_completing,this)};
104 var callbacks = {
105 'complete_reply': $.proxy(this.finish_completing, this)
106 };
92 IPython.notebook.kernel.complete(line, cur.ch, callbacks);
107 IPython.notebook.kernel.complete(line, cur.ch, callbacks);
93 }
108 }
94 };
109 };
@@ -105,13 +120,18 b' var IPython = (function(IPython ) {'
105 // append the introspection result, in order, at at the beginning of
120 // append the introspection result, in order, at at the beginning of
106 // the table and compute the replacement range from current cursor
121 // the table and compute the replacement range from current cursor
107 // positon and matched_text length.
122 // positon and matched_text length.
108 for(var i= matches.length-1; i>=0 ;--i)
123 for (var i = matches.length - 1; i >= 0; --i) {
109 {
124 results.unshift({
110 results.unshift(
125 str: matches[i],
111 { str : matches[i],
112 type : "introspection",
126 type: "introspection",
113 from : {line: cur.line, ch: cur.ch-matched_text.length},
127 from: {
114 to : {line: cur.line, ch: cur.ch}
128 line: cur.line,
129 ch: cur.ch - matched_text.length
130 },
131 to: {
132 line: cur.line,
133 ch: cur.ch
134 }
115 });
135 });
116 }
136 }
117
137
@@ -122,28 +142,29 b' var IPython = (function(IPython ) {'
122 if (!this.raw_result || !this.raw_result.length) return;
142 if (!this.raw_result || !this.raw_result.length) return;
123
143
124 // When there is only one completion, use it directly.
144 // When there is only one completion, use it directly.
125 if (this.autopick == true && this.raw_result.length == 1)
145 if (this.autopick == true && this.raw_result.length == 1) {
126 {
127 this.insert(this.raw_result[0]);
146 this.insert(this.raw_result[0]);
128 return;
147 return;
129 }
148 }
130
149
131 if (this.raw_result.length == 1)
150 if (this.raw_result.length == 1) {
132 {
133 // test if first and only completion totally matches
151 // test if first and only completion totally matches
134 // what is typed, in this case dismiss
152 // what is typed, in this case dismiss
135 var str = this.raw_result[0].str;
153 var str = this.raw_result[0].str;
136 var pre_cursor = this.editor.getRange({line:cur.line,ch:cur.ch-str.length},cur);
154 var pre_cursor = this.editor.getRange({
137 if(pre_cursor == str)
155 line: cur.line,
138 { this.close(); return ; }
156 ch: cur.ch - str.length
157 }, cur);
158 if (pre_cursor == str) {
159 this.close();
160 return;
161 }
139 }
162 }
140
163
141 this.complete = $('<div/>').addClass('completions');
164 this.complete = $('<div/>').addClass('completions');
142 this.complete.attr('id','complete');
165 this.complete.attr('id', 'complete');
143
166
144 this.sel = $('<select/>')
167 this.sel = $('<select/>').attr('multiple', 'true').attr('size', Math.min(10, this.raw_result.length));
145 .attr('multiple','true')
146 .attr('size',Math.min(10,this.raw_result.length));
147 var pos = this.editor.cursorCoords();
168 var pos = this.editor.cursorCoords();
148
169
149 // TODO: I propose to remove enough horizontal pixel
170 // TODO: I propose to remove enough horizontal pixel
@@ -155,15 +176,21 b' var IPython = (function(IPython ) {'
155 $('body').append(this.complete);
176 $('body').append(this.complete);
156 //build the container
177 //build the container
157 var that = this;
178 var that = this;
158 this.sel.dblclick(function(){that.pick();});
179 this.sel.dblclick(function() {
180 that.pick();
181 });
159 this.sel.blur(this.close);
182 this.sel.blur(this.close);
160 this.sel.keydown(function(event){that.keydown(event);});
183 this.sel.keydown(function(event) {
184 that.keydown(event);
185 });
161
186
162 this.build_gui_list(this.raw_result);
187 this.build_gui_list(this.raw_result);
163
188
164 this.sel.focus();
189 this.sel.focus();
165 // Opera sometimes ignores focusing a freshly created node
190 // Opera sometimes ignores focusing a freshly created node
166 if (window.opera) setTimeout(function(){if (!this.done) this.sel.focus();}, 100);
191 if (window.opera) setTimeout(function() {
192 if (!this.done) this.sel.focus();
193 }, 100);
167 return true;
194 return true;
168 }
195 }
169
196
@@ -174,9 +201,7 b' var IPython = (function(IPython ) {'
174 Completer.prototype.build_gui_list = function(completions){
201 Completer.prototype.build_gui_list = function(completions) {
175 // Need to clear the all list
202 // Need to clear the all list
176 for (var i = 0; i < completions.length; ++i) {
203 for (var i = 0; i < completions.length; ++i) {
177 var opt = $('<option/>')
204 var opt = $('<option/>').text(completions[i].str).addClass(completions[i].type);
178 .text(completions[i].str)
179 .addClass(completions[i].type);
180 this.sel.append(opt);
205 this.sel.append(opt);
181 }
206 }
182 this.sel.children().first().attr('selected','true');
207 this.sel.children().first().attr('selected', 'true');
@@ -192,7 +217,9 b' var IPython = (function(IPython ) {'
192 this.insert(this.raw_result[this.sel[0].selectedIndex]);
217 this.insert(this.raw_result[this.sel[0].selectedIndex]);
193 this.close();
218 this.close();
194 var that = this;
219 var that = this;
195 setTimeout(function(){that.editor.focus();}, 50);
220 setTimeout(function() {
221 that.editor.focus();
222 }, 50);
196 }
223 }
197
224
198
225
@@ -200,11 +227,19 b' var IPython = (function(IPython ) {'
200 var code = event.keyCode;
227 var code = event.keyCode;
201 var that = this;
228 var that = this;
202 // Enter
229 // Enter
203 if (code == key.enter) {CodeMirror.e_stop(event); this.pick();}
230 if (code == key.enter) {
231 CodeMirror.e_stop(event);
232 this.pick();
233 }
204 // Escape or backspace
234 // Escape or backspace
205 else if (code == key.esc ) {CodeMirror.e_stop(event); this.close(); this.editor.focus();}
235 else if (code == key.esc) {
206 else if (code == key.space || code == key.backspace) {this.close(); this.editor.focus();}
236 CodeMirror.e_stop(event);
207 else if (code == key.tab){
237 this.close();
238 this.editor.focus();
239 } else if (code == key.space || code == key.backspace) {
240 this.close();
241 this.editor.focus();
242 } else if (code == key.tab) {
208 //all the fastforwarding operation,
243 //all the fastforwarding operation,
209 //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
210 // 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>
@@ -217,17 +252,20 b' var IPython = (function(IPython ) {'
217 CodeMirror.e_stop(event);
252 CodeMirror.e_stop(event);
218 this.editor.focus();
253 this.editor.focus();
219 //reinvoke self
254 //reinvoke self
220 setTimeout(function(){that.carryOnCompletion();}, 50);
255 setTimeout(function() {
221 }
256 that.carryOnCompletion();
222 else if (code == key.upArrow || code == key.downArrow) {
257 }, 50);
258 } else if (code == key.upArrow || code == key.downArrow) {
223 // need to do that to be able to move the arrow
259 // need to do that to be able to move the arrow
224 // when on the first or last line ofo a code cell
260 // when on the first or last line ofo a code cell
225 event.stopPropagation();
261 event.stopPropagation();
226 }
262 } else if (code != key.upArrow && code != key.downArrow) {
227 else if (code != key.upArrow && code != key.downArrow) {
263 this.close();
228 this.close(); this.editor.focus();
264 this.editor.focus();
229 //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
230 setTimeout(function(){that.carryOnCompletion();}, 50);
266 setTimeout(function() {
267 that.carryOnCompletion();
268 }, 50);
231 }
269 }
232 }
270 }
233
271
General Comments 0
You need to be logged in to leave comments. Login now