I am using Ace Editor to build a code replay program. I store all the keys pressed when you type code, and then I replay them in Ace Editor. I have finished storing and replaying all keyboard/mouse input, but am having issues replaying tab presses.
Ace Editor handles tabs within a textarea DOM. The default behavior for a textarea when tab is pressed is to move to the next DOM, so I know they are using preventDefault() and using their own handler in order to allow softTab (insertion of 1,2,3, or 4 spaces before all highlighted text).
My goal is to cause Ace editor to trigger the tab event - such that whatever is currently highlighted in the Ace editor is tabbed over the correct number of spaces. Does anyone know how to do this?
Here are a list of options I've tried and why they don't work:
For example:
editor.getSession().on('change', function(e) {
if (handlers) {
var text = e.data.text;
if (text == ' ' || text == ' ' || text == ' ' || text == ' ') {
//FAILS because it doesn't know if its space or a single space tab.
For example (storage code):
function keypress_handler(e) {
var key = e.which;
var text = String.fromCharCode(key);
switch(key) {
case 9: //Tab
text = '\t'; // manually add tab
//Code to store this event for replay later
break;
}
For example (replay code):
// Assuming the cursor/selection is in the correct position
editor.insert(log.text);
At this point, I was beginning to think about building tab from scratch (when to shift multiple things if multiple lines are selected, how far to shift, how to handle if a word is half highlighted when tab is pressed), but Ace clearly already does this when tab is pressed, so I would like to just trigger the tab press. Normally to trigger a tab press, I'd simply do:
// trigger an artificial Tab Keydown event for Ace Editor using jQuery
var tab_press= $.Event('keydown');
tab_press = 9; // Tab keycode
$('.editor').trigger(tab_press);
But this causes results in no behavior. Any suggestions?
I read through the source code here:
https://github.com/ajaxorg/ace/blob/master/lib/ace/commands/default_commands.js
And found the following snippet of code:
{
name: "indent",
bindKey: bindKey("Tab", "Tab"),
exec: function(editor) { editor.indent(); },
multiSelectAction: "forEach",
scrollIntoView: "selectionPart"
}
Thus, to trigger a tab (that works in all cases), simply call:
editor.indent();
How incredibly simple - wish there was some documentation out there for this so that many hours could have been spared.