diff --git a/IPython/frontend/html/notebook/static/css/notebook.css b/IPython/frontend/html/notebook/static/css/notebook.css index d2a37af2a..01d376c27 100644 --- a/IPython/frontend/html/notebook/static/css/notebook.css +++ b/IPython/frontend/html/notebook/static/css/notebook.css @@ -406,6 +406,15 @@ div.text_cell_render { min-height:50px; } +.completions p{ + background: #DDF; + /*outline: none; + padding: 0px;*/ + border-bottom: black solid 1px; + padding: 1px; + font-family: monospace; +} + @media print { body { overflow: visible !important; } .ui-widget-content { border: 0px; } diff --git a/IPython/frontend/html/notebook/static/js/codecell.js b/IPython/frontend/html/notebook/static/js/codecell.js index 8aa744199..9bb1f6914 100644 --- a/IPython/frontend/html/notebook/static/js/codecell.js +++ b/IPython/frontend/html/notebook/static/js/codecell.js @@ -73,8 +73,8 @@ var IPython = (function (IPython) { var that = this; // whatever key is pressed, first, cancel the tooltip request before // they are sent, and remove tooltip if any - if(event.type === 'keydown' && this.tooltip_timeout != null){ - CodeCell.prototype.remove_and_cancell_tooltip(that.tooltip_timeout); + if(event.type === 'keydown' ){ + CodeCell.prototype.remove_and_cancel_tooltip(that.tooltip_timeout); that.tooltip_timeout=null; } @@ -145,12 +145,13 @@ var IPython = (function (IPython) { return false; }; - CodeCell.prototype.remove_and_cancell_tooltip = function(timeout) + CodeCell.prototype.remove_and_cancel_tooltip = function(timeout) { // note that we don't handle closing directly inside the calltip // as in the completer, because it is not focusable, so won't // get the event. - clearTimeout(timeout); + if(timeout != null) + { clearTimeout(timeout);} $('#tooltip').remove(); } @@ -229,9 +230,24 @@ var IPython = (function (IPython) { // setTimeout(CodeCell.prototype.remove_and_cancell_tooltip, 5000); }; - + // As you type completer CodeCell.prototype.finish_completing = function (matched_text, matches) { - // console.log("Got matches", matched_text, matches); + //return if not completing or nothing to complete + if (!this.is_completing || matches.length === 0) {return;} + + // for later readability + var key = { tab:9, + esc:27, + backspace:8, + space:13, + shift:16, + enter:32, + // _ is 189 + isCompSymbol : function (code) + {return ((code>64 && code <=122)|| code == 189)} + } + + // smart completion, sort kwarg ending with '=' var newm = new Array(); if(this.notebook.smart_completer) { @@ -245,7 +261,23 @@ var IPython = (function (IPython) { newm = kwargs.concat(other); matches=newm; } - if (!this.is_completing || matches.length === 0) {return;} + // end sort kwargs + + // give common prefix of a array of string + function sharedStart(A){ + 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); + } + return tem1; + } + return ""; + } + //try to check if the user is typing tab at least twice after a word // and completion is "done" @@ -268,57 +300,104 @@ var IPython = (function (IPython) { this.prevmatch=""; this.npressed=0; } - + // end fallback on tooltip + //================================== + // Real completion logic start here var that = this; var cur = this.completion_cursor; + var done = false; + + // call to dismmiss the completer + var close = function () { + if (done) return; + done = true; + if (complete!=undefined) + {complete.remove();} + that.is_completing = false; + that.completion_cursor = null; + }; + // insert the given text and exit the completer var insert = function (selected_text) { that.code_mirror.replaceRange( selected_text, {line: cur.line, ch: (cur.ch-matched_text.length)}, {line: cur.line, ch: cur.ch} ); + event.stopPropagation(); + event.preventDefault(); + close(); + setTimeout(function(){that.code_mirror.focus();}, 50); }; - if (matches.length === 1) { - insert(matches[0]); - setTimeout(function(){that.code_mirror.focus();}, 50); - return; + // insert the curent highlited selection and exit + var pick = function () { + insert(select.val()[0]); }; + + // Define function to clear the completer, refill it with the new + // matches, update the pseuso typing field. autopick insert match if + // only one left, in no matches (anymore) dismiss itself by pasting + // what the user have typed until then + var complete_with = function(matches,typed_text,autopick) + { + // If autopick an only one match, past. + // Used to 'pick' when pressing tab + if (matches.length < 1) { + insert(typed_text); + } else if (autopick && matches.length==1) { + insert(matches[0]); + } + //clear the previous completion if any + complete.children().children().remove(); + $('#asyoutype').text(typed_text); + select=$('#asyoutypeselect'); + for (var i=0; i').html(matches[i])); + } + select.children().first().attr('selected','true'); + } + + // create html for completer var complete = $('
').addClass('completions'); + complete.attr('id','complete'); + complete.append($('

').attr('id', 'asyoutype').html(matched_text));//pseudo input field + var select = $('