##// END OF EJS Templates
use \0 instead of 'wake up' to finish output...
use \0 instead of 'wake up' to finish output since we are now seeing the captured output, we don't need `wake up` at the end of all of our test outputs.

File last commit:

r19176:f48e011c
r20318:d5648dc2
Show More
completer.js
414 lines | 14.0 KiB | application/javascript | JavascriptLexer
MinRK
update completion_ and objection_info_request...
r16580 // Copyright (c) IPython Development Team.
// Distributed under the terms of the Modified BSD License.
Jonathan Frederic
Almost done!...
r17198 define([
'base/js/namespace',
Jonathan Frederic
MWE,...
r17200 'jquery',
Jonathan Frederic
Almost done!...
r17198 'base/js/utils',
'base/js/keyboard',
Jonathan Frederic
MWE,...
r17200 'notebook/js/contexthint',
Matthias BUSSONNIER
Update to codemirror 4...
r18280 'codemirror/lib/codemirror',
], function(IPython, $, utils, keyboard, CodeMirror) {
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 "use strict";
Susan Tan
Fixed various typos in docstrings.
r13822 // easier key mapping
Jonathan Frederic
Almost done!...
r17198 var keycodes = keyboard.keycodes;
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 var prepend_n_prc = function(str, n) {
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912 for( var i =0 ; i< n ; i++){
str = '%'+str ;
}
Matthias BUSSONNIER
don't care about lleading prct in completion...
r7348 return str;
MinRK
never use `for (var i in array)`...
r16226 };
Matthias BUSSONNIER
don't care about lleading prct in completion...
r7348
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 var _existing_completion = function(item, completion_array){
MinRK
never use `for (var i in array)`...
r16226 for( var i=0; i < completion_array.length; i++) {
if (completion_array[i].trim().substr(-item.length) == item) {
return true;
}
Matthias BUSSONNIER
Fix duplicate completion in notebook...
r11282 }
MinRK
never use `for (var i in array)`...
r16226 return false;
};
Matthias BUSSONNIER
beautify completer.js
r7190
Matthias BUSSONNIER
don't need to check for leading dot
r7303 // what is the common start of all completions
Matthias BUSSONNIER
pep8
r7349 function shared_start(B, drop_prct) {
Matthias BUSSONNIER
beautify completer.js
r7190 if (B.length == 1) {
return B[0];
}
MinRK
band-aid for completion...
r15322 var A = [];
Matthias BUSSONNIER
don't care about lleading prct in completion...
r7348 var common;
var min_lead_prct = 10;
Matthias BUSSONNIER
beautify completer.js
r7190 for (var i = 0; i < B.length; i++) {
Matthias BUSSONNIER
pep8
r7349 var str = B[i].str;
var localmin = 0;
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912 if(drop_prct === true){
Matthias BUSSONNIER
pep8
r7349 while ( str.substr(0, 1) == '%') {
Matthias BUSSONNIER
don't care about lleading prct in completion...
r7348 localmin = localmin+1;
str = str.substring(1);
}
}
Matthias BUSSONNIER
pep8
r7349 min_lead_prct = Math.min(min_lead_prct, localmin);
Matthias BUSSONNIER
don't care about lleading prct in completion...
r7348 A.push(str);
Matthias BUSSONNIER
beautify completer.js
r7190 }
Matthias BUSSONNIER
don't care about lleading prct in completion...
r7348
Matthias BUSSONNIER
beautify completer.js
r7190 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);
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 }
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912 if (tem1 === "" || tem2.indexOf(tem1) !== 0) {
Matthias BUSSONNIER
fix completion when shared start among completion item is null
r12068 return {
str:prepend_n_prc('', min_lead_prct),
type: "computed",
from: B[0].from,
to: B[0].to
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912 };
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 }
Matthias BUSSONNIER
beautify completer.js
r7190 return {
Matthias BUSSONNIER
pep8
r7349 str: prepend_n_prc(tem1, min_lead_prct),
Matthias BUSSONNIER
beautify completer.js
r7190 type: "computed",
from: B[0].from,
to: B[0].to
};
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 }
Matthias BUSSONNIER
beautify completer.js
r7190 return null;
}
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Matthias BUSSONNIER
move more code into the completer itself
r7141
Jonathan Frederic
Almost done!...
r17198 var Completer = function (cell, events) {
Brian E. Granger
Making completer.js independent of IPython.notebook.
r9221 this.cell = cell;
this.editor = cell.code_mirror;
var that = this;
Jessica B. Hamrick
Rename all status_event to kernel_event
r18238 events.on('kernel_busy.Kernel', function () {
Brian E. Granger
Making completer.js independent of IPython.notebook.
r9221 that.skip_kernel_completion = true;
});
Jessica B. Hamrick
Rename all status_event to kernel_event
r18238 events.on('kernel_idle.Kernel', function () {
Brian E. Granger
Making completer.js independent of IPython.notebook.
r9221 that.skip_kernel_completion = false;
});
};
Matthias BUSSONNIER
move more code into the completer itself
r7141
Matthias BUSSONNIER
space before function keyword in js
r7191 Completer.prototype.startCompletion = function () {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* call for a 'first' completion, that will set the editor and do some
* special behavior like autopicking if only one completion available.
*/
Matthias Bussonnier
handle somehting selected and multiple cursors and 4 tabs show content in pager
r18284 if (this.editor.somethingSelected()|| this.editor.getSelections().length > 1) return;
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 this.done = false;
// use to get focus back on opera
Matthias BUSSONNIER
remove CamelCasse methods from completer.js
r7192 this.carry_on_completion(true);
Matthias BUSSONNIER
Clean code, retab and minor fix...
r7170 };
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912
// easy access for julia to monkeypatch
//
Completer.reinvoke_re = /[%0-9a-z._/\\:~-]/i;
Completer.prototype.reinvoke= function(pre_cursor, block, cursor){
return Completer.reinvoke_re.test(pre_cursor);
MinRK
band-aid for completion...
r15322 };
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912
/**
*
* pass true as parameter if this is the first invocation of the completer
* this will prevent the completer to dissmiss itself if it is not on a
* word boundary like pressing tab after a space, and make it autopick the
* only choice if there is only one which prevent from popping the UI. as
* well as fast-forwarding the typing if all completion have a common
* shared start
**/
Completer.prototype.carry_on_completion = function (first_invocation) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* Pass true as parameter if you want the completer to autopick when
* only one completion. This function is automatically reinvoked at
* each keystroke with first_invocation = false
*/
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 var cur = this.editor.getCursor();
Matthias BUSSONNIER
simplify completer logic as we don't exec on behalf of cell...
r7174 var line = this.editor.getLine(cur.line);
Matthias BUSSONNIER
beautify completer.js
r7190 var pre_cursor = this.editor.getRange({
line: cur.line,
ch: cur.ch - 1
}, cur);
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142 // we need to check that we are still on a word boundary
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 // because while typing the completer is still reinvoking itself
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912 // so dismiss if we are on a "bad" caracter
if (!this.reinvoke(pre_cursor) && !first_invocation) {
Matthias BUSSONNIER
beautify completer.js
r7190 this.close();
return;
}
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 this.autopick = false;
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912 if (first_invocation) {
Matthias BUSSONNIER
beautify completer.js
r7190 this.autopick = true;
}
Matthias BUSSONNIER
more cleaning
r7143
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 // We want a single cursor position.
MinRK
fix this.editor reference
r18285 if (this.editor.somethingSelected()|| this.editor.getSelections().length > 1) {
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912 return;
MinRK
band-aid for completion...
r15322 }
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Matthias BUSSONNIER
simplify completer logic as we don't exec on behalf of cell...
r7174 // 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
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 var cursor_pos = utils.to_absolute_cursor_pos(this.editor, cur);
MinRK
band-aid for completion...
r15322 if (this.skip_kernel_completion) {
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 this.finish_completing({ content: {
MinRK
update completion_ and objection_info_request...
r16580 matches: [],
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 cursor_start: cursor_pos,
cursor_end: cursor_pos,
}});
Matthias BUSSONNIER
simplify completer logic as we don't exec on behalf of cell...
r7174 } else {
MinRK
update completion_ and objection_info_request...
r16580 this.cell.kernel.complete(this.editor.getValue(), cursor_pos,
$.proxy(this.finish_completing, this)
);
Matthias BUSSONNIER
simplify completer logic as we don't exec on behalf of cell...
r7174 }
Matthias BUSSONNIER
Clean code, retab and minor fix...
r7170 };
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142
MinRK
refactor js callbacks...
r13207 Completer.prototype.finish_completing = function (msg) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* let's build a function that wrap all that stuff into what is needed
* for the new completer:
*/
MinRK
refactor js callbacks...
r13207 var content = msg.content;
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 var start = content.cursor_start;
var end = content.cursor_end;
Brian Granger
Major refactoring of the Notebook, Kernel and CodeCell JavaScript....
r7168 var matches = content.matches;
Matthias BUSSONNIER
more cleaning
r7143
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142 var cur = this.editor.getCursor();
MinRK
update message spec adapter per review...
r16698 if (end === null) {
// adapted message spec replies don't have cursor position info,
// interpret end=null as current position,
// and negative start relative to that
end = utils.to_absolute_cursor_pos(this.editor, cur);
if (start < 0) {
start = end + start;
}
}
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142 var results = CodeMirror.contextHint(this.editor);
MinRK
band-aid for completion...
r15322 var filtered_results = [];
Matthias BUSSONNIER
[notebook] deduplicate completion results...
r7287 //remove results from context completion
//that are already in kernel completion
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 var i;
for (i=0; i < results.length; i++) {
MinRK
never use `for (var i in array)`...
r16226 if (!_existing_completion(results[i].str, matches)) {
filtered_results.push(results[i]);
MinRK
band-aid for completion...
r15322 }
Matthias BUSSONNIER
[notebook] deduplicate completion results...
r7287 }
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142
Matthias BUSSONNIER
more cleaning
r7143 // 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.
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 for (i = matches.length - 1; i >= 0; --i) {
MinRK
band-aid for completion...
r15322 filtered_results.unshift({
Matthias BUSSONNIER
beautify completer.js
r7190 str: matches[i],
type: "introspection",
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 from: utils.from_absolute_cursor_pos(this.editor, start),
to: utils.from_absolute_cursor_pos(this.editor, end)
Matthias BUSSONNIER
beautify completer.js
r7190 });
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142 }
// one the 2 sources results have been merge, deal with it
MinRK
band-aid for completion...
r15322 this.raw_result = filtered_results;
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
// if empty result return
if (!this.raw_result || !this.raw_result.length) return;
// When there is only one completion, use it directly.
MinRK
band-aid for completion...
r15322 if (this.autopick && this.raw_result.length == 1) {
Matthias BUSSONNIER
Clean code, retab and minor fix...
r7170 this.insert(this.raw_result[0]);
return;
}
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Matthias BUSSONNIER
beautify completer.js
r7190 if (this.raw_result.length == 1) {
Matthias BUSSONNIER
more cleaning
r7143 // test if first and only completion totally matches
// what is typed, in this case dismiss
Matthias BUSSONNIER
Clean code, retab and minor fix...
r7170 var str = this.raw_result[0].str;
Matthias BUSSONNIER
beautify completer.js
r7190 var pre_cursor = this.editor.getRange({
line: cur.line,
ch: cur.ch - str.length
}, cur);
if (pre_cursor == str) {
this.close();
return;
}
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 }
Jonathan Frederic
Getting a lot closer...
r15952 if (!this.visible) {
this.complete = $('<div/>').addClass('completions');
this.complete.attr('id', 'complete');
// Currently webkit doesn't use the size attr correctly. See:
// https://code.google.com/p/chromium/issues/detail?id=4579
Jonathan Frederic
Move width auto into less
r15960 this.sel = $('<select/>')
Jonathan Frederic
Getting a lot closer...
r15952 .attr('tabindex', -1)
.attr('multiple', 'true');
this.complete.append(this.sel);
this.visible = true;
$('body').append(this.complete);
//build the container
var that = this;
this.sel.dblclick(function () {
that.pick();
});
Jonathan Frederic
Finish implementing codemirror events
r15956 this.sel.focus(function () {
that.editor.focus();
});
Jonathan Frederic
More progress...
r15953 this._handle_keydown = function (cm, event) {
Jonathan Frederic
Getting a lot closer...
r15952 that.keydown(event);
Jonathan Frederic
More progress...
r15953 };
this.editor.on('keydown', this._handle_keydown);
Jonathan Frederic
Finish implementing codemirror events
r15956 this._handle_keypress = function (cm, event) {
that.keypress(event);
};
this.editor.on('keypress', this._handle_keypress);
Jonathan Frederic
Getting a lot closer...
r15952 }
this.sel.attr('size', Math.min(10, this.raw_result.length));
Brian E. Granger
Adjust tab completion widget if too close to bottom of page.
r12895
Brian E. Granger
Fixing minor comment.
r12897 // After everything is on the page, compute the postion.
// We put it above the code if it is too close to the bottom of the page.
MinRK
complete_reply has cursor_start and cursor_end, not matched_text
r16588 var pos = this.editor.cursorCoords(
utils.from_absolute_cursor_pos(this.editor, start)
);
Brian E. Granger
Adjust tab completion widget if too close to bottom of page.
r12895 var left = pos.left-3;
var top;
var cheight = this.complete.height();
var wheight = $(window).height();
if (pos.bottom+cheight+5 > wheight) {
top = pos.top-cheight-4;
} else {
top = pos.bottom+1;
}
this.complete.css('left', left + 'px');
this.complete.css('top', top + 'px');
Jonathan Frederic
Getting a lot closer...
r15952 // Clear and fill the list.
this.sel.text('');
Brian E. Granger
Removing inversion of the completion list.
r12896 this.build_gui_list(this.raw_result);
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 return true;
MinRK
band-aid for completion...
r15322 };
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Matthias BUSSONNIER
space before function keyword in js
r7191 Completer.prototype.insert = function (completion) {
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 this.editor.replaceRange(completion.str, completion.from, completion.to);
MinRK
band-aid for completion...
r15322 };
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Brian E. Granger
Removing inversion of the completion list.
r12896 Completer.prototype.build_gui_list = function (completions) {
for (var i = 0; i < completions.length; ++i) {
var opt = $('<option/>').text(completions[i].str).addClass(completions[i].type);
this.sel.append(opt);
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 }
Brian E. Granger
Removing inversion of the completion list.
r12896 this.sel.children().first().attr('selected', 'true');
this.sel.scrollTop(0);
MinRK
band-aid for completion...
r15322 };
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Matthias BUSSONNIER
space before function keyword in js
r7191 Completer.prototype.close = function () {
Matthias BUSSONNIER
beautify completer.js
r7190 this.done = true;
Jonathan Frederic
Add illusion that cell is in edit mode when complete is up,...
r15779 $('#complete').remove();
Jonathan Frederic
Shrink cleanup lines
r15962 this.editor.off('keydown', this._handle_keydown);
this.editor.off('keypress', this._handle_keypress);
Jonathan Frederic
Getting a lot closer...
r15952 this.visible = false;
MinRK
band-aid for completion...
r15322 };
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Matthias BUSSONNIER
space before function keyword in js
r7191 Completer.prototype.pick = function () {
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 this.insert(this.raw_result[this.sel[0].selectedIndex]);
this.close();
MinRK
band-aid for completion...
r15322 };
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142
Matthias BUSSONNIER
space before function keyword in js
r7191 Completer.prototype.keydown = function (event) {
Matthias BUSSONNIER
beautify completer.js
r7190 var code = event.keyCode;
var that = this;
Juergen Hasch
Improve special key handling in completer
r10239
Matthias BUSSONNIER
beautify completer.js
r7190 // Enter
Brian E. Granger
Removing old keyboard handling from IPython.utils.
r15619 if (code == keycodes.enter) {
Matthias BUSSONNIER
Update to codemirror 4...
r18280 event.codemirrorIgnore = true;
Matthias Bussonnier
rework keyboard management to avoit completer and up/down bugs
r18282 event._ipkmIgnore = true;
Matthias BUSSONNIER
Update to codemirror 4...
r18280 event.preventDefault();
Matthias BUSSONNIER
beautify completer.js
r7190 this.pick();
// Escape or backspace
Jonathan Frederic
More progress...
r15953 } else if (code == keycodes.esc || code == keycodes.backspace) {
Matthias BUSSONNIER
Update to codemirror 4...
r18280 event.codemirrorIgnore = true;
Matthias Bussonnier
rework keyboard management to avoit completer and up/down bugs
r18282 event._ipkmIgnore = true;
Matthias BUSSONNIER
Update to codemirror 4...
r18280 event.preventDefault();
Matthias BUSSONNIER
beautify completer.js
r7190 this.close();
Brian E. Granger
Removing old keyboard handling from IPython.utils.
r15619 } else if (code == keycodes.tab) {
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142 //all the fastforwarding operation,
Matthias BUSSONNIER
use strict and clean a little....
r7132 //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<tab><tab>
// to erase py
Matthias BUSSONNIER
pep8
r7349 var sh = shared_start(this.raw_result, true);
Matthias BUSSONNIER
beautify completer.js
r7190 if (sh) {
Matthias BUSSONNIER
use strict and clean a little....
r7132 this.insert(sh);
}
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142 this.close();
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 //reinvoke self
Matthias BUSSONNIER
space before function keyword in js
r7191 setTimeout(function () {
Matthias BUSSONNIER
remove CamelCasse methods from completer.js
r7192 that.carry_on_completion();
Matthias BUSSONNIER
beautify completer.js
r7190 }, 50);
Brian E. Granger
Removing old keyboard handling from IPython.utils.
r15619 } else if (code == keycodes.up || code == keycodes.down) {
Matthias BUSSONNIER
beautify completer.js
r7190 // need to do that to be able to move the arrow
// when on the first or last line ofo a code cell
Matthias BUSSONNIER
Update to codemirror 4...
r18280 event.codemirrorIgnore = true;
Matthias Bussonnier
rework keyboard management to avoit completer and up/down bugs
r18282 event._ipkmIgnore = true;
Matthias BUSSONNIER
Update to codemirror 4...
r18280 event.preventDefault();
Jonathan Frederic
Getting a lot closer...
r15952
Jonathan Frederic
More progress...
r15953 var options = this.sel.find('option');
var index = this.sel[0].selectedIndex;
if (code == keycodes.up) {
index--;
}
if (code == keycodes.down) {
index++;
}
index = Math.min(Math.max(index, 0), options.length-1);
this.sel[0].selectedIndex = index;
watercrossing
add page-up and page-down functionality to the autocomplete dropdown
r16736 } else if (code == keycodes.pageup || code == keycodes.pagedown) {
Matthias Bussonnier
rework keyboard management to avoit completer and up/down bugs
r18282 event._ipkmIgnore = true;
watercrossing
add page-up and page-down functionality to the autocomplete dropdown
r16736
var options = this.sel.find('option');
var index = this.sel[0].selectedIndex;
if (code == keycodes.pageup) {
index -= 10; // As 10 is the hard coded size of the drop down menu
} else {
index += 10;
}
index = Math.min(Math.max(index, 0), options.length-1);
this.sel[0].selectedIndex = index;
Jonathan Frederic
Finish implementing codemirror events
r15956 } else if (code == keycodes.left || code == keycodes.right) {
this.close();
Jonathan Frederic
More progress...
r15953 }
MinRK
band-aid for completion...
r15322 };
Matthias BUSSONNIER
implement the completer in a separate class...
r7131
Jonathan Frederic
Finish implementing codemirror events
r15956 Completer.prototype.keypress = function (event) {
Jonathan Frederic
Ran function comment conversion tool
r19176 /**
* FIXME: This is a band-aid.
* on keypress, trigger insertion of a single character.
* This simulates the old behavior of completion as you type,
* before events were disconnected and CodeMirror stopped
* receiving events while the completer is focused.
*/
Jonathan Frederic
Finish implementing codemirror events
r15956
var that = this;
var code = event.keyCode;
// don't handle keypress if it's not a character (arrows on FF)
// or ENTER/TAB
if (event.charCode === 0 ||
code == keycodes.tab ||
code == keycodes.enter
) return;
this.close();
this.editor.focus();
setTimeout(function () {
that.carry_on_completion();
}, 50);
};
Jonathan Frederic
Almost done!...
r17198
// For backwards compatability.
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 IPython.Completer = Completer;
Jonathan Frederic
Return dicts instead of classes,...
r17201 return {'Completer': Completer};
Jonathan Frederic
Almost done!...
r17198 });