Implement keybindings and such
This commit is contained in:
parent
808bb95538
commit
dbca4444bf
4 changed files with 88 additions and 57 deletions
|
|
@ -32,14 +32,16 @@ define(function(require, exports, module) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var oop = require("./lib/oop");
|
var oop = require("./lib/oop");
|
||||||
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
var Range = require('ace/range').Range;
|
||||||
|
|
||||||
var Autocomplete = function(editor) {
|
var Autocomplete = function(editor) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.editor = editor;
|
this.$editor = editor;
|
||||||
|
|
||||||
var originalOnTextInput = editor.onTextInput;
|
this.originalGoLineUp = editor.commands.commands.golineup.exec;
|
||||||
var originalSoftTabs = editor.session.getUseSoftTabs();
|
this.originalGoLineDown = editor.commands.commands.golinedown.exec;
|
||||||
|
this.originalIndent = editor.commands.commands.indent.exec;
|
||||||
|
this.originalOnTextInput = editor.onTextInput;
|
||||||
|
|
||||||
// Create the suggest list
|
// Create the suggest list
|
||||||
this.autocompleteContainer = document.createElement('div');
|
this.autocompleteContainer = document.createElement('div');
|
||||||
|
|
@ -51,86 +53,101 @@ var Autocomplete = function(editor) {
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
oop.implement(this, EventEmitter);
|
|
||||||
|
|
||||||
this.current = function() {
|
this.current = function() {
|
||||||
var children = element.childNodes;
|
var children = this.selection.childNodes;
|
||||||
for (var i = 0; i < children.length; i++) {
|
for (var i = 0; i < children.length; i++) {
|
||||||
var li = children[i];
|
var li = children[i];
|
||||||
if(li.className == 'ace_autocomplete_selected') {
|
if (li.className == 'ace_autocomplete_selected') {
|
||||||
return li;
|
return li;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.focusNext = function() {
|
this.focusNext = function() {
|
||||||
var curr = current();
|
var curr = this.current();
|
||||||
curr.className = '';
|
curr.className = '';
|
||||||
var focus = curr.nextSibling || curr.parentNode.firstChild;
|
var focus = curr.nextSibling || curr.parentNode.firstChild;
|
||||||
focus.className = 'ace_autocomplete_selected';
|
focus.className = 'ace_autocomplete_selected';
|
||||||
|
focus.selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.focusPrev = function() {
|
this.focusPrev = function() {
|
||||||
var curr = current();
|
var curr = this.current();
|
||||||
curr.className = '';
|
curr.className = '';
|
||||||
var focus = curr.previousSibling || curr.parentNode.lastChild;
|
var focus = curr.previousSibling || curr.parentNode.lastChild;
|
||||||
focus.className = 'ace_autocomplete_selected';
|
focus.className = 'ace_autocomplete_selected';
|
||||||
|
focus.selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ensureFocus = function() {
|
this.ensureFocus = function() {
|
||||||
if(!current()) {
|
if(!this.current()) {
|
||||||
element.firstChild.className = 'ace_autocomplete_selected';
|
this.selection.firstChild.className = 'ace_autocomplete_selected';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.replace = function() {
|
this.replace = function() {
|
||||||
var Range = require('ace/range').Range;
|
var _self = this;
|
||||||
var range = new Range(self.row, self.column, self.row, self.column + 1000);
|
|
||||||
// Firefox does not support innerText property, don't know about IE
|
|
||||||
// http://blog.coderlab.us/2005/09/22/using-the-innertext-property-with-firefox/
|
|
||||||
var selectedValue;
|
|
||||||
if(document.all){
|
|
||||||
selectedValue = current().innerText;
|
|
||||||
} else{
|
|
||||||
selectedValue = current().textContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
editor.session.replace(range, selectedValue);
|
var range = new Range(this.row, this.column, this.row, this.column + 1000);
|
||||||
// Deactivate asynchrounously, so that in case of ENTER - we don't reactivate immediately.
|
|
||||||
setTimeout(function() {
|
var selectedValue;
|
||||||
deactivate();
|
if (document.all) {
|
||||||
}, 0);
|
selectedValue = this.current().innerText;
|
||||||
}
|
} else {
|
||||||
|
selectedValue = this.current().textContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$editor.session.replace(range, selectedValue);
|
||||||
|
// Deactivate asynchrounously, so that in case of ENTER - we don't reactivate immediately.
|
||||||
|
setTimeout(function() {
|
||||||
|
_self.deactivate();
|
||||||
|
}, 0);
|
||||||
|
};
|
||||||
|
|
||||||
this.deactivate = function() {
|
this.deactivate = function() {
|
||||||
// Hide list
|
this.autocompleteContainer.parentNode.removeChild(this.autocompleteContainer);
|
||||||
element.style.display = 'none';
|
|
||||||
|
|
||||||
// Restore keyboard
|
this.$editor.commands.commands.golineup.exec = this.originalGoLineUp;
|
||||||
editor.session.setUseSoftTabs(originalSoftTabs);
|
this.$editor.commands.commands.golinedown.exec = this.originalGoLineDown;
|
||||||
editor.onTextInput = originalOnTextInput;
|
this.$editor.commands.commands.indent.exec = this.originalIndent;
|
||||||
|
this.$editor.onTextInput = this.originalOnTextInput;
|
||||||
|
|
||||||
self.active = false;
|
this.active = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Shows the list and reassigns keys
|
// Shows the list and reassigns keys
|
||||||
this.activate = function(row, column) {
|
this.activate = function(row, column) {
|
||||||
if(this.active) return;
|
if (this.active) return;
|
||||||
this.active = true;
|
|
||||||
this.row = row;
|
|
||||||
this.column = column;
|
|
||||||
|
|
||||||
// Position the list
|
var _self = this;
|
||||||
var coords = this.editor.renderer.textToScreenCoordinates(row, column);
|
|
||||||
this.autocompleteContainer.style.top = coords.pageY + 18 + 'px';
|
this.active = true;
|
||||||
this.autocompleteContainer.style.left = coords.pageX + -2 + 'px';
|
this.row = row;
|
||||||
this.autocompleteContainer.style.display = 'block';
|
this.column = column;
|
||||||
|
|
||||||
|
// Position the list
|
||||||
|
var coords = this.$editor.renderer.textToScreenCoordinates(row, column);
|
||||||
|
this.autocompleteContainer.style.top = coords.pageY + 18 + "px";
|
||||||
|
this.autocompleteContainer.style.left = coords.pageX + -2 + "px";
|
||||||
|
this.autocompleteContainer.style.display = "block";
|
||||||
|
|
||||||
|
this.$editor.commands.commands.golinedown.exec = function(env, args, request) { _self.focusNext(); };
|
||||||
|
this.$editor.commands.commands.golineup.exec = function(env, args, request) { _self.focusPrev(); };
|
||||||
|
this.$editor.commands.commands.indent.exec = function(env, args, request) { _self.replace(); };
|
||||||
|
|
||||||
|
this.$editor.onTextInput = function(text) {
|
||||||
|
if (text == "\n") {
|
||||||
|
_self.replace();
|
||||||
|
} else {
|
||||||
|
_self.originalOnTextInput.call(_self.$editor, text);
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sets the text the suggest should be based on.
|
// Sets the text the suggest should be based on.
|
||||||
// afterText indicates the position where the suggest box should start.
|
// afterText indicates the position where the suggest box should start.
|
||||||
this.suggest = function(text) {
|
this.suggest = function(text) {
|
||||||
var options = ["FUNK", "frunk", "blunk", "frunk", "blunk", "frunk", "blunk", "frunk", "blunk", "frunk", "blunk", "frunk", "blunk"];//matches(text);
|
var options = ["FUNK", "frunk", "blunk", "frunk", "blunk", "frunk", "blunk", "frunk", "blunk", "frunk", "blunk", "frunk", "blunk"];
|
||||||
if (options.length == 0) {
|
if (options.length == 0) {
|
||||||
return deactivate();
|
return deactivate();
|
||||||
}
|
}
|
||||||
|
|
@ -139,12 +156,18 @@ var Autocomplete = function(editor) {
|
||||||
var opt = this.selection.appendChild(document.createElement("option"));
|
var opt = this.selection.appendChild(document.createElement("option"));
|
||||||
opt.appendChild(document.createTextNode(options[n]));
|
opt.appendChild(document.createTextNode(options[n]));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.selection.firstChild.selected = true;
|
this.selection.firstChild.selected = true;
|
||||||
this.selection.size = Math.min(10, options.length);
|
this.selection.size = Math.min(5, options.length);
|
||||||
|
|
||||||
document.body.appendChild(this.autocompleteContainer);
|
document.body.appendChild(this.autocompleteContainer);
|
||||||
//ensureFocus();
|
this.ensureFocus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.isActive = function() {
|
||||||
|
return this.active;
|
||||||
|
};
|
||||||
|
|
||||||
}).call(Autocomplete.prototype);
|
}).call(Autocomplete.prototype);
|
||||||
|
|
||||||
exports.Autocomplete = Autocomplete;
|
exports.Autocomplete = Autocomplete;
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,6 @@ var EventEmitter = require("../lib/event_emitter").EventEmitter;
|
||||||
* @param {String} platform Identifier for the platform; must be either `'mac'` or `'win'`
|
* @param {String} platform Identifier for the platform; must be either `'mac'` or `'win'`
|
||||||
* @param {Array} commands A list of commands
|
* @param {Array} commands A list of commands
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
var CommandManager = function(platform, commands) {
|
var CommandManager = function(platform, commands) {
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,11 @@ exports.commands = [{
|
||||||
exec: function(editor) { editor.jumpToMatching(true); },
|
exec: function(editor) { editor.jumpToMatching(true); },
|
||||||
multiSelectAction: "forEach",
|
multiSelectAction: "forEach",
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
}, {
|
||||||
|
name: "hideautocomplete",
|
||||||
|
bindKey: bindKey("Esc", "Esc"),
|
||||||
|
exec: function(editor) { editor.$hideautocomplete(); },
|
||||||
|
readOnly: true
|
||||||
},
|
},
|
||||||
|
|
||||||
// commands disabled in readOnly mode
|
// commands disabled in readOnly mode
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ var Editor = function(renderer, session) {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setSession(session || new EditSession(""));
|
this.setSession(session || new EditSession(""));
|
||||||
this.auto = new Autocomplete(this);
|
this.autocomplete = new Autocomplete(this);
|
||||||
config.resetOptions(this);
|
config.resetOptions(this);
|
||||||
config._emit("editor", this);
|
config._emit("editor", this);
|
||||||
};
|
};
|
||||||
|
|
@ -475,18 +475,24 @@ var Editor = function(renderer, session) {
|
||||||
|
|
||||||
var source = this.session.getValue();
|
var source = this.session.getValue();
|
||||||
var _self = this;
|
var _self = this;
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
var cursor = _self.getCursorPosition();
|
var cursor = _self.getCursorPosition();
|
||||||
var line = _self.session.getLine(cursor.row);
|
var line = _self.session.getLine(cursor.row);
|
||||||
|
|
||||||
_self.auto.activate(cursor.row, cursor.column);
|
_self.autocomplete.activate(cursor.row, cursor.column);
|
||||||
_self.auto.suggest(name);
|
_self.autocomplete.suggest(name);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
// update cursor because tab characters can influence the cursor position
|
// update cursor because tab characters can influence the cursor position
|
||||||
this.$cursorChange();
|
this.$cursorChange();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.$hideautocomplete = function() {
|
||||||
|
if (this.autocomplete.isActive())
|
||||||
|
this.autocomplete.deactivate();
|
||||||
|
};
|
||||||
|
|
||||||
this.onTokenizerUpdate = function(e) {
|
this.onTokenizerUpdate = function(e) {
|
||||||
var rows = e.data;
|
var rows = e.data;
|
||||||
this.renderer.updateLines(rows.first, rows.last);
|
this.renderer.updateLines(rows.first, rows.last);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue