@ -47,24 +47,60 @@ var IPython = (function (IPython) {
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 . which === 40 && event . type === 'keypress' && tooltip _wait _time >= 0 ) {
// triger aon keypress (!) otherwise inconsistent event.which depending on plateform
// browser and keyboard layout !
// 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 ( ) ;
var pre _cursor = editor . getRange ( { line : cur . line , ch : 0 } , cur ) . trim ( ) ;
if ( pre _cursor === "" ) {
//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 ) ;
@ -108,11 +144,130 @@ var IPython = (function (IPython) {
} ;
} ;
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 ( reply ) {
defstring = reply . definition ;
docstring = reply . docstring ;
if ( docstring == null ) { docstring = "<empty docstring>" } ;
name = reply . name ;
var that = this ;
var tooltip = $ ( '<div/>' ) . attr ( 'id' , 'tooltip' ) . addClass ( 'tooltip' ) ;
// remove to have the tooltip not Limited in X and Y
tooltip . addClass ( 'smalltooltip' ) ;
var pre = $ ( '<pre/>' ) . html ( utils . fixConsole ( docstring ) ) ;
var expandlink = $ ( '<a/>' ) . attr ( 'href' , "#" ) ;
expandlink . addClass ( "ui-corner-all" ) ; //rounded corner
expandlink . attr ( 'role' , "button" ) ;
//expandlink.addClass('ui-button');
//expandlink.addClass('ui-state-default');
var expandspan = $ ( '<span/>' ) . text ( 'Expand' ) ;
expandspan . addClass ( 'ui-icon' ) ;
expandspan . addClass ( 'ui-icon-plus' ) ;
expandlink . append ( expandspan ) ;
expandlink . attr ( 'id' , 'expanbutton' ) ;
expandlink . click ( function ( ) {
tooltip . removeClass ( 'smalltooltip' ) ;
tooltip . addClass ( 'bigtooltip' ) ;
$ ( '#expanbutton' ) . remove ( ) ;
setTimeout ( function ( ) { that . code _mirror . focus ( ) ; } , 50 ) ;
} ) ;
var morelink = $ ( '<a/>' ) . attr ( 'href' , "#" ) ;
morelink . attr ( 'role' , "button" ) ;
morelink . addClass ( 'ui-button' ) ;
//morelink.addClass("ui-corner-all"); //rounded corner
//morelink.addClass('ui-state-default');
var morespan = $ ( '<span/>' ) . text ( 'Open in Pager' ) ;
morespan . addClass ( 'ui-icon' ) ;
morespan . addClass ( 'ui-icon-arrowstop-l-n' ) ;
morelink . append ( morespan ) ;
morelink . click ( function ( ) {
var msg _id = IPython . notebook . kernel . execute ( name + "?" ) ;
IPython . notebook . msg _cell _map [ msg _id ] = IPython . notebook . selected _cell ( ) . cell _id ;
CodeCell . prototype . remove _and _cancell _tooltip ( that . tooltip _timeout ) ;
setTimeout ( function ( ) { that . code _mirror . focus ( ) ; } , 50 ) ;
} ) ;
var closelink = $ ( '<a/>' ) . attr ( 'href' , "#" ) ;
closelink . attr ( 'role' , "button" ) ;
closelink . addClass ( 'ui-button' ) ;
//closelink.addClass("ui-corner-all"); //rounded corner
//closelink.adClass('ui-state-default'); // grey background and blue cross
var closespan = $ ( '<span/>' ) . text ( 'Close' ) ;
closespan . addClass ( 'ui-icon' ) ;
closespan . addClass ( 'ui-icon-close' ) ;
closelink . append ( closespan ) ;
closelink . click ( function ( ) {
CodeCell . prototype . remove _and _cancell _tooltip ( that . tooltip _timeout ) ;
setTimeout ( function ( ) { that . code _mirror . focus ( ) ; } , 50 ) ;
} ) ;
//construct the tooltip
tooltip . append ( closelink ) ;
tooltip . append ( expandlink ) ;
tooltip . append ( morelink ) ;
if ( defstring ) {
defstring _html = $ ( '<pre/>' ) . html ( utils . fixConsole ( defstring ) ) ;
tooltip . append ( defstring _html ) ;
}
tooltip . append ( pre ) ;
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 < matches . length ; ++ i ) {
if ( matches [ i ] . substr ( - 1 ) === '=' ) {
kwargs . push ( matches [ i ] ) ;
} else { other . push ( matches [ i ] ) ; }
}
newm = kwargs . concat ( other ) ;
matches = newm ;
}
if ( ! this . is _completing || matches . length === 0 ) { return ; }
//try to check if the user is typing tab at least twice after a word
// and completion is "done"
fallback _on _tooltip _after = 2
if ( matches . length == 1 && matched _text === matches [ 0 ] )
{
if ( this . npressed > fallback _on _tooltip _after && this . prevmatch == matched _text )
{
console . log ( 'Ok, you really want to complete after pressing tab ' + this . npressed + ' times !' ) ;
console . log ( 'You should understand that there is no (more) completion for that !' ) ;
console . log ( "I'll show you the tooltip, will you stop bothering me ?" ) ;
this . request _tooltip _after _time ( matched _text + '(' , 0 , this ) ;
return ;
}
this . prevmatch = matched _text
this . npressed = this . npressed + 1 ;
}
else
{
this . prevmatch = "" ;
this . npressed = 0 ;
}
var that = this ;
var cur = this . completion _cursor ;