move source files into ace folder

This commit is contained in:
Fabian Jakobs 2010-04-26 11:36:08 +02:00
commit 5fd3cd3f20
25 changed files with 24 additions and 24 deletions

View file

@ -40,30 +40,30 @@
<link rel="stylesheet" href="../css/editor.css" type="text/css" charset="utf-8">
<link rel="stylesheet" href="../css/tm.css" type="text/css" charset="utf-8">
<script src="../src/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/mode/Text.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/mode/JavaScript.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/mode/JavaScriptHighlightRules.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/mode/Html.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/mode/HtmlHighlightRules.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/mode/Css.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/mode/CssHighlightRules.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/mode/Xml.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/mode/XmlHighlightRules.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/MEventEmitter.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/Selection.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/Document.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/Tokenizer.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/BackgroundTokenizer.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/layer/Cursor.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/layer/Gutter.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/layer/Text.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/layer/Marker.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ScrollBar.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/TextInput.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/KeyBinding.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/Editor.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/VirtualRenderer.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/mode/Text.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/mode/JavaScript.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/mode/JavaScriptHighlightRules.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/mode/Html.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/mode/HtmlHighlightRules.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/mode/Css.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/mode/CssHighlightRules.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/mode/Xml.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/mode/XmlHighlightRules.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/MEventEmitter.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/Selection.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/Document.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/Tokenizer.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/BackgroundTokenizer.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/layer/Cursor.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/layer/Gutter.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/layer/Text.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/layer/Marker.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/ScrollBar.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/TextInput.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/KeyBinding.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/Editor.js" type="text/javascript" charset="utf-8"></script>
<script src="../src/ace/VirtualRenderer.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>

View file

@ -0,0 +1,107 @@
ace.provide("ace.BackgroundTokenizer");
ace.BackgroundTokenizer = function(tokenizer) {
this.running = false;
this.textLines = [];
this.lines = [];
this.currentLine = 0;
this.tokenizer = tokenizer;
var self = this;
this.$worker = function() {
if (!self.running) { return; }
var workerStart = new Date();
var startLine = self.currentLine;
var textLines = self.textLines;
var processedLines = 0;
while (self.currentLine < textLines.length) {
var line = textLines[self.currentLine];
var state = self.currentLine == 0 ? "start"
: self.lines[self.currentLine - 1].state;
self.lines[self.currentLine] = self.tokenizer.getLineTokens(line, state);
// only check every 30 lines
processedLines += 1;
if ((processedLines % 30 == 0) && (new Date() - workerStart) > 20) {
self.fireUpdateEvent(startLine, self.currentLine);
return setTimeout(self.$worker, 10);
}
self.currentLine++;
}
self.running = false;
self.fireUpdateEvent(startLine, textLines.length - 1);
};
this.$initEvents();
};
(function(){
ace.implement(this, ace.MEventEmitter);
this.setTokenizer = function(tokenizer) {
this.tokenizer = tokenizer;
this.lines = [];
this.start(0);
};
this.setLines = function(textLines) {
this.textLines = textLines;
this.lines = [];
this.stop();
};
this.fireUpdateEvent = function(firstRow, lastRow) {
var data = {
first: firstRow,
last: lastRow
};
this.$dispatchEvent("update", {data: data});
};
this.start = function(startRow) {
this.currentLine = Math.min(startRow || 0, this.currentLine,
this.textLines.length);
this.lines.splice(this.currentLine, this.lines.length);
if (!this.running) {
clearTimeout(this.running);
// pretty long delay to prevent the tokenizer from interfering with the user
this.running = setTimeout(this.$worker, 200);
}
};
this.stop = function() {
this.running = false;
};
this.getTokens = function(row) {
return this.$tokenizeRow(row).tokens;
};
this.getState = function(row) {
return this.$tokenizeRow(row).state;
};
this.$tokenizeRow = function(row) {
if (!this.lines[row]) {
var state = "start";
if (row > 0 && this.lines[row - 1]) {
state = this.lines[row - 1].state;
}
this.lines[row] = this.tokenizer.getLineTokens(this.textLines[row] || "", state);
}
return this.lines[row];
};
}).call(ace.BackgroundTokenizer.prototype);

393
src/ace/Document.js Normal file
View file

@ -0,0 +1,393 @@
ace.provide("ace.Document");
ace.Document = function(text, mode) {
this.$initEvents();
this.lines = this.$split(text);
this.modified = true;
this.selection = new ace.Selection(this);
this.listeners = [];
if (mode) {
this.setMode(mode);
}
};
(function() {
ace.implement(this, ace.MEventEmitter);
this.$split = function(text) {
return text.split(/\r\n|\r|\n/);
};
this.toString = function() {
return this.lines.join("\n");
};
this.getSelection = function() {
return this.selection;
};
this.fireChangeEvent = function(firstRow, lastRow) {
var data = {
firstRow: firstRow,
lastRow: lastRow
};
this.$dispatchEvent("change", { data: data});
};
this.getTabString = function() {
if (this.getUseSoftTabs()) {
return new Array(this.getTabSize()+1).join(" ");
} else {
return "\t";
}
};
this.$useSoftTabs = false;
this.setUseSoftTabs = function(useSoftTabs) {
if (this.$useSoftTabs === useSoftTabs) return;
this.$useSoftTabs = useSoftTabs;
};
this.getUseSoftTabs = function() {
return this.$useSoftTabs;
};
this.$tabSize = 4;
this.setTabSize = function(tabSize) {
if (this.$tabSize === tabSize) return;
this.$tabSize = tabSize;
this.$dispatchEvent("changeTabSize");
};
this.getTabSize = function() {
return this.$tabSize;
};
this.$mode = null;
this.setMode = function(mode) {
if (this.$mode === mode) return;
this.$mode = mode;
this.$dispatchEvent("changeMode");
};
this.getMode = function() {
if (!this.$mode) {
this.$mode = new ace.mode.Text();
}
return this.$mode;
};
this.$scrollTop = 0;
this.setScrollTopRow = function(scrollTopRow) {
if (this.$scrollTop === scrollTopRow) return;
this.$scrollTop = scrollTopRow;
this.$dispatchEvent("changeScrollTop");
};
this.getScrollTopRow = function() {
return this.$scrollTop;
};
this.getWidth = function() {
if (this.modified) {
this.modified = false;
var lines = this.lines;
var longestLine = 0;
for ( var i = 0; i < lines.length; i++) {
longestLine = Math.max(longestLine, lines[i].length);
}
this.width = longestLine;
}
return this.width;
};
this.getLine = function(row) {
return this.lines[row] || "";
};
this.getLength = function() {
return this.lines.length;
};
this.getTextRange = function(range) {
if (range.start.row == range.end.row) {
return this.lines[range.start.row].substring(range.start.column,
range.end.column);
}
else {
var lines = [];
lines.push(this.lines[range.start.row].substring(range.start.column));
lines.push.apply(lines, this.getLines(range.start.row+1, range.end.row-1));
lines.push(this.lines[range.end.row].substring(0, range.end.column));
return lines.join("\n");
}
};
this.getLines = function(firstRow, lastRow) {
return this.lines.slice(firstRow, lastRow+1);
};
this.findMatchingBracket = function(position) {
if (position.column == 0) return null;
var charBeforeCursor = this.getLine(position.row).charAt(position.column-1);
if (charBeforeCursor == "") return null;
var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/);
if (!match) {
return null;
}
if (match[1]) {
return this.$findClosingBracket(match[1], position);
} else {
return this.$findOpeningBracket(match[2], position);
}
};
this.$brackets = {
")": "(",
"(": ")",
"]": "[",
"[": "]",
"{": "}",
"}": "{"
};
this.$findOpeningBracket = function(bracket, position) {
var openBracket = this.$brackets[bracket];
var column = position.column - 2;
var row = position.row;
var depth = 1;
var line = this.getLine(row);
while (true) {
while(column >= 0) {
var char = line.charAt(column);
if (char == openBracket) {
depth -= 1;
if (depth == 0) {
return {row: row, column: column};
}
}
else if (char == bracket) {
depth +=1;
}
column -= 1;
}
row -=1;
if (row < 0) break;
var line = this.getLine(row);
var column = line.length-1;
}
return null;
};
this.$findClosingBracket = function(bracket, position) {
var closingBracket = this.$brackets[bracket];
var column = position.column;
var row = position.row;
var depth = 1;
var line = this.getLine(row);
var lineCount = this.getLength();
while (true) {
while(column < line.length) {
var char = line.charAt(column);
if (char == closingBracket) {
depth -= 1;
if (depth == 0) {
return {row: row, column: column};
}
}
else if (char == bracket) {
depth +=1;
}
column += 1;
}
row +=1;
if (row >= lineCount) break;
var line = this.getLine(row);
var column = 0;
}
return null;
};
this.insert = function(position, text) {
var end = this.$insert(position, text);
this.fireChangeEvent(position.row, position.row == end.row ? position.row
: undefined);
return end;
};
this.$insertLines = function(row, lines) {
var args = [row, 0];
args.push.apply(args, lines);
this.lines.splice.apply(this.lines, args);
},
this.$insert = function(position, text) {
this.modified = true;
var newLines = this.$split(text);
if (this.$isNewLine(text)) {
var line = this.lines[position.row] || "";
this.lines[position.row] = line.substring(0, position.column);
this.lines.splice(position.row + 1, 0, line.substring(position.column));
return {
row : position.row + 1,
column : 0
};
}
else if (newLines.length == 1) {
var line = this.lines[position.row] || "";
this.lines[position.row] = line.substring(0, position.column) + text
+ line.substring(position.column);
return {
row : position.row,
column : position.column + text.length
};
}
else {
var line = this.lines[position.row] || "";
this.lines[position.row] = line.substring(0, position.column)
+ newLines[0];
this.lines[position.row + 1] = newLines[newLines.length - 1]
+ line.substring(position.column);
if (newLines.length > 2) {
this.$insertLines(position.row + 1, newLines.slice(1, -1));
}
return {
row : position.row + newLines.length - 1,
column : newLines[newLines.length - 1].length
};
}
};
this.$isNewLine = function(text) {
return (text == "\r\n" || text == "\r" || text == "\n");
};
this.remove = function(range) {
this.$remove(range);
this.fireChangeEvent(range.start.row,
range.end.row == range.start.row ? range.start.row
: undefined);
return range.start;
};
this.$remove = function(range) {
this.modified = true;
var firstRow = range.start.row;
var lastRow = range.end.row;
var row = this.lines[firstRow].substring(0, range.start.column)
+ this.lines[lastRow].substring(range.end.column);
this.lines.splice(firstRow, lastRow - firstRow + 1, row);
return range.start;
};
this.replace = function(range, text) {
this.$remove(range);
if (text) {
var end = this.$insert(range.start, text);
}
else {
end = range.start;
}
var lastRemoved = range.end.column == 0 ? range.end.column - 1
: range.end.column;
this.fireChangeEvent(range.start.row, lastRemoved == end.row ? lastRemoved
: undefined);
return end;
};
this.indentRows = function(range, indentString) {
for (var i=range.start.row; i<= range.end.row; i++) {
this.lines[i] = indentString + this.getLine(i);
}
this.fireChangeEvent(range.start.row, range.end.row);
return indentString.length;
};
this.outdentRows = function(range, indentString) {
outdentLength = indentString.length;
for (var i=range.start.row; i<= range.end.row; i++) {
if (this.getLine(i).substr(0, outdentLength) !== indentString) {
return 0;
}
}
for (var i=range.start.row; i<= range.end.row; i++) {
this.lines[i] = this.getLine(i).substring(outdentLength);
}
this.fireChangeEvent(range.start.row, range.end.row);
return -outdentLength;
};
this.moveLinesUp = function(firstRow, lastRow) {
if (firstRow <= 0) return 0;
var removed = this.lines.splice(firstRow, lastRow-firstRow+1);
this.$insertLines(firstRow-1, removed);
this.fireChangeEvent(firstRow-1, lastRow);
return -1;
};
this.moveLinesDown = function(firstRow, lastRow) {
if (lastRow >= this.lines.length-1) return 0;
var removed = this.lines.splice(firstRow, lastRow-firstRow+1);
this.$insertLines(firstRow+1, removed);
this.fireChangeEvent(firstRow, lastRow+1);
return 1;
};
this.duplicateLines = function(firstRow, lastRow) {
var firstRow = this.$clipRowToDocument(firstRow);
var lastRow = this.$clipRowToDocument(lastRow);
var lines = this.getLines(firstRow, lastRow);
this.$insertLines(firstRow, lines);
var addedRows = lastRow - firstRow + 1;
this.fireChangeEvent(firstRow, lastRow+addedRows);
return addedRows;
};
this.$clipRowToDocument = function(row) {
return Math.max(0, Math.min(row, this.lines.length-1));
};
}).call(ace.Document.prototype);

661
src/ace/Editor.js Normal file
View file

@ -0,0 +1,661 @@
ace.provide("ace.Editor");
ace.Editor = function(renderer, doc) {
var container = renderer.getContainerElement();
this.container = container;
this.renderer = renderer;
this.textInput = new ace.TextInput(container, this);
new ace.KeyBinding(container, this);
var self = this;
ace.addListener(container, "mousedown", function(e) {
self.focus();
return ace.preventDefault(e);
});
var mouseTarget = renderer.getMouseEventTarget();
ace.addListener(mouseTarget, "mousedown", ace.bind(this.onMouseDown, this));
ace.addListener(mouseTarget, "dblclick", ace.bind(this.onMouseDoubleClick, this));
ace.addTripleClickListener(mouseTarget, ace.bind(this.onMouseTripleClick, this));
ace.addMouseWheelListener(mouseTarget, ace.bind(this.onMouseWheel, this));
this.$selectionMarker = null;
this.$highlightLineMarker = null;
this.$blockScrolling = false;
this.setDocument(doc || new ace.Document(""));
};
(function(){
this.setDocument = function(doc) {
if (this.doc == doc) return;
if (this.doc) {
this.doc.removeEventListener("change", this.$onDocumentChange);
this.doc.removeEventListener("changeMode", this.$onDocumentModeChange);
this.doc.removeEventListener("changeTabSize", this.$onDocumentChangeTabSize);
var selection = this.doc.getSelection();
this.selection.removeEventListener("changeCursor", this.$onCursorChange);
this.selection.removeEventListener("changeSelection", this.$onSelectionChange);
this.doc.setScrollTopRow(this.renderer.getScrollTopRow());
}
this.doc = doc;
this.$onDocumentChange = ace.bind(this.onDocumentChange, this);
doc.addEventListener("change", this.$onDocumentChange);
this.renderer.setDocument(doc);
this.$onDocumentModeChange = ace.bind(this.onDocumentModeChange, this);
doc.addEventListener("changeMode", this.$onDocumentModeChange);
this.$onDocumentChangeTabSize = ace.bind(this.renderer.draw, this.renderer);
doc.addEventListener("changeTabSize", this.$onDocumentChangeTabSize);
this.selection = doc.getSelection();
this.$onCursorChange = ace.bind(this.onCursorChange, this);
this.selection.addEventListener("changeCursor", this.$onCursorChange);
this.$onSelectionChange = ace.bind(this.onSelectionChange, this);
this.selection.addEventListener("changeSelection", this.$onSelectionChange);
this.onDocumentModeChange();
this.bgTokenizer.setLines(this.doc.lines);
this.renderer.draw();
this.onCursorChange();
this.onSelectionChange();
this.renderer.scrollToRow(doc.getScrollTopRow());
};
this.getDocument = function() {
return this.doc;
};
this.getSelection = function() {
return this.selection;
};
this.resize = function() {
this.renderer.onResize();
};
this.$highlightBrackets = function() {
if (this.$bracketHighlight) {
this.renderer.removeMarker(this.$bracketHighlight);
this.$bracketHighlight = null;
}
if (this.$highlightPending) {
return;
}
// perform highlight async to not block the browser during navigation
var self = this;
this.$highlightPending = true;
setTimeout(function() {
self.$highlightPending = false;
var pos = self.doc.findMatchingBracket(self.getCursorPosition());
if (pos) {
range = {
start: pos,
end: {
row: pos.row,
column: pos.column+1
}
};
self.$bracketHighlight = self.renderer.addMarker(range, "bracket");
}
}, 10);
};
this.focus = function() {
this.textInput.focus();
};
this.blur = function() {
this.textInput.blur();
};
this.onFocus = function() {
this.renderer.showCursor();
this.renderer.visualizeFocus();
};
this.onBlur = function() {
this.renderer.hideCursor();
this.renderer.visualizeBlur();
};
this.onDocumentChange = function(e) {
var data = e.data;
this.bgTokenizer.start(data.firstRow);
this.renderer.updateLines(data.firstRow, data.lastRow);
};
this.onTokenizerUpdate = function(e) {
var rows = e.data;
this.renderer.updateLines(rows.first, rows.last);
};
this.onCursorChange = function() {
this.$highlightBrackets();
this.renderer.updateCursor(this.getCursorPosition());
if (!this.$blockScrolling) {
this.renderer.scrollCursorIntoView();
}
this.$updateHighlightActiveLine();
};
this.$updateHighlightActiveLine = function() {
if (this.$highlightLineMarker) {
this.renderer.removeMarker(this.$highlightLineMarker);
}
this.$highlightLineMarker = null;
if (this.getHighlightActiveLine() && !this.selection.isMultiLine()) {
var cursor = this.getCursorPosition();
var range = {
start: {
row: cursor.row,
column: 0
},
end: {
row: cursor.row+1,
column: 0
}
};
this.$highlightLineMarker = this.renderer.addMarker(range, "active_line", "line");
}
};
this.onSelectionChange = function() {
if (this.$selectionMarker) {
this.renderer.removeMarker(this.$selectionMarker);
}
this.$selectionMarker = null;
if (!this.selection.isEmpty()) {
var range = this.selection.getRange();
var style = this.getSelectionStyle();
this.$selectionMarker = this.renderer.addMarker(range, "selection", style);
}
this.onCursorChange();
};
this.onDocumentModeChange = function() {
var mode = this.doc.getMode();
this.mode = mode;
var tokenizer = mode.getTokenizer();
if (!this.bgTokenizer) {
var onUpdate = ace.bind(this.onTokenizerUpdate, this);
this.bgTokenizer = new ace.BackgroundTokenizer(tokenizer);
this.bgTokenizer.addEventListener("update", onUpdate);
} else {
this.bgTokenizer.setTokenizer(tokenizer);
}
this.renderer.setTokenizer(this.bgTokenizer);
this.renderer.draw();
};
this.onMouseDown = function(e) {
var pageX = ace.getDocumentX(e);
var pageY = ace.getDocumentY(e);
var pos = this.renderer.screenToTextCoordinates(pageX, pageY);
this.moveCursorToPosition(pos);
this.selection.setSelectionAnchor(pos.row, pos.column);
this.renderer.scrollCursorIntoView();
var _self = this;
var mousePageX, mousePageY;
var onMouseSelection = function(e) {
mousePageX = ace.getDocumentX(e);
mousePageY = ace.getDocumentY(e);
};
var onMouseSelectionEnd = function() {
clearInterval(timerId);
};
var onSelectionInterval = function() {
if (mousePageX === undefined || mousePageY === undefined)
return;
selectionLead = _self.renderer.screenToTextCoordinates(mousePageX,
mousePageY);
_self.selection.selectToPosition(selectionLead);
_self.renderer.scrollCursorIntoView();
};
ace.capture(this.container, onMouseSelection, onMouseSelectionEnd);
var timerId = setInterval(onSelectionInterval, 20);
return ace.preventDefault(e);
};
this.onMouseDoubleClick = function(e) {
this.selection.selectWord();
};
this.onMouseTripleClick = function(e) {
this.selection.selectLine();
};
this.onMouseWheel = function(e) {
var delta = e.wheel;
this.renderer.scrollToY(this.renderer.getScrollTop() - (delta * 15));
return ace.preventDefault(e);
};
this.getCopyText = function() {
if (!this.selection.isEmpty()) {
return this.doc.getTextRange(this.getSelectionRange());
}
else {
return "";
}
};
this.onCut = function() {
if (this.$readOnly)
return;
if (!this.selection.isEmpty()) {
this.moveCursorToPosition(this.doc.remove(this.getSelectionRange()));
this.clearSelection();
}
};
this.onTextInput = function(text) {
if (this.$readOnly)
return;
var cursor = this.getCursorPosition();
text = text.replace("\t", this.doc.getTabString());
if (!this.selection.isEmpty()) {
var end = this.doc.replace(this.getSelectionRange(), text);
this.clearSelection();
}
else {
var end = this.doc.insert(cursor, text);
}
// multi line insert
var row = cursor.row;
if (row !== end.row) {
var line = this.doc.getLine(row);
var lineState = this.bgTokenizer.getState(row);
var indent = this.mode.getNextLineIndent(line, lineState, this.doc.getTabString());
if (indent) {
var indentRange = {
start: {
row: row+1,
column: 0
},
end : end
};
end.column += this.doc.indentRows(indentRange, indent);
}
}
this.moveCursorToPosition(end);
this.renderer.scrollCursorIntoView();
};
this.$selectionStyle = "line";
this.setSelectionStyle = function(style) {
if (this.$selectionStyle == style) return;
this.$selectionStyle = style;
this.onSelectionChange();
};
this.getSelectionStyle = function() {
return this.$selectionStyle;
};
this.$highlightActiveLine = true;
this.setHighlightActiveLine = function(shouldHighlight) {
if (this.$highlightActiveLine == shouldHighlight) return;
this.$highlightActiveLine = shouldHighlight;
this.$updateHighlightActiveLine();
};
this.getHighlightActiveLine = function() {
return this.$highlightActiveLine;
};
this.$showInvisibles = true;
this.setShowInvisibles = function(showInvisibles) {
showInvisibles = !!showInvisibles;
if (this.$showInvisibles == showInvisibles) return;
this.$showInvisibles = showInvisibles;
this.renderer.setShowInvisibles(showInvisibles);
this.renderer.draw();
};
this.getShowInvisibles = function() {
return this.showInvisibles;
};
this.$readOnly = false;
this.setReadOnly = function(readOnly) {
this.$readOnly = readOnly;
};
this.getReadOnly = function() {
return this.readOnly;
};
this.removeRight = function() {
if (this.$readOnly)
return;
if (this.selection.isEmpty()) {
this.selection.selectRight();
}
this.moveCursorToPosition(this.doc.remove(this.getSelectionRange()));
this.clearSelection();
};
this.removeLeft = function() {
if (this.$readOnly)
return;
if (this.selection.isEmpty()) {
this.selection.selectLeft();
}
this.moveCursorToPosition(this.doc.remove(this.getSelectionRange()));
this.clearSelection();
};
this.blockIndent = function(indentString) {
if (this.$readOnly)
return;
var indentString = indentString || this.doc.getTabString();
var addedColumns = this.doc.indentRows(this.getSelectionRange(), indentString);
this.selection.shiftSelection(addedColumns);
};
this.blockOutdent = function(indentString) {
if (this.$readOnly)
return;
var indentString = indentString || this.doc.getTabString();
var addedColumns = this.doc.outdentRows(this.getSelectionRange(), indentString);
this.selection.shiftSelection(addedColumns);
};
this.toggleCommentLines = function() {
if (this.$readOnly)
return;
var rows = this.$getSelectedRows();
var range = {
start: {
row: rows.first,
column: 0
},
end: {
row: rows.last,
column: 0
}
};
var state = this.bgTokenizer.getState(this.getCursorPosition().row);
var addedColumns = this.mode.toggleCommentLines(this.doc, range, state);
this.selection.shiftSelection(addedColumns);
};
this.removeLines = function() {
if (this.$readOnly)
return;
var rows = this.$getSelectedRows();
this.selection.setSelectionAnchor(rows.last+1, 0);
this.selection.selectTo(rows.first, 0);
this.doc.remove(this.getSelectionRange());
this.clearSelection();
};
this.moveLinesDown = function() {
if (this.$readOnly)
return;
this.$moveLines(function(firstRow, lastRow) {
return this.doc.moveLinesDown(firstRow, lastRow);
});
};
this.moveLinesUp = function() {
if (this.$readOnly)
return;
this.$moveLines(function(firstRow, lastRow) {
return this.doc.moveLinesUp(firstRow, lastRow);
});
};
this.copyLinesUp = function() {
if (this.$readOnly)
return;
this.$moveLines(function(firstRow, lastRow) {
this.doc.duplicateLines(firstRow, lastRow);
return 0;
});
};
this.copyLinesDown = function() {
if (this.$readOnly)
return;
this.$moveLines(function(firstRow, lastRow) {
return this.doc.duplicateLines(firstRow, lastRow);
});
};
this.$moveLines = function(mover) {
var rows = this.$getSelectedRows();
var linesMoved = mover.call(this, rows.first, rows.last);
var selection = this.selection;
selection.setSelectionAnchor(rows.last+linesMoved+1, 0);
selection.$moveSelection(function() {
selection.moveCursorTo(rows.first+linesMoved, 0);
});
};
this.$getSelectedRows = function() {
var range = this.getSelectionRange();
var firstRow = range.start.row;
var lastRow = range.end.row;
if (range.end.column == 0 && (range.start.row !== range.end.row)) {
lastRow -= 1;
}
return {
first: firstRow,
last: lastRow
};
};
this.onCompositionStart = function() {
this.renderer.showComposition(this.getCursorPosition());
this.onTextInput(" ");
};
this.onCompositionUpdate = function(text) {
this.renderer.setCompositionText(text);
};
this.onCompositionEnd = function() {
this.renderer.hideComposition();
this.removeLeft();
};
this.getFirstVisibleRow = function() {
return this.renderer.getFirstVisibleRow();
};
this.getLastVisibleRow = function() {
return this.renderer.getLastVisibleRow();
};
this.isRowVisible = function(row) {
return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow());
};
this.getVisibleRowCount = function() {
return this.getLastVisibleRow() - this.getFirstVisibleRow() + 1;
};
this.getPageDownRow = function() {
return this.renderer.getLastVisibleRow() - 1;
};
this.getPageUpRow = function() {
var firstRow = this.renderer.getFirstVisibleRow();
var lastRow = this.renderer.getLastVisibleRow();
return firstRow - (lastRow - firstRow) + 1;
};
this.scrollPageDown = function() {
this.scrollToRow(this.getPageDownRow());
};
this.scrollPageUp = function() {
this.renderer.scrollToRow(this.getPageUpRow());
};
this.scrollToRow = function(row) {
this.renderer.scrollToRow(row);
};
this.getCursorPosition = function() {
return this.selection.getCursor();
};
this.getSelectionRange = function() {
return this.selection.getRange();
};
this.clearSelection = function() {
this.selection.clearSelection();
};
this.moveCursorTo = function(row, column) {
this.selection.moveCursorTo(row, column);
};
this.moveCursorToPosition = function(pos) {
this.selection.moveCursorToPosition(pos);
};
this.gotoLine = function(lineNumber) {
this.$blockScrolling = true;
this.moveCursorTo(lineNumber-1, 0);
this.$blockScrolling = false;
if (!this.isRowVisible(this.getCursorPosition().row)) {
this.scrollToRow(lineNumber - 1 - Math.floor(this.getVisibleRowCount() / 2));
}
},
this.navigateTo = function(row, column) {
this.clearSelection();
this.moveCursorTo(row, column);
};
this.navigateUp = function() {
this.clearSelection();
this.selection.moveCursorUp();
};
this.navigateDown = function() {
this.clearSelection();
this.selection.moveCursorDown();
};
this.navigateLeft = function() {
if (!this.selection.isEmpty()) {
var selectionStart = this.getSelectionRange().start;
this.moveCursorToPosition(selectionStart);
}
else {
this.selection.moveCursorLeft();
}
this.clearSelection();
};
this.navigateRight = function() {
if (!this.selection.isEmpty()) {
var selectionEnd = this.getSelectionRange().end;
this.moveCursorToPosition(selectionEnd);
}
else {
this.selection.moveCursorRight();
}
this.clearSelection();
};
this.navigateLineStart = function() {
this.clearSelection();
this.selection.moveCursorLineStart();
};
this.navigateLineEnd = function() {
this.clearSelection();
this.selection.moveCursorLineEnd();
};
this.navigateFileEnd = function() {
this.clearSelection();
this.selection.moveCursorFileEnd();
};
this.navigateFileStart = function() {
this.clearSelection();
this.selection.moveCursorFileStart();
};
this.navigateWordRight = function() {
this.clearSelection();
this.selection.moveCursorWordRight();
};
this.navigateWordLeft = function() {
this.clearSelection();
this.selection.moveCursorWordLeft();
};
}).call(ace.Editor.prototype);

202
src/ace/KeyBinding.js Normal file
View file

@ -0,0 +1,202 @@
ace.provide("ace.KeyBinding");
ace.KeyBinding = function(element, editor) {
var keys = this.keys;
ace.addListener(element, "keydown", function(e) {
var key = e.keyCode;
var selection = editor.getSelection();
switch (key) {
case keys.A:
if (e.metaKey) {
selection.selectAll();
return ace.stopEvent(e);
}
break;
case keys.D:
if (e.metaKey) {
editor.removeLines();
return ace.stopEvent(e);
}
break;
case keys.L:
if (e.metaKey) {
var line = parseInt(prompt("Enter line number:"));
if (!isNaN(line)) {
editor.gotoLine(line);
return ace.stopEvent(e);
}
}
break;
case keys["7"]:
if (e.metaKey) {
editor.toggleCommentLines();
return ace.stopEvent(e);
};
break;
case keys.UP:
if (e.altKey && e.metaKey ) {
editor.copyLinesUp();
}
else if (e.altKey) {
editor.moveLinesUp();
}
else if (e.metaKey && e.shiftKey) {
selection.selectFileStart();
}
else if (e.metaKey) {
editor.navigateFileStart();
}
else if (e.shiftKey) {
selection.selectUp();
}
else {
editor.navigateUp();
}
return ace.stopEvent(e);
case keys.DOWN:
if (e.altKey && e.metaKey ) {
editor.copyLinesDown();
}
else if (e.altKey) {
editor.moveLinesDown();
}
else if (e.metaKey && e.shiftKey) {
selection.selectFileEnd();
}
else if (e.metaKey) {
editor.navigateFileEnd();
}
else if (e.shiftKey) {
selection.selectDown();
}
else {
editor.navigateDown();
}
return ace.stopEvent(e);
case keys.LEFT:
if (e.altKey && e.shiftKey) {
selection.selectWordLeft();
}
else if (e.altKey) {
editor.navigateWordLeft();
}
else if (e.metaKey && e.shiftKey) {
selection.selectLineStart();
}
else if (e.metaKey) {
editor.navigateLineStart();
}
else if (e.shiftKey) {
selection.selectLeft();
}
else {
editor.navigateLeft();
}
return ace.stopEvent(e);
case keys.RIGHT:
if (e.altKey && e.shiftKey) {
selection.selectWordRight();
}
else if (e.altKey) {
editor.navigateWordRight();
}
else if (e.metaKey && e.shiftKey) {
selection.selectLineEnd();
}
else if (e.metaKey) {
editor.navigateLineEnd();
}
else if (e.shiftKey) {
selection.selectRight();
}
else {
editor.navigateRight();
}
return ace.stopEvent(e);
case keys.PAGEDOWN:
if (e.shiftKey) {
selection.selectPageDown();
}
else {
editor.scrollPageDown();
}
return ace.stopEvent(e);
case keys.PAGEUP:
if (e.shiftKey) {
selection.selectPageUp();
}
else {
editor.scrollPageUp();
}
return ace.stopEvent(e);
case keys.POS1:
if (e.shiftKey) {
selection.selectLineStart();
}
else {
editor.navigateLineStart();
}
return ace.stopEvent(e);
case keys.END:
if (e.shiftKey) {
selection.selectLineEnd();
}
else {
editor.navigateLineEnd();
}
return ace.stopEvent(e);
case keys.DELETE:
editor.removeRight();
return ace.stopEvent(e);
case keys.BACKSPACE:
editor.removeLeft();
return ace.stopEvent(e);
case keys.TAB:
if (e.shiftKey) {
editor.blockOutdent();
} else if (selection.isMultiLine()) {
editor.blockIndent();
} else {
editor.onTextInput("\t");
}
return ace.stopEvent(e);
}
});
};
(function() {
this.keys = {
UP : 38,
RIGHT : 39,
DOWN : 40,
LEFT : 37,
PAGEUP : 33,
PAGEDOWN : 34,
POS1 : 36,
END : 35,
DELETE : 46,
BACKSPACE : 8,
TAB : 9,
A : 65,
D: 68,
L: 76,
"7": 55
};
}).call(ace.KeyBinding.prototype);

41
src/ace/MEventEmitter.js Normal file
View file

@ -0,0 +1,41 @@
ace.provide("ace.MEventEmitter");
ace.MEventEmitter = function() {
this.$initEvents = function() {
this.$eventRegistry = {};
};
this.$dispatchEvent = function(eventName, e) {
var listeners = this.$eventRegistry[eventName];
if (!listeners || !listeners.length) return;
var e = e || {};
e.type = eventName;
for (var i=0; i<listeners.length; i++) {
listeners[i](e);
}
};
this.addEventListener = function(eventName, callback) {
var listeners = this.$eventRegistry[eventName];
if (!listeners) {
var listeners = this.$eventRegistry[eventName] = [];
}
if (ace.arrayIndexOf(listeners, callback) == -1) {
listeners.push(callback);
}
};
this.removeEventListener = function(eventName, callback) {
var listeners = this.$eventRegistry[eventName];
if (!listeners) {
return;
}
var index = ace.arrayIndexOf(listeners, callback);
if (index !== -1) {
listeners.splice(index, 1);
}
};
};

44
src/ace/ScrollBar.js Normal file
View file

@ -0,0 +1,44 @@
ace.provide("ace.ScrollBar");
ace.ScrollBar = function(parent) {
this.$initEvents();
this.element = document.createElement("div");
this.element.className = "sb";
this.inner = document.createElement("div");
this.element.appendChild(this.inner);
parent.appendChild(this.element);
this.width = ace.scrollbarWidth();
this.element.style.width = this.width;
ace.addListener(this.element, "scroll", ace.bind(this.onScroll, this));
};
(function() {
ace.implement(this, ace.MEventEmitter);
this.onScroll = function() {
this.$dispatchEvent("scroll", {data: this.element.scrollTop});
};
this.getWidth = function() {
return this.width;
};
this.setHeight = function(height) {
this.element.style.height = Math.max(0, height - this.width) + "px";
};
this.setInnerHeight = function(height) {
this.inner.style.height = height + "px";
};
this.setScrollTop = function(scrollTop) {
this.element.scrollTop = scrollTop;
};
}).call(ace.ScrollBar.prototype);

394
src/ace/Selection.js Normal file
View file

@ -0,0 +1,394 @@
ace.provide("ace.Selection");
ace.Selection = function(doc) {
this.doc = doc;
this.$initEvents();
this.clearSelection();
this.selectionLead = {
row: 0,
column: 0
};
};
(function() {
ace.implement(this, ace.MEventEmitter);
this.isEmpty = function() {
return (this.selectionAnchor == null);
};
this.isMultiLine = function() {
if (this.isEmpty()) {
return false;
}
var range = this.getRange();
return (range.start.row !== range.end.row);
};
this.getCursor = function() {
return this.selectionLead;
};
this.setSelectionAnchor = function(row, column) {
this.clearSelection();
this.selectionAnchor = this.$clipPositionToDocument(row, column);
};
this.getSelectionAnchor = function() {
if (this.selectionAnchor) {
return this.$clone(this.selectionAnchor);
} else {
return this.$clone(this.selectionLead);
}
};
this.getSelectionLead = function() {
return this.$clone(this.selectionLead);
};
this.shiftSelection = function(columns) {
if (this.isEmpty()) {
this.moveCursorTo(this.selectionLead.row, this.selectionLead.column + columns);
return;
};
var anchor = this.getSelectionAnchor();
var lead = this.getSelectionLead();
this.setSelectionAnchor(anchor.row, anchor.column + columns);
this.$moveSelection(function() {
this.moveCursorTo(lead.row, lead.column + columns);
});
};
this.getRange = function() {
var anchor = this.selectionAnchor || this.selectionLead;
var lead = this.selectionLead;
if (anchor.row > lead.row
|| (anchor.row == lead.row && anchor.column > lead.column)) {
return {
start : lead,
end : anchor
};
}
else {
return {
start : anchor,
end : lead
};
}
};
this.clearSelection = function() {
if (this.selectionAnchor) {
this.selectionAnchor = null;
this.$dispatchEvent("changeSelection", {});
}
};
this.selectAll = function() {
var lastRow = this.doc.getLength() - 1;
this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
this.$moveSelection(function() {
this.moveCursorTo(0, 0);
});
};
this.$moveSelection = function(mover) {
var changed = false;
if (!this.selectionAnchor) {
changed = true;
this.selectionAnchor = this.$clone(this.selectionLead);
}
var cursor = this.$clone(this.selectionLead);
mover.call(this);
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
changed = true;
}
if (changed)
this.$dispatchEvent("changeSelection", {});
};
this.selectTo = function(row, column) {
this.$moveSelection(function() {
this.moveCursorTo(row, column);
});
};
this.selectToPosition = function(pos) {
this.$moveSelection(function() {
this.moveCursorToPosition(pos);
});
};
this.selectUp = function() {
this.$moveSelection(this.moveCursorUp);
};
this.selectDown = function() {
this.$moveSelection(this.moveCursorDown);
};
this.selectRight = function() {
this.$moveSelection(this.moveCursorRight);
};
this.selectLeft = function() {
this.$moveSelection(this.moveCursorLeft);
};
this.selectLineStart = function() {
this.$moveSelection(this.moveCursorLineStart);
};
this.selectLineEnd = function() {
this.$moveSelection(this.moveCursorLineEnd);
};
this.selectPageDown = function() {
var row = this.getPageDownRow() + Math.floor(this.getVisibleRowCount() / 2);
this.scrollPageDown();
this.$moveSelection(function() {
this.moveCursorTo(row, this.selectionLead.column);
});
};
this.selectPageUp = function() {
var visibleRows = this.getLastVisibleRow() - this.getFirstVisibleRow();
var row = this.getPageUpRow() + Math.round(visibleRows / 2);
this.scrollPageUp();
this.$moveSelection(function() {
this.moveCursorTo(row, this.selectionLead.column);
});
};
this.selectFileEnd = function() {
this.$moveSelection(this.moveCursorFileEnd);
};
this.selectFileStart = function() {
this.$moveSelection(this.moveCursorFileStart);
};
this.tokenRe = /^[\w\d]+/g;
this.nonTokenRe = /^[^\w\d]+/g;
this.selectWordRight = function() {
this.$moveSelection(this.moveCursorWordRight);
};
this.selectWordLeft = function() {
this.$moveSelection(this.moveCursorWordLeft);
};
this.selectWord = function() {
var cursor = this.selectionLead;
var line = this.doc.getLine(cursor.row);
var column = cursor.column;
var inToken = false;
if (column > 0) {
inToken = !!line.charAt(column - 1).match(this.tokenRe);
}
if (!inToken) {
inToken = !!line.charAt(column).match(this.tokenRe);
}
var re = inToken ? this.tokenRe : this.nonTokenRe;
var start = column;
if (start > 0) {
do {
start--;
}
while (start >= 0 && line.charAt(start).match(re));
start++;
}
var end = column;
while (end < line.length && line.charAt(end).match(re)) {
end++;
}
this.setSelectionAnchor(cursor.row, start);
this.$moveSelection(function() {
this.moveCursorTo(cursor.row, end);
});
};
this.selectLine = function() {
this.setSelectionAnchor(this.selectionLead.row, 0);
this.$moveSelection(function() {
this.moveCursorTo(this.selectionLead.row + 1, 0);
});
};
this.moveCursorUp = function() {
this.moveCursorBy(-1, 0);
};
this.moveCursorDown = function() {
this.moveCursorBy(1, 0);
};
this.moveCursorLeft = function() {
if (this.selectionLead.column == 0) {
if (this.selectionLead.row > 0) {
this.moveCursorTo(this.selectionLead.row - 1, this.doc
.getLine(this.selectionLead.row - 1).length);
}
}
else {
this.moveCursorBy(0, -1);
}
};
this.moveCursorRight = function() {
if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) {
if (this.selectionLead.row < this.doc.getLength() - 1) {
this.moveCursorTo(this.selectionLead.row + 1, 0);
}
}
else {
this.moveCursorBy(0, 1);
}
};
this.moveCursorLineStart = function() {
this.moveCursorTo(this.selectionLead.row, 0);
};
this.moveCursorLineEnd = function() {
this.moveCursorTo(this.selectionLead.row,
this.doc.getLine(this.selectionLead.row).length);
};
this.moveCursorFileEnd = function() {
var row = this.doc.getLength() - 1;
var column = this.doc.getLine(row).length;
this.moveCursorTo(row, column);
};
this.moveCursorFileStart = function() {
this.moveCursorTo(0, 0);
};
this.moveCursorWordRight = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
var line = this.doc.getLine(row);
var rightOfCursor = line.substring(column);
var match;
this.nonTokenRe.lastIndex = 0;
this.tokenRe.lastIndex = 0;
if (column == line.length) {
this.moveCursorRight();
return;
}
else if (match = this.nonTokenRe.exec(rightOfCursor)) {
column += this.nonTokenRe.lastIndex;
this.nonTokenRe.lastIndex = 0;
}
else if (match = this.tokenRe.exec(rightOfCursor)) {
column += this.tokenRe.lastIndex;
this.tokenRe.lastIndex = 0;
}
this.moveCursorTo(row, column);
};
this.moveCursorWordLeft = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
var line = this.doc.getLine(row);
var leftOfCursor = ace.stringReverse(line.substring(0, column));
var match;
this.nonTokenRe.lastIndex = 0;
this.tokenRe.lastIndex = 0;
if (column == 0) {
this.moveCursorLeft();
return;
}
else if (match = this.nonTokenRe.exec(leftOfCursor)) {
column -= this.nonTokenRe.lastIndex;
this.nonTokenRe.lastIndex = 0;
}
else if (match = this.tokenRe.exec(leftOfCursor)) {
column -= this.tokenRe.lastIndex;
this.tokenRe.lastIndex = 0;
}
this.moveCursorTo(row, column);
};
this.moveCursorBy = function(rows, chars) {
this.moveCursorTo(this.selectionLead.row + rows, this.selectionLead.column + chars);
};
this.moveCursorToPosition = function(position) {
this.moveCursorTo(position.row, position.column);
};
this.moveCursorTo = function(row, column) {
var cursor = this.$clipPositionToDocument(row, column);
if (cursor.row !== this.selectionLead.row || cursor.column !== this.selectionLead.column) {
this.selectionLead = cursor;
this.$dispatchEvent("changeCursor", { data: this.getCursor() });
}
};
this.moveCursorUp = function() {
this.moveCursorBy(-1, 0);
};
this.$clipPositionToDocument = function(row, column) {
var pos = {};
if (row >= this.doc.getLength()) {
pos.row = this.doc.getLength() - 1;
pos.column = this.doc.getLine(pos.row).length;
}
else if (row < 0) {
pos.row = 0;
pos.column = 0;
}
else {
pos.row = row;
pos.column = Math.min(this.doc.getLine(pos.row).length,
Math.max(0, column));
}
return pos;
};
this.$clone = function(pos) {
return {
row: pos.row,
column: pos.column
};
};
}).call(ace.Selection.prototype);

83
src/ace/TextInput.js Normal file
View file

@ -0,0 +1,83 @@
ace.provide("ace.TextInput");
ace.TextInput = function(parentNode, host) {
var text = document.createElement("textarea");
var style = text.style;
style.position = "absolute";
style.left = "-10000px";
style.top = "-10000px";
parentNode.appendChild(text);
var inCompostion = false;
var onTextInput = function(e) {
setTimeout(function() {
if (!inCompostion) {
if (text.value)
host.onTextInput(text.value);
text.value = "";
}
}, 0);
};
var onCompositionStart = function(e) {
inCompostion = true;
if (text.value)
host.onTextInput(text.value);
text.value = "";
host.onCompositionStart();
setTimeout(onCompositionUpdate, 0);
};
var onCompositionUpdate = function() {
host.onCompositionUpdate(text.value);
};
var onCompositionEnd = function() {
inCompostion = false;
host.onCompositionEnd();
onTextInput();
};
var onCopy = function() {
text.value = host.getCopyText();
text.select();
};
var onCut = function() {
text.value = host.getCopyText();
host.onCut();
text.select();
};
ace.addListener(text, "keypress", onTextInput);
ace.addListener(text, "textInput", onTextInput);
ace.addListener(text, "paste", onTextInput);
ace.addListener(text, "propertychange", onTextInput);
ace.addListener(text, "copy", onCopy);
ace.addListener(text, "cut", onCut);
ace.addListener(text, "compositionstart", onCompositionStart);
ace.addListener(text, "compositionupdate", onCompositionUpdate);
ace.addListener(text, "compositionend", onCompositionEnd);
ace.addListener(text, "blur", function() {
host.onBlur();
});
ace.addListener(text, "focus", function() {
host.onFocus();
});
this.focus = function() {
text.focus();
};
this.blur = function() {
text.blur();
};
};

92
src/ace/Tokenizer.js Normal file
View file

@ -0,0 +1,92 @@
ace.provide("ace.Tokenizer");
ace.Tokenizer = function(rules) {
this.rules = rules;
this.regExps = {};
for ( var key in this.rules) {
var state = this.rules[key];
var ruleRegExps = [];
for ( var i = 0; i < state.length; i++) {
ruleRegExps.push(state[i].regex);
};
this.regExps[key] = new RegExp("(?:(" + ruleRegExps.join(")|(")
+ ")|(.))", "g");
}
};
(function() {
this.getLineTokens = function(line, startState) {
var currentState = startState;
var state = this.rules[currentState];
var re = this.regExps[currentState];
re.lastIndex = 0;
var match, tokens = [];
var lastIndex = 0;
var token = {
type: null,
value: ""
};
while (match = re.exec(line)) {
var type = "text";
var value = match[0];
if (re.lastIndex == lastIndex) { throw new Error("tokenizer error"); }
lastIndex = re.lastIndex;
window.LOG && jstestdriver.console.log(currentState, match);
for ( var i = 0; i < state.length; i++) {
if (match[i + 1]) {
if (typeof state[i].token == "function") {
type = state[i].token(match[0]);
}
else {
type = state[i].token;
}
if (state[i].next && state[i].next !== currentState) {
currentState = state[i].next;
var state = this.rules[currentState];
var lastIndex = re.lastIndex;
var re = this.regExps[currentState];
re.lastIndex = lastIndex;
}
break;
}
};
if (token.type !== type) {
if (token.type) {
tokens.push(token);
}
token = {
type: type,
value: value
};
} else {
token.value += value;
}
};
if (token.type) {
tokens.push(token);
}
window.LOG && jstestdriver.console.log(tokens, currentState);
return {
tokens : tokens,
state : currentState
};
};
}).call(ace.Tokenizer.prototype);

318
src/ace/VirtualRenderer.js Normal file
View file

@ -0,0 +1,318 @@
ace.provide("ace.VirtualRenderer");
ace.VirtualRenderer = function(container) {
this.container = container;
ace.addCssClass(this.container, "editor");
this.scroller = document.createElement("div");
this.scroller.className = "scroller";
this.container.appendChild(this.scroller);
this.gutter = document.createElement("div");
this.gutter.className = "gutter";
this.container.appendChild(this.gutter);
this.gutterLayer = new ace.layer.Gutter(this.gutter);
this.markerLayer = new ace.layer.Marker(this.scroller);
var textLayer = this.textLayer = new ace.layer.Text(this.scroller);
this.canvas = textLayer.element;
this.characterWidth = textLayer.getCharacterWidth();
this.lineHeight = textLayer.getLineHeight();
this.cursorLayer = new ace.layer.Cursor(this.scroller);
this.layers = [ this.markerLayer, textLayer, this.cursorLayer ];
this.scrollBar = new ace.ScrollBar(container);
this.scrollBar.addEventListener("scroll", ace.bind(this.onScroll, this));
this.scrollTop = 0;
this.cursorPos = {
row : 0,
column : 0
};
this.onResize();
};
(function() {
this.setDocument = function(doc) {
this.lines = doc.lines;
this.doc = doc;
this.markerLayer.setDocument(doc);
this.textLayer.setDocument(doc);
};
this.setTokenizer = function(tokenizer) {
this.textLayer.setTokenizer(tokenizer);
};
this.$showInvisibles = true;
this.setShowInvisibles = function(showInvisibles) {
this.$showInvisibles = showInvisibles;
this.textLayer.setShowInvisibles(showInvisibles);
};
this.getContainerElement = function() {
return this.container;
};
this.getMouseEventTarget = function() {
return this.scroller;
};
this.getFirstVisibleRow = function() {
return this.layerConfig.firstRow || 0;
};
this.getLastVisibleRow = function() {
return this.layerConfig.lastRow || 0;
};
this.onResize = function()
{
var height = ace.getInnerHeight(this.container);
this.gutter.style.height = height + "px";
this.scroller.style.height = height + "px";
this.scrollBar.setHeight(height);
var width = ace.getInnerWidth(this.container);
var gutterWidth = this.gutter.offsetWidth;
this.scroller.style.left = gutterWidth + "px";
this.scroller.style.width = Math.max(0, width - gutterWidth - this.scrollBar.getWidth()) + "px";
if (this.doc) {
this.$updateScrollBar();
this.scrollToY(this.getScrollTop());
this.draw();
}
};
this.onScroll = function(e) {
this.scrollToY(e.data);
};
this.$updateScrollBar = function() {
this.scrollBar.setInnerHeight(this.doc.getLength() * this.lineHeight);
this.scrollBar.setScrollTop(this.scrollTop);
};
this.updateLines = function(firstRow, lastRow) {
var layerConfig = this.layerConfig;
if (firstRow > layerConfig.lastRow + 1) { return; }
if (lastRow < layerConfig.firstRow) { return; }
// if the last row is unknown -> redraw everything
if (lastRow === undefined) {
this.draw();
return;
}
// else update only the changed rows
this.textLayer.updateLines(layerConfig, firstRow, lastRow);
};
this.draw = function() {
var lines = this.lines;
var offset = this.scrollTop % this.lineHeight;
var minHeight = this.scroller.clientHeight + offset;
var charCount = this.doc.getWidth();
if (this.$showInvisibles)
charCount += 1;
var longestLine = Math.max(this.scroller.clientWidth, Math.round(charCount * this.characterWidth));
var lineCount = Math.ceil(minHeight / this.lineHeight);
var firstRow = Math.round((this.scrollTop - offset) / this.lineHeight);
var lastRow = Math.min(lines.length, firstRow + lineCount) - 1;
var layerConfig = this.layerConfig = {
width : longestLine,
firstRow : firstRow,
lastRow : lastRow,
lineHeight : this.lineHeight,
characterWidth : this.characterWidth
};
for ( var i = 0; i < this.layers.length; i++) {
var layer = this.layers[i];
var style = layer.element.style;
style.marginTop = (-offset) + "px";
style.height = minHeight + "px";
style.width = longestLine + "px";
layer.update(layerConfig);
};
this.gutterLayer.element.style.marginTop = (-offset) + "px";
this.gutterLayer.element.style.height = minHeight + "px";
this.gutterLayer.update(layerConfig);
this.$updateScrollBar();
};
this.addMarker = function(range, clazz, type) {
range.start = this.$documentToScreenPosition(range.start);
range.end = this.$documentToScreenPosition(range.end);
return this.markerLayer.addMarker(range, clazz, type);
};
this.removeMarker = function(markerId) {
this.markerLayer.removeMarker(markerId);
};
this.updateCursor = function(position) {
this.cursorLayer.setCursor(this.$documentToScreenPosition(position));
this.cursorLayer.update(this.layerConfig);
};
this.$documentToScreenPosition = function(pos) {
return {
row: pos.row,
column: this.$documentToScreenColumn(pos.row, pos.column)
};
};
this.$documentToScreenColumn = function(row, docColumn) {
var tabSize = this.doc.getTabSize();
var screenColumn = 0;
var remaining = docColumn;
var line = this.doc.getLine(row).split(/\t/g);
for (var i=0; i<line.length; i++) {
var len = line[i].length;
if (remaining > len) {
remaining -= (len + 1);
screenColumn += len + tabSize;
}
else {
screenColumn += remaining;
break;
}
}
return screenColumn;
};
this.$screenToDocumentColumn = function(row, screenColumn) {
var tabSize = this.doc.getTabSize();
var docColumn = 0;
var remaining = screenColumn;
var line = this.doc.getLine(row).split(/\t/g);
for (var i=0; i<line.length; i++) {
var len = line[i].length;
if (remaining >= len + tabSize) {
remaining -= (len + tabSize);
docColumn += (len + 1);
}
else if (remaining > len){
docColumn += len;
break;
}
else {
docColumn += remaining;
break;
}
}
return docColumn;
};
this.hideCursor = function() {
this.cursorLayer.hideCursor();
};
this.showCursor = function() {
this.cursorLayer.showCursor();
};
this.scrollCursorIntoView = function() {
var pos = this.cursorLayer.getPixelPosition();
var left = pos.left;
var top = pos.top;
if (this.getScrollTop() > top) {
this.scrollToY(top);
}
if (this.getScrollTop() + this.scroller.clientHeight < top
+ this.lineHeight) {
this.scrollToY(top + this.lineHeight - this.scroller.clientHeight);
}
if (this.scroller.scrollLeft > left) {
this.scroller.scrollLeft = left;
}
if (this.scroller.scrollLeft + this.scroller.clientWidth < left
+ this.characterWidth) {
this.scroller.scrollLeft = Math.round(left + this.characterWidth
- this.scroller.clientWidth);
}
},
this.getScrollTop = function() {
return this.scrollTop;
};
this.getScrollTopRow = function() {
return this.scrollTop / this.lineHeight;
};
this.scrollToRow = function(row) {
this.scrollToY(row * this.lineHeight);
};
this.scrollToY = function(scrollTop) {
var maxHeight = this.lines.length * this.lineHeight
- this.scroller.clientHeight;
var scrollTop = Math.max(0, Math.min(maxHeight, scrollTop));
if (this.scrollTop !== scrollTop) {
this.scrollTop = scrollTop;
this.$updateScrollBar();
this.draw();
}
};
this.screenToTextCoordinates = function(pageX, pageY) {
var canvasPos = this.scroller.getBoundingClientRect();
var col = Math.floor((pageX + this.scroller.scrollLeft - canvasPos.left)
/ this.characterWidth);
var row = Math.floor((pageY + this.scrollTop - canvasPos.top)
/ this.lineHeight);
return {
row : row,
column : this.$screenToDocumentColumn(row, col)
};
};
this.visualizeFocus = function() {
ace.addCssClass(this.container, "focus");
};
this.visualizeBlur = function() {
ace.removeCssClass(this.container, "focus");
};
this.showComposition = function(position) {
};
this.setCompositionText = function(text) {
};
this.hideComposition = function() {
};
}).call(ace.VirtualRenderer.prototype);

275
src/ace/ace.js Normal file
View file

@ -0,0 +1,275 @@
if (!window.ace)
ace = {};
ace.provide = function(namespace) {
var parts = namespace.split(".");
var obj = window;
for (var i=0; i<parts.length; i++) {
var part = parts[i];
if (!obj[part]) {
obj[part] = {};
}
obj = obj[part];
}
};
ace.inherits = function(ctor, superCtor) {
var tempCtor = function() {};
tempCtor.prototype = superCtor.prototype;
ctor.super_ = superCtor.prototype;
ctor.prototype = new tempCtor();
ctor.prototype.constructor = ctor;
};
ace.implement = function(proto, mixin) {
mixin.call(proto);
};
ace.addListener = function(elem, type, callback) {
if (elem.addEventListener) {
return elem.addEventListener(type, callback, false);
}
if (elem.attachEvent) {
var wrapper = function() {
callback(window.event);
};
callback.$$wrapper = wrapper;
elem.attachEvent("on" + type, wrapper);
}
};
ace.removeListener = function(elem, type, callback) {
if (elem.removeEventListener) {
return elem.removeEventListener(type, callback, false);
}
if (elem.detachEvent) {
elem.detachEvent("on" + type, callback.$$wrapper || callback);
}
};
ace.setText = function(elem, text) {
if (elem.innerText !== undefined) {
elem.innerText = text;
}
if (elem.textContent !== undefined) {
elem.textContent = text;
}
};
ace.stopEvent = function(e) {
ace.stopPropagation(e);
ace.preventDefault(e);
return false;
};
ace.stopPropagation = function(e) {
if (e.stopPropagation)
e.stopPropagation();
else
e.cancelBubble = true;
};
ace.preventDefault = function(e) {
if (e.preventDefault)
e.preventDefault();
else
e.returnValue = false;
};
ace.hasCssClass = function(el, name) {
var classes = el.className.split(/\s*/g);
return ace.arrayIndexOf(classes, name) !== -1;
};
ace.addCssClass = function(el, name) {
if (!ace.hasCssClass(el, name)) {
el.className += " " + name;
}
};
ace.removeCssClass = function(el, name) {
var classes = el.className.split(/\s+/g);
while (true) {
var index = ace.arrayIndexOf(classes, name);
if (index == -1) {
break;
}
classes.splice(index, 1);
}
el.className = classes.join(" ");
};
ace.getInnerWidth = function(element) {
return (parseInt(ace.computedStyle(element, "paddingLeft"))
+ parseInt(ace.computedStyle(element, "paddingRight")) + element.clientWidth);
};
ace.getInnerHeight = function(element) {
return (parseInt(ace.computedStyle(element, "paddingTop"))
+ parseInt(ace.computedStyle(element, "paddingBottom")) + element.clientHeight);
};
ace.computedStyle = function(element, style) {
if (window.getComputedStyle) {
return (window.getComputedStyle(element, null))[style];
}
else {
return element.currentStyle[style];
}
};
ace.scrollbarWidth = function() {
var inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";
var outer = document.createElement("div");
var style = outer.style;
style.position = "absolute";
style.left = "-10000px";
style.overflow = "hidden";
style.width = "200px";
style.height = "150px";
outer.appendChild(inner);
document.body.appendChild(outer);
var noScrollbar = inner.offsetWidth;
style.overflow = "scroll";
var withScrollbar = inner.offsetWidth;
if (noScrollbar == withScrollbar) {
withScrollbar = outer.clientWidth;
}
document.body.removeChild(outer);
return noScrollbar-withScrollbar;
};
ace.stringReverse = function(string) {
return string.split("").reverse().join("");
};
if (Array.prototype.indexOf) {
ace.arrayIndexOf = function(array, searchElement) {
return array.indexOf(searchElement);
};
}
else {
ace.arrayIndexOf = function(array, searchElement) {
for (var i=0; i<array.length; i++) {
if (array[i] == searchElement) {
return i;
}
}
return -1;
};
}
ace.bind = function(fcn, context) {
return function() {
return fcn.apply(context, arguments);
};
};
ace.getDocumentX = function(event) {
if (event.clientX) {
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
return event.clientX + scrollLeft;
} else {
return event.pageX;
}
};
ace.getDocumentY = function(event) {
if (event.clientY) {
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
return event.clientY + scrollTop;
} else {
return event.pageX;
}
};
if (document.documentElement.setCapture) {
ace.capture = function(el, eventHandler, releaseCaptureHandler) {
function onMouseMove(e) {
eventHandler(e);
return ace.stopPropagation(e);
}
function onReleaseCapture(e) {
eventHandler && eventHandler(e);
releaseCaptureHandler && releaseCaptureHandler();
ace.removeListener(el, "mousemove", eventHandler);
ace.removeListener(el, "mouseup", onReleaseCapture);
ace.removeListener(el, "losecapture", onReleaseCapture);
el.releaseCapture();
}
ace.addListener(el, "mousemove", eventHandler);
ace.addListener(el, "mouseup", onReleaseCapture);
ace.addListener(el, "losecapture", onReleaseCapture);
el.setCapture();
};
}
else {
ace.capture = function(el, eventHandler, releaseCaptureHandler) {
function onMouseMove(e) {
eventHandler(e);
e.stopPropagation();
}
function onMouseUp(e) {
eventHandler && eventHandler(e);
releaseCaptureHandler && releaseCaptureHandler();
document.removeEventListener("mousemove", onMouseMove, true);
document.removeEventListener("mouseup", onMouseUp, true);
e.stopPropagation();
}
document.addEventListener("mousemove", onMouseMove, true);
document.addEventListener("mouseup", onMouseUp, true);
};
}
ace.addMouseWheelListener = function(el, callback) {
var listener = function(e) {
e.wheel = (e.wheelDelta) ? e.wheelDelta / 120
: -(e.detail || 0) / 3;
callback(e);
};
ace.addListener(el, "DOMMouseScroll", listener);
ace.addListener(el, "mousewheel", listener);
};
ace.autoremoveListener = function(el, type, callback, timeout) {
var listener = function(e) {
clearTimeout(timeoutId);
remove();
callback(e);
};
var remove = function() {
ace.removeListener(el, type, listener);
};
ace.addListener(el, type, listener);
var timeoutId = setTimeout(remove, timeout);
};
ace.addTripleClickListener = function(el, callback) {
ace.addListener(el, "mousedown", function() {
ace.autoremoveListener(el, "mousedown", function() {
ace.autoremoveListener(el, "mousedown", callback, 300);
}, 300);
});
};

85
src/ace/layer/Cursor.js Normal file
View file

@ -0,0 +1,85 @@
ace.provide("ace.layer.Cursor");
ace.layer.Cursor = function(parentEl) {
this.element = document.createElement("div");
this.element.className = "layer cursor-layer";
parentEl.appendChild(this.element);
this.cursor = document.createElement("div");
this.cursor.className = "cursor";
this.isVisible = false;
};
(function() {
this.setCursor = function(position) {
this.position = {
row : position.row,
column : position.column
};
};
this.hideCursor = function() {
this.isVisible = false;
if (this.cursor.parentNode) {
this.cursor.parentNode.removeChild(this.cursor);
}
clearInterval(this.blinkId);
};
this.showCursor = function() {
this.isVisible = true;
this.element.appendChild(this.cursor);
var cursor = this.cursor;
cursor.style.visibility = "visible";
this.restartTimer();
};
this.restartTimer = function() {
clearInterval(this.blinkId);
if (!this.isVisible) {
return;
}
var cursor = this.cursor;
this.blinkId = setInterval(function() {
cursor.style.visibility = "hidden";
setTimeout(function() {
cursor.style.visibility = "visible";
}, 400);
}, 1000);
};
this.getPixelPosition = function() {
return this.pixelPos || {
left : 0,
top : 0
};
};
this.update = function(config) {
if (!this.position)
return;
var cursorLeft = Math.round(this.position.column * config.characterWidth);
var cursorTop = this.position.row * config.lineHeight;
this.pixelPos = {
left : cursorLeft,
top : cursorTop
};
this.cursor.style.left = cursorLeft + "px";
this.cursor.style.top = (cursorTop - (config.firstRow * config.lineHeight))
+ "px";
this.cursor.style.height = config.lineHeight + "px";
if (this.isVisible) {
this.element.appendChild(this.cursor);
}
this.restartTimer();
};
}).call(ace.layer.Cursor.prototype);

22
src/ace/layer/Gutter.js Normal file
View file

@ -0,0 +1,22 @@
ace.provide("ace.layer.Gutter");
ace.layer.Gutter = function(parentEl) {
this.element = document.createElement("div");
this.element.className = "layer gutter-layer";
parentEl.appendChild(this.element);
};
(function() {
this.update = function(config) {
var html = [];
for ( var i = config.firstRow; i <= config.lastRow; i++) {
html.push("<div class='gutter-cell' style='height:" + config.lineHeight
+ "px;'>", (i+1), "</div>");
html.push("</div>");
}
this.element.innerHTML = html.join("");
};
}).call(ace.layer.Gutter.prototype);

165
src/ace/layer/Marker.js Normal file
View file

@ -0,0 +1,165 @@
ace.provide("ace.layer.Marker");
ace.layer.Marker = function(parentEl) {
this.element = document.createElement("div");
this.element.className = "layer marker-layer";
parentEl.appendChild(this.element);
this.markers = {};
this.$markerId = 1;
};
(function() {
this.setDocument = function(doc) {
this.doc = doc;
};
this.addMarker = function(range, clazz, type) {
var id = this.$markerId++;
this.markers[id] = {
range : range,
type : type || "line",
clazz : clazz
};
this.update();
return id;
};
this.removeMarker = function(markerId) {
var marker = this.markers[markerId];
if (marker) {
delete (this.markers[markerId]);
this.update();
}
};
this.update = function(config) {
var config = config || this.config;
if (!config)
return;
this.config = config;
var html = [];
for ( var key in this.markers) {
var marker = this.markers[key];
var range = {
start: marker.range.start,
end: marker.range.end
};
// clip
if (range.start.row > config.lastRow) continue;
if (range.end.row < config.firstRow) continue;
if (range.end.row > config.lastRow) {
range.end = {
row: config.lastRow+1,
column: 0
};
}
if (range.start.row < config.firstRow) {
range.start = {
row: config.firstRow,
column: 0
};
}
if (range.start.row !== range.end.row) {
if (marker.type == "text") {
this.drawTextMarker(html, range, marker.clazz, config);
} else {
this.drawMultiLineMarker(html, range, marker.clazz, config);
}
}
else {
this.drawSingleLineMarker(html, range, marker.clazz, config);
}
}
this.element.innerHTML = html.join("");
};
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
// selection start
var row = range.start.row;
var lineRange = { start: {}, end: {}};
lineRange.start.row = row;
lineRange.start.column = range.start.column;
lineRange.end.row = row;
lineRange.end.column = this.doc.getLine(row).length;
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig);
// selection end
var row = range.end.row;
lineRange.start.row = row;
lineRange.start.column = 0;
lineRange.end.row = row;
lineRange.end.column = range.end.column;
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig);
for (var row = range.start.row + 1; row < range.end.row; row++) {
lineRange.start.row = row;
lineRange.end.row = row;
lineRange.end.column = this.doc.getLine(row).length;
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig);
}
};
this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) {
var height = layerConfig.lineHeight;
var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth));
var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight;
var left = Math.round(range.start.column * layerConfig.characterWidth);
stringBuilder.push(
"<div class='", clazz, "' style='",
"height:", height, "px;",
"width:", width, "px;",
"top:", top, "px;",
"left:", left, "px;'></div>"
);
var top = (range.end.row - layerConfig.firstRow) * layerConfig.lineHeight;
var width = Math.round(range.end.column * layerConfig.characterWidth);
stringBuilder.push(
"<div class='", clazz, "' style='",
"height:", height, "px;",
"top:", top, "px;",
"width:", width, "px;'></div>"
);
for (var row = range.start.row + 1; row < range.end.row; row++) {
var top = (row - layerConfig.firstRow) * layerConfig.lineHeight;
stringBuilder.push(
"<div class='", clazz, "' style='",
"height:", height, "px;",
"width:", layerConfig.width, "px;",
"top:", top, "px;'></div>"
);
}
};
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig) {
var height = layerConfig.lineHeight;
var width = Math.round((range.end.column - range.start.column) * layerConfig.characterWidth);
var top = (range.start.row - layerConfig.firstRow) * layerConfig.lineHeight;
var left = Math.round(range.start.column * layerConfig.characterWidth);
stringBuilder.push(
"<div class='", clazz, "' style='",
"height:", height, "px;",
"width:", width, "px;",
"top:", top, "px;",
"left:", left,"px;'></div>"
);
};
}).call(ace.layer.Marker.prototype);

133
src/ace/layer/Text.js Normal file
View file

@ -0,0 +1,133 @@
ace.provide("ace.layer.Text");
ace.layer.Text = function(parentEl) {
this.element = document.createElement("div");
this.element.className = "layer text-layer";
parentEl.appendChild(this.element);
this.$measureSizes();
};
(function() {
// this.EOF_CHAR = "&para;";
this.EOF_CHAR = "&para;";
this.EOL_CHAR = "&not;";
// this.TAB_CHAR = "&#x2023;";
this.TAB_CHAR = "&rarr;";
this.setTokenizer = function(tokenizer) {
this.tokenizer = tokenizer;
};
this.getLineHeight = function() {
return this.lineHeight;
};
this.getCharacterWidth = function() {
return this.characterWidth;
};
this.$measureSizes = function() {
var measureNode = document.createElement("div");
var style = measureNode.style;
style.width = style.height = "auto";
style.left = style.top = "-1000px";
style.visibility = "hidden";
style.position = "absolute";
style.overflow = "visible";
measureNode.innerHTML = new Array(1000).join("Xy");
this.element.appendChild(measureNode);
// in FF 3.6 monospace fonts can have a fixed sub pixel width.
// that's why we have to measure many characters
// Note: characterWidth can be a float!
this.lineHeight = measureNode.offsetHeight;
this.characterWidth = measureNode.offsetWidth / 2000;
this.element.removeChild(measureNode);
};
this.setDocument = function(doc) {
this.doc = doc;
};
this.$showInvisibles = true;
this.setShowInvisibles = function(showInvisibles) {
this.$showInvisibles = showInvisibles;
};
this.$computeTabString = function() {
var tabSize = this.doc.getTabSize();
if (this.$showInvisibles) {
var halfTab = (tabSize) / 2;
this.$tabString = "<span class='invisible'>"
+ new Array(Math.floor(halfTab)).join("&nbsp;")
+ this.TAB_CHAR
+ new Array(Math.ceil(halfTab)+1).join("&nbsp;")
+ "</span>";
} else {
this.$tabString = new Array(tabSize+1).join("&nbsp;");
}
};
this.updateLines = function(layerConfig, firstRow, lastRow) {
this.$computeTabString();
var first = Math.max(firstRow, layerConfig.firstRow);
var last = Math.min(lastRow, layerConfig.lastRow);
var lineElements = this.element.childNodes;
for ( var i = first; i <= last; i++) {
var html = [];
this.renderLine(html, i);
var lineElement = lineElements[i - layerConfig.firstRow];
lineElement.innerHTML = html.join("");
};
};
this.update = function(config) {
this.$computeTabString();
var html = [];
for ( var i = config.firstRow; i <= config.lastRow; i++) {
html.push("<div class='line' style='height:" + this.lineHeight + "px;", "width:",
config.width, "px'>");
this.renderLine(html, i), html.push("</div>");
}
this.element.innerHTML = html.join("");
};
this.renderLine = function(stringBuilder, row) {
var tokens = this.tokenizer.getTokens(row);
for ( var i = 0; i < tokens.length; i++) {
var token = tokens[i];
var output = token.value
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/g, "&nbsp;")
.replace(/\t/g, this.$tabString);
if (token.type !== "text") {
stringBuilder.push("<span class='", token.type, "'>", output, "</span>");
}
else {
stringBuilder.push(output);
}
};
if (this.$showInvisibles) {
if (row !== this.doc.getLength() - 1) {
stringBuilder.push("<span class='invisible'>" + this.EOL_CHAR + "</span>");
} else {
stringBuilder.push("<span class='invisible'>" + this.EOF_CHAR + "</span>");
}
}
};
}).call(ace.layer.Text.prototype);

27
src/ace/mode/Css.js Normal file
View file

@ -0,0 +1,27 @@
ace.provide("ace.mode.Css");
ace.mode.Css = function() {
this.$tokenizer = new ace.Tokenizer(new ace.mode.CssHighlightRules().getRules());
};
ace.inherits(ace.mode.Css, ace.mode.Text);
(function() {
this.getNextLineIndent = function(line, state, tab) {
var indent = this.$getIndent(line);
// ignore braces in comments
var tokens = this.$tokenizer.getLineTokens(line, state).tokens;
if (tokens.length && tokens[tokens.length-1].type == "comment") {
return indent;
}
var match = line.match(/^.*\{\s*$/);
if (match) {
indent += tab;
}
return indent;
};
}).call(ace.mode.Css.prototype);

View file

@ -0,0 +1,184 @@
ace.provide("ace.mode.CssHighlightRules");
ace.mode.CssHighlightRules = function() {
var properties = {
"width": 1,
"height": 1,
"top": 1,
"left": 1,
"right": 1,
"bottom": 1,
"overflow": 1,
"overflow-x": 1,
"overflow-y": 1,
"background": 1,
"font": 1,
"font-style": 1,
"font-family": 1,
"font-size": 1,
"text-align": 1,
"white-space": 1,
"color": 1,
"z-index": 1,
"position": 1,
"cursor": 1,
"box-sizing": 1,
"-webkit-box-sizing": 1,
"-moz-box-sizing": 1,
"margin": 1,
"padding": 1,
"padding-top": 1,
"padding-right": 1,
"padding-bottom": 1,
"padding-left": 1,
"border": 1,
"border-top": 1,
"border-right": 1,
"border-left": 1,
"border-bottom": 1
};
var functions = {
"rgb": 1,
"rgba": 1
};
var constants = {
"absolute": 1,
"relative": 1,
"fixed": 1,
"solid": 1,
"hidden": 1,
"scroll": 1,
"no-wrap": 1
};
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
function ic(str) {
var re = [];
var chars = str.split("");
for (var i=0; i<chars.length; i++) {
re.push(
"[",
chars[i].toLowerCase(),
chars[i].toUpperCase(),
"]"
);
}
return re.join("");
}
this.$rules = {
"start" : [ {
token : "comment", // multi line comment
regex : "\\/\\*",
next : "comment"
}, {
token : "string", // single line
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
}, {
token : "string", // single line
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
}, {
token : "number",
regex : numRe + ic("em")
}, {
token : "number",
regex : numRe + ic("ex")
}, {
token : "number",
regex : numRe + ic("px")
}, {
token : "number",
regex : numRe + ic("cm")
}, {
token : "number",
regex : numRe + ic("mm")
}, {
token : "number",
regex : numRe + ic("in")
}, {
token : "number",
regex : numRe + ic("pt")
}, {
token : "number",
regex : numRe + ic("pc")
}, {
token : "number",
regex : numRe + ic("deg")
}, {
token : "number",
regex : numRe + ic("rad")
}, {
token : "number",
regex : numRe + ic("grad")
}, {
token : "number",
regex : numRe + ic("ms")
}, {
token : "number",
regex : numRe + ic("s")
}, {
token : "number",
regex : numRe + ic("hz")
}, {
token : "number",
regex : numRe + ic("khz")
}, {
token : "number",
regex : numRe + "%"
}, {
token : "number",
regex : numRe
}, {
token : "number", // hex6 color
regex : "#[a-fA-F0-9]{6}"
}, {
token : "number", // hex3 color
regex : "#[a-fA-F0-9]{3}"
}, {
token : "lparen",
regex : "\{"
}, {
token : "rparen",
regex : "\}"
}, {
token : function(value) {
if (properties[value.toLowerCase()]) {
return "buildin-constant";
}
else if (functions[value.toLowerCase()]) {
return "buildin-function";
}
else if (constants[value.toLowerCase()]) {
return "library-constant";
}
else {
return "identifier";
}
},
regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
}],
"comment" : [{
token : "comment", // closing comment
regex : ".*?\\*\\/",
next : "start"
}, {
token : "comment", // comment spanning whole line
regex : ".+"
}]
};
};
(function() {
this.getRules = function() {
return this.$rules;
};
}).call(ace.mode.CssHighlightRules.prototype);

41
src/ace/mode/Html.js Normal file
View file

@ -0,0 +1,41 @@
ace.provide("ace.mode.Html");
ace.mode.Html = function() {
this.$tokenizer = new ace.Tokenizer(new ace.mode.HtmlHighlightRules().getRules());
this.$js = new ace.mode.JavaScript();
this.$css = new ace.mode.Css();
};
ace.inherits(ace.mode.Html, ace.mode.Text);
(function() {
this.toggleCommentLines = function(doc, range, state) {
var split = state.split("js-");
if (!split[0] && split[1]) {
return this.$js.toggleCommentLines(doc, range, state);
}
var split = state.split("css-");
if (!split[0] && split[1]) {
return this.$css.toggleCommentLines(doc, range, state);
}
return 0;
};
this.getNextLineIndent = function(line, state, tab) {
var split = state.split("js-");
if (!split[0] && split[1]) {
return this.$js.getNextLineIndent(line, split[1], tab);
}
var split = state.split("css-");
if (!split[0] && split[1]) {
return this.$css.getNextLineIndent(line, split[1], tab);
}
return "";
};
}).call(ace.mode.Html.prototype);

View file

@ -0,0 +1,152 @@
ace.provide("ace.mode.HtmlHighlightRules");
ace.mode.HtmlHighlightRules = function() {
// regexp must not have capturing parentheses
// regexps are ordered -> the first match is used
this.$rules = {
start : [ {
token : "text",
regex : "<\\!\\[CDATA\\[",
next : "cdata"
}, {
token : "xml_pe",
regex : "<\\?.*?\\?>"
}, {
token : "comment",
regex : "<\\!--",
next : "comment"
}, {
token : "text",
regex : "<(?=\s*script)",
next : "script"
}, {
token : "text",
regex : "<(?=\s*style)",
next : "css"
}, {
token : "text", // opening tag
regex : "<\\/?",
next : "tag"
}, {
token : "text",
regex : "\\s+"
}, {
token : "text",
regex : "[^<]+"
} ],
script : [ {
token : "text",
regex : ">",
next : "js-start"
}, {
token : "keyword",
regex : "[-_a-zA-Z0-9:]+"
}, {
token : "text",
regex : "\\s+"
}, {
token : "string",
regex : '".*?"'
}, {
token : "string",
regex : "'.*?'"
} ],
css : [ {
token : "text",
regex : ">",
next : "css-start"
}, {
token : "keyword",
regex : "[-_a-zA-Z0-9:]+"
}, {
token : "text",
regex : "\\s+"
}, {
token : "string",
regex : '".*?"'
}, {
token : "string",
regex : "'.*?'"
} ],
tag : [ {
token : "text",
regex : ">",
next : "start"
}, {
token : "keyword",
regex : "[-_a-zA-Z0-9:]+"
}, {
token : "text",
regex : "\\s+"
}, {
token : "string",
regex : '".*?"'
}, {
token : "string",
regex : "'.*?'"
} ],
cdata : [ {
token : "text",
regex : "\\]\\]>",
next : "start"
}, {
token : "text",
regex : "\\s+"
}, {
token : "text",
regex : ".+"
} ],
comment : [ {
token : "comment",
regex : ".*?-->",
next : "start"
}, {
token : "comment",
regex : ".+"
} ]
};
var jsRules = new ace.mode.JavaScriptHighlightRules().getRules();
this.$addRules(jsRules, "js-");
this.$rules["js-start"].unshift({
token: "text",
regex: "<\\/(?=script)",
next: "tag"
});
var cssRules = new ace.mode.CssHighlightRules().getRules();
this.$addRules(cssRules, "css-");
this.$rules["css-start"].unshift({
token: "text",
regex: "<\\/(?=style)",
next: "tag"
});
};
(function() {
this.$addRules = function(rules, prefix) {
for (var key in rules) {
var state = rules[key];
for (var i=0; i<state.length; i++) {
var rule = state[i];
if (rule.next) {
rule.next = prefix + rule.next;
}
}
this.$rules[prefix + key] = state;
}
};
this.getRules = function() {
return this.$rules;
};
}).call(ace.mode.HtmlHighlightRules.prototype);

Some files were not shown because too many files have changed in this diff Show more