##// END OF EJS Templates
Initial implementation of latex->unicode completer.
Initial implementation of latex->unicode completer.

File last commit:

r17700:7b6d94ef
r17738:678fe5fb
Show More
completer.js
400 lines | 13.6 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',
Jonathan Frederic
Almost done!...
r17198 ], function(IPython, $, utils, keyboard) {
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;
Jonathan Frederic
Almost done!...
r17198 events.on('status_busy.Kernel', function () {
Brian E. Granger
Making completer.js independent of IPython.notebook.
r9221 that.skip_kernel_completion = true;
});
Jonathan Frederic
Almost done!...
r17198 events.on('status_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 () {
Matthias BUSSONNIER
clean code, remove duplicate unused lines
r7142 // call for a 'first' completion, that will set the editor and do some
Jonathan Frederic
Getting a lot closer...
r15952 // special behavior like autopicking if only one completion available.
Matthias BUSSONNIER
implement the completer in a separate class...
r7131 if (this.editor.somethingSelected()) return;
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) {
Susan Tan
Fixed various typos in docstrings.
r13822 // Pass true as parameter if you want the completer to autopick when
Matthias BUSSONNIER
more cleaning
r7143 // only one completion. This function is automatically reinvoked at
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912 // 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.
Matthias BUSSONNIER
Partial fix to #3653 (from foo import <tab>)...
r12912 if (this.editor.somethingSelected()) {
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) {
Matthias BUSSONNIER
more cleaning
r7143 // let's build a function that wrap all that stuff into what is needed
// for the new completer:
Brian E. Granger
Initial messing around....
r17700 console.log(msg);
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) {
Jonathan Frederic
Finish implementing codemirror events
r15956 CodeMirror.e_stop(event);
Matthias BUSSONNIER
beautify completer.js
r7190 this.pick();
// Escape or backspace
Jonathan Frederic
More progress...
r15953 } else if (code == keycodes.esc || code == keycodes.backspace) {
Jonathan Frederic
Finish implementing codemirror events
r15956 CodeMirror.e_stop(event);
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
Jonathan Frederic
Finish implementing codemirror events
r15956 CodeMirror.e_stop(event);
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) {
CodeMirror.e_stop(event);
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) {
// 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.
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 });