diff --git a/Makefile.dryice.js b/Makefile.dryice.js
index 49bf0b28..f8e1383c 100755
--- a/Makefile.dryice.js
+++ b/Makefile.dryice.js
@@ -293,27 +293,30 @@ function getWriteFilters(options, projectType, main) {
if (options.noconflict)
filters.push(namespace(options.ns));
-
+
+ if (options.exportModule && projectType == "main" || projectType == "ext") {
+ filters.push(exportAce(options.ns, options.exportModule,
+ options.noconflict ? options.ns : "", projectType == "ext" && main));
+ }
+
if (options.compress)
filters.push(copy.filter.uglifyjs);
- // copy.filter.uglifyjs.options.ascii = true; doesn't work with some uglify.js versions
+ // copy.filter.uglifyjs.options.ascii_only = true; doesn't work with some uglify.js versions
filters.push(function(text) {
- var t1 = text.replace(/[\x80-\uffff]/g, function(c) {
+ var text = text.replace(/[\x00-\x08\x0b\x0c\x0e\x19\x80-\uffff]/g, function(c) {
c = c.charCodeAt(0).toString(16);
+ if (c.length == 1)
+ return "\\x0" + c;
if (c.length == 2)
return "\\x" + c;
if (c.length == 3)
- c = "0" + c;
+ return "\\u0" + c;
return "\\u" + c;
});
return text;
});
- if (options.exportModule && projectType == "main" || projectType == "ext") {
- filters.push(exportAce(options.ns, options.exportModule,
- options.noconflict ? options.ns : "", projectType == "ext" && main));
- }
return filters;
}
@@ -550,15 +553,6 @@ var detectTextModules = function(input, source) {
detectTextModules.onRead = true;
copy.filter.addDefines = detectTextModules;
-function generateThemesModule(themes) {
- var themelist = [
- 'define(function(require, exports, module) {',
- '\n\nmodule.exports.themes = ' + JSON.stringify(themes, null, ' '),
- ';\n\n});'
- ].join('');
- fs.writeFileSync(__dirname + '/lib/ace/ext/themelist_utils/themes.js', themelist, 'utf8');
-}
-
function inlineTextModules(text) {
var deps = [];
return text.replace(/, *['"]ace\/requirejs\/text!(.*?)['"]| require\(['"](?:ace|[.\/]+)\/requirejs\/text!(.*?)['"]\)/g, function(_, dep, call) {
@@ -574,14 +568,38 @@ function inlineTextModules(text) {
});
call = textModules[dep];
- // if (deps.length > 1)
- // console.log(call.length)
if (call)
return " " + call;
}
});
}
+var CommonJsProject = copy.createCommonJsProject({roots:[]}).constructor;
+CommonJsProject.prototype.getCurrentModules = function() {
+ function isDep(child, parent) {
+ if (!modules[parent])
+ return false;
+ var deps = modules[parent].deps;
+ if (deps[child]) return true;
+ return Object.keys(deps).some(function(x) {
+ return isDep(child, x)
+ });
+ }
+ var depMap = {}, modules = this.currentModules;
+ return Object.keys(this.currentModules).map(function(moduleName) {
+ module = modules[moduleName];
+ module.id = moduleName;
+ module.isSpecial = !/define\(\'[^']*',/.test(module.source);
+ return module;
+ }).sort(function(a, b) {
+ if (a.isSpecial) return -1;
+ if (b.isSpecial) return 1;
+ if (isDep(a.id, b.id)) return -1;
+ if (isDep(b.id, a.id)) return 1;
+ return Object.keys(a.deps).length - Object.keys(b.deps).length || a.id.localeCompare(b.id)
+ });
+};
+
// TODO: replace with project.clone once it is fixed in dryice
function cloneProject(project) {
var clone = copy.createCommonJsProject({
@@ -602,16 +620,12 @@ function cloneProject(project) {
}
function copyFileSync(srcFile, destFile) {
- var BUF_LENGTH = 64*1024,
- buf = new Buffer(BUF_LENGTH),
- bytesRead = BUF_LENGTH,
- pos = 0,
- fdr = null,
- fdw = null;
-
-
- fdr = fs.openSync(srcFile, 'r');
- fdw = fs.openSync(destFile, 'w');
+ var BUF_LENGTH = 64*1024;
+ var buf = new Buffer(BUF_LENGTH);
+ var bytesRead = BUF_LENGTH;
+ var pos = 0;
+ var fdr = fs.openSync(srcFile, 'r');
+ var fdw = fs.openSync(destFile, 'w');
while (bytesRead === BUF_LENGTH) {
bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
@@ -652,13 +666,12 @@ function exportAce(ns, module, requireBase, extModule) {
requireBase = requireBase || "window";
module = module || "ace/ace";
return function(text) {
-
var template = function() {
(function() {
REQUIRE_NS.require(["MODULE"], function(a) {
- a && a.config.init();
+ a && a.config.init(true);
if (!window.NS)
- window.NS = {};
+ window.NS = a;
for (var key in a) if (a.hasOwnProperty(key))
NS[key] = a[key];
});
@@ -674,6 +687,8 @@ function exportAce(ns, module, requireBase, extModule) {
};
}
+ text = text.replace(/function init\(packaged\) {/, "init(true);$&\n");
+
return (text + ";" + template
.toString()
.replace(/MODULE/g, module)
@@ -696,6 +711,15 @@ function updateModes() {
})
}
+function generateThemesModule(themes) {
+ var themelist = [
+ 'define(function(require, exports, module) {',
+ '\n\nmodule.exports.themes = ' + JSON.stringify(themes, null, ' '),
+ ';\n\n});'
+ ].join('');
+ fs.writeFileSync(__dirname + '/lib/ace/ext/themelist_utils/themes.js', themelist, 'utf8');
+}
+
if (!module.parent)
main(process.argv);
else
diff --git a/lib/ace/autocomplete/popup.js b/lib/ace/autocomplete/popup.js
index ca40cad1..02ef21ee 100644
--- a/lib/ace/autocomplete/popup.js
+++ b/lib/ace/autocomplete/popup.js
@@ -86,8 +86,7 @@ var AcePopup = function(parentNode) {
popup.on("mousedown", function(e) {
var pos = e.getDocumentPosition();
- popup.moveCursorToPosition(pos);
- popup.selection.clearSelection();
+ popup.selection.moveToPosition(pos);
selectionMarker.start.row = selectionMarker.end.row = pos.row;
e.stop();
});
diff --git a/lib/ace/config.js b/lib/ace/config.js
index f8614c1a..1d927e45 100644
--- a/lib/ace/config.js
+++ b/lib/ace/config.js
@@ -144,8 +144,8 @@ exports.loadModule = function(moduleName, onLoad) {
// initialization
-exports.init = function() {
- options.packaged = require.packaged || module.packaged || (global.define && define.packaged);
+function init(packaged) {
+ options.packaged = packaged || require.packaged || module.packaged || (global.define && define.packaged);
if (!global.document)
return "";
@@ -190,6 +190,8 @@ exports.init = function() {
exports.set(key, scriptOptions[key]);
};
+exports.init = init;
+
function deHyphenate(str) {
return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
}
diff --git a/lib/ace/document.js b/lib/ace/document.js
index 24d82cc3..a2ca7210 100644
--- a/lib/ace/document.js
+++ b/lib/ace/document.js
@@ -56,7 +56,7 @@ var Document = function(text) {
// There has to be one line at least in the document. If you pass an empty
// string to the insert function, nothing will happen. Workaround.
- if (text.length == 0) {
+ if (text.length === 0) {
this.$lines = [""];
} else if (Array.isArray(text)) {
this._insertLines(0, text);
@@ -107,10 +107,10 @@ var Document = function(text) {
**/
// check for IE split bug
- if ("aaa".split(/a/).length == 0)
+ if ("aaa".split(/a/).length === 0)
this.$split = function(text) {
return text.replace(/\r\n|\r/g, "\n").split("\n");
- }
+ };
else
this.$split = function(text) {
return text.split(/\r\n|\r|\n/);
@@ -120,6 +120,7 @@ var Document = function(text) {
this.$detectNewLine = function(text) {
var match = text.match(/^.*?(\r\n|\r|\n)/m);
this.$autoNewLine = match ? match[1] : "\n";
+ this._signal("changeNewLineMode");
};
/**
@@ -136,11 +137,11 @@ var Document = function(text) {
case "unix":
return "\n";
default:
- return this.$autoNewLine;
+ return this.$autoNewLine || "\n";
}
};
- this.$autoNewLine = "\n";
+ this.$autoNewLine = "";
this.$newLineMode = "auto";
/**
* [Sets the new line mode.]{: #Document.setNewLineMode.desc}
@@ -152,6 +153,7 @@ var Document = function(text) {
return;
this.$newLineMode = newLineMode;
+ this._signal("changeNewLineMode");
};
/**
@@ -311,9 +313,10 @@ var Document = function(text) {
// apply doesn't work for big arrays (smallest threshold is on safari 0xFFFF)
// to circumvent that we have to break huge inserts into smaller chunks here
- if (lines.length > 0xFFFF) {
- var end = this._insertLines(row, lines.slice(0xFFFF));
- lines = lines.slice(0, 0xFFFF);
+ while (lines.length > 0xF000) {
+ var end = this._insertLines(row, lines.slice(0, 0xF000));
+ lines = lines.slice(0xF000);
+ row = end.row;
}
var args = [row, 0];
@@ -327,7 +330,7 @@ var Document = function(text) {
lines: lines
};
this._signal("change", { data: delta });
- return end || range.end;
+ return range.end;
};
/**
diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js
index 8f772db7..9689ea5c 100644
--- a/lib/ace/edit_session.js
+++ b/lib/ace/edit_session.js
@@ -281,13 +281,13 @@ var EditSession = function(text, mode) {
**/
this.setValue = function(text) {
this.doc.setValue(text);
- this.selection.moveCursorTo(0, 0);
- this.selection.clearSelection();
+ this.selection.moveTo(0, 0);
this.$resetRowCache(0);
this.$deltas = [];
this.$deltasDoc = [];
this.$deltasFold = [];
+ this.setUndoManager(this.$undoManager);
this.getUndoManager().reset();
};
@@ -412,7 +412,7 @@ var EditSession = function(text, mode) {
}
self.mergeUndoDeltas = false;
self.$deltas = [];
- }
+ };
this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager);
}
};
@@ -470,7 +470,7 @@ var EditSession = function(text, mode) {
* @param {Number} tabSize The new tab size
**/
this.setTabSize = function(tabSize) {
- this.setOption("tabSize", tabSize)
+ this.setOption("tabSize", tabSize);
};
/**
* Returns the current tab size.
@@ -486,7 +486,7 @@ var EditSession = function(text, mode) {
*
**/
this.isTabStop = function(position) {
- return this.$useSoftTabs && (position.column % this.$tabSize == 0);
+ return this.$useSoftTabs && (position.column % this.$tabSize === 0);
};
this.$overwrite = false;
@@ -500,7 +500,7 @@ var EditSession = function(text, mode) {
*
**/
this.setOverwrite = function(overwrite) {
- this.setOption("overwrite", overwrite)
+ this.setOption("overwrite", overwrite);
};
/**
@@ -622,14 +622,14 @@ var EditSession = function(text, mode) {
clazz : clazz,
inFront: !!inFront,
id: id
- }
+ };
if (inFront) {
this.$frontMarkers[id] = marker;
- this._signal("changeFrontMarker")
+ this._signal("changeFrontMarker");
} else {
this.$backMarkers[id] = marker;
- this._signal("changeBackMarker")
+ this._signal("changeBackMarker");
}
return id;
@@ -652,10 +652,10 @@ var EditSession = function(text, mode) {
if (inFront) {
this.$frontMarkers[id] = marker;
- this._signal("changeFrontMarker")
+ this._signal("changeFrontMarker");
} else {
this.$backMarkers[id] = marker;
- this._signal("changeBackMarker")
+ this._signal("changeBackMarker");
}
return marker;
@@ -696,7 +696,7 @@ var EditSession = function(text, mode) {
this.$searchHighlight = this.addDynamicMarker(highlight);
}
this.$searchHighlight.setRegexp(re);
- }
+ };
// experimental
this.highlightLines = function(startRow, endRow, clazz, inFront) {
@@ -1043,14 +1043,14 @@ var EditSession = function(text, mode) {
};
this.getLineWidgetMaxWidth = function() {
- if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth
+ if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth;
var width = 0;
this.lineWidgets.forEach(function(w) {
if (w && w.screenWidth > width)
width = w.screenWidth;
});
return this.lineWidgetWidth = width;
- }
+ };
this.$computeWidth = function(force) {
if (this.$modified || force) {
@@ -1268,7 +1268,7 @@ var EditSession = function(text, mode) {
// Check if this range and the last undo range has something in common.
// If true, merge the ranges.
if (lastUndoRange != null) {
- if (Range.comparePoints(lastUndoRange.start, range.start) == 0) {
+ if (Range.comparePoints(lastUndoRange.start, range.start) === 0) {
lastUndoRange.start.column += range.end.column - range.start.column;
lastUndoRange.end.column += range.end.column - range.start.column;
}
@@ -1556,10 +1556,7 @@ var EditSession = function(text, mode) {
// If wrapMode is activaed, the wrapData array has to be initialized.
if (useWrapMode) {
var len = this.getLength();
- this.$wrapData = [];
- for (var i = 0; i < len; i++) {
- this.$wrapData.push([]);
- }
+ this.$wrapData = Array(len);
this.$updateWrapData(0, len - 1);
}
@@ -1719,16 +1716,10 @@ var EditSession = function(text, mode) {
lastRow = firstRow;
} else {
- var args;
- if (useWrapMode) {
- args = [firstRow, 0];
- for (var i = 0; i < len; i++) args.push([]);
- this.$wrapData.splice.apply(this.$wrapData, args);
- } else {
- args = Array(len);
- args.unshift(firstRow, 0);
- this.$rowLengthCache.splice.apply(this.$rowLengthCache, args);
- }
+ var args = Array(len);
+ args.unshift(firstRow, 0);
+ var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache
+ arr.splice.apply(arr, args);
// If some new line is added inside of a foldLine, then split
// the fold line up.
@@ -1833,8 +1824,7 @@ var EditSession = function(text, mode) {
lines[foldLine.end.row].length + 1
);
- wrapData[foldLine.start.row]
- = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
+ wrapData[foldLine.start.row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);
row = foldLine.end.row + 1;
}
}
@@ -2023,9 +2013,6 @@ var EditSession = function(text, mode) {
* The first position indicates the number of columns for `str` on screen.
* The second value contains the position of the document column that this function read until.
*
- *
- *
- *
**/
this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {
if (maxScreenColumn == 0)
@@ -2326,14 +2313,16 @@ var EditSession = function(text, mode) {
// Clamp textLine if in wrapMode.
if (this.$useWrapMode) {
var wrapRow = this.$wrapData[foldStartRow];
- var screenRowOffset = 0;
- while (textLine.length >= wrapRow[screenRowOffset]) {
- screenRow ++;
- screenRowOffset++;
+ if (wrapRow) {
+ var screenRowOffset = 0;
+ while (textLine.length >= wrapRow[screenRowOffset]) {
+ screenRow ++;
+ screenRowOffset++;
+ }
+ textLine = textLine.substring(
+ wrapRow[screenRowOffset - 1] || 0, textLine.length
+ );
}
- textLine = textLine.substring(
- wrapRow[screenRowOffset - 1] || 0, textLine.length
- );
}
return {
@@ -2387,7 +2376,8 @@ var EditSession = function(text, mode) {
var foldStart = fold ? fold.start.row :Infinity;
while (row < lastRow) {
- screenRows += this.$wrapData[row].length + 1;
+ var splits = this.$wrapData[row];
+ screenRows += splits ? splits.length + 1 : 1;
row ++;
if (row > foldStart) {
row = fold.end.row+1;
@@ -2403,14 +2393,17 @@ var EditSession = function(text, mode) {
return screenRows;
};
-
- // For every keystroke this gets called once per char in the whole doc!!
- // Wouldn't hurt to make it a bit faster for c >= 0x1100
-
+
/**
* @private
*
*/
+ this.$setFontMetrics = function(fm) {
+ // todo
+ }
+
+ // For every keystroke this gets called once per char in the whole doc!!
+ // Wouldn't hurt to make it a bit faster for c >= 0x1100
function isFullWidth(c) {
if (c < 0x1100)
return false;
diff --git a/lib/ace/editor.js b/lib/ace/editor.js
index 06ce384b..300e4399 100644
--- a/lib/ace/editor.js
+++ b/lib/ace/editor.js
@@ -289,14 +289,13 @@ var Editor = function(renderer, session) {
* Sets a new editsession to use. This method also emits the `'changeSession'` event.
* @param {EditSession} session The new session to use
*
- *
**/
this.setSession = function(session) {
if (this.session == session)
return;
- if (this.session) {
- var oldSession = this.session;
+ var oldSession = this.session;
+ if (oldSession) {
this.session.removeEventListener("change", this.$onDocumentChange);
this.session.removeEventListener("changeMode", this.$onChangeMode);
this.session.removeEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
@@ -318,76 +317,80 @@ var Editor = function(renderer, session) {
}
this.session = session;
-
- this.$onDocumentChange = this.onDocumentChange.bind(this);
- session.addEventListener("change", this.$onDocumentChange);
- this.renderer.setSession(session);
-
- this.$onChangeMode = this.onChangeMode.bind(this);
- session.addEventListener("changeMode", this.$onChangeMode);
-
- this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);
- session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
-
- this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer);
- session.addEventListener("changeTabSize", this.$onChangeTabSize);
-
- this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);
- session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit);
-
- this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);
- session.addEventListener("changeWrapMode", this.$onChangeWrapMode);
-
- this.$onChangeFold = this.onChangeFold.bind(this);
- session.addEventListener("changeFold", this.$onChangeFold);
-
- this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
- this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker);
-
- this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
- this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker);
-
- this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
- this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint);
-
- this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
- this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation);
-
- this.$onCursorChange = this.onCursorChange.bind(this);
- this.session.addEventListener("changeOverwrite", this.$onCursorChange);
-
- this.$onScrollTopChange = this.onScrollTopChange.bind(this);
- this.session.addEventListener("changeScrollTop", this.$onScrollTopChange);
-
- this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);
- this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange);
-
- this.selection = session.getSelection();
- this.selection.addEventListener("changeCursor", this.$onCursorChange);
-
- this.$onSelectionChange = this.onSelectionChange.bind(this);
- this.selection.addEventListener("changeSelection", this.$onSelectionChange);
-
- this.onChangeMode();
-
- this.$blockScrolling += 1;
- this.onCursorChange();
- this.$blockScrolling -= 1;
-
- this.onScrollTopChange();
- this.onScrollLeftChange();
- this.onSelectionChange();
- this.onChangeFrontMarker();
- this.onChangeBackMarker();
- this.onChangeBreakpoint();
- this.onChangeAnnotation();
- this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();
- this.renderer.updateFull();
+ if (session) {
+ this.$onDocumentChange = this.onDocumentChange.bind(this);
+ session.addEventListener("change", this.$onDocumentChange);
+ this.renderer.setSession(session);
+
+ this.$onChangeMode = this.onChangeMode.bind(this);
+ session.addEventListener("changeMode", this.$onChangeMode);
+
+ this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);
+ session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate);
+
+ this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer);
+ session.addEventListener("changeTabSize", this.$onChangeTabSize);
+
+ this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);
+ session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit);
+
+ this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);
+ session.addEventListener("changeWrapMode", this.$onChangeWrapMode);
+
+ this.$onChangeFold = this.onChangeFold.bind(this);
+ session.addEventListener("changeFold", this.$onChangeFold);
+
+ this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);
+ this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker);
+
+ this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);
+ this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker);
+
+ this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);
+ this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint);
+
+ this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);
+ this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation);
+
+ this.$onCursorChange = this.onCursorChange.bind(this);
+ this.session.addEventListener("changeOverwrite", this.$onCursorChange);
+
+ this.$onScrollTopChange = this.onScrollTopChange.bind(this);
+ this.session.addEventListener("changeScrollTop", this.$onScrollTopChange);
+
+ this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);
+ this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange);
+
+ this.selection = session.getSelection();
+ this.selection.addEventListener("changeCursor", this.$onCursorChange);
+
+ this.$onSelectionChange = this.onSelectionChange.bind(this);
+ this.selection.addEventListener("changeSelection", this.$onSelectionChange);
+
+ this.onChangeMode();
+
+ this.$blockScrolling += 1;
+ this.onCursorChange();
+ this.$blockScrolling -= 1;
+
+ this.onScrollTopChange();
+ this.onScrollLeftChange();
+ this.onSelectionChange();
+ this.onChangeFrontMarker();
+ this.onChangeBackMarker();
+ this.onChangeBreakpoint();
+ this.onChangeAnnotation();
+ this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();
+ this.renderer.updateFull();
+ }
this._signal("changeSession", {
session: session,
oldSession: oldSession
});
+
+ oldSession && oldSession._signal("changeEditor", {oldEditor: this});
+ session && session._signal("changeEditor", {editor: this});
};
/**
@@ -660,7 +663,7 @@ var Editor = function(renderer, session) {
if (this.$highlightActiveLine) {
if ((this.$selectionStyle != "line" || !this.selection.isMultiLine()))
highlight = this.getCursorPosition();
- if (this.renderer.$maxLines && this.session.getLength() === 1)
+ if (this.renderer.$maxLines && this.session.getLength() === 1 && !(this.renderer.$minLines > 1))
highlight = false;
}
@@ -846,14 +849,13 @@ var Editor = function(renderer, session) {
* Inserts `text` into wherever the cursor is pointing.
* @param {String} text The new text to add
*
- *
**/
- this.insert = function(text) {
+ this.insert = function(text, pasted) {
var session = this.session;
var mode = session.getMode();
var cursor = this.getCursorPosition();
- if (this.getBehavioursEnabled()) {
+ if (this.getBehavioursEnabled() && !pasted) {
// Get a transform if the current mode wants one.
var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text);
if (transform) {
@@ -1942,8 +1944,7 @@ var Editor = function(renderer, session) {
else
this.selection.selectTo(pos.row, pos.column);
} else {
- this.clearSelection();
- this.moveCursorTo(pos.row, pos.column);
+ this.selection.moveTo(pos.row, pos.column);
}
}
};
@@ -1978,8 +1979,7 @@ var Editor = function(renderer, session) {
* @related Editor.moveCursorTo
**/
this.navigateTo = function(row, column) {
- this.clearSelection();
- this.moveCursorTo(row, column);
+ this.selection.moveTo(row, column);
};
/**
@@ -1994,8 +1994,7 @@ var Editor = function(renderer, session) {
return this.moveCursorToPosition(selectionStart);
}
this.selection.clearSelection();
- times = times || 1;
- this.selection.moveCursorBy(-times, 0);
+ this.selection.moveCursorBy(-times || -1, 0);
};
/**
@@ -2010,8 +2009,7 @@ var Editor = function(renderer, session) {
return this.moveCursorToPosition(selectionEnd);
}
this.selection.clearSelection();
- times = times || 1;
- this.selection.moveCursorBy(times, 0);
+ this.selection.moveCursorBy(times || 1, 0);
};
/**
@@ -2155,8 +2153,7 @@ var Editor = function(renderer, session) {
this.$blockScrolling += 1;
var selection = this.getSelectionRange();
- this.clearSelection();
- this.selection.moveCursorTo(0, 0);
+ this.selection.moveTo(0, 0);
for (var i = ranges.length - 1; i >= 0; --i) {
if(this.$tryReplace(ranges[i], replacement)) {
diff --git a/lib/ace/ext/emmet.js b/lib/ace/ext/emmet.js
index 6647da40..896a66d8 100644
--- a/lib/ace/ext/emmet.js
+++ b/lib/ace/ext/emmet.js
@@ -130,8 +130,7 @@ AceEmmetEditor.prototype = {
*/
setCaretPos: function(index){
var pos = this.ace.indexToPosition(index);
- this.ace.clearSelection();
- this.ace.selection.moveCursorToPosition(pos);
+ this.ace.selection.moveToPosition(pos);
},
/**
diff --git a/lib/ace/ext/error_marker.js b/lib/ace/ext/error_marker.js
index 5e87529e..2f5466b0 100644
--- a/lib/ace/ext/error_marker.js
+++ b/lib/ace/ext/error_marker.js
@@ -122,8 +122,7 @@ exports.showErrorMarker = function(editor, dir) {
};
}
editor.session.unfold(pos.row);
- editor.selection.moveCursorToPosition(pos);
- editor.selection.clearSelection();
+ editor.selection.moveToPosition(pos);
var w = {
row: pos.row,
@@ -143,12 +142,12 @@ exports.showErrorMarker = function(editor, dir) {
el.className = "error_widget " + gutterAnno.className;
el.innerHTML = gutterAnno.text.join("
");
- var kb = {
- handleKeyboard:function(_,hashId, keyString) {
- if (hashId === 0 && keyString === "esc") {
- w.destroy();
- return true;
- }
+ el.appendChild(dom.createElement("div"));
+
+ var kb = function(_, hashId, keyString) {
+ if (hashId === 0 && (keyString === "esc" || keyString === "return")) {
+ w.destroy();
+ return {command: "null"};
}
};
diff --git a/lib/ace/keyboard/vim.js b/lib/ace/keyboard/vim.js
index fdd88117..3ae4842f 100644
--- a/lib/ace/keyboard/vim.js
+++ b/lib/ace/keyboard/vim.js
@@ -145,8 +145,8 @@ exports.handler = {
if (hashId == -1 || hashId == 1 || hashId === 0 && key.length > 1) {
if (cmds.inputBuffer.idle && startCommands[key])
return startCommands[key];
- cmds.inputBuffer.push(editor, key);
- return {command: "null", passEvent: false};
+ var isHandled = cmds.inputBuffer.push(editor, key);
+ return {command: "null", passEvent: !isHandled};
} // if no modifier || shift: wait for input.
else if (key.length == 1 && (hashId === 0 || hashId == 4)) {
return {command: "null", passEvent: true};
diff --git a/lib/ace/keyboard/vim/commands.js b/lib/ace/keyboard/vim/commands.js
index dd3357d6..e48446f4 100644
--- a/lib/ace/keyboard/vim/commands.js
+++ b/lib/ace/keyboard/vim/commands.js
@@ -201,8 +201,7 @@ var actions = exports.actions = {
//editor.selection.selectLine();
//editor.selection.selectLeft();
var row = editor.getCursorPosition().row;
- editor.selection.clearSelection();
- editor.selection.moveCursorTo(row, 0);
+ editor.selection.moveTo(row, 0);
editor.selection.selectLineEnd();
editor.selection.visualLineStart = row;
@@ -582,13 +581,11 @@ var handleCursorMove = exports.onCursorMove = function(editor, e) {
var cursorRow = editor.getCursorPosition().row;
if(originRow <= cursorRow) {
var endLine = editor.session.getLine(cursorRow);
- editor.selection.clearSelection();
- editor.selection.moveCursorTo(originRow, 0);
+ editor.selection.moveTo(originRow, 0);
editor.selection.selectTo(cursorRow, endLine.length);
} else {
var endLine = editor.session.getLine(originRow);
- editor.selection.clearSelection();
- editor.selection.moveCursorTo(originRow, endLine.length);
+ editor.selection.moveTo(originRow, endLine.length);
editor.selection.selectTo(cursorRow, 0);
}
}
diff --git a/lib/ace/keyboard/vim/maps/motions.js b/lib/ace/keyboard/vim/maps/motions.js
index ae457d54..630ba66a 100644
--- a/lib/ace/keyboard/vim/maps/motions.js
+++ b/lib/ace/keyboard/vim/maps/motions.js
@@ -53,8 +53,7 @@ function Motion(m) {
var a = getPos(editor, range, count, param, false);
if (!a)
return;
- editor.clearSelection();
- editor.moveCursorTo(a.row, a.column);
+ editor.selection.moveTo(a.row, a.column);
};
m.sel = function(editor, range, count, param) {
var a = getPos(editor, range, count, param, true);
diff --git a/lib/ace/keyboard/vim/maps/util.js b/lib/ace/keyboard/vim/maps/util.js
index af0e07c7..a216c2cc 100644
--- a/lib/ace/keyboard/vim/maps/util.js
+++ b/lib/ace/keyboard/vim/maps/util.js
@@ -122,13 +122,11 @@ module.exports = {
},
copyLine: function(editor) {
var pos = editor.getCursorPosition();
- editor.selection.clearSelection();
- editor.moveCursorTo(pos.row, pos.column);
+ editor.selection.moveTo(pos.row, pos.column);
editor.selection.selectLine();
registers._default.isLine = true;
registers._default.text = editor.getCopyText().replace(/\n$/, "");
- editor.selection.clearSelection();
- editor.moveCursorTo(pos.row, pos.column);
+ editor.selection.moveTo(pos.row, pos.column);
}
};
});
diff --git a/lib/ace/layer/cursor.js b/lib/ace/layer/cursor.js
index aaf3ffec..4578482a 100644
--- a/lib/ace/layer/cursor.js
+++ b/lib/ace/layer/cursor.js
@@ -190,7 +190,7 @@ var Cursor = function(parentEl) {
for (var i = 0, n = selections.length; i < n; i++) {
var pixelPos = this.getPixelPosition(selections[i].cursor, true);
if ((pixelPos.top > config.height + config.offset ||
- pixelPos.top < -config.offset) && i > 1) {
+ pixelPos.top < 0) && i > 1) {
continue;
}
diff --git a/lib/ace/layer/font_metrics.js b/lib/ace/layer/font_metrics.js
new file mode 100644
index 00000000..45fa44cb
--- /dev/null
+++ b/lib/ace/layer/font_metrics.js
@@ -0,0 +1,158 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Distributed under the BSD license:
+ *
+ * Copyright (c) 2010, Ajax.org B.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Ajax.org B.V. nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define(function(require, exports, module) {
+
+var oop = require("../lib/oop");
+var dom = require("../lib/dom");
+var lang = require("../lib/lang");
+var EventEmitter = require("../lib/event_emitter").EventEmitter;
+
+var CHAR_COUNT = 0;
+
+var FontMetrics = exports.FontMetrics = function(parentEl, interval) {
+ this.el = dom.createElement("div");
+ this.$setMeasureNodeStyles(this.el.style, true);
+
+ this.$main = dom.createElement("div");
+ this.$setMeasureNodeStyles(this.$main.style);
+
+ this.$measureNode = dom.createElement("div");
+ this.$setMeasureNodeStyles(this.$measureNode.style);
+
+
+ this.el.appendChild(this.$main);
+ this.el.appendChild(this.$measureNode);
+ parentEl.appendChild(this.el);
+
+ if (!CHAR_COUNT)
+ this.$testFractionalRect();
+ this.$measureNode.textContent = lang.stringRepeat("X", CHAR_COUNT);
+
+ this.$characterSize = {width: 0, height: 0};
+ this.checkForSizeChanges();
+};
+
+(function() {
+
+ oop.implement(this, EventEmitter);
+
+ this.$characterSize = {width: 0, height: 0};
+
+ this.$testFractionalRect = function() {
+ var el = dom.createElement("div");
+ this.$setMeasureNodeStyles(el.style);
+ el.style.width = "0.2px";
+ document.documentElement.appendChild(el);
+ var w = el.getBoundingClientRect().width;
+ if (w > 0 && w < 1)
+ CHAR_COUNT = 1;
+ else
+ CHAR_COUNT = 100;
+ el.parentNode.removeChild(el);
+ };
+
+ this.$setMeasureNodeStyles = function(style, isRoot) {
+ style.width = style.height = "auto";
+ style.left = style.top = "-100px";
+ style.visibility = "hidden";
+ style.position = "fixed";
+ style.whiteSpace = "pre";
+ style.font = "inherit";
+ style.overflow = isRoot ? "hidden" : "visible";
+ };
+
+ this.checkForSizeChanges = function() {
+ var size = this.$measureSizes();
+ if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {
+ this.$measureNode.style.fontWeight = "bold";
+ var boldSize = this.$measureSizes();
+ this.$measureNode.style.fontWeight = "";
+ this.$characterSize = size;
+ this.charSizes = Object.create(null);
+ this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height;
+ this._emit("changeCharacterSize", {data: size});
+ }
+ };
+
+ this.$pollSizeChanges = function() {
+ if (this.$pollSizeChangesTimer)
+ return this.$pollSizeChangesTimer;
+ var self = this;
+ return this.$pollSizeChangesTimer = setInterval(function() {
+ self.checkForSizeChanges();
+ }, 500);
+ };
+
+ this.setPolling = function(val) {
+ if (val) {
+ this.$pollSizeChanges();
+ } else {
+ if (this.$pollSizeChangesTimer)
+ this.$pollSizeChangesTimer;
+ }
+ };
+
+ this.$measureSizes = function() {
+ var rect = this.$measureNode.getBoundingClientRect();
+ var size = {
+ height: rect.height,
+ width: rect.width / CHAR_COUNT
+ };
+ // Size and width can be null if the editor is not visible or
+ // detached from the document
+ if (size.width === 0 || size.height === 0)
+ return null;
+ return size;
+ };
+
+ this.$measureCharWidth = function(ch) {
+ this.$main.textContent = lang.stringRepeat(ch, CHAR_COUNT);
+ var rect = this.$main.getBoundingClientRect();
+ return rect.width / CHAR_COUNT;
+ };
+
+ this.getCharacterWidth = function(ch) {
+ var w = this.charSizes[ch];
+ if (w === undefined) {
+ this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width;
+ }
+ return w;
+ };
+
+ this.destroy = function() {
+ clearInterval(this.$pollSizeChangesTimer);
+ if (this.el && this.el.parentNode)
+ this.el.parentNode.removeChild(this.el);
+ };
+
+}).call(FontMetrics.prototype);
+
+});
diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js
index 620a2690..7b206f61 100644
--- a/lib/ace/layer/gutter.js
+++ b/lib/ace/layer/gutter.js
@@ -120,7 +120,8 @@ var Gutter = function(parentEl) {
this.update = function(config) {
var session = this.session;
var firstRow = config.firstRow;
- var lastRow = Math.min(config.lastRow + 1, session.getLength() - 1); // needed to compensate
+ var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar
+ session.getLength() - 1);
var fold = session.getNextFoldLine(firstRow);
var foldStart = fold ? fold.start.row : Infinity;
var foldWidgets = this.$showFoldWidgets && session.foldWidgets;
diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js
index 4290233d..fd81f5ff 100644
--- a/lib/ace/layer/text.js
+++ b/lib/ace/layer/text.js
@@ -41,154 +41,58 @@ var Text = function(parentEl) {
this.element = dom.createElement("div");
this.element.className = "ace_layer ace_text-layer";
parentEl.appendChild(this.element);
-
- this.$characterSize = {width: 0, height: 0};
- this.checkForSizeChanges();
- this.$pollSizeChanges();
+ this.$updateEolChar = this.$updateEolChar.bind(this);
};
(function() {
oop.implement(this, EventEmitter);
- this.EOF_CHAR = "\xB6"; //"¶";
- this.EOL_CHAR = "\xAC"; //"¬";
- this.TAB_CHAR = "\u2192"; //"→" "\u21E5";
- this.SPACE_CHAR = "\xB7"; //"·";
+ this.EOF_CHAR = "\xB6";
+ this.EOL_CHAR_LF = "\xAC";
+ this.EOL_CHAR_CRLF = "\xa4";
+ this.EOL_CHAR = this.EOL_CHAR_LF;
+ this.TAB_CHAR = "\u2192"; //"\u21E5";
+ this.SPACE_CHAR = "\xB7";
this.$padding = 0;
+ this.$updateEolChar = function() {
+ var EOL_CHAR = this.session.doc.getNewLineCharacter() == "\n"
+ ? this.EOL_CHAR_LF
+ : this.EOL_CHAR_CRLF;
+ if (this.EOL_CHAR != EOL_CHAR) {
+ this.EOL_CHAR = EOL_CHAR;
+ return true;
+ }
+ }
+
this.setPadding = function(padding) {
this.$padding = padding;
this.element.style.padding = "0 " + padding + "px";
};
this.getLineHeight = function() {
- return this.$characterSize.height || 0;
+ return this.$fontMetrics.$characterSize.height || 0;
};
this.getCharacterWidth = function() {
- return this.$characterSize.width || 0;
+ return this.$fontMetrics.$characterSize.width || 0;
};
+
+ this.$setFontMetrics = function(measure) {
+ this.$fontMetrics = measure;
+ this.$fontMetrics.on("changeCharacterSize", function(e) {
+ this._signal("changeCharacterSize", e);
+ }.bind(this));
+ this.$pollSizeChanges();
+ }
this.checkForSizeChanges = function() {
- var size = this.$measureSizes();
- if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {
- this.$measureNode.style.fontWeight = "bold";
- var boldSize = this.$measureSizes();
- this.$measureNode.style.fontWeight = "";
- this.$characterSize = size;
- this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height;
- this._emit("changeCharacterSize", {data: size});
- }
+ this.$fontMetrics.checkForSizeChanges();
};
-
this.$pollSizeChanges = function() {
- var self = this;
- this.$pollSizeChangesTimer = setInterval(function() {
- self.checkForSizeChanges();
- }, 500);
+ return this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges();
};
-
- this.$fontStyles = {
- fontFamily : 1,
- fontSize : 1,
- fontWeight : 1,
- fontStyle : 1,
- lineHeight : 1
- };
-
- this.$measureSizes = useragent.isIE || useragent.isOldGecko ? function() {
- var n = 1000;
- if (!this.$measureNode) {
- var measureNode = this.$measureNode = dom.createElement("div");
- var style = measureNode.style;
-
- style.width = style.height = "auto";
- style.left = style.top = (-n * 40) + "px";
-
- style.visibility = "hidden";
- style.position = "fixed";
- style.overflow = "visible";
- style.whiteSpace = "nowrap";
-
- // 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!
- measureNode.innerHTML = lang.stringRepeat("Xy", n);
-
- if (this.element.ownerDocument.body) {
- this.element.ownerDocument.body.appendChild(measureNode);
- } else {
- var container = this.element.parentNode;
- while (!dom.hasCssClass(container, "ace_editor"))
- container = container.parentNode;
- container.appendChild(measureNode);
- }
- }
-
- // Size and width can be null if the editor is not visible or
- // detached from the document
- if (!this.element.offsetWidth)
- return null;
-
- var style = this.$measureNode.style;
- var computedStyle = dom.computedStyle(this.element);
- for (var prop in this.$fontStyles)
- style[prop] = computedStyle[prop];
-
- var size = {
- height: this.$measureNode.offsetHeight,
- width: this.$measureNode.offsetWidth / (n * 2)
- };
-
- // Size and width can be null if the editor is not visible or
- // detached from the document
- if (size.width == 0 || size.height == 0)
- return null;
-
- return size;
- }
- : function() {
- if (!this.$measureNode) {
- var measureNode = this.$measureNode = dom.createElement("div");
- var style = measureNode.style;
-
- style.width = style.height = "auto";
- style.left = style.top = -100 + "px";
-
- style.visibility = "hidden";
- style.position = "fixed";
- style.overflow = "visible";
- style.whiteSpace = "nowrap";
-
- // fixes fractional fixed-width fonts; see http://git.io/CavZNw
- measureNode.innerHTML = lang.stringRepeat("X", 100);
-
- var container = this.element.parentNode;
- while (container && !dom.hasCssClass(container, "ace_editor"))
- container = container.parentNode;
-
- if (!container)
- return this.$measureNode = null;
-
- container.appendChild(measureNode);
- }
-
- var rect = this.$measureNode.getBoundingClientRect();
-
- var size = {
- height: rect.height,
- width: rect.width / 100
- };
-
- // Size and width can be null if the editor is not visible or
- // detached from the document
- if (size.width == 0 || size.height == 0)
- return null;
-
- return size;
- };
-
this.setSession = function(session) {
this.session = session;
this.$computeTabString();
diff --git a/lib/ace/lib/event.js b/lib/ace/lib/event.js
index 6721b19c..9ad0c3ac 100644
--- a/lib/ace/lib/event.js
+++ b/lib/ace/lib/event.js
@@ -33,7 +33,6 @@ define(function(require, exports, module) {
var keys = require("./keys");
var useragent = require("./useragent");
-var dom = require("./dom");
exports.addListener = function(elem, type, callback) {
if (elem.addEventListener) {
@@ -170,7 +169,7 @@ exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbac
};
exports.addListener(el, "mousedown", function(e) {
- if (exports.getButton(e) != 0) {
+ if (exports.getButton(e) !== 0) {
clicks = 0;
} else if (e.detail > 1) {
clicks++;
@@ -210,22 +209,27 @@ exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbac
}
};
-function normalizeCommandKeys(callback, e, keyCode) {
- var hashId = 0;
- if ((useragent.isOpera && !("KeyboardEvent" in window)) && useragent.isMac) {
- hashId = 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0)
- | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0);
- } else {
- hashId = 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0)
- | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0);
+var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window)
+ ? function(e) {
+ return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0);
}
+ : function(e) {
+ return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0);
+ };
+
+exports.getModifierString = function(e) {
+ return keys.KEY_MODS[getModifierHash(e)];
+};
+
+function normalizeCommandKeys(callback, e, keyCode) {
+ var hashId = getModifierHash(e);
if (!useragent.isMac && pressedKeys) {
if (pressedKeys[91] || pressedKeys[92])
hashId |= 8;
if (pressedKeys.altGr) {
if ((3 & hashId) != 3)
- pressedKeys.altGr = 0
+ pressedKeys.altGr = 0;
else
return;
}
@@ -267,12 +271,11 @@ function normalizeCommandKeys(callback, e, keyCode) {
if (!hashId && keyCode === 13) {
if (e.location || e.keyLocation === 3) {
- callback(e, hashId, -keyCode)
+ callback(e, hashId, -keyCode);
if (e.defaultPrevented)
return;
}
}
-
// If there is no hashId and the keyCode is not a function key, then
// we don't call the callback as we don't handle a command key here
@@ -281,8 +284,6 @@ function normalizeCommandKeys(callback, e, keyCode) {
return false;
}
-
-
return callback(e, hashId, keyCode);
}
diff --git a/lib/ace/lib/keys.js b/lib/ace/lib/keys.js
index 916d9f00..78cede51 100644
--- a/lib/ace/lib/keys.js
+++ b/lib/ace/lib/keys.js
@@ -133,6 +133,15 @@ var Keys = (function() {
// workaround for firefox bug
ret[173] = '-';
+
+ (function() {
+ var mods = ["cmd", "ctrl", "alt", "shift"];
+ for (var i = Math.pow(2, mods.length); i--;) {
+ ret.KEY_MODS[i] = mods.filter(function(x) {
+ return i & ret.KEY_MODS[x];
+ }).join("-") + "-";
+ }
+ })();
return ret;
})();
@@ -140,6 +149,6 @@ oop.mixin(exports, Keys);
exports.keyCodeToString = function(keyCode) {
return (Keys[keyCode] || String.fromCharCode(keyCode)).toLowerCase();
-}
+};
});
diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js
index 5bdd997c..2709168e 100644
--- a/lib/ace/mode/behaviour/cstyle.js
+++ b/lib/ace/mode/behaviour/cstyle.js
@@ -41,89 +41,34 @@ var SAFE_INSERT_IN_TOKENS =
var SAFE_INSERT_BEFORE_TOKENS =
["text", "paren.rparen", "punctuation.operator", "comment"];
+var context;
+var contextCache = {}
+var initContext = function(editor) {
+ var id = -1;
+ if (editor.multiSelect) {
+ id = editor.selection.id;
+ if (contextCache.rangeCount != editor.multiSelect.rangeCount)
+ contextCache = {rangeCount: editor.multiSelect.rangeCount};
+ }
+ if (contextCache[id])
+ return context = contextCache[id];
+ context = contextCache[id] = {
+ autoInsertedBrackets: 0,
+ autoInsertedRow: -1,
+ autoInsertedLineEnd: "",
+ maybeInsertedBrackets: 0,
+ maybeInsertedRow: -1,
+ maybeInsertedLineStart: "",
+ maybeInsertedLineEnd: ""
+ };
+};
-var autoInsertedBrackets = 0;
-var autoInsertedRow = -1;
-var autoInsertedLineEnd = "";
-var maybeInsertedBrackets = 0;
-var maybeInsertedRow = -1;
-var maybeInsertedLineStart = "";
-var maybeInsertedLineEnd = "";
-
-var CstyleBehaviour = function () {
-
- CstyleBehaviour.isSaneInsertion = function(editor, session) {
- var cursor = editor.getCursorPosition();
- var iterator = new TokenIterator(session, cursor.row, cursor.column);
-
- // Don't insert in the middle of a keyword/identifier/lexical
- if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) {
- // Look ahead in case we're at the end of a token
- var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1);
- if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS))
- return false;
- }
-
- // Only insert in front of whitespace/comments
- iterator.stepForward();
- return iterator.getCurrentTokenRow() !== cursor.row ||
- this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS);
- };
-
- CstyleBehaviour.$matchTokenType = function(token, types) {
- return types.indexOf(token.type || token) > -1;
- };
-
- CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) {
- var cursor = editor.getCursorPosition();
- var line = session.doc.getLine(cursor.row);
- // Reset previous state if text or context changed too much
- if (!this.isAutoInsertedClosing(cursor, line, autoInsertedLineEnd[0]))
- autoInsertedBrackets = 0;
- autoInsertedRow = cursor.row;
- autoInsertedLineEnd = bracket + line.substr(cursor.column);
- autoInsertedBrackets++;
- };
-
- CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) {
- var cursor = editor.getCursorPosition();
- var line = session.doc.getLine(cursor.row);
- if (!this.isMaybeInsertedClosing(cursor, line))
- maybeInsertedBrackets = 0;
- maybeInsertedRow = cursor.row;
- maybeInsertedLineStart = line.substr(0, cursor.column) + bracket;
- maybeInsertedLineEnd = line.substr(cursor.column);
- maybeInsertedBrackets++;
- };
-
- CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) {
- return autoInsertedBrackets > 0 &&
- cursor.row === autoInsertedRow &&
- bracket === autoInsertedLineEnd[0] &&
- line.substr(cursor.column) === autoInsertedLineEnd;
- };
-
- CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) {
- return maybeInsertedBrackets > 0 &&
- cursor.row === maybeInsertedRow &&
- line.substr(cursor.column) === maybeInsertedLineEnd &&
- line.substr(0, cursor.column) == maybeInsertedLineStart;
- };
-
- CstyleBehaviour.popAutoInsertedClosing = function() {
- autoInsertedLineEnd = autoInsertedLineEnd.substr(1);
- autoInsertedBrackets--;
- };
-
- CstyleBehaviour.clearMaybeInsertedClosing = function() {
- maybeInsertedBrackets = 0;
- maybeInsertedRow = -1;
- };
-
- this.add("braces", "insertion", function (state, action, editor, session, text) {
+var CstyleBehaviour = function() {
+ this.add("braces", "insertion", function(state, action, editor, session, text) {
var cursor = editor.getCursorPosition();
var line = session.doc.getLine(cursor.row);
if (text == '{') {
+ initContext(editor);
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) {
@@ -147,6 +92,7 @@ var CstyleBehaviour = function () {
}
}
} else if (text == '}') {
+ initContext(editor);
var rightChar = line.substring(cursor.column, cursor.column + 1);
if (rightChar == '}') {
var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row});
@@ -159,9 +105,10 @@ var CstyleBehaviour = function () {
}
}
} else if (text == "\n" || text == "\r\n") {
+ initContext(editor);
var closing = "";
if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) {
- closing = lang.stringRepeat("}", maybeInsertedBrackets);
+ closing = lang.stringRepeat("}", context.maybeInsertedBrackets);
CstyleBehaviour.clearMaybeInsertedClosing();
}
var rightChar = line.substring(cursor.column, cursor.column + 1);
@@ -173,6 +120,7 @@ var CstyleBehaviour = function () {
} else if (closing) {
var next_indent = this.$getIndent(line);
} else {
+ CstyleBehaviour.clearMaybeInsertedClosing();
return;
}
var indent = next_indent + session.getTabString();
@@ -186,22 +134,24 @@ var CstyleBehaviour = function () {
}
});
- this.add("braces", "deletion", function (state, action, editor, session, range) {
+ this.add("braces", "deletion", function(state, action, editor, session, range) {
var selected = session.doc.getTextRange(range);
if (!range.isMultiLine() && selected == '{') {
+ initContext(editor);
var line = session.doc.getLine(range.start.row);
var rightChar = line.substring(range.end.column, range.end.column + 1);
if (rightChar == '}') {
range.end.column++;
return range;
} else {
- maybeInsertedBrackets--;
+ context.maybeInsertedBrackets--;
}
}
});
- this.add("parens", "insertion", function (state, action, editor, session, text) {
+ this.add("parens", "insertion", function(state, action, editor, session, text) {
if (text == '(') {
+ initContext(editor);
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
if (selected !== "" && editor.getWrapBehavioursEnabled()) {
@@ -217,6 +167,7 @@ var CstyleBehaviour = function () {
};
}
} else if (text == ')') {
+ initContext(editor);
var cursor = editor.getCursorPosition();
var line = session.doc.getLine(cursor.row);
var rightChar = line.substring(cursor.column, cursor.column + 1);
@@ -233,9 +184,10 @@ var CstyleBehaviour = function () {
}
});
- this.add("parens", "deletion", function (state, action, editor, session, range) {
+ this.add("parens", "deletion", function(state, action, editor, session, range) {
var selected = session.doc.getTextRange(range);
if (!range.isMultiLine() && selected == '(') {
+ initContext(editor);
var line = session.doc.getLine(range.start.row);
var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
if (rightChar == ')') {
@@ -245,8 +197,9 @@ var CstyleBehaviour = function () {
}
});
- this.add("brackets", "insertion", function (state, action, editor, session, text) {
+ this.add("brackets", "insertion", function(state, action, editor, session, text) {
if (text == '[') {
+ initContext(editor);
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
if (selected !== "" && editor.getWrapBehavioursEnabled()) {
@@ -262,6 +215,7 @@ var CstyleBehaviour = function () {
};
}
} else if (text == ']') {
+ initContext(editor);
var cursor = editor.getCursorPosition();
var line = session.doc.getLine(cursor.row);
var rightChar = line.substring(cursor.column, cursor.column + 1);
@@ -278,9 +232,10 @@ var CstyleBehaviour = function () {
}
});
- this.add("brackets", "deletion", function (state, action, editor, session, range) {
+ this.add("brackets", "deletion", function(state, action, editor, session, range) {
var selected = session.doc.getTextRange(range);
if (!range.isMultiLine() && selected == '[') {
+ initContext(editor);
var line = session.doc.getLine(range.start.row);
var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
if (rightChar == ']') {
@@ -290,8 +245,9 @@ var CstyleBehaviour = function () {
}
});
- this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
+ this.add("string_dquotes", "insertion", function(state, action, editor, session, text) {
if (text == '"' || text == "'") {
+ initContext(editor);
var quote = text;
var selection = editor.getSelectionRange();
var selected = session.doc.getTextRange(selection);
@@ -350,9 +306,10 @@ var CstyleBehaviour = function () {
}
});
- this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
+ this.add("string_dquotes", "deletion", function(state, action, editor, session, range) {
var selected = session.doc.getTextRange(range);
if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
+ initContext(editor);
var line = session.doc.getLine(range.start.row);
var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
if (rightChar == selected) {
@@ -364,6 +321,79 @@ var CstyleBehaviour = function () {
};
+
+CstyleBehaviour.isSaneInsertion = function(editor, session) {
+ var cursor = editor.getCursorPosition();
+ var iterator = new TokenIterator(session, cursor.row, cursor.column);
+
+ // Don't insert in the middle of a keyword/identifier/lexical
+ if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) {
+ // Look ahead in case we're at the end of a token
+ var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1);
+ if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS))
+ return false;
+ }
+
+ // Only insert in front of whitespace/comments
+ iterator.stepForward();
+ return iterator.getCurrentTokenRow() !== cursor.row ||
+ this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS);
+};
+
+CstyleBehaviour.$matchTokenType = function(token, types) {
+ return types.indexOf(token.type || token) > -1;
+};
+
+CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) {
+ var cursor = editor.getCursorPosition();
+ var line = session.doc.getLine(cursor.row);
+ // Reset previous state if text or context changed too much
+ if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0]))
+ context.autoInsertedBrackets = 0;
+ context.autoInsertedRow = cursor.row;
+ context.autoInsertedLineEnd = bracket + line.substr(cursor.column);
+ context.autoInsertedBrackets++;
+};
+
+CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) {
+ var cursor = editor.getCursorPosition();
+ var line = session.doc.getLine(cursor.row);
+ if (!this.isMaybeInsertedClosing(cursor, line))
+ context.maybeInsertedBrackets = 0;
+ context.maybeInsertedRow = cursor.row;
+ context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket;
+ context.maybeInsertedLineEnd = line.substr(cursor.column);
+ context.maybeInsertedBrackets++;
+};
+
+CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) {
+ return context.autoInsertedBrackets > 0 &&
+ cursor.row === context.autoInsertedRow &&
+ bracket === context.autoInsertedLineEnd[0] &&
+ line.substr(cursor.column) === context.autoInsertedLineEnd;
+};
+
+CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) {
+ return context.maybeInsertedBrackets > 0 &&
+ cursor.row === context.maybeInsertedRow &&
+ line.substr(cursor.column) === context.maybeInsertedLineEnd &&
+ line.substr(0, cursor.column) == context.maybeInsertedLineStart;
+};
+
+CstyleBehaviour.popAutoInsertedClosing = function() {
+ context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1);
+ context.autoInsertedBrackets--;
+};
+
+CstyleBehaviour.clearMaybeInsertedClosing = function() {
+ if (context) {
+ context.maybeInsertedBrackets = 0;
+ context.maybeInsertedRow = -1;
+ }
+};
+
+
+
oop.inherits(CstyleBehaviour, Behaviour);
exports.CstyleBehaviour = CstyleBehaviour;
diff --git a/lib/ace/mode/html/saxparser.js b/lib/ace/mode/html/saxparser.js
index 966630d5..079f2e5c 100644
--- a/lib/ace/mode/html/saxparser.js
+++ b/lib/ace/mode/html/saxparser.js
@@ -1,5 +1,5 @@
-define(["require", "exports", "module"], function(require, exports, module){
-require=(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s