//---------------------------------------------------------------------------- // Copyright (C) 2008-2011 The IPython Development Team // // Distributed under the terms of the BSD License. The full license is in // the file COPYING, distributed as part of this software. //---------------------------------------------------------------------------- //============================================================================ // CodeCell //============================================================================ var IPython = (function (IPython) { var utils = IPython.utils; var CodeCell = function (notebook) { this.code_mirror = null; this.input_prompt_number = ' '; this.is_completing = false; this.completion_cursor = null; this.outputs = []; this.collapsed = false; IPython.Cell.apply(this, arguments); }; CodeCell.prototype = new IPython.Cell(); CodeCell.prototype.create_element = function () { var cell = $('
').addClass('cell border-box-sizing code_cell vbox'); cell.attr('tabindex','2'); var input = $('
').addClass('input hbox'); input.append($('
').addClass('prompt input_prompt')); var input_area = $('
').addClass('input_area box-flex1'); this.code_mirror = CodeMirror(input_area.get(0), { indentUnit : 4, mode: 'python', theme: 'ipython', readOnly: this.read_only, onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this) }); input.append(input_area); var output = $('
').addClass('output vbox'); cell.append(input).append(output); this.element = cell; this.collapse() }; //TODO, try to diminish the number of parameters. CodeCell.prototype.request_tooltip_after_time = function (pre_cursor,time,that){ if (pre_cursor === "" || pre_cursor === "(" ) { // don't do anything if line beggin with '(' or is empty } else { // Will set a timer to request tooltip in `time` that.tooltip_timeout = setTimeout(function(){ IPython.notebook.request_tool_tip(that, pre_cursor) },time); } }; CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) { // This method gets called in CodeMirror's onKeyDown/onKeyPress // handlers and is used to provide custom key handling. Its return // value is used to determine if CodeMirror should ignore the event: // true = ignore, false = don't ignore. // note that we are comparing and setting the time to wait at each key press. // a better wqy might be to generate a new function on each time change and // assign it to CodeCell.prototype.request_tooltip_after_time tooltip_wait_time = this.notebook.time_before_tooltip; tooltip_on_tab = this.notebook.tooltip_on_tab; 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); that.tooltip_timeout=null; } if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) { // Always ignore shift-enter in CodeMirror as we handle it. return true; }else if (event.keyCode === 53 && event.type === 'keydown' && tooltip_wait_time >= 0) { // Pressing '(' , request tooltip, don't forget to reappend it var cursor = editor.getCursor(); var pre_cursor = editor.getRange({line:cursor.line,ch:0},cursor).trim()+'('; CodeCell.prototype.request_tooltip_after_time(pre_cursor,tooltip_wait_time,that); } else if (event.keyCode === 9 && event.type == 'keydown') { // Tab completion. var cur = editor.getCursor(); //Do not trim here because of tooltip var pre_cursor = editor.getRange({line:cur.line,ch:0},cur); if (pre_cursor.trim() === "") { // Don't autocomplete if the part of the line before the cursor // is empty. In this case, let CodeMirror handle indentation. return false; } else if ((pre_cursor.substr(-1) === "("|| pre_cursor.substr(-1) === " ") && tooltip_on_tab ) { CodeCell.prototype.request_tooltip_after_time(pre_cursor,0,that); } else { pre_cursor.trim(); // Autocomplete the current line. event.stop(); var line = editor.getLine(cur.line); this.is_completing = true; this.completion_cursor = cur; IPython.notebook.complete_cell(this, line, cur.ch); return true; } } else if (event.keyCode === 8 && event.type == 'keydown') { // If backspace and the line ends with 4 spaces, remove them. var cur = editor.getCursor(); var line = editor.getLine(cur.line); var ending = line.slice(-4); if (ending === ' ') { editor.replaceRange('', {line: cur.line, ch: cur.ch-4}, {line: cur.line, ch: cur.ch} ); event.stop(); return true; } else { return false; }; } else if (event.keyCode === 76 && event.ctrlKey && event.shiftKey && event.type == 'keydown') { // toggle line numbers with Ctrl-Shift-L this.toggle_line_numbers(); } else { // keypress/keyup also trigger on TAB press, and we don't want to // use those to disable tab completion. if (this.is_completing && event.keyCode !== 9) { var ed_cur = editor.getCursor(); var cc_cur = this.completion_cursor; if (ed_cur.line !== cc_cur.line || ed_cur.ch !== cc_cur.ch) { this.is_completing = false; this.completion_cursor = null; }; }; return false; }; }; CodeCell.prototype.remove_and_cancell_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); $('#tooltip').remove(); } CodeCell.prototype.finish_tooltip = function (defstring,docstring) { shortened = function(string){ if(string.length > 200){ return string.trim().substring(0,197)+'...'; } else { return string.trim() } } var that = this; var tooltip = $('
').attr('id', 'tooltip').addClass('tooltip'); if(defstring){ defstring_html= $('
').html(utils.fixConsole(defstring));
            tooltip.append(defstring_html);
        }
        tooltip.append($('
').html(utils.fixConsole(shortened(docstring))));
        var pos = this.code_mirror.cursorCoords();
        tooltip.css('left',pos.x+'px');
        tooltip.css('top',pos.yBot+'px');
        $('body').append(tooltip);

        // issues with cross-closing if multiple tooltip in less than 5sec
        // keep it comented for now
        // setTimeout(CodeCell.prototype.remove_and_cancell_tooltip, 5000);
    };


    CodeCell.prototype.finish_completing = function (matched_text, matches) {
        // console.log("Got matches", matched_text, matches);
        var newm = new Array();
        if(this.notebook.smart_completer)
        {
            kwargs = new Array();
            other = new Array();
            for(var i=0;i').addClass('completions');
        var select = $('