// function completer. // // completer should be a class that take an cell instance var IPython = (function(IPython ) { // that will prevent us from misspelling "use strict"; // easyier key mapping 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); } 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 }; } return null; } var Completer = function(cell) { this.editor = cell.code_mirror; // if last caractere before cursor is not in this, we stop completing this.reg = /[0-9a-z.]/i; // casse insensitive } Completer.prototype.kernelCompletionRequest = function(){ var cur = this.editor.getCursor(); var line = this.editor.getLine(cur.line); // one could fork here and directly call finish completing if kernel is busy var callbacks = {'complete_reply': $.proxy(this.finish_completing,this)}; IPython.notebook.kernel.complete(line, cur.ch, callbacks); } 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 // if (this.editor.somethingSelected()) return; this.done = false; // use to get focus back on opera this.carryOnCompletion(true); } Completer.prototype.carryOnCompletion = function(ff) { // 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 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(!this.reg.test(pre_cursor)){ this.close(); return;} this.autopick = false; 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 this.kernelCompletionRequest(); } 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; var matches = content.matches; var cur = this.editor.getCursor(); var results = CodeMirror.contextHint(this.editor); // 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} }) } // one the 2 sources results have been merge, deal with it this.raw_result = results; // if empty result return 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) { this.insert(this.raw_result[0]); return true; } 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 cur = this.editor.getCursor(); 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.sel = $('