diff --git a/IPython/frontend/html/notebook/static/js/completer.js b/IPython/frontend/html/notebook/static/js/completer.js index 775d17c..f8ee122 100644 --- a/IPython/frontend/html/notebook/static/js/completer.js +++ b/IPython/frontend/html/notebook/static/js/completer.js @@ -1,8 +1,7 @@ // function completer. // // completer should be a class that take an cell instance - -var IPython = (function(IPython ) { +var IPython = (function(IPython) { // that will prevent us from misspelling "use strict"; @@ -10,50 +9,55 @@ var IPython = (function(IPython ) { var key = IPython.utils.keycodes; // what is the common start of all completions - function sharedStart(B){ - if(B.length == 1){return B[0];} - var A = new Array(); - for(var i=0; i< B.length; i++) - { - A.push(B[i].str); + + + function sharedStart(B) { + if (B.length == 1) { + return B[0]; + } + var A = new Array(); + for (var i = 0; i < B.length; i++) { + A.push(B[i].str); + } + if (A.length > 1) { + var tem1, tem2, s; + A = A.slice(0).sort(); + tem1 = A[0]; + s = tem1.length; + tem2 = A.pop(); + while (s && tem2.indexOf(tem1) == -1) { + tem1 = tem1.substring(0, --s); } - if(A.length > 1 ){ - var tem1, tem2, s; - A = A.slice(0).sort(); - tem1 = A[0]; - s = tem1.length; - tem2 = A.pop(); - while(s && tem2.indexOf(tem1) == -1){ - tem1 = tem1.substring(0, --s); - } - if (tem1 == "" || tem2.indexOf(tem1) != 0){return null;} - return { str : tem1, - type : "computed", - from : B[0].from, - to : B[0].to - }; + if (tem1 == "" || tem2.indexOf(tem1) != 0) { + return null; } - return null; + return { + str: tem1, + type: "computed", + from: B[0].from, + to: B[0].to + }; } + return null; + } var Completer = function(cell) { - this.editor = cell.code_mirror; - var that = this; - $([IPython.events]).on('status_busy.Kernel',function () { - that.skip_kernel_completion = true; - }); - $([IPython.events]).on('status_idle.Kernel',function () { - that.skip_kernel_completion = false; - }); + this.editor = cell.code_mirror; + var that = this; + $([IPython.events]).on('status_busy.Kernel', function() { + that.skip_kernel_completion = true; + }); + $([IPython.events]).on('status_idle.Kernel', function() { + that.skip_kernel_completion = false; + }); - }; + }; - Completer.prototype.startCompletion = function() - { + Completer.prototype.startCompletion = function() { // call for a 'first' completion, that will set the editor and do some // special behaviour like autopicking if only one completion availlable // @@ -67,33 +71,44 @@ var IPython = (function(IPython ) { // Pass true as parameter if you want the commpleter to autopick when // only one completion. This function is automatically reinvoked at // each keystroke with ff = false - var cur = this.editor.getCursor(); var line = this.editor.getLine(cur.line); - var pre_cursor = this.editor.getRange({line:cur.line,ch:cur.ch-1},cur); + var pre_cursor = this.editor.getRange({ + line: cur.line, + ch: cur.ch - 1 + }, cur); // we need to check that we are still on a word boundary // because while typing the completer is still reinvoking itself - if(!/[0-9a-z._]/i.test(pre_cursor)){ this.close(); return;} + if (!/[0-9a-z._]/i.test(pre_cursor)) { + this.close(); + return; + } this.autopick = false; - if( ff != 'undefined' && ff==true) - { this.autopick=true; } + if (ff != 'undefined' && ff == true) { + this.autopick = true; + } // We want a single cursor position. if (this.editor.somethingSelected()) return; // one kernel completion came back, finish_completing will be called with the results // we fork here and directly call finish completing if kernel is busy - if (this.skip_kernel_completion == true){ - this.finish_completing({'matches' :[], matched_text : ""}) + if (this.skip_kernel_completion == true) { + this.finish_completing({ + 'matches': [], + matched_text: "" + }) } else { - var callbacks = {'complete_reply': $.proxy(this.finish_completing,this)}; + var callbacks = { + 'complete_reply': $.proxy(this.finish_completing, this) + }; IPython.notebook.kernel.complete(line, cur.ch, callbacks); } }; - Completer.prototype.finish_completing =function (content) { + Completer.prototype.finish_completing = function(content) { // let's build a function that wrap all that stuff into what is needed // for the new completer: var matched_text = content.matched_text; @@ -105,14 +120,19 @@ var IPython = (function(IPython ) { // append the introspection result, in order, at at the beginning of // the table and compute the replacement range from current cursor // positon and matched_text length. - for(var i= matches.length-1; i>=0 ;--i) - { - results.unshift( - { str : matches[i], - type : "introspection", - from : {line: cur.line, ch: cur.ch-matched_text.length}, - to : {line: cur.line, ch: cur.ch} - }); + for (var i = matches.length - 1; i >= 0; --i) { + results.unshift({ + str: matches[i], + type: "introspection", + from: { + line: cur.line, + ch: cur.ch - matched_text.length + }, + to: { + line: cur.line, + ch: cur.ch + } + }); } // one the 2 sources results have been merge, deal with it @@ -122,113 +142,131 @@ var IPython = (function(IPython ) { if (!this.raw_result || !this.raw_result.length) return; // When there is only one completion, use it directly. - if (this.autopick == true && this.raw_result.length == 1) - { + if (this.autopick == true && this.raw_result.length == 1) { this.insert(this.raw_result[0]); return; } - if (this.raw_result.length == 1) - { + if (this.raw_result.length == 1) { // test if first and only completion totally matches // what is typed, in this case dismiss var str = this.raw_result[0].str; - var pre_cursor = this.editor.getRange({line:cur.line,ch:cur.ch-str.length},cur); - if(pre_cursor == str) - { this.close(); return ; } + var pre_cursor = this.editor.getRange({ + line: cur.line, + ch: cur.ch - str.length + }, cur); + if (pre_cursor == str) { + this.close(); + return; + } } this.complete = $('
').addClass('completions'); - this.complete.attr('id','complete'); + this.complete.attr('id', 'complete'); - this.sel = $('') - .attr('multiple','true') - .attr('size',Math.min(10,this.raw_result.length)); + this.sel = $('').attr('multiple', 'true').attr('size', Math.min(10, this.raw_result.length)); var pos = this.editor.cursorCoords(); // TODO: I propose to remove enough horizontal pixel // to align the text later - this.complete.css('left',pos.x+'px'); - this.complete.css('top',pos.yBot+'px'); + this.complete.css('left', pos.x + 'px'); + this.complete.css('top', pos.yBot + 'px'); this.complete.append(this.sel); $('body').append(this.complete); //build the container var that = this; - this.sel.dblclick(function(){that.pick();}); + this.sel.dblclick(function() { + that.pick(); + }); this.sel.blur(this.close); - this.sel.keydown(function(event){that.keydown(event);}); + this.sel.keydown(function(event) { + that.keydown(event); + }); this.build_gui_list(this.raw_result); this.sel.focus(); // Opera sometimes ignores focusing a freshly created node - if (window.opera) setTimeout(function(){if (!this.done) this.sel.focus();}, 100); + if (window.opera) setTimeout(function() { + if (!this.done) this.sel.focus(); + }, 100); return true; } Completer.prototype.insert = function(completion) { this.editor.replaceRange(completion.str, completion.from, completion.to); - } + } - Completer.prototype.build_gui_list = function(completions){ + Completer.prototype.build_gui_list = function(completions) { // Need to clear the all list for (var i = 0; i < completions.length; ++i) { - var opt = $('') - .text(completions[i].str) - .addClass(completions[i].type); + var opt = $('').text(completions[i].str).addClass(completions[i].type); this.sel.append(opt); } - this.sel.children().first().attr('selected','true'); + this.sel.children().first().attr('selected', 'true'); } Completer.prototype.close = function() { - if (this.done) return; - this.done = true; - $('.completions').remove(); - } + if (this.done) return; + this.done = true; + $('.completions').remove(); + } - Completer.prototype.pick = function(){ + Completer.prototype.pick = function() { this.insert(this.raw_result[this.sel[0].selectedIndex]); this.close(); var that = this; - setTimeout(function(){that.editor.focus();}, 50); - } + setTimeout(function() { + that.editor.focus(); + }, 50); + } Completer.prototype.keydown = function(event) { - var code = event.keyCode; - var that = this; - // Enter - if (code == key.enter) {CodeMirror.e_stop(event); this.pick();} - // Escape or backspace - else if (code == key.esc ) {CodeMirror.e_stop(event); this.close(); this.editor.focus();} - else if (code == key.space || code == key.backspace) {this.close(); this.editor.focus();} - else if (code == key.tab){ + var code = event.keyCode; + var that = this; + // Enter + if (code == key.enter) { + CodeMirror.e_stop(event); + this.pick(); + } + // Escape or backspace + else if (code == key.esc) { + CodeMirror.e_stop(event); + this.close(); + this.editor.focus(); + } else if (code == key.space || code == key.backspace) { + this.close(); + this.editor.focus(); + } else if (code == key.tab) { //all the fastforwarding operation, //Check that shared start is not null which can append with prefixed completion // like %pylab , pylab have no shred start, and ff will result in py