Compare commits
319 commits
fix/webkit
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca8da0a3f3 | ||
|
|
f10da4cdb0 | ||
|
|
d953740339 | ||
|
|
6cec0b28b2 | ||
|
|
3f31ca57ed | ||
|
|
fb7144b622 | ||
|
|
2249d06337 | ||
|
|
1514d5f374 | ||
|
|
446e3e1bf9 | ||
|
|
652dd7009c | ||
|
|
3d23e1e98f | ||
|
|
cafc7e7ce1 | ||
|
|
abdc4c7510 | ||
|
|
8c1d0ab7cf | ||
|
|
9f57989043 | ||
|
|
2a089863e2 | ||
|
|
386c508042 | ||
|
|
dc7643db8d | ||
|
|
5705a7c2c1 | ||
|
|
2e2d9bcdc9 | ||
|
|
a799a4086f | ||
|
|
af5c7a9c3b | ||
|
|
fe96eef206 | ||
|
|
0a3b002e28 | ||
|
|
60439d927f | ||
|
|
95bb17d04b | ||
|
|
2c1b565591 | ||
|
|
53ea1a8665 | ||
|
|
9534e4ea92 | ||
|
|
fa86327b3d | ||
|
|
a68e8bea01 | ||
|
|
88d8cf3447 | ||
|
|
9e9aa8f328 | ||
|
|
93c39ca5b0 | ||
|
|
0db985a3d7 | ||
|
|
ad5802be06 | ||
|
|
0abd9ec30e | ||
|
|
6d205a8f7e | ||
|
|
d2dc26f5a5 | ||
|
|
ef4537a099 | ||
|
|
46f76b4b06 | ||
|
|
71d1ca9d20 | ||
|
|
263a45db02 | ||
|
|
9323a2616b | ||
|
|
ad22b71cfe | ||
|
|
cd8099b0ad | ||
|
|
a61d304cbb | ||
|
|
e72f1d8337 | ||
|
|
d080fe51d4 | ||
|
|
32cb8c6b0e | ||
|
|
3ce8d76c89 | ||
|
|
a842dcdee3 | ||
|
|
0dcb1281cd | ||
|
|
65ad04082f | ||
|
|
b6f7e5d6a1 | ||
|
|
5a3bf2570f | ||
|
|
2d7ebc34b6 | ||
|
|
87044e8816 | ||
|
|
82453d884b | ||
|
|
636ace5178 | ||
|
|
3673aabe2a | ||
|
|
694d7431b7 | ||
|
|
89b9a8ac72 | ||
|
|
67c7da75b6 | ||
|
|
662cd11975 | ||
|
|
68d531ecb2 | ||
|
|
e58fa3e6d7 | ||
|
|
e610365e67 | ||
|
|
65b2cf2855 | ||
|
|
2008ab813f | ||
|
|
ecb699aa11 | ||
|
|
63687f693b | ||
|
|
685ba18451 | ||
|
|
1ec6eb7b5d | ||
|
|
1027dcea7c | ||
|
|
961f8c4893 | ||
|
|
27284cd29f | ||
|
|
04f4292fbc | ||
|
|
4e6d48bf2e | ||
|
|
80f43beb73 | ||
|
|
cf0c81a25f | ||
|
|
ee90854917 | ||
|
|
ff4429dd5a | ||
|
|
487408e84d | ||
|
|
2713d0a8db | ||
|
|
b0ce5630c9 | ||
|
|
d89311e596 | ||
|
|
5482db1c4d | ||
|
|
eb70d5a6c8 | ||
|
|
abe0286420 | ||
|
|
094b8a147a | ||
|
|
f0d01b93d4 | ||
|
|
ef9cc542e7 | ||
|
|
73808101cd | ||
|
|
0753f9aa12 | ||
|
|
f270b4ae69 | ||
|
|
121e0e51f4 | ||
|
|
846c2fb3d3 | ||
|
|
cd1c5a42c9 | ||
|
|
282331b133 | ||
|
|
db0313f2ad | ||
|
|
37a80b35da | ||
|
|
75f66697f6 | ||
|
|
32847a6761 | ||
|
|
0d0b0b4356 | ||
|
|
a0a31e16a2 | ||
|
|
295ae4dc81 | ||
|
|
d38849ef9f | ||
|
|
184df6d18e | ||
|
|
ff0cc12efc | ||
|
|
1b9c8bfc88 | ||
|
|
e42bc9a265 | ||
|
|
12be220297 | ||
|
|
7ae5c862c2 | ||
|
|
d8f7003fb8 | ||
|
|
76ac79f116 | ||
|
|
1a6e2f83f2 | ||
|
|
6b62974118 | ||
|
|
461faa9184 | ||
|
|
ede82e7137 | ||
|
|
f0b3aa0a6f | ||
|
|
fb5f272f81 | ||
|
|
c458f96d3a | ||
|
|
6070fe96f7 | ||
|
|
6a2d3fcb09 | ||
|
|
8b29f7f3c9 | ||
|
|
48de4711eb | ||
|
|
bb3fa62824 | ||
|
|
6bdc0d6cbb | ||
|
|
510d060cb2 | ||
|
|
da8d545985 | ||
|
|
4f655e71d9 | ||
|
|
8f686eb795 | ||
|
|
6fad60f546 | ||
|
|
1ae86f896a | ||
|
|
4e4df645cc | ||
|
|
0bf729d88f | ||
|
|
cc40177114 | ||
|
|
fcb4023e52 | ||
|
|
22f802a9ff | ||
|
|
14a8e1f5d9 | ||
|
|
a2e05ac438 | ||
|
|
f17c67cd01 | ||
|
|
9c6720edca | ||
|
|
4dd8eda928 | ||
|
|
cb83a974b4 | ||
|
|
75556854b9 | ||
|
|
7e9e5aea17 | ||
|
|
bb16d65cbb | ||
|
|
c39134411d | ||
|
|
cb0816b183 | ||
|
|
e551b090b7 | ||
|
|
c5602489f4 | ||
|
|
1c1d56b3ea | ||
|
|
a78bf8e5ef | ||
|
|
d9db903190 | ||
|
|
4af37cd722 | ||
|
|
dd69f5939c | ||
|
|
cac9e261e3 | ||
|
|
0216e8bbfd | ||
|
|
38e3452313 | ||
|
|
fb7b23e627 | ||
|
|
1b1006ac1d | ||
|
|
101656ea5c | ||
|
|
6a07619ad2 | ||
|
|
a5c619bda8 | ||
|
|
3adde642dc | ||
|
|
967177bbc5 | ||
|
|
60c639a34b | ||
|
|
de9e5226bf | ||
|
|
76e05b7fd5 | ||
|
|
2506bb0921 | ||
|
|
481bca1b09 | ||
|
|
01f5846ee3 | ||
|
|
cca4ab8b45 | ||
|
|
ae4989eea1 | ||
|
|
6df244d429 | ||
|
|
b5064a4bb3 | ||
|
|
9905267e4d | ||
|
|
bed3a18d49 | ||
|
|
49ff504639 | ||
|
|
a035cd2558 | ||
|
|
9a275f304d | ||
|
|
b6910a3094 | ||
|
|
27ad846641 | ||
|
|
34d80e81ca | ||
|
|
3c34a9852f | ||
|
|
a0fe09f3be | ||
|
|
906b6c9d8d | ||
|
|
74800e84ee | ||
|
|
8f49d3d897 | ||
|
|
9654382294 | ||
|
|
5ce334e930 | ||
|
|
7572a9543e | ||
|
|
b3da9336ee | ||
|
|
4bc34f4eae | ||
|
|
16b542aea4 | ||
|
|
60a1281708 | ||
|
|
2ff39c2192 | ||
|
|
34f57e7499 | ||
|
|
04e75ea0db | ||
|
|
b0475ce3e4 | ||
|
|
d86b2fd7ee | ||
|
|
0b20e4dc1d | ||
|
|
388f0235b7 | ||
|
|
d9e4b52ee1 | ||
|
|
703a5394e3 | ||
|
|
42b43b1fbe | ||
|
|
3e32d5bf7e | ||
|
|
385a285c58 | ||
|
|
c840471248 | ||
|
|
3fe1383cdc | ||
|
|
6b88b939c2 | ||
|
|
1621c1519c | ||
|
|
0da0566bac | ||
|
|
b93d772720 | ||
|
|
845a6d4e98 | ||
|
|
8df1eb70c5 | ||
|
|
63178a0511 | ||
|
|
9f8cb78f37 | ||
|
|
acd41efcb6 | ||
|
|
64eaf47c4d | ||
|
|
c769031e78 | ||
|
|
8a8bc206db | ||
|
|
7db217dfe0 | ||
|
|
847bfa4bfe | ||
|
|
135b9e5baf | ||
|
|
c356c14940 | ||
|
|
2d06dc6316 | ||
|
|
8c4173ba11 | ||
|
|
fe57baaae1 | ||
|
|
0c3246e0df | ||
|
|
d21be42c8a | ||
|
|
ccd5d689cc | ||
|
|
fb41c6ce4e | ||
|
|
3b703dad56 | ||
|
|
0a7d192b3d | ||
|
|
c0b300a8e8 | ||
|
|
68abe8507a | ||
|
|
d62315a740 | ||
|
|
eddc5563d8 | ||
|
|
57f6fbd768 | ||
|
|
100022564c | ||
|
|
b57f2e2ae3 | ||
|
|
264923e4df | ||
|
|
e1a5492a7f | ||
|
|
5e4facea44 | ||
|
|
37ab8daabe | ||
|
|
55bf8e56d3 | ||
|
|
ced37c0c19 | ||
|
|
a50833cfea | ||
|
|
b2b0e73e0f | ||
|
|
72edcd332d | ||
|
|
bcc2cd9b68 | ||
|
|
f4ea1ccb6a | ||
|
|
a06739af9a | ||
|
|
aceddd9f8f | ||
|
|
ad9aa35ffe | ||
|
|
b66fb6def8 | ||
|
|
0054bb8794 | ||
|
|
07d01fda44 | ||
|
|
4aff48a837 | ||
|
|
4b8a9a475b | ||
|
|
eccc98b83b | ||
|
|
e7afb4f19e | ||
|
|
8919b113d1 | ||
|
|
ded43d9d69 | ||
|
|
14850f5b9e | ||
|
|
b9a4f293ed | ||
|
|
56cb246c78 | ||
|
|
60dd224d96 | ||
|
|
067a1ee68b | ||
|
|
95eed25439 | ||
|
|
7da354d5f3 | ||
|
|
18b3c57de9 | ||
|
|
8019a21475 | ||
|
|
eec012b24e | ||
|
|
004a19855a | ||
|
|
d619e4e746 | ||
|
|
27264bb9d9 | ||
|
|
a4532dd8b9 | ||
|
|
64f2fc4015 | ||
|
|
ffaf44ec0b | ||
|
|
bacaeb07d8 | ||
|
|
525fe1ffe3 | ||
|
|
bb827051a6 | ||
|
|
6502a3d2cb | ||
|
|
f625dfeea3 | ||
|
|
60367772a9 | ||
|
|
29023787e5 | ||
|
|
ad54d2c46c | ||
|
|
1f7582b5a6 | ||
|
|
ec97ad7904 | ||
|
|
27b6d6dcd3 | ||
|
|
6b60bcbbd6 | ||
|
|
46f3d77068 | ||
|
|
c8d1df203e | ||
|
|
4299db01bd | ||
|
|
b5af2c898c | ||
|
|
c8fca3053c | ||
|
|
8d57d8765f | ||
|
|
7f1bc7af2f | ||
|
|
6b280bf6bb | ||
|
|
35a27fd1ba | ||
|
|
ddd695ee3f | ||
|
|
f59708a5ba | ||
|
|
ef0e8da522 | ||
|
|
08edcdfc98 | ||
|
|
3a048cdf61 | ||
|
|
f2a2e4e1a8 | ||
|
|
6fe381f633 | ||
|
|
91df7cd663 | ||
|
|
8624ab8dcb | ||
|
|
b503e65e03 | ||
|
|
612478e39f | ||
|
|
810e196cc6 | ||
|
|
026af74016 | ||
|
|
27768230c8 | ||
|
|
2e6f12725b |
189 changed files with 12958 additions and 2990 deletions
|
|
@ -7,16 +7,9 @@ Feel free to fork and improve/enhance Ace any way you want. If you feel that the
|
|||
|
||||
There are two versions of the agreement:
|
||||
|
||||
1. [The Individual CLA](https://github.com/ajaxorg/ace/raw/master/doc/Contributor_License_Agreement-v2.pdf): use this version if you're working on an ajax.org in your spare time, or can clearly claim ownership of copyright in what you'll be submitting.
|
||||
2. [The Corporate CLA](https://github.com/ajaxorg/ace/raw/master/doc/Corporate_Contributor_License_Agreement-v2.pdf): have your corporate lawyer review and submit this if your company is going to be contributing to ajax.org projects
|
||||
1. [The Individual CLA](https://docs.google.com/a/c9.io/forms/d/1MfmfrxqD_PNlNsuK0lC2KSelRLxGLGfh_wEcG0ijVvo/viewform): use this version if you're working on the Cloud9 SDK or open source projects in your spare time, or can clearly claim ownership of copyright in what you'll be submitting.
|
||||
2. [The Corporate CLA](https://docs.google.com/a/c9.io/forms/d/1vFejn4111GdnCNuQ6BfnJDaxdsUEMD4KCo1ayovAfu0/viewform): have your corporate lawyer review and submit this if your company is going to be contributing to the Cloud9 SDK and/or open source projects.
|
||||
|
||||
If you want to contribute to an ajax.org project please print the CLA and fill it out and sign it. Then either send it by snail mail or fax to us or send it back scanned (or as a photo) by email.
|
||||
If you want to contribute to the Cloud9 SDK and/or open source projects please go to the online form, fill it out and submit it.
|
||||
|
||||
Email: ace+cla@c9.io
|
||||
|
||||
Fax: +31 (0) 206388953
|
||||
|
||||
Address: Ajax.org B.V.
|
||||
Keizersgracht 241
|
||||
1016 EA, Amsterdam
|
||||
the Netherlands
|
||||
Happy coding, Cloud9
|
||||
|
|
|
|||
|
|
@ -1,3 +1,16 @@
|
|||
Version 1.2.0-pre
|
||||
|
||||
* New Features
|
||||
- Indented soft wrap (danyaPostfactum)
|
||||
|
||||
* API Changes
|
||||
- unified delta types `{start, end, action, lines}` (Alden Daniels https://github.com/ajaxorg/ace/pull/1745)
|
||||
- "change" event listeners on session and editor get delta objects directly
|
||||
|
||||
2015.04.03 Version 1.1.9
|
||||
|
||||
- Small Enhancements and Bugfixes
|
||||
|
||||
2014.11.08 Version 1.1.8
|
||||
|
||||
* API Changes
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ function buildAceModuleInternal(opts, callback) {
|
|||
ignore: opts.ignore || [],
|
||||
withRequire: false,
|
||||
basepath: ACE_HOME,
|
||||
transforms: [normalizeLineEndings],
|
||||
afterRead: [optimizeTextModules]
|
||||
}, write);
|
||||
}
|
||||
|
|
@ -407,6 +408,10 @@ function getLoadedFileList(options, callback, result) {
|
|||
callback(Object.keys(deps));
|
||||
}
|
||||
|
||||
function normalizeLineEndings(module) {
|
||||
module.source = module.source.replace(/\r\n/g, "\n");
|
||||
}
|
||||
|
||||
function optimizeTextModules(sources) {
|
||||
var textModules = {};
|
||||
return sources.filter(function(pkg) {
|
||||
|
|
@ -452,10 +457,10 @@ function optimizeTextModules(sources) {
|
|||
if (/\.css$/.test(pkg.id)) {
|
||||
// remove unnecessary whitespace from css
|
||||
input = input.replace(/\n\s+/g, "\n");
|
||||
input = '"' + input.replace(/\r?\n/g, '\\\n') + '"';
|
||||
input = '"' + input.replace(/\n/g, '\\\n') + '"';
|
||||
} else {
|
||||
// but don't break other files!
|
||||
input = '"' + input.replace(/\r?\n/g, '\\n\\\n') + '"';
|
||||
input = '"' + input.replace(/\n/g, '\\n\\\n') + '"';
|
||||
}
|
||||
textModules[pkg.id] = input;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ By default the editor only supports plain text mode; many other languages are av
|
|||
The mode can then be used like this:
|
||||
|
||||
```javascript
|
||||
var JavaScriptMode = require("ace/mode/javascript").Mode;
|
||||
var JavaScriptMode = ace.require("ace/mode/javascript").Mode;
|
||||
editor.getSession().setMode(new JavaScriptMode());
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -38,69 +38,62 @@
|
|||
|
||||
var ACE_NAMESPACE = "";
|
||||
|
||||
var global = (function() {
|
||||
return this;
|
||||
})();
|
||||
var global = (function() { return this; })();
|
||||
if (!global && typeof window != "undefined") global = window; // strict mode
|
||||
|
||||
|
||||
if (!ACE_NAMESPACE && typeof requirejs !== "undefined")
|
||||
return;
|
||||
|
||||
|
||||
var _define = function(module, deps, payload) {
|
||||
if (typeof module !== 'string') {
|
||||
if (_define.original)
|
||||
_define.original.apply(window, arguments);
|
||||
var define = function(module, deps, payload) {
|
||||
if (typeof module !== "string") {
|
||||
if (define.original)
|
||||
define.original.apply(this, arguments);
|
||||
else {
|
||||
console.error('dropping module because define wasn\'t a string.');
|
||||
console.error("dropping module because define wasn\'t a string.");
|
||||
console.trace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (arguments.length == 2)
|
||||
payload = deps;
|
||||
|
||||
if (!_define.modules) {
|
||||
_define.modules = {};
|
||||
_define.payloads = {};
|
||||
if (!define.modules[module]) {
|
||||
define.payloads[module] = payload;
|
||||
define.modules[module] = null;
|
||||
}
|
||||
|
||||
_define.payloads[module] = payload;
|
||||
_define.modules[module] = null;
|
||||
};
|
||||
|
||||
define.modules = {};
|
||||
define.payloads = {};
|
||||
|
||||
/**
|
||||
* Get at functionality define()ed using the function above
|
||||
*/
|
||||
var _require = function(parentId, module, callback) {
|
||||
if (Object.prototype.toString.call(module) === "[object Array]") {
|
||||
if (typeof module === "string") {
|
||||
var payload = lookup(parentId, module);
|
||||
if (payload != undefined) {
|
||||
callback && callback();
|
||||
return payload;
|
||||
}
|
||||
} else if (Object.prototype.toString.call(module) === "[object Array]") {
|
||||
var params = [];
|
||||
for (var i = 0, l = module.length; i < l; ++i) {
|
||||
var dep = lookup(parentId, module[i]);
|
||||
if (!dep && _require.original)
|
||||
return _require.original.apply(window, arguments);
|
||||
if (dep == undefined && require.original)
|
||||
return;
|
||||
params.push(dep);
|
||||
}
|
||||
if (callback) {
|
||||
callback.apply(null, params);
|
||||
}
|
||||
return callback && callback.apply(null, params) || true;
|
||||
}
|
||||
else if (typeof module === 'string') {
|
||||
var payload = lookup(parentId, module);
|
||||
if (!payload && _require.original)
|
||||
return _require.original.apply(window, arguments);
|
||||
};
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
else {
|
||||
if (_require.original)
|
||||
return _require.original.apply(window, arguments);
|
||||
}
|
||||
var require = function(module, callback) {
|
||||
var packagedModule = _require("", module, callback);
|
||||
if (packagedModule == undefined && require.original)
|
||||
return require.original.apply(this, arguments);
|
||||
return packagedModule;
|
||||
};
|
||||
|
||||
var normalizeModule = function(parentId, moduleName) {
|
||||
|
|
@ -119,7 +112,6 @@ var normalizeModule = function(parentId, moduleName) {
|
|||
moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
|
||||
}
|
||||
}
|
||||
|
||||
return moduleName;
|
||||
};
|
||||
|
||||
|
|
@ -128,12 +120,11 @@ var normalizeModule = function(parentId, moduleName) {
|
|||
* definition function if needed.
|
||||
*/
|
||||
var lookup = function(parentId, moduleName) {
|
||||
|
||||
moduleName = normalizeModule(parentId, moduleName);
|
||||
|
||||
var module = _define.modules[moduleName];
|
||||
var module = define.modules[moduleName];
|
||||
if (!module) {
|
||||
module = _define.payloads[moduleName];
|
||||
module = define.payloads[moduleName];
|
||||
if (typeof module === 'function') {
|
||||
var exports = {};
|
||||
var mod = {
|
||||
|
|
@ -149,19 +140,15 @@ var lookup = function(parentId, moduleName) {
|
|||
|
||||
var returnValue = module(req, exports, mod);
|
||||
exports = returnValue || mod.exports;
|
||||
_define.modules[moduleName] = exports;
|
||||
delete _define.payloads[moduleName];
|
||||
define.modules[moduleName] = exports;
|
||||
delete define.payloads[moduleName];
|
||||
}
|
||||
module = _define.modules[moduleName] = exports || module;
|
||||
module = define.modules[moduleName] = exports || module;
|
||||
}
|
||||
return module;
|
||||
};
|
||||
|
||||
function exportAce(ns) {
|
||||
var require = function(module, callback) {
|
||||
return _require("", module, callback);
|
||||
};
|
||||
|
||||
var root = global;
|
||||
if (ns) {
|
||||
if (!global[ns])
|
||||
|
|
@ -170,13 +157,13 @@ function exportAce(ns) {
|
|||
}
|
||||
|
||||
if (!root.define || !root.define.packaged) {
|
||||
_define.original = root.define;
|
||||
root.define = _define;
|
||||
define.original = root.define;
|
||||
root.define = define;
|
||||
root.define.packaged = true;
|
||||
}
|
||||
|
||||
if (!root.require || !root.require.packaged) {
|
||||
_require.original = root.require;
|
||||
require.original = root.require;
|
||||
root.require = require;
|
||||
root.require.packaged = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,13 @@
|
|||
<style type="text/css" media="screen">
|
||||
|
||||
.ace_editor {
|
||||
position: relative !important;
|
||||
border: 1px solid lightgray;
|
||||
margin: auto;
|
||||
height: 200px;
|
||||
width: 80%;
|
||||
}
|
||||
.scrollmargin {
|
||||
height: 100px;
|
||||
height: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -24,6 +23,8 @@
|
|||
<div class="scrollmargin"></div>
|
||||
<pre id="editor2">minHeight = 2 lines</pre>
|
||||
<div class="scrollmargin"></div>
|
||||
<pre id="editor3" style="width: 40%;"></pre>
|
||||
<div class="scrollmargin"></div>
|
||||
<pre id="editor"></pre>
|
||||
|
||||
<script src="kitchen-sink/require.js"></script>
|
||||
|
|
@ -46,6 +47,13 @@ require(["ace/ace"], function(ace) {
|
|||
editor2.setOption("maxLines", 30);
|
||||
editor2.setOption("minLines", 2);
|
||||
|
||||
var editor = ace.edit("editor3");
|
||||
editor.setOptions({
|
||||
autoScrollEditorIntoView: true,
|
||||
maxLines: 8
|
||||
});
|
||||
editor.renderer.setScrollMargin(10, 10, 10, 10);
|
||||
|
||||
var editor = ace.edit("editor");
|
||||
editor.setTheme("ace/theme/tomorrow");
|
||||
editor.session.setMode("ace/mode/html");
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
<pre id="editor"></pre>
|
||||
|
||||
<!-- load emmet code and snippets compiled for browser -->
|
||||
<script src="https://nightwing.github.io/emmet-core/emmet.js"></script>
|
||||
<script src="https://cloud9ide.github.io/emmet-core/emmet.js"></script>
|
||||
|
||||
<script src="kitchen-sink/require.js"></script>
|
||||
<script>
|
||||
|
|
|
|||
|
|
@ -531,7 +531,7 @@ new StatusBar(env.editor, cmdLine.container);
|
|||
|
||||
|
||||
var Emmet = require("ace/ext/emmet");
|
||||
net.loadScript("https://nightwing.github.io/emmet-core/emmet.js", function() {
|
||||
net.loadScript("https://cloud9ide.github.io/emmet-core/emmet.js", function() {
|
||||
Emmet.setCore(window.emmet);
|
||||
env.editor.setOption("enableEmmet", true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ function warn() {
|
|||
s.shift(); // remove the getter
|
||||
s = s.join("\n");
|
||||
// allow easy access to ace in console, but not in ace code
|
||||
if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}/.test(s)) {
|
||||
if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}|\(<anonymous>:\d+:\d+\)/.test(s)) {
|
||||
console.error("trying to access to global variable");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,13 +169,44 @@ function loadDoc(name, callback) {
|
|||
});
|
||||
}
|
||||
|
||||
function saveDoc(name, callback) {
|
||||
var doc = fileCache[name] || name;
|
||||
if (!doc || !doc.session)
|
||||
return callback("Unknown document: " + name);
|
||||
|
||||
var path = doc.path;
|
||||
var parts = path.split("/");
|
||||
if (parts[0] == "docs")
|
||||
path = "demo/kitchen-sink/" + path;
|
||||
else if (parts[0] == "ace")
|
||||
path = "lib/" + path;
|
||||
|
||||
upload(path, doc.session.getValue(), callback);
|
||||
}
|
||||
|
||||
function upload(url, data, callback) {
|
||||
url = net.qualifyURL(url);
|
||||
if (!/https?:/.test(url))
|
||||
return callback(new Error("Unsupported url scheme"));
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", url, true);
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState === 4) {
|
||||
callback(!/^2../.test(xhr.status));
|
||||
}
|
||||
};
|
||||
xhr.send(data);
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
fileCache: fileCache,
|
||||
docs: sort(prepareDocList(docs)),
|
||||
ownSource: prepareDocList(ownSource),
|
||||
hugeDocs: prepareDocList(hugeDocs),
|
||||
initDoc: initDoc,
|
||||
loadDoc: loadDoc
|
||||
loadDoc: loadDoc,
|
||||
saveDoc: saveDoc,
|
||||
};
|
||||
module.exports.all = {
|
||||
"Mode Examples": module.exports.docs,
|
||||
|
|
|
|||
171
demo/kitchen-sink/docs/abc.abc
Normal file
171
demo/kitchen-sink/docs/abc.abc
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
%abc-2.1
|
||||
H:This file contains some example English tunes
|
||||
% note that the comments (like this one) are to highlight usages
|
||||
% and would not normally be included in such detail
|
||||
O:England % the origin of all tunes is England
|
||||
|
||||
X:1 % tune no 1
|
||||
T:Dusty Miller, The % title
|
||||
T:Binny's Jig % an alternative title
|
||||
C:Trad. % traditional
|
||||
R:DH % double hornpipe
|
||||
M:3/4 % meter
|
||||
K:G % key
|
||||
B>cd BAG|FA Ac BA|B>cd BAG|DG GB AG:|
|
||||
Bdd gfg|aA Ac BA|Bdd gfa|gG GB AG:|
|
||||
BG G/2G/2G BG|FA Ac BA|BG G/2G/2G BG|DG GB AG:|
|
||||
W:Hey, the dusty miller, and his dusty coat;
|
||||
W:He will win a shilling, or he spend a groat.
|
||||
W:Dusty was the coat, dusty was the colour;
|
||||
W:Dusty was the kiss, that I got frae the miller.
|
||||
|
||||
X:2
|
||||
T:Old Sir Simon the King
|
||||
C:Trad.
|
||||
S:Offord MSS % from Offord manuscript
|
||||
N:see also Playford % reference note
|
||||
M:9/8
|
||||
R:SJ % slip jig
|
||||
N:originally in C % transcription note
|
||||
K:G
|
||||
D|GFG GAG G2D|GFG GAG F2D|EFE EFE EFG|A2G F2E D2:|
|
||||
D|GAG GAB d2D|GAG GAB c2D|[1 EFE EFE EFG|[A2G] F2E D2:|\ % no line-break in score
|
||||
M:12/8 % change of meter
|
||||
[2 E2E EFE E2E EFG|\ % no line-break in score
|
||||
M:9/8 % change of meter
|
||||
A2G F2E D2|]
|
||||
|
||||
X:3
|
||||
T:William and Nancy
|
||||
T:New Mown Hay
|
||||
T:Legacy, The
|
||||
C:Trad.
|
||||
O:England; Gloucs; Bledington % place of origin
|
||||
B:Sussex Tune Book % can be found in these books
|
||||
B:Mally's Cotswold Morris vol.1 2
|
||||
D:Morris On % can be heard on this record
|
||||
P:(AB)2(AC)2A % play the parts in this order
|
||||
M:6/8
|
||||
K:G
|
||||
[P:A] D|"G"G2G GBd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
|
||||
[P:B] d|"G"e2d B2d|"C"gfe "G"d2d| "G"e2d B2d|"C"gfe "D7"d2c|
|
||||
"G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
|
||||
% changes of meter, using inline fields
|
||||
[T:Slows][M:4/4][L:1/4][P:C]"G"d2|"C"e2 "G"d2|B2 d2|"Em"gf "A7"e2|"D7"d2 "G"d2|\
|
||||
"C"e2 "G"d2|[M:3/8][L:1/8] "G"B2 d |[M:6/8] "C"gfe "D7"d2c|
|
||||
"G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
|
||||
|
||||
X:4
|
||||
T:South Downs Jig
|
||||
R:jig
|
||||
S:Robert Harbron
|
||||
M:6/8
|
||||
L:1/8
|
||||
K:G
|
||||
|: d | dcA G3 | EFG AFE | DEF GAB | cde d2d |
|
||||
dcA G3 | EFG AFE | DEF GAB | cAF G2 :|
|
||||
B | Bcd e2c | d2B c2A | Bcd e2c | [M:9/8]d2B c2B A3 |
|
||||
[M:6/8]DGF E3 | cBA FED | DEF GAB |1 cAF G2 :|2 cAF G3 |]
|
||||
|
||||
X:5
|
||||
T:Atholl Brose
|
||||
% in this example, which reproduces Highland Bagpipe gracing,
|
||||
% the large number of grace notes mean that it is more convenient to be specific about
|
||||
% score line-breaks (using the $ symbol), rather than using code line breaks to indicate them
|
||||
I:linebreak $
|
||||
K:D
|
||||
{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad|
|
||||
{gcd}c<{e}A {gAGAG}A>e {ag}a>f {gef}e>d|
|
||||
{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad|
|
||||
{g}c/d/e {g}G>{d}B {gf}gG {dc}d>B:|$
|
||||
{g}c<e {gf}g>e {ag}a>e {gf}g>e|
|
||||
{g}c<e {gf}g>e {ag}a2 {GdG}a>d|
|
||||
{g}c<e {gf}g>e {ag}a>e {gf}g>f|
|
||||
{gef}e>d {gf}g>d {gBd}B<{e}G {dc}d>B|
|
||||
{g}c<e {gf}g>e {ag}a>e {gf}g>e|
|
||||
{g}c<e {gf}g>e {ag}a2 {GdG}ad|
|
||||
{g}c<{GdG}e {gf}ga {f}g>e {g}f>d|
|
||||
{g}e/f/g {Gdc}d>c {gBd}B<{e}G {dc}d2|]
|
||||
|
||||
X:6
|
||||
T:Untitled Reel
|
||||
C:Trad.
|
||||
K:D
|
||||
eg|a2ab ageg|agbg agef|g2g2 fgag|f2d2 d2:|\
|
||||
ed|cecA B2ed|cAcA E2ed|cecA B2ed|c2A2 A2:|
|
||||
K:G
|
||||
AB|cdec BcdB|ABAF GFE2|cdec BcdB|c2A2 A2:|
|
||||
|
||||
X:7
|
||||
T:Kitchen Girl
|
||||
C:Trad.
|
||||
K:D
|
||||
[c4a4] [B4g4]|efed c2cd|e2f2 gaba|g2e2 e2fg|
|
||||
a4 g4|efed cdef|g2d2 efed|c2A2 A4:|
|
||||
K:G
|
||||
ABcA BAGB|ABAG EDEG|A2AB c2d2|e3f edcB|ABcA BAGB|
|
||||
ABAG EGAB|cBAc BAG2|A4 A4:|
|
||||
|
||||
%abc-2.1
|
||||
%%pagewidth 21cm
|
||||
%%pageheight 29.7cm
|
||||
%%topspace 0.5cm
|
||||
%%topmargin 1cm
|
||||
%%botmargin 0cm
|
||||
%%leftmargin 1cm
|
||||
%%rightmargin 1cm
|
||||
%%titlespace 0cm
|
||||
%%titlefont Times-Bold 32
|
||||
%%subtitlefont Times-Bold 24
|
||||
%%composerfont Times 16
|
||||
%%vocalfont Times-Roman 14
|
||||
%%staffsep 60pt
|
||||
%%sysstaffsep 20pt
|
||||
%%musicspace 1cm
|
||||
%%vocalspace 5pt
|
||||
%%measurenb 0
|
||||
%%barsperstaff 5
|
||||
%%scale 0.7
|
||||
X: 1
|
||||
T: Canzonetta a tre voci
|
||||
C: Claudio Monteverdi (1567-1643)
|
||||
M: C
|
||||
L: 1/4
|
||||
Q: "Andante mosso" 1/4 = 110
|
||||
%%score [1 2 3]
|
||||
V: 1 clef=treble name="Soprano"sname="A"
|
||||
V: 2 clef=treble name="Alto" sname="T"
|
||||
V: 3 clef=bass middle=d name="Tenor" sname="B"
|
||||
%%MIDI program 1 75 % recorder
|
||||
%%MIDI program 2 75
|
||||
%%MIDI program 3 75
|
||||
K: Eb
|
||||
% 1 - 4
|
||||
[V: 1] |:z4 |z4 |f2ec |_ddcc |
|
||||
w: Son que-sti~i cre-spi cri-ni~e
|
||||
w: Que-sti son gli~oc-chi che mi-
|
||||
[V: 2] |:c2BG|AAGc|(F/G/A/B/)c=A|B2AA |
|
||||
w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il vi-so e
|
||||
w: Que-sti son~gli oc-chi che mi-ran - - - - do fi-so mi-
|
||||
[V: 3] |:z4 |f2ec|_ddcf |(B/c/_d/e/)ff|
|
||||
w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il
|
||||
w: Que-sti son~gli oc-chi che mi-ran - - - - do
|
||||
% 5 - 9
|
||||
[V: 1] cAB2 |cAAA |c3B|G2!fermata!Gz ::e4|
|
||||
w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,
|
||||
w: ran-do fi-so, tut-to re-stai con-qui-so.
|
||||
[V: 2] AAG2 |AFFF |A3F|=E2!fermata!Ez::c4|
|
||||
w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,
|
||||
w: ran-do fi-so tut-to re-stai con-qui-so.
|
||||
[V: 3] (ag/f/e2)|A_ddd|A3B|c2!fermata!cz ::A4|
|
||||
w: vi - - - so ond' io ti-man-go~uc-ci-so. Deh,
|
||||
w: fi - - - so tut-to re-stai con-qui-so.
|
||||
% 10 - 15
|
||||
[V: 1] f_dec |B2c2|zAGF |\
|
||||
w: dim-me-lo ben mi-o, che que-sto\
|
||||
=EFG2 |1F2z2:|2F8|] % more notes
|
||||
w: sol de-si-o_. % more lyrics
|
||||
[V: 2] ABGA |G2AA|GF=EF |(GF3/2=E//D//E)|1F2z2:|2F8|]
|
||||
w: dim-me-lo ben mi-o, che que-sto sol de-si - - - - o_.
|
||||
[V: 3] _dBc>d|e2AF|=EFc_d|c4 |1F2z2:|2F8|]
|
||||
w: dim-me-lo ben mi-o, che que-sto sol de-si-o_.
|
||||
9
demo/kitchen-sink/docs/lean.lean
Normal file
9
demo/kitchen-sink/docs/lean.lean
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import logic
|
||||
section
|
||||
variables (A : Type) (p q : A → Prop)
|
||||
|
||||
example : (∀x : A, p x ∧ q x) → ∀y : A, p y :=
|
||||
assume H : ∀x : A, p x ∧ q x,
|
||||
take y : A,
|
||||
show p y, from and.elim_left (H y)
|
||||
end
|
||||
|
|
@ -20,7 +20,7 @@ class Range
|
|||
end
|
||||
end
|
||||
|
||||
{:id => 34, :key => "value"}
|
||||
{:id => ?", :key => "value"}
|
||||
|
||||
|
||||
herDocs = [<<'FOO', <<BAR, <<-BAZ, <<-`EXEC`] #comment
|
||||
|
|
|
|||
72
demo/kitchen-sink/docs/sqlserver.sqlserver
Normal file
72
demo/kitchen-sink/docs/sqlserver.sqlserver
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
-- =============================================
|
||||
-- Author: Morgan Yarbrough
|
||||
-- Create date: 4/27/2015
|
||||
-- Description: Test procedure that shows off language features.
|
||||
-- Includes non-standard folding with region comments using either
|
||||
-- line comments or block comments (both are demonstrated below).
|
||||
-- This mode imitates SSMS and it designed to be used with SQL Server theme.
|
||||
-- =============================================
|
||||
CREATE PROCEDURE dbo.TestProcedure
|
||||
|
||||
--#region parameters
|
||||
@vint INT = 1
|
||||
,@vdate DATE = NULL
|
||||
,@vdatetime DATETIME = DATEADD(dd, 1, GETDATE())
|
||||
,@vvarchar VARCHAR(MAX) = ''
|
||||
--#endregion
|
||||
|
||||
AS
|
||||
BEGIN
|
||||
|
||||
/*#region set statements */
|
||||
SET NOCOUNT ON;
|
||||
SET XACT_ABORT ON;
|
||||
SET QUOTED_IDENTIFIER ON;
|
||||
/*#endregion*/
|
||||
|
||||
/**
|
||||
* These comments will produce a fold widget
|
||||
*/
|
||||
|
||||
-- folding demonstration
|
||||
SET @vint = CASE
|
||||
WHEN @vdate IS NULL
|
||||
THEN 1
|
||||
ELSE 2
|
||||
END
|
||||
|
||||
-- another folding demonstration
|
||||
IF @vint = 1
|
||||
BEGIN
|
||||
SET @vvarchar = 'one'
|
||||
SET @vint = DATEDIFF(dd, @vdate, @vdatetime)
|
||||
END
|
||||
|
||||
-- this mode handles strings properly
|
||||
DECLARE @sql NVARCHAR(4000) = N'SELECT TOP(1) OrderID
|
||||
FROM Orders
|
||||
WHERE @OrderDate > GETDATE()'
|
||||
|
||||
-- this mode is aware of built in stored procedures
|
||||
EXECUTE sp_executesql @sql
|
||||
|
||||
-- demonstrating some syntax highlighting
|
||||
SELECT Orders.OrderID
|
||||
,Customers.CompanyName
|
||||
,DATEFROMPARTS(YEAR(GETDATE()), 1, 1) AS FirstDayOfYear
|
||||
FROM Orders
|
||||
INNER JOIN Customers
|
||||
ON Orders.CustomerID = Customers.CustomerID
|
||||
WHERE CompanyName NOT LIKE '%something'
|
||||
OR CompanyName IS NULL
|
||||
OR CompanyName IN ('bla', 'nothing')
|
||||
|
||||
-- this mode includes snippets
|
||||
-- place your cusor at the end of the line below and trigger auto complete (Ctrl+Space)
|
||||
createpr
|
||||
|
||||
-- SQL Server allows using keywords as object names (not recommended) as long as they are wrapped in brackets
|
||||
DATABASE -- keyword
|
||||
[DATABASE] -- not a keyword
|
||||
|
||||
END
|
||||
|
|
@ -53,16 +53,16 @@ require("ace/commands/default_commands").commands.push({
|
|||
return;
|
||||
}
|
||||
|
||||
var rowCount = 10;
|
||||
var rowCount = 10;
|
||||
var w = {
|
||||
row: row,
|
||||
// rowCount: rowCount,
|
||||
fixedWidth: true,
|
||||
el: dom.createElement("div"),
|
||||
editor: editor
|
||||
editor: inlineEditor
|
||||
};
|
||||
var el = w.el;
|
||||
el.appendChild(inlineEditor.container);
|
||||
el.appendChild(inlineEditor.container);
|
||||
|
||||
if (!editor.session.widgetManager) {
|
||||
editor.session.widgetManager = new LineWidgets(editor.session);
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Static Code highlighter using Ace</title>
|
||||
<meta name="author" content="Matthew Kastor">
|
||||
<title>Static Code highlighter using Ace</title>
|
||||
<meta name="author" content="Matthew Kastor">
|
||||
<style type="text/css">
|
||||
.code {
|
||||
width: 50%;
|
||||
position: relative;
|
||||
white-space: pre-wrap;
|
||||
border: solid lightgrey 1px
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
|
@ -21,9 +21,8 @@
|
|||
<div class="code" ace-mode="ace/mode/css" ace-theme="ace/theme/chrome" ace-gutter="true">
|
||||
.code {
|
||||
width: 50%;
|
||||
|
||||
position: relative;
|
||||
white-space: pre-wrap;
|
||||
border: solid lightgrey 1px
|
||||
}
|
||||
|
||||
</div>
|
||||
|
|
@ -35,6 +34,26 @@ function wobble (flam) {
|
|||
|
||||
</pre>
|
||||
|
||||
|
||||
<div class="code" ace-mode="ace/mode/lua" ace-theme="ace/theme/chrome" ace-gutter="true" style="width: 30em;">
|
||||
--[[--
|
||||
num_args takes in 5.1 byte code and extracts the number of arguments from its function header.
|
||||
--]]--
|
||||
|
||||
function int(t)
|
||||
return t:byte(1) + t:byte(2) * 0x100 + t:byte(3) * 0x10000 + t:byte(4) * 0x1000000
|
||||
end
|
||||
|
||||
function num_args(func)
|
||||
local dump = string.dump(func)
|
||||
local offset, cursor = int(dump:sub(13)), offset + 26
|
||||
--Get the params and var flag (whether there's a ... in the param)
|
||||
return dump:sub(cursor):byte(), dump:sub(cursor+1):byte()
|
||||
end
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<script src="kitchen-sink/require.js"></script>
|
||||
<script>
|
||||
require.config({paths: { "ace" : "../lib/ace"}});
|
||||
|
|
|
|||
|
|
@ -2,15 +2,13 @@
|
|||
* Simple node.js server, which generates the synax highlighted version of itself
|
||||
* using the Ace modes and themes on the server and serving a static web page.
|
||||
*/
|
||||
// $'
|
||||
|
||||
// include ace search path and modules
|
||||
require("amd-loader");
|
||||
|
||||
// load jsdom, which is required by Ace
|
||||
require("../../lib/ace/test/mockdom");
|
||||
|
||||
var http = require("http");
|
||||
var fs = require("fs");
|
||||
var resolve = require("path").resolve;
|
||||
|
||||
// load the highlighter and the desired mode and theme
|
||||
var highlighter = require("../../lib/ace/ext/static_highlight");
|
||||
|
|
@ -20,15 +18,22 @@ var theme = require("../../lib/ace/theme/twilight");
|
|||
var port = process.env.PORT || 2222;
|
||||
|
||||
http.createServer(function(req, res) {
|
||||
var url = req.url;
|
||||
var path = /[^#?\x00]*/.exec(url)[0];
|
||||
var root = resolve(__dirname + "/../../").replace(/\\/g, "/");
|
||||
path = resolve(root + "/" + path).replace(/\\/g, "/");
|
||||
if (path.indexOf(root + "/") != 0)
|
||||
path = __filename;
|
||||
res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"});
|
||||
fs.readFile(__filename, "utf8", function(err, data) {
|
||||
fs.readFile(path, "utf8", function(err, data) {
|
||||
if (err) data = err.message;
|
||||
var highlighted = highlighter.render(data, new JavaScriptMode(), theme);
|
||||
res.end(
|
||||
'<html><body>\n' +
|
||||
'<style type="text/css" media="screen">\n' +
|
||||
highlighted.css +
|
||||
'</style>\n' +
|
||||
highlighted.html +
|
||||
highlighted.html +
|
||||
'</body></html>'
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -18,7 +18,7 @@ $(function() {
|
|||
});
|
||||
|
||||
ace.config.loadModule("ace/ext/emmet", function() {
|
||||
ace.require("ace/lib/net").loadScript("http://nightwing.github.io/emmet-core/emmet.js", function() {
|
||||
ace.require("ace/lib/net").loadScript("http://cloud9ide.github.io/emmet-core/emmet.js", function() {
|
||||
embedded_editor.setOption("enableEmmet", true);
|
||||
editor.setOption("enableEmmet", true);
|
||||
});
|
||||
|
|
|
|||
59
experiments/debug_mem_leak.html
Normal file
59
experiments/debug_mem_leak.html
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="../demo/kitchen-sink/require.js"></script>
|
||||
<script type="text/javascript">
|
||||
require.config({
|
||||
paths: { ace: "../lib/ace" },
|
||||
waitSeconds: 0
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p><button onclick="toggleEditor()">Toggle editor</button></p>
|
||||
|
||||
<div id="container"></div>
|
||||
<script>
|
||||
var editor;
|
||||
var counter = 0
|
||||
|
||||
function toggleEditor() {
|
||||
if (!editor) {
|
||||
var root = document.createElement("div");
|
||||
root.style.height = "100px";
|
||||
root.setAttribute("id", "editor");
|
||||
root.textContent = "function foo(items) {\nvar x = 'All this is syntax highlighted';\nreturn x;\n}";
|
||||
|
||||
document.getElementById("container").appendChild(root);
|
||||
|
||||
editor = ace.edit(root);
|
||||
|
||||
if (counter++ % 2)
|
||||
editor.setTheme("ace/theme/monokai");
|
||||
else
|
||||
editor.setTheme("ace/theme/clouds");
|
||||
|
||||
editor.session.setMode("ace/mode/javascript");
|
||||
} else {
|
||||
editor.destroy();
|
||||
var el = editor.container;
|
||||
el.parentNode.removeChild(el);
|
||||
|
||||
editor.container = null
|
||||
editor.renderer = null
|
||||
|
||||
editor = null;
|
||||
|
||||
var root = document.getElementById("editor")
|
||||
if (root)
|
||||
root.parentNode.removeChild(root);
|
||||
}
|
||||
}
|
||||
require(["ace/ace"], function(ace) {
|
||||
window.ace = ace;
|
||||
toggleEditor();
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
12
index.html
12
index.html
|
|
@ -196,8 +196,7 @@ console.log(addResult);
|
|||
<p><span class="expand_arrow">></span> <a href="https://github.com/ajaxorg/ace/tree/master/lib/ace/theme" target="_blank">See all themes</a></p>
|
||||
<h2>Setting the Programming Language Mode</h2>
|
||||
<p>By default, the editor supports plain text mode. All other language modes are available as separate modules, loaded on demand like this:</p>
|
||||
<pre><code class="javascript">editor.getSession().setMode("ace/mode/javascript");
|
||||
</code></pre>
|
||||
<pre><code class="javascript">editor.getSession().setMode("ace/mode/javascript");</code></pre>
|
||||
<!--h2>One Editor, Multiple Sessions</h2>
|
||||
<p>Ace keeps everything about the state of the editor (selection, scroll position, etc.)
|
||||
in <code class="javascript">editor.session</code>. This means you can grab the
|
||||
|
|
@ -471,7 +470,6 @@ var fonts = lang.arrayToMap(
|
|||
<pre><code class="language-javascript">this.$rules = {
|
||||
"start" : [ {
|
||||
token : "text",
|
||||
merge : true,
|
||||
regex : "<\\!\\[CDATA\\[",
|
||||
next : "cdata"
|
||||
},
|
||||
|
|
@ -481,13 +479,7 @@ var fonts = lang.arrayToMap(
|
|||
regex : "\\]\\]>",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "text",
|
||||
merge : true,
|
||||
regex : "\\s+"
|
||||
}, {
|
||||
token : "text",
|
||||
merge : true,
|
||||
regex : ".+"
|
||||
defaultToken : "text"
|
||||
} ]
|
||||
};</code></pre>
|
||||
<p>In this extremly short sample, we're defining some highlighting rules for when Ace detectes a <code><![CDATA</code> tag. When one is encountered, the tokenizer moves from <code>start</code> into the <code>cdata</code> state. It remains there, applying the <code>text</code> token to any string it encounters. Finally, when it hits a closing <code>]></code> symbol, it returns to the <code>start</code> state and continues to tokenize anything else.</p>
|
||||
|
|
|
|||
|
|
@ -99,72 +99,54 @@ var Anchor = exports.Anchor = function(doc, row, column) {
|
|||
* - `value`: An object describing the new Anchor position
|
||||
*
|
||||
**/
|
||||
this.onChange = function(e) {
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
|
||||
if (range.start.row == range.end.row && range.start.row != this.row)
|
||||
this.onChange = function(delta) {
|
||||
if (delta.start.row == delta.end.row && delta.start.row != this.row)
|
||||
return;
|
||||
|
||||
if (range.start.row > this.row)
|
||||
if (delta.start.row > this.row)
|
||||
return;
|
||||
|
||||
if (range.start.row == this.row && range.start.column > this.column)
|
||||
return;
|
||||
|
||||
var row = this.row;
|
||||
var column = this.column;
|
||||
var start = range.start;
|
||||
var end = range.end;
|
||||
|
||||
if (delta.action === "insertText") {
|
||||
if (start.row === row && start.column <= column) {
|
||||
if (start.column === column && this.$insertRight) {
|
||||
// do nothing
|
||||
} else if (start.row === end.row) {
|
||||
column += end.column - start.column;
|
||||
} else {
|
||||
column -= start.column;
|
||||
row += end.row - start.row;
|
||||
}
|
||||
} else if (start.row !== end.row && start.row < row) {
|
||||
row += end.row - start.row;
|
||||
}
|
||||
} else if (delta.action === "insertLines") {
|
||||
if (start.row === row && column === 0 && this.$insertRight) {
|
||||
// do nothing
|
||||
}
|
||||
else if (start.row <= row) {
|
||||
row += end.row - start.row;
|
||||
}
|
||||
} else if (delta.action === "removeText") {
|
||||
if (start.row === row && start.column < column) {
|
||||
if (end.column >= column)
|
||||
column = start.column;
|
||||
else
|
||||
column = Math.max(0, column - (end.column - start.column));
|
||||
|
||||
} else if (start.row !== end.row && start.row < row) {
|
||||
if (end.row === row)
|
||||
column = Math.max(0, column - end.column) + start.column;
|
||||
row -= (end.row - start.row);
|
||||
} else if (end.row === row) {
|
||||
row -= end.row - start.row;
|
||||
column = Math.max(0, column - end.column) + start.column;
|
||||
}
|
||||
} else if (delta.action == "removeLines") {
|
||||
if (start.row <= row) {
|
||||
if (end.row <= row)
|
||||
row -= end.row - start.row;
|
||||
else {
|
||||
row = start.row;
|
||||
column = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setPosition(row, column, true);
|
||||
|
||||
var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight);
|
||||
this.setPosition(point.row, point.column, true);
|
||||
};
|
||||
|
||||
function $pointsInOrder(point1, point2, equalPointsInOrder) {
|
||||
var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column;
|
||||
return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter);
|
||||
}
|
||||
|
||||
function $getTransformedPoint(delta, point, moveIfEqual) {
|
||||
// Get delta info.
|
||||
var deltaIsInsert = delta.action == "insert";
|
||||
var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row);
|
||||
var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);
|
||||
var deltaStart = delta.start;
|
||||
var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.
|
||||
|
||||
// DELTA AFTER POINT: No change needed.
|
||||
if ($pointsInOrder(point, deltaStart, moveIfEqual)) {
|
||||
return {
|
||||
row: point.row,
|
||||
column: point.column
|
||||
};
|
||||
}
|
||||
|
||||
// DELTA BEFORE POINT: Move point by delta shift.
|
||||
if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {
|
||||
return {
|
||||
row: point.row + deltaRowShift,
|
||||
column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0)
|
||||
};
|
||||
}
|
||||
|
||||
// DELTA ENVELOPS POINT (delete only): Move point to delta start.
|
||||
// TODO warn if delta.action != "remove" ?
|
||||
|
||||
return {
|
||||
row: deltaStart.row,
|
||||
column: deltaStart.column
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the anchor position to the specified row and column. If `noClip` is `true`, the position is not clipped.
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insertLines(1, ["123", "456"]);
|
||||
doc.insertFullLines(1, ["123", "456"]);
|
||||
assert.position(anchor.getPosition(), 3, 4);
|
||||
},
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insertNewLine({row: 0, column: 0});
|
||||
doc.insertMergedLines({row: 0, column: 0}, ['', '']);
|
||||
assert.position(anchor.getPosition(), 2, 4);
|
||||
},
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insertNewLine({row: 1, column: 2});
|
||||
doc.insertMergedLines({row: 1, column: 2}, ['', '']);
|
||||
assert.position(anchor.getPosition(), 2, 2);
|
||||
},
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\n1\n2\nkinners");
|
||||
var anchor = new Anchor(doc, 3, 4);
|
||||
|
||||
doc.removeLines(1, 2);
|
||||
doc.removeFullLines(1, 2);
|
||||
assert.position(anchor.getPosition(), 1, 4);
|
||||
},
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners\n123");
|
||||
var anchor = new Anchor(doc, 1, 5);
|
||||
|
||||
doc.removeLines(1, 1);
|
||||
doc.removeFullLines(1, 1);
|
||||
assert.position(anchor.getPosition(), 1, 0);
|
||||
},
|
||||
|
||||
|
|
@ -208,9 +208,9 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners\n123");
|
||||
var anchor = new Anchor(doc, 2, 4);
|
||||
|
||||
doc.removeLines(0, 3);
|
||||
doc.removeFullLines(0, 3);
|
||||
assert.position(anchor.getPosition(), 0, 0);
|
||||
doc.insertLines(0, ["a", "b", "c"]);
|
||||
doc.insertFullLines(0, ["a", "b", "c"]);
|
||||
assert.position(anchor.getPosition(), 3, 0);
|
||||
assert.equal(doc.getValue(), "a\nb\nc\n");
|
||||
}
|
||||
|
|
|
|||
108
lib/ace/apply_delta.js
Normal file
108
lib/ace/apply_delta.js
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/* ***** 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) {
|
||||
"use strict";
|
||||
|
||||
function throwDeltaError(delta, errorText){
|
||||
console.log("Invalid Delta:", delta);
|
||||
throw "Invalid Delta: " + errorText;
|
||||
}
|
||||
|
||||
function positionInDocument(docLines, position) {
|
||||
return position.row >= 0 && position.row < docLines.length &&
|
||||
position.column >= 0 && position.column <= docLines[position.row].length;
|
||||
}
|
||||
|
||||
function validateDelta(docLines, delta) {
|
||||
// Validate action string.
|
||||
if (delta.action != "insert" && delta.action != "remove")
|
||||
throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
|
||||
|
||||
// Validate lines type.
|
||||
if (!(delta.lines instanceof Array))
|
||||
throwDeltaError(delta, "delta.lines must be an Array");
|
||||
|
||||
// Validate range type.
|
||||
if (!delta.start || !delta.end)
|
||||
throwDeltaError(delta, "delta.start/end must be an present");
|
||||
|
||||
// Validate that the start point is contained in the document.
|
||||
var start = delta.start;
|
||||
if (!positionInDocument(docLines, delta.start))
|
||||
throwDeltaError(delta, "delta.start must be contained in document");
|
||||
|
||||
// Validate that the end point is contained in the document (remove deltas only).
|
||||
var end = delta.end;
|
||||
if (delta.action == "remove" && !positionInDocument(docLines, end))
|
||||
throwDeltaError(delta, "delta.end must contained in document for 'remove' actions");
|
||||
|
||||
// Validate that the .range size matches the .lines size.
|
||||
var numRangeRows = end.row - start.row;
|
||||
var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));
|
||||
if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)
|
||||
throwDeltaError(delta, "delta.range must match delta lines");
|
||||
}
|
||||
|
||||
exports.applyDelta = function(docLines, delta, doNotValidate) {
|
||||
// disabled validation since it breaks autocompletion popup
|
||||
// if (!doNotValidate)
|
||||
// validateDelta(docLines, delta);
|
||||
|
||||
var row = delta.start.row;
|
||||
var startColumn = delta.start.column;
|
||||
var line = docLines[row] || "";
|
||||
switch (delta.action) {
|
||||
case "insert":
|
||||
var lines = delta.lines;
|
||||
if (lines.length === 1) {
|
||||
docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
|
||||
} else {
|
||||
var args = [row, 1].concat(delta.lines);
|
||||
docLines.splice.apply(docLines, args);
|
||||
docLines[row] = line.substring(0, startColumn) + docLines[row];
|
||||
docLines[row + delta.lines.length - 1] += line.substring(startColumn);
|
||||
}
|
||||
break;
|
||||
case "remove":
|
||||
var endColumn = delta.end.column;
|
||||
var endRow = delta.end.row;
|
||||
if (row === endRow) {
|
||||
docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
|
||||
} else {
|
||||
docLines.splice(
|
||||
row, endRow - row + 1,
|
||||
line.substring(0, startColumn) + docLines[endRow].substring(endColumn)
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -40,9 +40,10 @@ var dom = require("./lib/dom");
|
|||
var snippetManager = require("./snippets").snippetManager;
|
||||
|
||||
var Autocomplete = function() {
|
||||
this.autoInsert = true;
|
||||
this.autoInsert = false;
|
||||
this.autoSelect = true;
|
||||
this.exactMatch = false;
|
||||
this.gatherCompletionsId = 0;
|
||||
this.keyboardHandler = new HashHandler();
|
||||
this.keyboardHandler.bindKeys(this.commands);
|
||||
|
||||
|
|
@ -59,7 +60,6 @@ var Autocomplete = function() {
|
|||
};
|
||||
|
||||
(function() {
|
||||
this.gatherCompletionsId = 0;
|
||||
|
||||
this.$init = function() {
|
||||
this.popup = new AcePopup(document.body || document.documentElement);
|
||||
|
|
@ -84,6 +84,8 @@ var Autocomplete = function() {
|
|||
|
||||
this.popup.setData(this.completions.filtered);
|
||||
|
||||
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
|
||||
|
||||
var renderer = editor.renderer;
|
||||
this.popup.setRow(this.autoSelect ? 0 : -1);
|
||||
if (!keepPopupPosition) {
|
||||
|
|
@ -98,7 +100,7 @@ var Autocomplete = function() {
|
|||
var rect = editor.container.getBoundingClientRect();
|
||||
pos.top += rect.top - renderer.layerConfig.offset;
|
||||
pos.left += rect.left - editor.renderer.scrollLeft;
|
||||
pos.left += renderer.$gutterLayer.gutterWidth;
|
||||
pos.left += renderer.gutterWidth;
|
||||
|
||||
this.popup.show(pos, lineHeight);
|
||||
} else if (keepPopupPosition && !prefix) {
|
||||
|
|
@ -115,10 +117,9 @@ var Autocomplete = function() {
|
|||
this.changeTimer.cancel();
|
||||
this.hideDocTooltip();
|
||||
|
||||
if (this.popup && this.popup.isOpen) {
|
||||
this.gatherCompletionsId += 1;
|
||||
this.gatherCompletionsId += 1;
|
||||
if (this.popup && this.popup.isOpen)
|
||||
this.popup.hide();
|
||||
}
|
||||
|
||||
if (this.base)
|
||||
this.base.detach();
|
||||
|
|
@ -141,10 +142,11 @@ var Autocomplete = function() {
|
|||
// we have to check if activeElement is a child of popup because
|
||||
// on IE preventDefault doesn't stop scrollbar from being focussed
|
||||
var el = document.activeElement;
|
||||
var text = this.editor.textInput.getElement()
|
||||
if (el != text && el.parentNode != this.popup.container
|
||||
&& el != this.tooltipNode && e.relatedTarget != this.tooltipNode
|
||||
&& e.relatedTarget != text
|
||||
var text = this.editor.textInput.getElement();
|
||||
var fromTooltip = e.relatedTarget && e.relatedTarget == this.tooltipNode;
|
||||
var container = this.popup && this.popup.container;
|
||||
if (el != text && el.parentNode != container && !fromTooltip
|
||||
&& el != this.tooltipNode && e.relatedTarget != text
|
||||
) {
|
||||
this.detach();
|
||||
}
|
||||
|
|
@ -204,7 +206,6 @@ var Autocomplete = function() {
|
|||
"Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); },
|
||||
|
||||
"Esc": function(editor) { editor.completer.detach(); },
|
||||
"Space": function(editor) { editor.completer.detach(); editor.insert(" ");},
|
||||
"Return": function(editor) { return editor.completer.insertMatch(); },
|
||||
"Shift-Return": function(editor) { editor.completer.insertMatch(true); },
|
||||
"Tab": function(editor) {
|
||||
|
|
@ -261,7 +262,6 @@ var Autocomplete = function() {
|
|||
editor.completer = this;
|
||||
}
|
||||
|
||||
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
|
||||
editor.on("changeSelection", this.changeListener);
|
||||
editor.on("blur", this.blurListener);
|
||||
editor.on("mousedown", this.mousedownListener);
|
||||
|
|
@ -350,7 +350,7 @@ var Autocomplete = function() {
|
|||
doc = selected;
|
||||
|
||||
if (typeof doc == "string")
|
||||
doc = {docText: doc}
|
||||
doc = {docText: doc};
|
||||
if (!doc || !(doc.docHTML || doc.docText))
|
||||
return this.hideDocTooltip();
|
||||
this.showDocTooltip(doc);
|
||||
|
|
@ -408,16 +408,16 @@ Autocomplete.startCommand = {
|
|||
exec: function(editor) {
|
||||
if (!editor.completer)
|
||||
editor.completer = new Autocomplete();
|
||||
editor.completer.autoInsert =
|
||||
editor.completer.autoInsert = false;
|
||||
editor.completer.autoSelect = true;
|
||||
editor.completer.showPopup(editor);
|
||||
// needed for firefox on mac
|
||||
// prevent ctrl-space opening context menu on firefox on mac
|
||||
editor.completer.cancelContextMenu();
|
||||
},
|
||||
bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"
|
||||
};
|
||||
|
||||
var FilteredList = function(array, filterText, mutateData) {
|
||||
var FilteredList = function(array, filterText) {
|
||||
this.all = array;
|
||||
this.filtered = array;
|
||||
this.filterText = filterText || "";
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var EditSession = require("../edit_session").EditSession;
|
||||
var Renderer = require("../virtual_renderer").VirtualRenderer;
|
||||
var Editor = require("../editor").Editor;
|
||||
var Range = require("../range").Range;
|
||||
|
|
@ -197,8 +196,12 @@ var AcePopup = function(parentNode) {
|
|||
|
||||
if (data.meta) {
|
||||
var maxW = popup.renderer.$size.scrollerWidth / popup.renderer.layerConfig.characterWidth;
|
||||
if (data.meta.length + data.caption.length < maxW - 2)
|
||||
tokens.push({type: "rightAlignedText", value: data.meta});
|
||||
var metaData = data.meta;
|
||||
if (metaData.length + data.caption.length > maxW - 2) {
|
||||
// trim meta to fit this popup and add ellipsis
|
||||
metaData = metaData.substr(0, maxW - data.caption.length - 3) + "\u2026"
|
||||
}
|
||||
tokens.push({type: "rightAlignedText", value: metaData});
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
|
|
@ -217,8 +220,8 @@ var AcePopup = function(parentNode) {
|
|||
|
||||
popup.data = [];
|
||||
popup.setData = function(list) {
|
||||
popup.data = list || [];
|
||||
popup.setValue(lang.stringRepeat("\n", list.length), -1);
|
||||
popup.data = list || [];
|
||||
popup.setRow(0);
|
||||
};
|
||||
popup.getData = function(row) {
|
||||
|
|
@ -338,4 +341,4 @@ dom.importCssString("\
|
|||
|
||||
exports.AcePopup = AcePopup;
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -68,11 +68,10 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||
var endLine = -1;
|
||||
var doc = self.doc;
|
||||
|
||||
var startLine = currentLine;
|
||||
while (self.lines[currentLine])
|
||||
currentLine++;
|
||||
|
||||
var startLine = currentLine;
|
||||
|
||||
|
||||
var len = doc.getLength();
|
||||
var processedLines = 0;
|
||||
self.running = false;
|
||||
|
|
@ -172,13 +171,12 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||
}
|
||||
|
||||
this.$updateOnChange = function(delta) {
|
||||
var range = delta.range;
|
||||
var startRow = range.start.row;
|
||||
var len = range.end.row - startRow;
|
||||
var startRow = delta.start.row;
|
||||
var len = delta.end.row - startRow;
|
||||
|
||||
if (len === 0) {
|
||||
this.lines[startRow] = null;
|
||||
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
||||
} else if (delta.action == "remove") {
|
||||
this.lines.splice(startRow, len + 1, null);
|
||||
this.states.splice(startRow, len + 1, null);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,49 @@ module.exports = {
|
|||
|
||||
forceTokenize(doc)
|
||||
testStates(doc, ["comment_regex_allowed", "start", "no_regex"])
|
||||
},
|
||||
"test background tokenizer sends update event" : function() {
|
||||
var doc = new EditSession([
|
||||
"/*",
|
||||
"var",
|
||||
"juhu",
|
||||
"*/"
|
||||
]);
|
||||
doc.setMode("./mode/javascript");
|
||||
|
||||
var updateEvent = null;
|
||||
doc.bgTokenizer.on("update", function(e) {
|
||||
updateEvent = e.data;
|
||||
});
|
||||
function checkEvent(first, last) {
|
||||
assert.ok(!updateEvent, "unneccessary update event");
|
||||
doc.bgTokenizer.running = 1;
|
||||
doc.bgTokenizer.$worker();
|
||||
assert.ok(updateEvent);
|
||||
assert.equal([first, last] + "",
|
||||
[updateEvent.first, updateEvent.last] + "")
|
||||
updateEvent = null;
|
||||
}
|
||||
|
||||
forceTokenize(doc);
|
||||
var comment = "comment_regex_allowed";
|
||||
testStates(doc, [comment, comment, comment, "start"]);
|
||||
|
||||
doc.remove(new Range(0,0,0,2));
|
||||
testStates(doc, [comment, comment, comment, "start"]);
|
||||
|
||||
checkEvent(0, 3);
|
||||
testStates(doc, ["start", "no_regex", "no_regex", "regex"]);
|
||||
|
||||
// insert /* and and press down several times quickly
|
||||
doc.insert({row:0, column:0}, "/*");
|
||||
doc.getTokens(0);
|
||||
doc.getTokens(1);
|
||||
doc.getTokens(2);
|
||||
checkEvent(0, 3);
|
||||
|
||||
forceTokenize(doc);
|
||||
testStates(doc, [comment, comment, comment, "start"]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -97,29 +97,33 @@ exports.commands = [{
|
|||
name: "fold",
|
||||
bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"),
|
||||
exec: function(editor) { editor.session.toggleFold(false); },
|
||||
multiSelectAction: "forEach",
|
||||
scrollIntoView: "center",
|
||||
readOnly: true
|
||||
}, {
|
||||
name: "unfold",
|
||||
bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"),
|
||||
exec: function(editor) { editor.session.toggleFold(true); },
|
||||
multiSelectAction: "forEach",
|
||||
scrollIntoView: "center",
|
||||
readOnly: true
|
||||
}, {
|
||||
name: "toggleFoldWidget",
|
||||
bindKey: bindKey("F2", "F2"),
|
||||
exec: function(editor) { editor.session.toggleFoldWidget(); },
|
||||
multiSelectAction: "forEach",
|
||||
scrollIntoView: "center",
|
||||
readOnly: true
|
||||
}, {
|
||||
name: "toggleParentFoldWidget",
|
||||
bindKey: bindKey("Alt-F2", "Alt-F2"),
|
||||
exec: function(editor) { editor.session.toggleFoldWidget(true); },
|
||||
multiSelectAction: "forEach",
|
||||
scrollIntoView: "center",
|
||||
readOnly: true
|
||||
}, {
|
||||
name: "foldall",
|
||||
bindKey: bindKey("Ctrl-Alt-0", "Ctrl-Command-Option-0"),
|
||||
bindKey: bindKey(null, "Ctrl-Command-Option-0"),
|
||||
exec: function(editor) { editor.session.foldAll(); },
|
||||
scrollIntoView: "center",
|
||||
readOnly: true
|
||||
|
|
@ -415,10 +419,16 @@ exports.commands = [{
|
|||
readOnly: true
|
||||
}, {
|
||||
name: "passKeysToBrowser",
|
||||
bindKey: bindKey("null", "null"),
|
||||
bindKey: bindKey(null, null),
|
||||
exec: function() {},
|
||||
passEvent: true,
|
||||
readOnly: true
|
||||
}, {
|
||||
name: "copy",
|
||||
exec: function(editor) {
|
||||
// placeholder for replay macro
|
||||
},
|
||||
readOnly: true
|
||||
},
|
||||
|
||||
// commands disabled in readOnly mode
|
||||
|
|
@ -435,6 +445,12 @@ exports.commands = [{
|
|||
},
|
||||
scrollIntoView: "cursor",
|
||||
multiSelectAction: "forEach"
|
||||
}, {
|
||||
name: "paste",
|
||||
exec: function(editor, args) {
|
||||
editor.$handlePaste(args);
|
||||
},
|
||||
scrollIntoView: "cursor"
|
||||
}, {
|
||||
name: "removeline",
|
||||
bindKey: bindKey("Ctrl-D", "Command-D"),
|
||||
|
|
|
|||
|
|
@ -69,18 +69,14 @@ exports.iSearchCommands = [{
|
|||
bindKey: {win: "Ctrl-F", mac: "Command-F"},
|
||||
exec: function(iSearch) {
|
||||
iSearch.cancelSearch(true);
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}
|
||||
}, {
|
||||
name: "searchForward",
|
||||
bindKey: {win: "Ctrl-S|Ctrl-K", mac: "Ctrl-S|Command-G"},
|
||||
exec: function(iSearch, options) {
|
||||
options.useCurrentOrPrevSearch = true;
|
||||
iSearch.next(options);
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}
|
||||
}, {
|
||||
name: "searchBackward",
|
||||
bindKey: {win: "Ctrl-R|Ctrl-Shift-K", mac: "Ctrl-R|Command-Shift-G"},
|
||||
|
|
@ -88,42 +84,30 @@ exports.iSearchCommands = [{
|
|||
options.useCurrentOrPrevSearch = true;
|
||||
options.backwards = true;
|
||||
iSearch.next(options);
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}
|
||||
}, {
|
||||
name: "extendSearchTerm",
|
||||
exec: function(iSearch, string) {
|
||||
iSearch.addString(string);
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}
|
||||
}, {
|
||||
name: "extendSearchTermSpace",
|
||||
bindKey: "space",
|
||||
exec: function(iSearch) { iSearch.addString(' '); },
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
exec: function(iSearch) { iSearch.addString(' '); }
|
||||
}, {
|
||||
name: "shrinkSearchTerm",
|
||||
bindKey: "backspace",
|
||||
exec: function(iSearch) {
|
||||
iSearch.removeChar();
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}
|
||||
}, {
|
||||
name: 'confirmSearch',
|
||||
bindKey: 'return',
|
||||
exec: function(iSearch) { iSearch.deactivate(); },
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
exec: function(iSearch) { iSearch.deactivate(); }
|
||||
}, {
|
||||
name: 'cancelSearch',
|
||||
bindKey: 'esc|Ctrl-G',
|
||||
exec: function(iSearch) { iSearch.deactivate(true); },
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
exec: function(iSearch) { iSearch.deactivate(true); }
|
||||
}, {
|
||||
name: 'occurisearch',
|
||||
bindKey: 'Ctrl-O',
|
||||
|
|
@ -131,9 +115,7 @@ exports.iSearchCommands = [{
|
|||
var options = oop.mixin({}, iSearch.$options);
|
||||
iSearch.deactivate();
|
||||
occurStartCommand.exec(iSearch.$editor, options);
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}
|
||||
}, {
|
||||
name: "yankNextWord",
|
||||
bindKey: "Ctrl-w",
|
||||
|
|
@ -142,9 +124,7 @@ exports.iSearchCommands = [{
|
|||
range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorWordRight(); }),
|
||||
string = ed.session.getTextRange(range);
|
||||
iSearch.addString(string);
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}
|
||||
}, {
|
||||
name: "yankNextChar",
|
||||
bindKey: "Ctrl-Alt-y",
|
||||
|
|
@ -153,15 +133,11 @@ exports.iSearchCommands = [{
|
|||
range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorRight(); }),
|
||||
string = ed.session.getTextRange(range);
|
||||
iSearch.addString(string);
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}
|
||||
}, {
|
||||
name: 'recenterTopBottom',
|
||||
bindKey: 'Ctrl-l',
|
||||
exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); },
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); }
|
||||
}, {
|
||||
name: 'selectAllMatches',
|
||||
bindKey: 'Ctrl-space',
|
||||
|
|
@ -173,18 +149,19 @@ exports.iSearchCommands = [{
|
|||
return ranges.concat(ea ? ea : []); }, []) : [];
|
||||
iSearch.deactivate(false);
|
||||
ranges.forEach(ed.selection.addRange.bind(ed.selection));
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}
|
||||
}, {
|
||||
name: 'searchAsRegExp',
|
||||
bindKey: 'Alt-r',
|
||||
exec: function(iSearch) {
|
||||
iSearch.convertNeedleToRegExp();
|
||||
},
|
||||
readOnly: true,
|
||||
isIncrementalSearchCommand: true
|
||||
}];
|
||||
}
|
||||
}].map(function(cmd) {
|
||||
cmd.readOnly = true;
|
||||
cmd.isIncrementalSearchCommand = true;
|
||||
cmd.scrollIntoView = "animate-cursor";
|
||||
return cmd;
|
||||
});
|
||||
|
||||
function IncrementalSearchKeyboardHandler(iSearch) {
|
||||
this.$iSearch = iSearch;
|
||||
|
|
@ -192,7 +169,7 @@ function IncrementalSearchKeyboardHandler(iSearch) {
|
|||
|
||||
oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
|
||||
|
||||
;(function() {
|
||||
(function() {
|
||||
|
||||
this.attach = function(editor) {
|
||||
var iSearch = this.$iSearch;
|
||||
|
|
@ -201,15 +178,19 @@ oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
|
|||
if (!e.command.isIncrementalSearchCommand) return undefined;
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return e.command.exec(iSearch, e.args || {});
|
||||
var scrollTop = editor.session.getScrollTop();
|
||||
var result = e.command.exec(iSearch, e.args || {});
|
||||
editor.renderer.scrollCursorIntoView(null, 0.5);
|
||||
editor.renderer.animateScrolling(scrollTop);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.detach = function(editor) {
|
||||
if (!this.$commandExecHandler) return;
|
||||
editor.commands.removeEventListener('exec', this.$commandExecHandler);
|
||||
delete this.$commandExecHandler;
|
||||
}
|
||||
};
|
||||
|
||||
var handleKeyboard$super = this.handleKeyboard;
|
||||
this.handleKeyboard = function(data, hashId, key, keyCode) {
|
||||
|
|
@ -222,7 +203,7 @@ oop.inherits(IncrementalSearchKeyboardHandler, HashHandler);
|
|||
if (extendCmd) { return {command: extendCmd, args: key}; }
|
||||
}
|
||||
return {command: "null", passEvent: hashId == 0 || hashId == 4};
|
||||
}
|
||||
};
|
||||
|
||||
}).call(IncrementalSearchKeyboardHandler.prototype);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ var AppConfig = require("./lib/app_config").AppConfig;
|
|||
module.exports = exports = new AppConfig();
|
||||
|
||||
var global = (function() {
|
||||
return this;
|
||||
return this || typeof window != "undefined" && window;
|
||||
})();
|
||||
|
||||
var options = {
|
||||
|
|
|
|||
|
|
@ -160,6 +160,8 @@
|
|||
z-index: 1;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
/* workaround for chrome bug https://github.com/ajaxorg/ace/issues/2312*/
|
||||
word-wrap: normal;
|
||||
white-space: pre;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
|
@ -420,3 +422,30 @@
|
|||
position: absolute;
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
/*
|
||||
styles = []
|
||||
for (var i = 1; i < 16; i++) {
|
||||
styles.push(".ace_br" + i + "{" + (
|
||||
["top-left", "top-right", "bottom-right", "bottom-left"]
|
||||
).map(function(x, j) {
|
||||
return i & (1<<j) ? "border-" + x + "-radius: 3px;" : ""
|
||||
}).filter(Boolean).join(" ") + "}")
|
||||
}
|
||||
styles.join("\n")
|
||||
*/
|
||||
.ace_br1 {border-top-left-radius : 3px;}
|
||||
.ace_br2 {border-top-right-radius : 3px;}
|
||||
.ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}
|
||||
.ace_br4 {border-bottom-right-radius: 3px;}
|
||||
.ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}
|
||||
.ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}
|
||||
.ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}
|
||||
.ace_br8 {border-bottom-left-radius : 3px;}
|
||||
.ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
|
|
|
|||
|
|
@ -32,36 +32,36 @@ define(function(require, exports, module) {
|
|||
"use strict";
|
||||
|
||||
var oop = require("./lib/oop");
|
||||
var applyDelta = require("./apply_delta").applyDelta;
|
||||
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
||||
var Range = require("./range").Range;
|
||||
var Anchor = require("./anchor").Anchor;
|
||||
|
||||
/**
|
||||
* Contains the text of the document. Document can be attached to several [[EditSession `EditSession`]]s.
|
||||
*
|
||||
* At its core, `Document`s are just an array of strings, with each row in the document matching up to the array index.
|
||||
*
|
||||
* @class Document
|
||||
**/
|
||||
|
||||
/**
|
||||
/**
|
||||
*
|
||||
* Creates a new `Document`. If `text` is included, the `Document` contains those strings; otherwise, it's empty.
|
||||
* @param {String | Array} text The starting text
|
||||
* @constructor
|
||||
**/
|
||||
|
||||
var Document = function(text) {
|
||||
this.$lines = [];
|
||||
var Document = function(textOrLines) {
|
||||
this.$lines = [""];
|
||||
|
||||
// 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 (textOrLines.length === 0) {
|
||||
this.$lines = [""];
|
||||
} else if (Array.isArray(text)) {
|
||||
this._insertLines(0, text);
|
||||
} else if (Array.isArray(textOrLines)) {
|
||||
this.insertMergedLines({row: 0, column: 0}, textOrLines);
|
||||
} else {
|
||||
this.insert({row: 0, column:0}, text);
|
||||
this.insert({row: 0, column:0}, textOrLines);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -75,9 +75,9 @@ var Document = function(text) {
|
|||
* @param {String} text The text to use
|
||||
**/
|
||||
this.setValue = function(text) {
|
||||
var len = this.getLength();
|
||||
this.remove(new Range(0, 0, len, this.getLine(len-1).length));
|
||||
this.insert({row: 0, column:0}, text);
|
||||
var len = this.getLength() - 1;
|
||||
this.remove(new Range(0, 0, len, this.getLine(len).length));
|
||||
this.insert({row: 0, column: 0}, text);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -98,7 +98,7 @@ var Document = function(text) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Splits a string of text on any newline (`\n`) or carriage-return ('\r') characters.
|
||||
* Splits a string of text on any newline (`\n`) or carriage-return (`\r`) characters.
|
||||
*
|
||||
* @method $split
|
||||
* @param {String} text The text to work with
|
||||
|
|
@ -107,14 +107,15 @@ 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
|
||||
} else {
|
||||
this.$split = function(text) {
|
||||
return text.split(/\r\n|\r|\n/);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
this.$detectNewLine = function(text) {
|
||||
|
|
@ -207,32 +208,49 @@ var Document = function(text) {
|
|||
};
|
||||
|
||||
/**
|
||||
* [Given a range within the document, this function returns all the text within that range as a single string.]{: #Document.getTextRange.desc}
|
||||
* @param {Range} range The range to work with
|
||||
* Returns all the text within `range` as a single string.
|
||||
* @param {Range} range The range to work with.
|
||||
*
|
||||
* @returns {String}
|
||||
**/
|
||||
this.getTextRange = function(range) {
|
||||
if (range.start.row == range.end.row) {
|
||||
return this.getLine(range.start.row)
|
||||
.substring(range.start.column, range.end.column);
|
||||
return this.getLinesForRange(range).join(this.getNewLineCharacter());
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all the text within `range` as an array of lines.
|
||||
* @param {Range} range The range to work with.
|
||||
*
|
||||
* @returns {Array}
|
||||
**/
|
||||
this.getLinesForRange = function(range) {
|
||||
var lines;
|
||||
if (range.start.row === range.end.row) {
|
||||
// Handle a single-line range.
|
||||
lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];
|
||||
} else {
|
||||
// Handle a multi-line range.
|
||||
lines = this.getLines(range.start.row, range.end.row);
|
||||
lines[0] = (lines[0] || "").substring(range.start.column);
|
||||
var l = lines.length - 1;
|
||||
if (range.end.row - range.start.row == l)
|
||||
lines[l] = lines[l].substring(0, range.end.column);
|
||||
}
|
||||
var lines = this.getLines(range.start.row, range.end.row);
|
||||
lines[0] = (lines[0] || "").substring(range.start.column);
|
||||
var l = lines.length - 1;
|
||||
if (range.end.row - range.start.row == l)
|
||||
lines[l] = lines[l].substring(0, range.end.column);
|
||||
return lines.join(this.getNewLineCharacter());
|
||||
return lines;
|
||||
};
|
||||
|
||||
this.$clipPosition = function(position) {
|
||||
var length = this.getLength();
|
||||
if (position.row >= length) {
|
||||
position.row = Math.max(0, length - 1);
|
||||
position.column = this.getLine(length-1).length;
|
||||
} else if (position.row < 0)
|
||||
position.row = 0;
|
||||
return position;
|
||||
// Deprecated methods retained for backwards compatibility.
|
||||
this.insertLines = function(row, lines) {
|
||||
console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead.");
|
||||
return this.insertFullLines(row, lines);
|
||||
};
|
||||
this.removeLines = function(firstRow, lastRow) {
|
||||
console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead.");
|
||||
return this.removeFullLines(firstRow, lastRow);
|
||||
};
|
||||
this.insertNewLine = function(position) {
|
||||
console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.");
|
||||
return this.insertMergedLines(position, ["", ""]);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -243,53 +261,97 @@ var Document = function(text) {
|
|||
*
|
||||
**/
|
||||
this.insert = function(position, text) {
|
||||
if (!text || text.length === 0)
|
||||
return position;
|
||||
|
||||
position = this.$clipPosition(position);
|
||||
|
||||
// only detect new lines if the document has no line break yet
|
||||
// Only detect new lines if the document has no line break yet.
|
||||
if (this.getLength() <= 1)
|
||||
this.$detectNewLine(text);
|
||||
|
||||
var lines = this.$split(text);
|
||||
var firstLine = lines.splice(0, 1)[0];
|
||||
var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
|
||||
|
||||
position = this.insertInLine(position, firstLine);
|
||||
if (lastLine !== null) {
|
||||
position = this.insertNewLine(position); // terminate first line
|
||||
position = this._insertLines(position.row, lines);
|
||||
position = this.insertInLine(position, lastLine || "");
|
||||
|
||||
return this.insertMergedLines(position, this.$split(text));
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts `text` into the `position` at the current row. This method also triggers the `"change"` event.
|
||||
*
|
||||
* This differs from the `insert` method in two ways:
|
||||
* 1. This does NOT handle newline characters (single-line text only).
|
||||
* 2. This is faster than the `insert` method for single-line text insertions.
|
||||
*
|
||||
* @param {Object} position The position to insert at; it's an object that looks like `{ row: row, column: column}`
|
||||
* @param {String} text A chunk of text
|
||||
* @returns {Object} Returns an object containing the final row and column, like this:
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
**/
|
||||
this.insertInLine = function(position, text) {
|
||||
var start = this.clippedPos(position.row, position.column);
|
||||
var end = this.pos(position.row, position.column + text.length);
|
||||
|
||||
this.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "insert",
|
||||
lines: [text]
|
||||
}, true);
|
||||
|
||||
return this.clonePos(end);
|
||||
};
|
||||
|
||||
this.clippedPos = function(row, column) {
|
||||
var length = this.getLength();
|
||||
if (row === undefined) {
|
||||
row = length;
|
||||
} else if (row < 0) {
|
||||
row = 0;
|
||||
} else if (row >= length) {
|
||||
row = length - 1;
|
||||
column = undefined;
|
||||
}
|
||||
var line = this.getLine(row);
|
||||
if (column == undefined)
|
||||
column = line.length;
|
||||
column = Math.min(Math.max(column, 0), line.length);
|
||||
return {row: row, column: column};
|
||||
};
|
||||
|
||||
this.clonePos = function(pos) {
|
||||
return {row: pos.row, column: pos.column};
|
||||
};
|
||||
|
||||
this.pos = function(row, column) {
|
||||
return {row: row, column: column};
|
||||
};
|
||||
|
||||
this.$clipPosition = function(position) {
|
||||
var length = this.getLength();
|
||||
if (position.row >= length) {
|
||||
position.row = Math.max(0, length - 1);
|
||||
position.column = this.getLine(length - 1).length;
|
||||
} else {
|
||||
position.row = Math.max(0, position.row);
|
||||
position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);
|
||||
}
|
||||
return position;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fires whenever the document changes.
|
||||
*
|
||||
* Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available:
|
||||
*
|
||||
* * `"insertLines"` (emitted by [[Document.insertLines]])
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `lines`: the lines in the document that are changing
|
||||
* * `"insertText"` (emitted by [[Document.insertNewLine]])
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `text`: the text that's being added
|
||||
* * `"removeLines"` (emitted by [[Document.insertLines]])
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `lines`: the lines in the document that were removed
|
||||
* * `nl`: the new line character (as defined by [[Document.getNewLineCharacter]])
|
||||
* * `"removeText"` (emitted by [[Document.removeInLine]] and [[Document.removeNewLine]])
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `text`: the text that's being removed
|
||||
*
|
||||
* @event change
|
||||
* @param {Object} e Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties.
|
||||
*
|
||||
**/
|
||||
* Fires whenever the document changes.
|
||||
*
|
||||
* Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available:
|
||||
*
|
||||
* * `"insert"`
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `lines`: the lines being added
|
||||
* * `"remove"`
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `lines`: the lines being removed
|
||||
*
|
||||
* @event change
|
||||
* @param {Object} e Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties.
|
||||
*
|
||||
**/
|
||||
|
||||
/**
|
||||
* Inserts the elements in `lines` into the document, starting at the row index given by `row`. This method also triggers the `'change'` event.
|
||||
* Inserts the elements in `lines` into the document as full lines (does not merge with existing line), starting at the row index given by `row`. This method also triggers the `"change"` event.
|
||||
* @param {Number} row The index of the row to insert at
|
||||
* @param {Array} lines An array of strings
|
||||
* @returns {Object} Contains the final row and column, like this:
|
||||
|
|
@ -302,100 +364,57 @@ var Document = function(text) {
|
|||
* ```
|
||||
*
|
||||
**/
|
||||
this.insertLines = function(row, lines) {
|
||||
if (row >= this.getLength())
|
||||
return this.insert({row: row, column: 0}, "\n" + lines.join("\n"));
|
||||
return this._insertLines(Math.max(row, 0), lines);
|
||||
};
|
||||
this._insertLines = function(row, lines) {
|
||||
if (lines.length == 0)
|
||||
return {row: row, column: 0};
|
||||
|
||||
// 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
|
||||
while (lines.length > 0xF000) {
|
||||
var end = this._insertLines(row, lines.slice(0, 0xF000));
|
||||
lines = lines.slice(0xF000);
|
||||
row = end.row;
|
||||
this.insertFullLines = function(row, lines) {
|
||||
// Clip to document.
|
||||
// Allow one past the document end.
|
||||
row = Math.min(Math.max(row, 0), this.getLength());
|
||||
|
||||
// Calculate insertion point.
|
||||
var column = 0;
|
||||
if (row < this.getLength()) {
|
||||
// Insert before the specified row.
|
||||
lines = lines.concat([""]);
|
||||
column = 0;
|
||||
} else {
|
||||
// Insert after the last row in the document.
|
||||
lines = [""].concat(lines);
|
||||
row--;
|
||||
column = this.$lines[row].length;
|
||||
}
|
||||
|
||||
// Insert.
|
||||
this.insertMergedLines({row: row, column: column}, lines);
|
||||
};
|
||||
|
||||
var args = [row, 0];
|
||||
args.push.apply(args, lines);
|
||||
this.$lines.splice.apply(this.$lines, args);
|
||||
|
||||
var range = new Range(row, 0, row + lines.length, 0);
|
||||
var delta = {
|
||||
action: "insertLines",
|
||||
range: range,
|
||||
/**
|
||||
* Inserts the elements in `lines` into the document, starting at the position index given by `row`. This method also triggers the `"change"` event.
|
||||
* @param {Number} row The index of the row to insert at
|
||||
* @param {Array} lines An array of strings
|
||||
* @returns {Object} Contains the final row and column, like this:
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
* If `lines` is empty, this function returns an object containing the current row, and column, like this:
|
||||
* ```
|
||||
* {row: row, column: 0}
|
||||
* ```
|
||||
*
|
||||
**/
|
||||
this.insertMergedLines = function(position, lines) {
|
||||
var start = this.clippedPos(position.row, position.column);
|
||||
var end = {
|
||||
row: start.row + lines.length - 1,
|
||||
column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length
|
||||
};
|
||||
|
||||
this.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "insert",
|
||||
lines: lines
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
return range.end;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts a new line into the document at the current row's `position`. This method also triggers the `'change'` event.
|
||||
* @param {Object} position The position to insert at
|
||||
* @returns {Object} Returns an object containing the final row and column, like this:<br/>
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
*
|
||||
**/
|
||||
this.insertNewLine = function(position) {
|
||||
position = this.$clipPosition(position);
|
||||
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, line.length));
|
||||
|
||||
var end = {
|
||||
row : position.row + 1,
|
||||
column : 0
|
||||
};
|
||||
|
||||
var delta = {
|
||||
action: "insertText",
|
||||
range: Range.fromPoints(position, end),
|
||||
text: this.getNewLineCharacter()
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
|
||||
return end;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event.
|
||||
* @param {Object} position The position to insert at; it's an object that looks like `{ row: row, column: column}`
|
||||
* @param {String} text A chunk of text
|
||||
* @returns {Object} Returns an object containing the final row and column, like this:
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
*
|
||||
**/
|
||||
this.insertInLine = function(position, text) {
|
||||
if (text.length == 0)
|
||||
return position;
|
||||
|
||||
var line = this.$lines[position.row] || "";
|
||||
|
||||
this.$lines[position.row] = line.substring(0, position.column) + text
|
||||
+ line.substring(position.column);
|
||||
|
||||
var end = {
|
||||
row : position.row,
|
||||
column : position.column + text.length
|
||||
};
|
||||
|
||||
var delta = {
|
||||
action: "insertText",
|
||||
range: Range.fromPoints(position, end),
|
||||
text: text
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
|
||||
return end;
|
||||
});
|
||||
|
||||
return this.clonePos(end);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -405,113 +424,90 @@ var Document = function(text) {
|
|||
*
|
||||
**/
|
||||
this.remove = function(range) {
|
||||
if (!(range instanceof Range))
|
||||
range = Range.fromPoints(range.start, range.end);
|
||||
// clip to document
|
||||
range.start = this.$clipPosition(range.start);
|
||||
range.end = this.$clipPosition(range.end);
|
||||
|
||||
if (range.isEmpty())
|
||||
return range.start;
|
||||
|
||||
var firstRow = range.start.row;
|
||||
var lastRow = range.end.row;
|
||||
|
||||
if (range.isMultiLine()) {
|
||||
var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
|
||||
var lastFullRow = lastRow - 1;
|
||||
|
||||
if (range.end.column > 0)
|
||||
this.removeInLine(lastRow, 0, range.end.column);
|
||||
|
||||
if (lastFullRow >= firstFullRow)
|
||||
this._removeLines(firstFullRow, lastFullRow);
|
||||
|
||||
if (firstFullRow != firstRow) {
|
||||
this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
|
||||
this.removeNewLine(range.start.row);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.removeInLine(firstRow, range.start.column, range.end.column);
|
||||
}
|
||||
return range.start;
|
||||
var start = this.clippedPos(range.start.row, range.start.column);
|
||||
var end = this.clippedPos(range.end.row, range.end.column);
|
||||
this.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "remove",
|
||||
lines: this.getLinesForRange({start: start, end: end})
|
||||
});
|
||||
return this.clonePos(start);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the specified columns from the `row`. This method also triggers the `'change'` event.
|
||||
* @param {Number} row The row to remove from
|
||||
* @param {Number} startColumn The column to start removing at
|
||||
* @param {Number} endColumn The column to stop removing at
|
||||
* @returns {Object} Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.<br/>If `startColumn` is equal to `endColumn`, this function returns nothing.
|
||||
*
|
||||
**/
|
||||
* Removes the specified columns from the `row`. This method also triggers a `"change"` event.
|
||||
* @param {Number} row The row to remove from
|
||||
* @param {Number} startColumn The column to start removing at
|
||||
* @param {Number} endColumn The column to stop removing at
|
||||
* @returns {Object} Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.<br/>If `startColumn` is equal to `endColumn`, this function returns nothing.
|
||||
*
|
||||
**/
|
||||
this.removeInLine = function(row, startColumn, endColumn) {
|
||||
if (startColumn == endColumn)
|
||||
return;
|
||||
|
||||
var range = new Range(row, startColumn, row, endColumn);
|
||||
var line = this.getLine(row);
|
||||
var removed = line.substring(startColumn, endColumn);
|
||||
var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
|
||||
this.$lines.splice(row, 1, newLine);
|
||||
|
||||
var delta = {
|
||||
action: "removeText",
|
||||
range: range,
|
||||
text: removed
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
return range.start;
|
||||
var start = this.clippedPos(row, startColumn);
|
||||
var end = this.clippedPos(row, endColumn);
|
||||
|
||||
this.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "remove",
|
||||
lines: this.getLinesForRange({start: start, end: end})
|
||||
}, true);
|
||||
|
||||
return this.clonePos(start);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a range of full lines. This method also triggers the `'change'` event.
|
||||
* Removes a range of full lines. This method also triggers the `"change"` event.
|
||||
* @param {Number} firstRow The first row to be removed
|
||||
* @param {Number} lastRow The last row to be removed
|
||||
* @returns {[String]} Returns all the removed lines.
|
||||
*
|
||||
**/
|
||||
this.removeLines = function(firstRow, lastRow) {
|
||||
if (firstRow < 0 || lastRow >= this.getLength())
|
||||
return this.remove(new Range(firstRow, 0, lastRow + 1, 0));
|
||||
return this._removeLines(firstRow, lastRow);
|
||||
};
|
||||
|
||||
this._removeLines = function(firstRow, lastRow) {
|
||||
var range = new Range(firstRow, 0, lastRow + 1, 0);
|
||||
var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
|
||||
|
||||
var delta = {
|
||||
action: "removeLines",
|
||||
range: range,
|
||||
nl: this.getNewLineCharacter(),
|
||||
lines: removed
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
return removed;
|
||||
this.removeFullLines = function(firstRow, lastRow) {
|
||||
// Clip to document.
|
||||
firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);
|
||||
lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1);
|
||||
|
||||
// Calculate deletion range.
|
||||
// Delete the ending new line unless we're at the end of the document.
|
||||
// If we're at the end of the document, delete the starting new line.
|
||||
var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0;
|
||||
var deleteLastNewLine = lastRow < this.getLength() - 1;
|
||||
var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow );
|
||||
var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 );
|
||||
var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow );
|
||||
var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length );
|
||||
var range = new Range(startRow, startCol, endRow, endCol);
|
||||
|
||||
// Store delelted lines with bounding newlines ommitted (maintains previous behavior).
|
||||
var deletedLines = this.$lines.slice(firstRow, lastRow + 1);
|
||||
|
||||
this.applyDelta({
|
||||
start: range.start,
|
||||
end: range.end,
|
||||
action: "remove",
|
||||
lines: this.getLinesForRange(range)
|
||||
});
|
||||
|
||||
// Return the deleted lines.
|
||||
return deletedLines;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the new line between `row` and the row immediately following it. This method also triggers the `'change'` event.
|
||||
* Removes the new line between `row` and the row immediately following it. This method also triggers the `"change"` event.
|
||||
* @param {Number} row The row to check
|
||||
*
|
||||
**/
|
||||
this.removeNewLine = function(row) {
|
||||
var firstLine = this.getLine(row);
|
||||
var secondLine = this.getLine(row+1);
|
||||
|
||||
var range = new Range(row, firstLine.length, row+1, 0);
|
||||
var line = firstLine + secondLine;
|
||||
|
||||
this.$lines.splice(row, 2, line);
|
||||
|
||||
var delta = {
|
||||
action: "removeText",
|
||||
range: range,
|
||||
text: this.getNewLineCharacter()
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
if (row < this.getLength() - 1 && row >= 0) {
|
||||
this.applyDelta({
|
||||
start: this.pos(row, this.getLine(row).length),
|
||||
end: this.pos(row + 1, 0),
|
||||
action: "remove",
|
||||
lines: ["", ""]
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -525,9 +521,9 @@ var Document = function(text) {
|
|||
*
|
||||
**/
|
||||
this.replace = function(range, text) {
|
||||
if (!(range instanceof Range))
|
||||
if (!range instanceof Range)
|
||||
range = Range.fromPoints(range.start, range.end);
|
||||
if (text.length == 0 && range.isEmpty())
|
||||
if (text.length === 0 && range.isEmpty())
|
||||
return range.start;
|
||||
|
||||
// Shortcut: If the text we want to insert is the same as it is already
|
||||
|
|
@ -536,55 +532,106 @@ var Document = function(text) {
|
|||
return range.end;
|
||||
|
||||
this.remove(range);
|
||||
var end;
|
||||
if (text) {
|
||||
var end = this.insert(range.start, text);
|
||||
end = this.insert(range.start, text);
|
||||
}
|
||||
else {
|
||||
end = range.start;
|
||||
}
|
||||
|
||||
|
||||
return end;
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies all the changes previously accumulated. These can be either `'insertText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
||||
* Applies all changes in `deltas` to the document.
|
||||
* @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions)
|
||||
**/
|
||||
this.applyDeltas = function(deltas) {
|
||||
for (var i=0; i<deltas.length; i++) {
|
||||
var delta = deltas[i];
|
||||
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||
|
||||
if (delta.action == "insertLines")
|
||||
this.insertLines(range.start.row, delta.lines);
|
||||
else if (delta.action == "insertText")
|
||||
this.insert(range.start, delta.text);
|
||||
else if (delta.action == "removeLines")
|
||||
this._removeLines(range.start.row, range.end.row - 1);
|
||||
else if (delta.action == "removeText")
|
||||
this.remove(range);
|
||||
this.applyDelta(deltas[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reverts any changes previously applied. These can be either `'insertText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
||||
* Reverts all changes in `deltas` from the document.
|
||||
* @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions)
|
||||
**/
|
||||
this.revertDeltas = function(deltas) {
|
||||
for (var i=deltas.length-1; i>=0; i--) {
|
||||
var delta = deltas[i];
|
||||
|
||||
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||
|
||||
if (delta.action == "insertLines")
|
||||
this._removeLines(range.start.row, range.end.row - 1);
|
||||
else if (delta.action == "insertText")
|
||||
this.remove(range);
|
||||
else if (delta.action == "removeLines")
|
||||
this._insertLines(range.start.row, delta.lines);
|
||||
else if (delta.action == "removeText")
|
||||
this.insert(range.start, delta.text);
|
||||
this.revertDelta(deltas[i]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Applies `delta` to the document.
|
||||
* @param {Object} delta A delta object (can include "insert" and "remove" actions)
|
||||
**/
|
||||
this.applyDelta = function(delta, doNotValidate) {
|
||||
var isInsert = delta.action == "insert";
|
||||
// An empty range is a NOOP.
|
||||
if (isInsert ? delta.lines.length <= 1 && !delta.lines[0]
|
||||
: !Range.comparePoints(delta.start, delta.end)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInsert && delta.lines.length > 20000)
|
||||
this.$splitAndapplyLargeDelta(delta, 20000);
|
||||
|
||||
// Apply.
|
||||
applyDelta(this.$lines, delta, doNotValidate);
|
||||
this._signal("change", delta);
|
||||
};
|
||||
|
||||
this.$splitAndapplyLargeDelta = function(delta, MAX) {
|
||||
// Split large insert deltas. This is necessary because:
|
||||
// 1. We need to support splicing delta lines into the document via $lines.splice.apply(...)
|
||||
// 2. fn.apply() doesn't work for a large number of params. The smallest threshold is on chrome 40 ~42000.
|
||||
// we use 20000 to leave some space for actual stack
|
||||
//
|
||||
// To Do: Ideally we'd be consistent and also split 'delete' deltas. We don't do this now, because delete
|
||||
// delta handling is too slow. If we make delete delta handling faster we can split all large deltas
|
||||
// as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js
|
||||
// If we do this, update validateDelta() to limit the number of lines in a delete delta.
|
||||
var lines = delta.lines;
|
||||
var l = lines.length;
|
||||
var row = delta.start.row;
|
||||
var column = delta.start.column;
|
||||
var from = 0, to = 0;
|
||||
do {
|
||||
from = to;
|
||||
to += MAX - 1;
|
||||
var chunk = lines.slice(from, to);
|
||||
if (to > l) {
|
||||
// Update remaining delta.
|
||||
delta.lines = chunk;
|
||||
delta.start.row = row + from;
|
||||
delta.start.column = column;
|
||||
break;
|
||||
}
|
||||
chunk.push("");
|
||||
this.applyDelta({
|
||||
start: this.pos(row + from, column),
|
||||
end: this.pos(row + to, column = 0),
|
||||
action: delta.action,
|
||||
lines: chunk
|
||||
}, true);
|
||||
} while(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts `delta` from the document.
|
||||
* @param {Object} delta A delta object (can include "insert" and "remove" actions)
|
||||
**/
|
||||
this.revertDelta = function(delta) {
|
||||
this.applyDelta({
|
||||
start: this.clonePos(delta.start),
|
||||
end: this.clonePos(delta.end),
|
||||
action: (delta.action == "insert" ? "remove" : "insert"),
|
||||
lines: delta.lines.slice()
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an index position in a document to a `{row, column}` object.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.insert({row: 0, column: 1}, "juhu");
|
||||
assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
|
||||
|
|
@ -63,9 +63,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.insertNewLine({row: 0, column: 1});
|
||||
doc.insertMergedLines({row: 0, column: 1}, ['', '']);
|
||||
assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
|
|
@ -80,9 +80,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.insertLines(0, ["aa", "bb"]);
|
||||
doc.insertFullLines(0, ["aa", "bb"]);
|
||||
assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
|
|
@ -97,9 +97,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.insertLines(2, ["aa", "bb"]);
|
||||
doc.insertFullLines(2, ["aa", "bb"]);
|
||||
assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n"));
|
||||
},
|
||||
|
||||
|
|
@ -107,9 +107,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.insertLines(1, ["aa", "bb"]);
|
||||
doc.insertFullLines(1, ["aa", "bb"]);
|
||||
assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
|
|
@ -124,7 +124,7 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.insert({row: 0, column: 0}, "aa\nbb\ncc");
|
||||
assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
|
||||
|
|
@ -141,9 +141,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.insert({row: 2, column: 0}, "aa\nbb\ncc");
|
||||
doc.insert({row: 1, column: 2}, "aa\nbb\ncc");
|
||||
assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
|
|
@ -158,7 +158,7 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.insert({row: 0, column: 1}, "aa\nbb\ncc");
|
||||
assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
|
||||
|
|
@ -175,7 +175,7 @@ module.exports = {
|
|||
var doc = new Document(["1234", "5678"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.remove(new Range(0, 1, 0, 3));
|
||||
assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
|
||||
|
|
@ -192,7 +192,7 @@ module.exports = {
|
|||
var doc = new Document(["1234", "5678"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.remove(new Range(0, 4, 1, 0));
|
||||
assert.equal(doc.getValue(), ["12345678"].join("\n"));
|
||||
|
|
@ -209,7 +209,7 @@ module.exports = {
|
|||
var doc = new Document(["1234", "5678", "abcd"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.remove(new Range(0, 2, 2, 2));
|
||||
assert.equal(doc.getValue(), ["12cd"].join("\n"));
|
||||
|
|
@ -226,7 +226,7 @@ module.exports = {
|
|||
var doc = new Document(["1234", "5678", "abcd"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
|
||||
doc.remove(new Range(1, 0, 3, 0));
|
||||
assert.equal(doc.getValue(), ["1234", ""].join("\n"));
|
||||
|
|
@ -235,7 +235,7 @@ module.exports = {
|
|||
"test: remove lines should return the removed lines" : function() {
|
||||
var doc = new Document(["1234", "5678", "abcd"]);
|
||||
|
||||
var removed = doc.removeLines(1, 2);
|
||||
var removed = doc.removeFullLines(1, 2);
|
||||
assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n"));
|
||||
},
|
||||
|
||||
|
|
@ -296,6 +296,35 @@ module.exports = {
|
|||
"test: empty document has to contain one line": function() {
|
||||
var doc = new Document("");
|
||||
assert.equal(doc.$lines.length, 1);
|
||||
},
|
||||
|
||||
"test: ignore empty delta": function() {
|
||||
var doc = new Document("");
|
||||
doc.on("change", function() {
|
||||
throw "should ignore empty delta";
|
||||
})
|
||||
doc.insert({row: 0, column: 0}, "");
|
||||
doc.insert({row: 1, column: 1}, "");
|
||||
doc.remove({start: {row: 1, column: 1}, end: {row: 1, column: 1}});
|
||||
},
|
||||
|
||||
"test: inserting huge delta": function() {
|
||||
var doc = new Document("");
|
||||
var val = "";
|
||||
var MAX = 0xF000;
|
||||
for (var i = 0; i < 10 * MAX; i++) {
|
||||
val += i + "\n"
|
||||
}
|
||||
doc.setValue(val);
|
||||
assert.equal(doc.getValue(), val);
|
||||
|
||||
for (var i = 3 * MAX + 2; i >= 3 * MAX - 2; i--) {
|
||||
val = doc.getLines(0, i).join("\n");
|
||||
doc.setValue("\nab");
|
||||
assert.equal(doc.getValue(), "\nab");
|
||||
doc.insert({row: 1, column: 1}, val);
|
||||
assert.equal(doc.getValue(), "\na" + val + "b");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ var EditSession = function(text, mode) {
|
|||
this.$foldData = [];
|
||||
this.$foldData.toString = function() {
|
||||
return this.join("\n");
|
||||
}
|
||||
};
|
||||
this.on("changeFold", this.onChangeFold.bind(this));
|
||||
this.$onChange = this.onChange.bind(this);
|
||||
|
||||
|
|
@ -249,13 +249,12 @@ var EditSession = function(text, mode) {
|
|||
this.$resetRowCache(fold.start.row);
|
||||
};
|
||||
|
||||
this.onChange = function(e) {
|
||||
var delta = e.data;
|
||||
this.onChange = function(delta) {
|
||||
this.$modified = true;
|
||||
|
||||
this.$resetRowCache(delta.range.start.row);
|
||||
this.$resetRowCache(delta.start.row);
|
||||
|
||||
var removedFolds = this.$updateInternalDataOnChange(e);
|
||||
var removedFolds = this.$updateInternalDataOnChange(delta);
|
||||
if (!this.$fromUndo && this.$undoManager && !delta.ignore) {
|
||||
this.$deltasDoc.push(delta);
|
||||
if (removedFolds && removedFolds.length != 0) {
|
||||
|
|
@ -269,7 +268,7 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
|
||||
this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta);
|
||||
this._signal("change", e);
|
||||
this._signal("change", delta);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -679,10 +678,10 @@ var EditSession = function(text, mode) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Returns an array containing the IDs of all the markers, either front or back.
|
||||
* Returns an object containing all of the markers, either front or back.
|
||||
* @param {Boolean} inFront If `true`, indicates you only want front markers; `false` indicates only back markers
|
||||
*
|
||||
* @returns {Array}
|
||||
* @returns {Object}
|
||||
**/
|
||||
this.getMarkers = function(inFront) {
|
||||
return inFront ? this.$frontMarkers : this.$backMarkers;
|
||||
|
|
@ -893,17 +892,17 @@ var EditSession = function(text, mode) {
|
|||
config.loadModule(["mode", path], function(m) {
|
||||
if (this.$modeId !== path)
|
||||
return cb && cb();
|
||||
if (this.$modes[path] && !options)
|
||||
return this.$onChangeMode(this.$modes[path]);
|
||||
if (m && m.Mode) {
|
||||
if (this.$modes[path] && !options) {
|
||||
this.$onChangeMode(this.$modes[path]);
|
||||
} else if (m && m.Mode) {
|
||||
m = new m.Mode(options);
|
||||
if (!options) {
|
||||
this.$modes[path] = m;
|
||||
m.$id = path;
|
||||
}
|
||||
this.$onChangeMode(m);
|
||||
cb && cb();
|
||||
}
|
||||
cb && cb();
|
||||
}.bind(this));
|
||||
|
||||
// set mode to text until loading is finished
|
||||
|
|
@ -1146,6 +1145,19 @@ var EditSession = function(text, mode) {
|
|||
this.remove = function(range) {
|
||||
return this.doc.remove(range);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a range of full lines. This method also triggers the `'change'` event.
|
||||
* @param {Number} firstRow The first row to be removed
|
||||
* @param {Number} lastRow The last row to be removed
|
||||
* @returns {[String]} Returns all the removed lines.
|
||||
*
|
||||
* @related Document.removeFullLines
|
||||
*
|
||||
**/
|
||||
this.removeFullLines = function(firstRow, lastRow){
|
||||
return this.doc.removeFullLines(firstRow, lastRow);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts previous changes to your document.
|
||||
|
|
@ -1222,39 +1234,36 @@ var EditSession = function(text, mode) {
|
|||
|
||||
this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
|
||||
function isInsert(delta) {
|
||||
var insert =
|
||||
delta.action === "insertText" || delta.action === "insertLines";
|
||||
return isUndo ? !insert : insert;
|
||||
return isUndo ? delta.action !== "insert" : delta.action === "insert";
|
||||
}
|
||||
|
||||
var delta = deltas[0];
|
||||
var range, point;
|
||||
var lastDeltaIsInsert = false;
|
||||
if (isInsert(delta)) {
|
||||
range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||
range = Range.fromPoints(delta.start, delta.end);
|
||||
lastDeltaIsInsert = true;
|
||||
} else {
|
||||
range = Range.fromPoints(delta.range.start, delta.range.start);
|
||||
range = Range.fromPoints(delta.start, delta.start);
|
||||
lastDeltaIsInsert = false;
|
||||
}
|
||||
|
||||
for (var i = 1; i < deltas.length; i++) {
|
||||
delta = deltas[i];
|
||||
if (isInsert(delta)) {
|
||||
point = delta.range.start;
|
||||
point = delta.start;
|
||||
if (range.compare(point.row, point.column) == -1) {
|
||||
range.setStart(delta.range.start);
|
||||
range.setStart(point);
|
||||
}
|
||||
point = delta.range.end;
|
||||
point = delta.end;
|
||||
if (range.compare(point.row, point.column) == 1) {
|
||||
range.setEnd(delta.range.end);
|
||||
range.setEnd(point);
|
||||
}
|
||||
lastDeltaIsInsert = true;
|
||||
} else {
|
||||
point = delta.range.start;
|
||||
point = delta.start;
|
||||
if (range.compare(point.row, point.column) == -1) {
|
||||
range =
|
||||
Range.fromPoints(delta.range.start, delta.range.start);
|
||||
range = Range.fromPoints(delta.start, delta.start);
|
||||
}
|
||||
lastDeltaIsInsert = false;
|
||||
}
|
||||
|
|
@ -1368,7 +1377,7 @@ var EditSession = function(text, mode) {
|
|||
this.indentRows = function(startRow, endRow, indentString) {
|
||||
indentString = indentString.replace(/\t/g, this.getTabString());
|
||||
for (var row=startRow; row<=endRow; row++)
|
||||
this.insert({row: row, column:0}, indentString);
|
||||
this.doc.insertInLine({row: row, column: 0}, indentString);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1425,11 +1434,11 @@ var EditSession = function(text, mode) {
|
|||
x.end.row += diff;
|
||||
return x;
|
||||
});
|
||||
|
||||
|
||||
var lines = dir == 0
|
||||
? this.doc.getLines(firstRow, lastRow)
|
||||
: this.doc.removeLines(firstRow, lastRow);
|
||||
this.doc.insertLines(firstRow+diff, lines);
|
||||
: this.doc.removeFullLines(firstRow, lastRow);
|
||||
this.doc.insertFullLines(firstRow+diff, lines);
|
||||
folds.length && this.addFolds(folds);
|
||||
return diff;
|
||||
};
|
||||
|
|
@ -1439,8 +1448,6 @@ var EditSession = function(text, mode) {
|
|||
* @param {Number} lastRow The final row to move up
|
||||
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
|
||||
*
|
||||
* @related Document.insertLines
|
||||
*
|
||||
**/
|
||||
this.moveLinesUp = function(firstRow, lastRow) {
|
||||
return this.$moveLines(firstRow, lastRow, -1);
|
||||
|
|
@ -1451,8 +1458,6 @@ var EditSession = function(text, mode) {
|
|||
* @param {Number} firstRow The starting row to move down
|
||||
* @param {Number} lastRow The final row to move down
|
||||
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
|
||||
*
|
||||
* @related Document.insertLines
|
||||
**/
|
||||
this.moveLinesDown = function(firstRow, lastRow) {
|
||||
return this.$moveLines(firstRow, lastRow, 1);
|
||||
|
|
@ -1580,13 +1585,11 @@ var EditSession = function(text, mode) {
|
|||
**/
|
||||
this.setWrapLimitRange = function(min, max) {
|
||||
if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) {
|
||||
this.$wrapLimitRange = {
|
||||
min: min,
|
||||
max: max
|
||||
};
|
||||
this.$wrapLimitRange = { min: min, max: max };
|
||||
this.$modified = true;
|
||||
// This will force a recalculation of the wrap limit
|
||||
this._signal("changeWrapMode");
|
||||
if (this.$useWrapMode)
|
||||
this._signal("changeWrapMode");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1658,34 +1661,23 @@ var EditSession = function(text, mode) {
|
|||
};
|
||||
};
|
||||
|
||||
this.$updateInternalDataOnChange = function(e) {
|
||||
this.$updateInternalDataOnChange = function(delta) {
|
||||
var useWrapMode = this.$useWrapMode;
|
||||
var len;
|
||||
var action = e.data.action;
|
||||
var firstRow = e.data.range.start.row;
|
||||
var lastRow = e.data.range.end.row;
|
||||
var start = e.data.range.start;
|
||||
var end = e.data.range.end;
|
||||
var action = delta.action;
|
||||
var start = delta.start;
|
||||
var end = delta.end;
|
||||
var firstRow = start.row;
|
||||
var lastRow = end.row;
|
||||
var len = lastRow - firstRow;
|
||||
var removedFolds = null;
|
||||
|
||||
if (action.indexOf("Lines") != -1) {
|
||||
if (action == "insertLines") {
|
||||
lastRow = firstRow + (e.data.lines.length);
|
||||
} else {
|
||||
lastRow = firstRow;
|
||||
}
|
||||
len = e.data.lines ? e.data.lines.length : lastRow - firstRow;
|
||||
} else {
|
||||
len = lastRow - firstRow;
|
||||
}
|
||||
|
||||
|
||||
this.$updating = true;
|
||||
if (len != 0) {
|
||||
if (action.indexOf("remove") != -1) {
|
||||
if (action === "remove") {
|
||||
this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len);
|
||||
|
||||
var foldLines = this.$foldData;
|
||||
removedFolds = this.getFoldsInRange(e.data.range);
|
||||
removedFolds = this.getFoldsInRange(delta);
|
||||
this.removeFolds(removedFolds);
|
||||
|
||||
var foldLine = this.getFoldLine(end.row);
|
||||
|
|
@ -1750,10 +1742,10 @@ var EditSession = function(text, mode) {
|
|||
} else {
|
||||
// Realign folds. E.g. if you add some new chars before a fold, the
|
||||
// fold should "move" to the right.
|
||||
len = Math.abs(e.data.range.start.column - e.data.range.end.column);
|
||||
if (action.indexOf("remove") != -1) {
|
||||
len = Math.abs(delta.start.column - delta.end.column);
|
||||
if (action === "remove") {
|
||||
// Get all the folds in the change range and remove them.
|
||||
removedFolds = this.getFoldsInRange(e.data.range);
|
||||
removedFolds = this.getFoldsInRange(delta);
|
||||
this.removeFolds(removedFolds);
|
||||
|
||||
len = -len;
|
||||
|
|
@ -1837,7 +1829,7 @@ var EditSession = function(text, mode) {
|
|||
TAB_SPACE = 12;
|
||||
|
||||
|
||||
this.$computeWrapSplits = function(tokens, wrapLimit) {
|
||||
this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) {
|
||||
if (tokens.length == 0) {
|
||||
return [];
|
||||
}
|
||||
|
|
@ -1848,6 +1840,31 @@ var EditSession = function(text, mode) {
|
|||
|
||||
var isCode = this.$wrapAsCode;
|
||||
|
||||
var indentedSoftWrap = this.$indentedSoftWrap;
|
||||
var maxIndent = wrapLimit <= Math.max(2 * tabSize, 8)
|
||||
|| indentedSoftWrap === false ? 0 : Math.floor(wrapLimit / 2);
|
||||
|
||||
function getWrapIndent() {
|
||||
var indentation = 0;
|
||||
if (maxIndent === 0)
|
||||
return indentation;
|
||||
if (indentedSoftWrap) {
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var token = tokens[i];
|
||||
if (token == SPACE)
|
||||
indentation += 1;
|
||||
else if (token == TAB)
|
||||
indentation += tabSize;
|
||||
else if (token == TAB_SPACE)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isCode && indentedSoftWrap !== false)
|
||||
indentation += tabSize;
|
||||
return Math.min(indentation, maxIndent);
|
||||
}
|
||||
function addSplit(screenPos) {
|
||||
var displayed = tokens.slice(lastSplit, screenPos);
|
||||
|
||||
|
|
@ -1864,14 +1881,18 @@ var EditSession = function(text, mode) {
|
|||
len -= 1;
|
||||
});
|
||||
|
||||
if (!splits.length) {
|
||||
indent = getWrapIndent();
|
||||
splits.indent = indent;
|
||||
}
|
||||
lastDocSplit += len;
|
||||
splits.push(lastDocSplit);
|
||||
lastSplit = screenPos;
|
||||
}
|
||||
|
||||
while (displayLength - lastSplit > wrapLimit) {
|
||||
var indent = 0;
|
||||
while (displayLength - lastSplit > wrapLimit - indent) {
|
||||
// This is, where the split should be.
|
||||
var split = lastSplit + wrapLimit;
|
||||
var split = lastSplit + wrapLimit - indent;
|
||||
|
||||
// If there is a space or tab at this split position, then making
|
||||
// a split is simple.
|
||||
|
|
@ -1931,7 +1952,7 @@ var EditSession = function(text, mode) {
|
|||
|
||||
// === ELSE ===
|
||||
// Search for the first non space/tab/placeholder/punctuation token backwards.
|
||||
var minSplit = Math.max(split - (isCode ? 10 : wrapLimit-(wrapLimit>>2)), lastSplit - 1);
|
||||
var minSplit = Math.max(split - (wrapLimit -(wrapLimit>>2)), lastSplit - 1);
|
||||
while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
|
||||
split --;
|
||||
}
|
||||
|
|
@ -1959,7 +1980,7 @@ var EditSession = function(text, mode) {
|
|||
// around -> force a split.
|
||||
if (tokens[split] == CHAR_EXT)
|
||||
split--;
|
||||
addSplit(split);
|
||||
addSplit(split - indent);
|
||||
}
|
||||
return splits;
|
||||
};
|
||||
|
|
@ -2066,6 +2087,16 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
};
|
||||
|
||||
this.getRowWrapIndent = function(screenRow) {
|
||||
if (this.$useWrapMode) {
|
||||
var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
|
||||
var splits = this.$wrapData[pos.row];
|
||||
return splits.length && splits[0] < pos.column ? splits.indent : 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position (on screen) for the last character in the provided screen row.
|
||||
* @param {Number} screenRow The screen row to check
|
||||
|
|
@ -2203,20 +2234,21 @@ var EditSession = function(text, mode) {
|
|||
line = this.getLine(docRow);
|
||||
foldLine = null;
|
||||
}
|
||||
|
||||
var wrapIndent = 0;
|
||||
if (this.$useWrapMode) {
|
||||
var splits = this.$wrapData[docRow];
|
||||
if (splits) {
|
||||
var splitIndex = Math.floor(screenRow - row);
|
||||
column = splits[splitIndex];
|
||||
if(splitIndex > 0 && splits.length) {
|
||||
wrapIndent = splits.indent;
|
||||
docColumn = splits[splitIndex - 1] || splits[splits.length - 1];
|
||||
line = line.substring(docColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
|
||||
docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1];
|
||||
|
||||
// We remove one character at the end so that the docColumn
|
||||
// position returned is not associated to the next row on the screen.
|
||||
|
|
@ -2308,6 +2340,7 @@ var EditSession = function(text, mode) {
|
|||
textLine = this.getLine(docRow).substring(0, docColumn);
|
||||
foldStartRow = docRow;
|
||||
}
|
||||
var wrapIndent = 0;
|
||||
// Clamp textLine if in wrapMode.
|
||||
if (this.$useWrapMode) {
|
||||
var wrapRow = this.$wrapData[foldStartRow];
|
||||
|
|
@ -2320,12 +2353,13 @@ var EditSession = function(text, mode) {
|
|||
textLine = textLine.substring(
|
||||
wrapRow[screenRowOffset - 1] || 0, textLine.length
|
||||
);
|
||||
wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
row: screenRow,
|
||||
column: this.$getStringScreenWidth(textLine)[0]
|
||||
column: wrapIndent + this.$getStringScreenWidth(textLine)[0]
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -2467,6 +2501,7 @@ config.defineOptions(EditSession.prototype, "session", {
|
|||
|
||||
if (this.$wrap == value)
|
||||
return;
|
||||
this.$wrap = value;
|
||||
if (!value) {
|
||||
this.setUseWrapMode(false);
|
||||
} else {
|
||||
|
|
@ -2474,7 +2509,6 @@ config.defineOptions(EditSession.prototype, "session", {
|
|||
this.setWrapLimitRange(col, col);
|
||||
this.setUseWrapMode(true);
|
||||
}
|
||||
this.$wrap = value;
|
||||
},
|
||||
get: function() {
|
||||
if (this.getUseWrapMode()) {
|
||||
|
|
@ -2505,6 +2539,7 @@ config.defineOptions(EditSession.prototype, "session", {
|
|||
},
|
||||
initialValue: "auto"
|
||||
},
|
||||
indentedSoftWrap: { initialValue: true },
|
||||
firstLineNumber: {
|
||||
set: function() {this._signal("changeBreakpoint");},
|
||||
initialValue: 1
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ function BracketMatch() {
|
|||
typeRe = new RegExp(
|
||||
"(\\.?" +
|
||||
token.type.replace(".", "\\.").replace("rparen", ".paren")
|
||||
.replace(/\b(?:end|start|begin)\b/, "")
|
||||
.replace(/\b(?:end)\b/, "(?:start|begin|end)")
|
||||
+ ")+"
|
||||
);
|
||||
}
|
||||
|
|
@ -174,7 +174,7 @@ function BracketMatch() {
|
|||
typeRe = new RegExp(
|
||||
"(\\.?" +
|
||||
token.type.replace(".", "\\.").replace("lparen", ".paren")
|
||||
.replace(/\b(?:end|start|begin)\b/, "")
|
||||
.replace(/\b(?:start|begin)\b/, "(?:start|begin|end)")
|
||||
+ ")+"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -794,7 +794,7 @@ function Folding() {
|
|||
this.foldAll(startRow, endRow, options.all ? 10000 : 0);
|
||||
} else if (options.children) {
|
||||
endRow = range ? range.end.row : this.getLength();
|
||||
this.foldAll(row + 1, range.end.row, options.all ? 10000 : 0);
|
||||
this.foldAll(row + 1, endRow, options.all ? 10000 : 0);
|
||||
} else if (range) {
|
||||
if (options.all)
|
||||
range.collapseChildren = 10000;
|
||||
|
|
@ -829,15 +829,13 @@ function Folding() {
|
|||
}
|
||||
};
|
||||
|
||||
this.updateFoldWidgets = function(e) {
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
var firstRow = range.start.row;
|
||||
var len = range.end.row - firstRow;
|
||||
this.updateFoldWidgets = function(delta) {
|
||||
var firstRow = delta.start.row;
|
||||
var len = delta.end.row - firstRow;
|
||||
|
||||
if (len === 0) {
|
||||
this.foldWidgets[firstRow] = null;
|
||||
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
||||
} else if (delta.action == 'remove') {
|
||||
this.foldWidgets.splice(firstRow, len + 1, null);
|
||||
} else {
|
||||
var args = Array(len + 1);
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ module.exports = {
|
|||
session.setUseWrapMode(true);
|
||||
session.setWrapLimitRange(12, 12);
|
||||
session.adjustWrapLimit(80);
|
||||
|
||||
session.setOption("wrapMethod", "text");
|
||||
assert.position(session.documentToScreenPosition(0, 11), 0, 11);
|
||||
assert.position(session.documentToScreenPosition(0, 12), 1, 0);
|
||||
},
|
||||
|
|
@ -380,7 +380,8 @@ module.exports = {
|
|||
line = lang.stringTrimRight(line);
|
||||
var tokens = EditSession.prototype.$getDisplayTokens(line);
|
||||
var splits = EditSession.prototype.$computeWrapSplits(tokens, wrapLimit, tabSize);
|
||||
// console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
|
||||
console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
|
||||
|
||||
assert.ok(splits.length == assertEqual.length);
|
||||
for (var i = 0; i < splits.length; i++) {
|
||||
assert.ok(splits[i] == assertEqual[i]);
|
||||
|
|
@ -388,6 +389,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
EditSession.prototype.$wrapAsCode = true;
|
||||
EditSession.prototype.$indentedSoftWrap = false;
|
||||
// Basic splitting.
|
||||
computeAndAssert("foo bar foo bar", [ 12 ]);
|
||||
computeAndAssert("foo bar f bar", [ 12 ]);
|
||||
|
|
@ -413,16 +415,26 @@ module.exports = {
|
|||
computeAndAssert("ぁぁ", [1], 2);
|
||||
computeAndAssert(" ぁぁ", [1, 2], 2);
|
||||
computeAndAssert(" ぁ\tぁ", [1, 3], 2);
|
||||
computeAndAssert(" ぁぁ\tぁ", [1, 4], 4);
|
||||
computeAndAssert(" ぁぁ\tぁ", [2, 4], 4);
|
||||
computeAndAssert("ぁぁ ぁぁ\tぁ", [3, 6], 6);
|
||||
|
||||
// Test wrapping for punctuation.
|
||||
computeAndAssert(" ab.c;ef++", [1, 3, 5, 7, 8], 2);
|
||||
computeAndAssert(" ab.c;ef++", [2, 4, 6, 8], 2);
|
||||
computeAndAssert(" ab.c;ef++", [3, 5, 8], 3);
|
||||
computeAndAssert(" a.b", [1, 2, 3], 1);
|
||||
computeAndAssert("#>>", [1, 2], 1);
|
||||
|
||||
// Test wrapping for punctuation in
|
||||
EditSession.prototype.$wrapAsCode = false;
|
||||
computeAndAssert("ab cde, Juhu kinners", [3, 8, 13, 19], 6);
|
||||
|
||||
// test indented wrapping
|
||||
EditSession.prototype.$indentedSoftWrap = true;
|
||||
computeAndAssert("foo bar foo bar foo bara foo", [12, 25]);
|
||||
computeAndAssert("fooooooooooooooooooooooooooo", [12, 24]);
|
||||
computeAndAssert("\t\tfoo bar fooooooooooobooooooo", [6, 10, 16, 22, 28]);
|
||||
computeAndAssert("\t\t\tfoo bar fooooooooooobooooooo", [3, 7, 11, 17, 23, 29]);
|
||||
computeAndAssert("\tfoo \t \t \t \t bar", [6, 12]); // 14
|
||||
},
|
||||
|
||||
"test get longest line" : function() {
|
||||
|
|
@ -430,12 +442,12 @@ module.exports = {
|
|||
session.setTabSize(4);
|
||||
assert.equal(session.getScreenWidth(), 2);
|
||||
|
||||
session.doc.insertNewLine({row: 0, column: Infinity});
|
||||
session.doc.insertLines(1, ["123"]);
|
||||
session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']);
|
||||
session.doc.insertFullLines(1, ["123"]);
|
||||
assert.equal(session.getScreenWidth(), 3);
|
||||
|
||||
session.doc.insertNewLine({row: 0, column: Infinity});
|
||||
session.doc.insertLines(1, ["\t\t"]);
|
||||
session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']);
|
||||
session.doc.insertFullLines(1, ["\t\t"]);
|
||||
|
||||
assert.equal(session.getScreenWidth(), 8);
|
||||
|
||||
|
|
@ -459,9 +471,9 @@ module.exports = {
|
|||
|
||||
session.setUseWrapMode(true);
|
||||
|
||||
document.insertLines(0, ["a", "b"]);
|
||||
document.insertLines(2, ["c", "d"]);
|
||||
document.removeLines(1, 2);
|
||||
document.insertFullLines(0, ["a", "b"]);
|
||||
document.insertFullLines(2, ["c", "d"]);
|
||||
document.removeFullLines(1, 2);
|
||||
},
|
||||
|
||||
"test wrapMode init has to create wrapData array": function() {
|
||||
|
|
|
|||
|
|
@ -150,9 +150,8 @@ var Editor = function(renderer, session) {
|
|||
args: commadEvent.args,
|
||||
scrollTop: this.renderer.scrollTop
|
||||
};
|
||||
if (this.curOp.command.name)
|
||||
if (this.curOp.command.name && this.curOp.command.scrollIntoView !== undefined)
|
||||
this.$blockScrolling++;
|
||||
// this.selections.push(this.selection.toJSON());
|
||||
};
|
||||
|
||||
this.endOperation = function(e) {
|
||||
|
|
@ -161,10 +160,14 @@ var Editor = function(renderer, session) {
|
|||
return this.curOp = null;
|
||||
this._signal("beforeEndOperation");
|
||||
var command = this.curOp.command;
|
||||
if (command.name && this.$blockScrolling)
|
||||
if (command.name && this.$blockScrolling > 0)
|
||||
this.$blockScrolling--;
|
||||
if (command && command.scrollIntoView) {
|
||||
switch (command.scrollIntoView) {
|
||||
var scrollIntoView = command && command.scrollIntoView;
|
||||
if (scrollIntoView) {
|
||||
switch (scrollIntoView) {
|
||||
case "center-animate":
|
||||
scrollIntoView = "animate";
|
||||
/* fall through */
|
||||
case "center":
|
||||
this.renderer.scrollCursorIntoView(null, 0.5);
|
||||
break;
|
||||
|
|
@ -182,7 +185,7 @@ var Editor = function(renderer, session) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
if (command.scrollIntoView == "animate")
|
||||
if (scrollIntoView == "animate")
|
||||
this.renderer.animateScrolling(this.curOp.scrollTop);
|
||||
}
|
||||
|
||||
|
|
@ -275,6 +278,10 @@ var Editor = function(renderer, session) {
|
|||
this.setSession = function(session) {
|
||||
if (this.session == session)
|
||||
return;
|
||||
|
||||
// make sure operationEnd events are not emitted to wrong session
|
||||
if (this.curOp) this.endOperation();
|
||||
this.curOp = {};
|
||||
|
||||
var oldSession = this.session;
|
||||
if (oldSession) {
|
||||
|
|
@ -374,6 +381,8 @@ var Editor = function(renderer, session) {
|
|||
oldSession: oldSession
|
||||
});
|
||||
|
||||
this.curOp = null;
|
||||
|
||||
oldSession && oldSession._signal("changeEditor", {oldEditor: this});
|
||||
session && session._signal("changeEditor", {editor: this});
|
||||
};
|
||||
|
|
@ -545,9 +554,12 @@ var Editor = function(renderer, session) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (token.type.indexOf("tag-open") != -1)
|
||||
if (token.type.indexOf("tag-open") != -1) {
|
||||
token = iterator.stepForward();
|
||||
|
||||
if (!token)
|
||||
return;
|
||||
}
|
||||
|
||||
var tag = token.value;
|
||||
var depth = 0;
|
||||
var prevToken = iterator.stepBackward();
|
||||
|
|
@ -680,20 +692,15 @@ var Editor = function(renderer, session) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.onDocumentChange = function(e) {
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
var lastRow;
|
||||
this.onDocumentChange = function(delta) {
|
||||
// Rerender and emit "change" event.
|
||||
var wrap = this.session.$useWrapMode;
|
||||
var lastRow = (delta.start.row == delta.end.row ? delta.end.row : Infinity);
|
||||
this.renderer.updateLines(delta.start.row, lastRow, wrap);
|
||||
|
||||
if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines")
|
||||
lastRow = range.end.row;
|
||||
else
|
||||
lastRow = Infinity;
|
||||
this.renderer.updateLines(range.start.row, lastRow, this.session.$useWrapMode);
|
||||
|
||||
this._signal("change", e);
|
||||
|
||||
// update cursor because tab characters can influence the cursor position
|
||||
this._signal("change", delta);
|
||||
|
||||
// Update cursor because tab characters can influence the cursor position.
|
||||
this.$cursorChange();
|
||||
this.$updateHighlightActiveLine();
|
||||
};
|
||||
|
|
@ -908,14 +915,16 @@ var Editor = function(renderer, session) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.onPaste = function(text) {
|
||||
// todo this should change when paste becomes a command
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
||||
var e = {text: text};
|
||||
this.onPaste = function(text, event) {
|
||||
var e = {text: text, event: event};
|
||||
this.commands.exec("paste", this, e);
|
||||
};
|
||||
|
||||
this.$handlePaste = function(e) {
|
||||
if (typeof e == "string")
|
||||
e = {text: e};
|
||||
this._signal("paste", e);
|
||||
text = e.text;
|
||||
var text = e.text;
|
||||
if (!this.inMultiSelectMode || this.inVirtualSelectionMode) {
|
||||
this.insert(text);
|
||||
} else {
|
||||
|
|
@ -933,7 +942,6 @@ var Editor = function(renderer, session) {
|
|||
this.session.insert(range.start, lines[i]);
|
||||
}
|
||||
}
|
||||
this.renderer.scrollCursorIntoView();
|
||||
};
|
||||
|
||||
this.execCommand = function(command, args) {
|
||||
|
|
@ -1289,7 +1297,7 @@ var Editor = function(renderer, session) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Removes words of text from the editor. A "word" is defined as a string of characters bookended by whitespace.
|
||||
* Removes the current selection or one character.
|
||||
* @param {String} dir The direction of the deletion to occur, either "left" or "right"
|
||||
*
|
||||
**/
|
||||
|
|
@ -1621,15 +1629,7 @@ var Editor = function(renderer, session) {
|
|||
**/
|
||||
this.removeLines = function() {
|
||||
var rows = this.$getSelectedRows();
|
||||
var range;
|
||||
if (rows.first === 0 || rows.last+1 < this.session.getLength())
|
||||
range = new Range(rows.first, 0, rows.last+1, 0);
|
||||
else
|
||||
range = new Range(
|
||||
rows.first-1, this.session.getLine(rows.first-1).length,
|
||||
rows.last, this.session.getLine(rows.last).length
|
||||
);
|
||||
this.session.remove(range);
|
||||
this.session.removeFullLines(rows.first, rows.last);
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
|
|
@ -2682,6 +2682,7 @@ config.defineOptions(Editor.prototype, "editor", {
|
|||
useSoftTabs: "session",
|
||||
tabSize: "session",
|
||||
wrap: "session",
|
||||
indentedSoftWrap: "session",
|
||||
foldStyle: "session",
|
||||
mode: "session"
|
||||
});
|
||||
|
|
|
|||
|
|
@ -578,15 +578,14 @@ var onSelectionChange = function(evt) {
|
|||
* and deleting text.
|
||||
* @param {!Event} evt The event.
|
||||
*/
|
||||
var onChange = function(evt) {
|
||||
var data = evt.data;
|
||||
var onChange = function(delta) {
|
||||
switch (data.action) {
|
||||
case 'removeText':
|
||||
case 'remove':
|
||||
cvox.Api.speak(data.text, 0, DELETED_PROP);
|
||||
/* Let the future cursor change event know it's from text change. */
|
||||
changed = true;
|
||||
break;
|
||||
case 'insertText':
|
||||
case 'insert':
|
||||
cvox.Api.speak(data.text, 0);
|
||||
/* Let the future cursor change event know it's from text change. */
|
||||
changed = true;
|
||||
|
|
|
|||
|
|
@ -44,13 +44,12 @@ var ElasticTabstopsLite = function(editor) {
|
|||
this.onExec = function() {
|
||||
recordChanges = true;
|
||||
};
|
||||
this.onChange = function(e) {
|
||||
var range = e.data.range
|
||||
this.onChange = function(delta) {
|
||||
if (recordChanges) {
|
||||
if (changedRows.indexOf(range.start.row) == -1)
|
||||
changedRows.push(range.start.row);
|
||||
if (range.end.row != range.start.row)
|
||||
changedRows.push(range.end.row);
|
||||
if (changedRows.indexOf(delta.start.row) == -1)
|
||||
changedRows.push(delta.start.row);
|
||||
if (delta.end.row != delta.start.row)
|
||||
changedRows.push(delta.end.row);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ exports.updateCommands = function(editor, enabled) {
|
|||
};
|
||||
|
||||
exports.isSupportedMode = function(modeId) {
|
||||
return modeId && /css|less|scss|sass|stylus|html|php|twig|ejs/.test(modeId);
|
||||
return modeId && /css|less|scss|sass|stylus|html|php|twig|ejs|handlebars/.test(modeId);
|
||||
};
|
||||
|
||||
var onChangeMode = function(e, target) {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ function findAnnotations(session, row, dir) {
|
|||
if (i < 0)
|
||||
i = -i - 1;
|
||||
|
||||
if (i >= annotations.length - 1)
|
||||
if (i >= annotations.length)
|
||||
i = dir > 0 ? 0 : annotations.length - 1;
|
||||
else if (i === 0 && dir < 0)
|
||||
i = annotations.length - 1;
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ var loadSnippetFile = function(id) {
|
|||
function getCompletionPrefix(editor) {
|
||||
var pos = editor.getCursorPosition();
|
||||
var line = editor.session.getLine(pos.row);
|
||||
var prefix = util.retrievePrecedingIdentifier(line, pos.column);
|
||||
var prefix;
|
||||
// Try to find custom prefixes on the completers
|
||||
editor.completers.forEach(function(completer) {
|
||||
if (completer.identifierRegexps) {
|
||||
|
|
@ -150,16 +150,13 @@ function getCompletionPrefix(editor) {
|
|||
});
|
||||
}
|
||||
});
|
||||
return prefix;
|
||||
return prefix || util.retrievePrecedingIdentifier(line, pos.column);
|
||||
}
|
||||
|
||||
var doLiveAutocomplete = function(e) {
|
||||
var editor = e.editor;
|
||||
var text = e.args || "";
|
||||
var hasCompleter = editor.completer && editor.completer.activated;
|
||||
|
||||
|
||||
|
||||
// We don't want to autocomplete with no prefix
|
||||
if (e.command.name === "backspace") {
|
||||
if (hasCompleter && !getCompletionPrefix(editor))
|
||||
|
|
@ -174,7 +171,6 @@ var doLiveAutocomplete = function(e) {
|
|||
editor.completer = new Autocomplete();
|
||||
}
|
||||
// Disable autoInsert
|
||||
editor.completer.autoSelect = false;
|
||||
editor.completer.autoInsert = false;
|
||||
editor.completer.showPopup(editor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ module.exports.generateSettingsMenu = function generateSettingsMenu (editor) {
|
|||
});
|
||||
|
||||
var el = topmenu.appendChild(document.createElement('div'));
|
||||
var version = "1.1.8";
|
||||
var version = "1.1.9";
|
||||
el.style.padding = "1em";
|
||||
el.textContent = "Ace version " + version;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,11 @@ Mode.prototype.supportsFile = function(filename) {
|
|||
// todo firstlinematch
|
||||
var supportedModes = {
|
||||
ABAP: ["abap"],
|
||||
ABC: ["abc"],
|
||||
ActionScript:["as"],
|
||||
ADA: ["ada|adb"],
|
||||
Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],
|
||||
AsciiDoc: ["asciidoc"],
|
||||
AsciiDoc: ["asciidoc|adoc"],
|
||||
Assembly_x86:["asm"],
|
||||
AutoHotKey: ["ahk"],
|
||||
BatchFile: ["bat|cmd"],
|
||||
|
|
@ -98,6 +99,7 @@ var supportedModes = {
|
|||
JSX: ["jsx"],
|
||||
Julia: ["jl"],
|
||||
LaTeX: ["tex|latex|ltx|bib"],
|
||||
Lean: ["lean|hlean"],
|
||||
LESS: ["less"],
|
||||
Liquid: ["liquid"],
|
||||
Lisp: ["lisp"],
|
||||
|
|
@ -115,12 +117,13 @@ var supportedModes = {
|
|||
MUSHCode: ["mc|mush"],
|
||||
MySQL: ["mysql"],
|
||||
Nix: ["nix"],
|
||||
Nim: ["nim"],
|
||||
ObjectiveC: ["m|mm"],
|
||||
OCaml: ["ml|mli"],
|
||||
Pascal: ["pas|p"],
|
||||
Perl: ["pl|pm"],
|
||||
pgSQL: ["pgsql"],
|
||||
PHP: ["php|phtml"],
|
||||
PHP: ["php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp"],
|
||||
Powershell: ["ps1"],
|
||||
Praat: ["praat|praatscript|psc|proc"],
|
||||
Prolog: ["plg|prolog"],
|
||||
|
|
@ -144,6 +147,7 @@ var supportedModes = {
|
|||
Soy_Template:["soy"],
|
||||
Space: ["space"],
|
||||
SQL: ["sql"],
|
||||
SQLServer: ["sqlserver"],
|
||||
Stylus: ["styl|stylus"],
|
||||
SVG: ["svg"],
|
||||
Tcl: ["tcl"],
|
||||
|
|
@ -158,9 +162,11 @@ var supportedModes = {
|
|||
Velocity: ["vm"],
|
||||
Verilog: ["v|vh|sv|svh"],
|
||||
VHDL: ["vhd|vhdl"],
|
||||
XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl"],
|
||||
XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"],
|
||||
XQuery: ["xq"],
|
||||
YAML: ["yaml|yml"]
|
||||
YAML: ["yaml|yml"],
|
||||
// Add the missing mode "Django" to ext-modelist
|
||||
Django: ["html"]
|
||||
};
|
||||
|
||||
var nameOverrides = {
|
||||
|
|
@ -189,4 +195,3 @@ module.exports = {
|
|||
};
|
||||
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +1,31 @@
|
|||
.ace_static_highlight {
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;
|
||||
font-size: 12px;
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;
|
||||
font-size: 12px;
|
||||
white-space: pre-wrap
|
||||
}
|
||||
|
||||
.ace_static_highlight .ace_gutter {
|
||||
width: 25px !important;
|
||||
float: left;
|
||||
width: 2em;
|
||||
text-align: right;
|
||||
padding: 0 3px 0 0;
|
||||
margin-right: 3px;
|
||||
position: static !important;
|
||||
}
|
||||
|
||||
.ace_static_highlight .ace_line { clear: both; }
|
||||
.ace_static_highlight.ace_show_gutter .ace_line {
|
||||
padding-left: 2.6em;
|
||||
}
|
||||
|
||||
.ace_static_highlight .ace_line { position: relative; }
|
||||
|
||||
.ace_static_highlight .ace_gutter-cell {
|
||||
-moz-user-select: -moz-none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: -moz-none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ var baseStyles = require("../requirejs/text!./static.css");
|
|||
var config = require("../config");
|
||||
var dom = require("../lib/dom");
|
||||
|
||||
var SimpleTextLayer = function() {
|
||||
this.config = {};
|
||||
};
|
||||
SimpleTextLayer.prototype = TextLayer.prototype;
|
||||
|
||||
var highlight = function(el, opts, callback) {
|
||||
var m = el.className.match(/lang-(\w+)/);
|
||||
|
|
@ -149,12 +153,8 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
|
|||
session.setUseWorker(false);
|
||||
session.setMode(mode);
|
||||
|
||||
var textLayer = new TextLayer(document.createElement("div"));
|
||||
var textLayer = new SimpleTextLayer();
|
||||
textLayer.setSession(session);
|
||||
textLayer.config = {
|
||||
characterWidth: 10,
|
||||
lineHeight: 20
|
||||
};
|
||||
|
||||
session.setValue(input);
|
||||
|
||||
|
|
@ -171,7 +171,8 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
|
|||
|
||||
// let's prepare the whole html
|
||||
var html = "<div class='" + theme.cssClass + "'>" +
|
||||
"<div class='ace_static_highlight' style='counter-reset:ace_line " + (lineStart - 1) + "'>" +
|
||||
"<div class='ace_static_highlight" + (disableGutter ? "" : " ace_show_gutter") +
|
||||
"' style='counter-reset:ace_line " + (lineStart - 1) + "'>" +
|
||||
stringBuilder.join("") +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ module.exports = {
|
|||
var mode = new JavaScriptMode();
|
||||
|
||||
var result = highlighter.render(snippet, mode, theme);
|
||||
assert.equal(result.html, "<div class='ace-tomorrow'><div class='ace_static_highlight' style='counter-reset:ace_line 0'>"
|
||||
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>/**\xa0this\xa0is\xa0a\xa0function</span>\n</div>"
|
||||
assert.equal(result.html, "<div class='ace-tomorrow'><div class='ace_static_highlight ace_show_gutter' style='counter-reset:ace_line 0'>"
|
||||
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>/** this is a function</span>\n</div>"
|
||||
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*</span>\n</div>"
|
||||
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_comment ace_doc'>*/</span>\n</div>"
|
||||
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_storage ace_type'>function</span>\xa0<span class='ace_entity ace_name ace_function'>hello</span>\xa0<span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span>\xa0<span class='ace_paren ace_lparen'>{</span>\n</div>"
|
||||
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span>\xa0\xa0\xa0\xa0<span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span>\xa0<span class='ace_keyword ace_operator'>*</span>\xa0<span class='ace_identifier'>b</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_identifier'>c</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_string'>'sup$'</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span>\n</div>"
|
||||
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_storage ace_type'>function</span> <span class='ace_entity ace_name ace_function'>hello</span> <span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>, </span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>, </span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span> <span class='ace_paren ace_lparen'>{</span>\n</div>"
|
||||
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span> <span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span> <span class='ace_keyword ace_operator'>*</span> <span class='ace_identifier'>b</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_identifier'>c</span> <span class='ace_keyword ace_operator'>+</span> <span class='ace_string'>'sup$'</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span>\n</div>"
|
||||
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'></span><span class='ace_paren ace_rparen'>}</span>\n</div>"
|
||||
+ "</div></div>");
|
||||
assert.ok(!!result.css);
|
||||
|
|
|
|||
|
|
@ -51,12 +51,14 @@ var themeData = [
|
|||
["Dreamweaver" ],
|
||||
["Eclipse" ],
|
||||
["GitHub" ],
|
||||
["IPlastic" ],
|
||||
["Solarized Light"],
|
||||
["TextMate" ],
|
||||
["Tomorrow" ],
|
||||
["XCode" ],
|
||||
["Kuroir"],
|
||||
["KatzenMilch"],
|
||||
["SQL Server" ,"sqlserver" , "light"],
|
||||
["Ambiance" ,"ambiance" , "dark"],
|
||||
["Chaos" ,"chaos" , "dark"],
|
||||
["Clouds Midnight" ,"clouds_midnight" , "dark"],
|
||||
|
|
@ -71,6 +73,7 @@ var themeData = [
|
|||
["Solarized Dark" ,"solarized_dark" , "dark"],
|
||||
["Terminal" ,"terminal" , "dark"],
|
||||
["Tomorrow Night" ,"tomorrow_night" , "dark"],
|
||||
["The Night After Tomorrow" ,"the_night_after_tomorrow" , "dark"],
|
||||
["Tomorrow Night Blue" ,"tomorrow_night_blue" , "dark"],
|
||||
["Tomorrow Night Bright","tomorrow_night_bright" , "dark"],
|
||||
["Tomorrow Night 80s" ,"tomorrow_night_eighties" , "dark"],
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ function objectToRegExp(obj) {
|
|||
this.$mousedownHandler = ed.addEventListener('mousedown', this.onMouseDown.bind(this));
|
||||
this.selectionFix(ed);
|
||||
this.statusMessage(true);
|
||||
}
|
||||
};
|
||||
|
||||
this.deactivate = function(reset) {
|
||||
this.cancelSearch(reset);
|
||||
|
|
@ -117,7 +117,7 @@ function objectToRegExp(obj) {
|
|||
}
|
||||
ed.onPaste = this.$originalEditorOnPaste;
|
||||
this.message('');
|
||||
}
|
||||
};
|
||||
|
||||
this.selectionFix = function(editor) {
|
||||
// Fix selection bug: When clicked inside the editor
|
||||
|
|
@ -128,7 +128,7 @@ function objectToRegExp(obj) {
|
|||
if (editor.selection.isEmpty() && !editor.session.$emacsMark) {
|
||||
editor.clearSelection();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.highlight = function(regexp) {
|
||||
var sess = this.$editor.session,
|
||||
|
|
@ -136,7 +136,7 @@ function objectToRegExp(obj) {
|
|||
new SearchHighlight(null, "ace_isearch-result", "text"));
|
||||
hl.setRegexp(regexp);
|
||||
sess._emit("changeBackMarker"); // force highlight layer redraw
|
||||
}
|
||||
};
|
||||
|
||||
this.cancelSearch = function(reset) {
|
||||
var e = this.$editor;
|
||||
|
|
@ -150,7 +150,7 @@ function objectToRegExp(obj) {
|
|||
}
|
||||
this.highlight(null);
|
||||
return Range.fromPoints(this.$currentPos, this.$currentPos);
|
||||
}
|
||||
};
|
||||
|
||||
this.highlightAndFindWithNeedle = function(moveToNext, needleUpdateFunc) {
|
||||
if (!this.$editor) return null;
|
||||
|
|
@ -163,7 +163,7 @@ function objectToRegExp(obj) {
|
|||
if (options.needle.length === 0) {
|
||||
this.statusMessage(true);
|
||||
return this.cancelSearch(true);
|
||||
};
|
||||
}
|
||||
|
||||
// try to find the next occurence and enable highlighting marker
|
||||
options.start = this.$currentPos;
|
||||
|
|
@ -176,13 +176,13 @@ function objectToRegExp(obj) {
|
|||
this.$editor.selection.setRange(Range.fromPoints(shouldSelect ? this.$startPos : found.end, found.end));
|
||||
if (moveToNext) this.$currentPos = found.end;
|
||||
// highlight after cursor move, so selection works properly
|
||||
this.highlight(options.re)
|
||||
this.highlight(options.re);
|
||||
}
|
||||
|
||||
this.statusMessage(found);
|
||||
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
this.addString = function(s) {
|
||||
return this.highlightAndFindWithNeedle(false, function(needle) {
|
||||
|
|
@ -192,7 +192,7 @@ function objectToRegExp(obj) {
|
|||
reObj.expression += s;
|
||||
return objectToRegExp(reObj);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.removeChar = function(c) {
|
||||
return this.highlightAndFindWithNeedle(false, function(needle) {
|
||||
|
|
@ -202,7 +202,7 @@ function objectToRegExp(obj) {
|
|||
reObj.expression = reObj.expression.substring(0, reObj.expression.length-1);
|
||||
return objectToRegExp(reObj);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.next = function(options) {
|
||||
// try to find the next occurence of whatever we have searched for
|
||||
|
|
@ -215,29 +215,29 @@ function objectToRegExp(obj) {
|
|||
return options.useCurrentOrPrevSearch && needle.length === 0 ?
|
||||
this.$prevNeedle || '' : needle;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.onMouseDown = function(evt) {
|
||||
// when mouse interaction happens then we quit incremental search
|
||||
this.deactivate();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
this.onPaste = function(text) {
|
||||
this.addString(text);
|
||||
}
|
||||
};
|
||||
|
||||
this.convertNeedleToRegExp = function() {
|
||||
return this.highlightAndFindWithNeedle(false, function(needle) {
|
||||
return isRegExp(needle) ? needle : stringToRegExp(needle, 'ig');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.convertNeedleToString = function() {
|
||||
return this.highlightAndFindWithNeedle(false, function(needle) {
|
||||
return isRegExp(needle) ? regExpToObject(needle).expression : needle;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.statusMessage = function(found) {
|
||||
var options = this.$options, msg = '';
|
||||
|
|
@ -245,7 +245,7 @@ function objectToRegExp(obj) {
|
|||
msg += 'isearch: ' + options.needle;
|
||||
msg += found ? '' : ' (not found)';
|
||||
this.message(msg);
|
||||
}
|
||||
};
|
||||
|
||||
this.message = function(msg) {
|
||||
if (this.$editor.showCommandLine) {
|
||||
|
|
@ -254,7 +254,7 @@ function objectToRegExp(obj) {
|
|||
} else {
|
||||
console.log(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}).call(IncrementalSearch.prototype);
|
||||
|
||||
|
|
|
|||
|
|
@ -428,7 +428,7 @@ exports.emacsKeys = {
|
|||
"M-;": "togglecomment",
|
||||
|
||||
"C-/|C-x u|S-C--|C-z": "undo",
|
||||
"S-C-/|S-C-x u|C--|S-C-z": "redo", //infinite undo?
|
||||
"S-C-/|S-C-x u|C--|S-C-z": "redo", // infinite undo?
|
||||
// vertical editing
|
||||
"C-x r": "selectRectangularRegion",
|
||||
"M-x": {command: "focusCommandLine", args: "M-x "}
|
||||
|
|
@ -483,7 +483,7 @@ exports.handler.addCommands({
|
|||
// different. Deactivate the mark when setMark is run with active
|
||||
// mark
|
||||
if (transientMarkModeActive && (mark || !hasNoSelection)) {
|
||||
if (editor.inMultiSelectMode) editor.forEachSelection({exec: editor.clearSelection.bind(editor)})
|
||||
if (editor.inMultiSelectMode) editor.forEachSelection({exec: editor.clearSelection.bind(editor)});
|
||||
else editor.clearSelection();
|
||||
if (mark) editor.pushEmacsMark(null);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -87,9 +87,12 @@ MultiHashHandler.prototype = HashHandler.prototype;
|
|||
}
|
||||
};
|
||||
|
||||
this.bindKey = function(key, command, asDefault) {
|
||||
if (typeof key == "object")
|
||||
this.bindKey = function(key, command, position) {
|
||||
if (typeof key == "object") {
|
||||
if (position == undefined)
|
||||
position = key.position;
|
||||
key = key[this.platform];
|
||||
}
|
||||
if (!key)
|
||||
return;
|
||||
if (typeof command == "function")
|
||||
|
|
@ -110,11 +113,15 @@ MultiHashHandler.prototype = HashHandler.prototype;
|
|||
}
|
||||
var binding = this.parseKeys(keyPart);
|
||||
var id = KEY_MODS[binding.hashId] + binding.key;
|
||||
this._addCommandToBinding(chain + id, command, asDefault);
|
||||
this._addCommandToBinding(chain + id, command, position);
|
||||
}, this);
|
||||
};
|
||||
|
||||
this._addCommandToBinding = function(keyId, command, asDefault) {
|
||||
function getPosition(command) {
|
||||
return typeof command == "object" && command.bindKey
|
||||
&& command.bindKey.position || 0;
|
||||
}
|
||||
this._addCommandToBinding = function(keyId, command, position) {
|
||||
var ckb = this.commandKeyBinding, i;
|
||||
if (!command) {
|
||||
delete ckb[keyId];
|
||||
|
|
@ -126,11 +133,21 @@ MultiHashHandler.prototype = HashHandler.prototype;
|
|||
} else if ((i = ckb[keyId].indexOf(command)) != -1) {
|
||||
ckb[keyId].splice(i, 1);
|
||||
}
|
||||
|
||||
if (asDefault || command.isDefault)
|
||||
ckb[keyId].unshift(command);
|
||||
else
|
||||
ckb[keyId].push(command);
|
||||
|
||||
if (typeof position != "number") {
|
||||
if (position || command.isDefault)
|
||||
position = -100;
|
||||
else
|
||||
position = getPosition(command);
|
||||
}
|
||||
var commands = ckb[keyId];
|
||||
for (i = 0; i < commands.length; i++) {
|
||||
var other = commands[i];
|
||||
var otherPos = getPosition(other);
|
||||
if (otherPos > position)
|
||||
break;
|
||||
}
|
||||
commands.splice(i, 0, command);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -219,10 +236,18 @@ MultiHashHandler.prototype = HashHandler.prototype;
|
|||
}
|
||||
}
|
||||
|
||||
if (data.$keyChain && keyCode > 0)
|
||||
data.$keyChain = "";
|
||||
if (data.$keyChain) {
|
||||
if ((!hashId || hashId == 4) && keyString.length == 1)
|
||||
data.$keyChain = data.$keyChain.slice(0, -key.length - 1); // wait for input
|
||||
else if (hashId == -1 || keyCode > 0)
|
||||
data.$keyChain = ""; // reset keyChain
|
||||
}
|
||||
return {command: command};
|
||||
};
|
||||
|
||||
this.getStatusText = function(editor, data) {
|
||||
return data.$keyChain || "";
|
||||
};
|
||||
|
||||
}).call(HashHandler.prototype);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ var TextInput = function(parentNode, host) {
|
|||
text.setAttribute("spellcheck", false);
|
||||
|
||||
text.style.opacity = "0";
|
||||
if (useragent.isOldIE) text.style.top = "-100px";
|
||||
if (useragent.isOldIE) text.style.top = "-1000px";
|
||||
parentNode.insertBefore(text, parentNode.firstChild);
|
||||
|
||||
var PLACEHOLDER = "\x01\x01";
|
||||
|
|
@ -76,8 +76,9 @@ var TextInput = function(parentNode, host) {
|
|||
resetSelection();
|
||||
});
|
||||
this.focus = function() {
|
||||
if (tempStyle) return text.focus();
|
||||
text.style.position = "fixed";
|
||||
text.style.top = "-10000000px";
|
||||
text.style.top = "-1000px";
|
||||
text.focus();
|
||||
setTimeout(function() {
|
||||
text.style.position = "";
|
||||
|
|
@ -305,7 +306,7 @@ var TextInput = function(parentNode, host) {
|
|||
var data = handleClipboardData(e);
|
||||
if (typeof data == "string") {
|
||||
if (data)
|
||||
host.onPaste(data);
|
||||
host.onPaste(data, e);
|
||||
if (useragent.isIE)
|
||||
setTimeout(resetSelection);
|
||||
event.preventDefault(e);
|
||||
|
|
|
|||
|
|
@ -66,23 +66,25 @@ define(function(require, exports, module) {
|
|||
var d = "";
|
||||
function format(p) {
|
||||
if (typeof p != "object")
|
||||
return p + ""
|
||||
return p + "";
|
||||
if ("line" in p) {
|
||||
return p.line + ":" + p.ch
|
||||
return p.line + ":" + p.ch;
|
||||
}
|
||||
if ("anchor" in p) {
|
||||
return format(p.anchor) + "->" + format(p.head)
|
||||
return format(p.anchor) + "->" + format(p.head);
|
||||
}
|
||||
if (Array.isArray(p))
|
||||
return "[" + p.map(function(x) {return format(x)})+"]"
|
||||
return JSON.stringify(p)
|
||||
return "[" + p.map(function(x) {
|
||||
return format(x);
|
||||
}) + "]";
|
||||
return JSON.stringify(p);
|
||||
}
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var p = arguments[i]
|
||||
var f = format(p)
|
||||
d+= f+" "
|
||||
var p = arguments[i];
|
||||
var f = format(p);
|
||||
d += f + " ";
|
||||
}
|
||||
console.log(d)
|
||||
console.log(d);
|
||||
}
|
||||
var Range = require("../range").Range;
|
||||
var EventEmitter = require("../lib/event_emitter").EventEmitter;
|
||||
|
|
@ -94,6 +96,7 @@ define(function(require, exports, module) {
|
|||
var useragent = require("../lib/useragent");
|
||||
var SearchHighlight = require("../search_highlight").SearchHighlight;
|
||||
var multiSelectCommands = require("../commands/multi_select_commands");
|
||||
var TextModeTokenRe = require("../mode/text").Mode.prototype.tokenRe;
|
||||
require("../multi_select");
|
||||
|
||||
var CodeMirror = function(ace) {
|
||||
|
|
@ -157,6 +160,11 @@ define(function(require, exports, module) {
|
|||
CodeMirror.signal = function(o, name, e) { return o._signal(name, e) };
|
||||
CodeMirror.on = event.addListener;
|
||||
CodeMirror.off = event.removeListener;
|
||||
CodeMirror.isWordChar = function(ch) {
|
||||
TextModeTokenRe.lastIndex = 0;
|
||||
return TextModeTokenRe.test(ch);
|
||||
};
|
||||
|
||||
(function() {
|
||||
oop.implement(CodeMirror.prototype, EventEmitter);
|
||||
|
||||
|
|
@ -170,13 +178,6 @@ define(function(require, exports, module) {
|
|||
return this.ace.inVirtualSelectionMode && this.ace.selection.index;
|
||||
};
|
||||
this.onChange = function(delta) {
|
||||
var oldDelta = delta.data;
|
||||
delta = {
|
||||
start: oldDelta.range.start,
|
||||
end: oldDelta.range.end,
|
||||
action: oldDelta.action,
|
||||
lines: oldDelta.lines || [oldDelta.text]
|
||||
};// v1.2 api compatibility
|
||||
if (delta.action[0] == 'i') {
|
||||
var change = { text: delta.lines };
|
||||
var curOp = this.curOp = this.curOp || {};
|
||||
|
|
@ -256,6 +257,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
if (!this.ace.inVirtualSelectionMode)
|
||||
this.ace.exitMultiSelectMode();
|
||||
this.ace.session.unfold({row: line, column: ch});
|
||||
this.ace.selection.moveTo(line, ch);
|
||||
};
|
||||
this.getCursor = function(p) {
|
||||
|
|
@ -383,13 +385,19 @@ define(function(require, exports, module) {
|
|||
sel.moveCursorBy(0, increment);
|
||||
}
|
||||
};
|
||||
this.findPosV = function(start, amaount, unit, goalColumn) {
|
||||
this.findPosV = function(start, amount, unit, goalColumn) {
|
||||
if (unit == 'page') {
|
||||
var renderer = this.ace.renderer;
|
||||
var config = renderer.layerConfig;
|
||||
amount = amount * Math.floor(config.height / config.lineHeight);
|
||||
unit = 'line';
|
||||
}
|
||||
if (unit == 'line') {
|
||||
var screenPos = this.ace.session.documentToScreenPosition(start.line, start.ch);
|
||||
if (goalColumn != null)
|
||||
screenPos.column = goalColumn;
|
||||
screenPos.row += amaount;
|
||||
// not what codemirror does but vim mode needs only it
|
||||
screenPos.row += amount;
|
||||
// not what codemirror does but vim mode needs only this
|
||||
screenPos.row = Math.min(Math.max(0, screenPos.row), this.ace.session.getScreenLength() - 1);
|
||||
var pos = this.ace.session.screenToDocumentPosition(screenPos.row, screenPos.column);
|
||||
return toCmPos(pos);
|
||||
|
|
@ -475,8 +483,12 @@ define(function(require, exports, module) {
|
|||
};
|
||||
this.scrollInfo = function() { return 0; };
|
||||
this.scrollIntoView = function(pos, margin) {
|
||||
if (pos)
|
||||
this.ace.renderer.scrollCursorIntoView(toAcePos(pos), null, margin);
|
||||
if (pos) {
|
||||
var renderer = this.ace.renderer;
|
||||
var viewMargin = { "top": 0, "bottom": margin };
|
||||
renderer.scrollCursorIntoView(toAcePos(pos),
|
||||
(renderer.lineHeight * 2) / renderer.$size.scrollerHeight, viewMargin);
|
||||
}
|
||||
};
|
||||
this.getLine = function(row) { return this.ace.session.getLine(row) };
|
||||
this.getRange = function(s, e) {
|
||||
|
|
@ -559,7 +571,6 @@ define(function(require, exports, module) {
|
|||
highlight.session = null;
|
||||
};
|
||||
highlight.updateOnChange = function(delta) {
|
||||
delta = delta.data.range;// v1.2 api compatibility
|
||||
var row = delta.start.row;
|
||||
if (row == delta.end.row) highlight.cache[row] = undefined;
|
||||
else highlight.cache.splice(row, highlight.cache.length);
|
||||
|
|
@ -636,6 +647,9 @@ define(function(require, exports, module) {
|
|||
this.refresh = function() {
|
||||
return this.ace.resize(true);
|
||||
};
|
||||
this.getMode = function() {
|
||||
return { name : this.getOption("mode") };
|
||||
}
|
||||
}).call(CodeMirror.prototype);
|
||||
function toAcePos(cmPos) {
|
||||
return {row: cmPos.line, column: cmPos.ch};
|
||||
|
|
@ -716,10 +730,14 @@ CodeMirror.defineExtension = function(name, fn) {
|
|||
CodeMirror.prototype[name] = fn;
|
||||
};
|
||||
dom.importCssString(".normal-mode .ace_cursor{\
|
||||
border: 0!important;\
|
||||
border: 1px solid red;\
|
||||
background-color: red;\
|
||||
opacity: 0.5;\
|
||||
}.ace_dialog {\
|
||||
}\
|
||||
.normal-mode .ace_hidden-cursors .ace_cursor{\
|
||||
background-color: transparent;\
|
||||
}\
|
||||
.ace_dialog {\
|
||||
position: absolute;\
|
||||
left: 0; right: 0;\
|
||||
background: white;\
|
||||
|
|
@ -745,23 +763,6 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
font-family: monospace;\
|
||||
}", "vimMode");
|
||||
(function() {
|
||||
function dialogDiv(cm, template, bottom) {
|
||||
var wrap = cm.ace.container;
|
||||
var dialog;
|
||||
dialog = wrap.appendChild(document.createElement("div"));
|
||||
if (bottom)
|
||||
dialog.className = "ace_dialog ace_dialog-bottom";
|
||||
else
|
||||
dialog.className = "ace_dialog ace_dialog-top";
|
||||
|
||||
if (typeof template == "string") {
|
||||
dialog.innerHTML = template;
|
||||
} else { // Assuming it's a detached DOM element.
|
||||
dialog.appendChild(template);
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
function closeNotification(cm, newVal) {
|
||||
if (cm.state.currentNotificationClose)
|
||||
cm.state.currentNotificationClose();
|
||||
|
|
@ -793,7 +794,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
if (inp) {
|
||||
if (options.value) {
|
||||
inp.value = options.value;
|
||||
inp.select();
|
||||
if (options.select !== false) inp.select();
|
||||
}
|
||||
|
||||
if (options.onInput)
|
||||
|
|
@ -1121,7 +1122,11 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
|
||||
var numberRegex = /[\d]/;
|
||||
var wordRegexp = [(/\w/), (/[^\w\s]/)], bigWordRegexp = [(/\S/)];
|
||||
var wordCharTest = [CodeMirror.isWordChar, function(ch) {
|
||||
return ch && !CodeMirror.isWordChar(ch) && !/\s/.test(ch);
|
||||
}], bigWordCharTest = [function(ch) {
|
||||
return /\S/.test(ch);
|
||||
}];
|
||||
function makeKeyRange(start, size) {
|
||||
var keys = [];
|
||||
for (var i = start; i < start + size; i++) {
|
||||
|
|
@ -1163,18 +1168,30 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
|
||||
var options = {};
|
||||
function defineOption(name, defaultValue, type) {
|
||||
if (defaultValue === undefined) { throw Error('defaultValue is required'); }
|
||||
function defineOption(name, defaultValue, type, aliases, callback) {
|
||||
if (defaultValue === undefined && !callback) {
|
||||
throw Error('defaultValue is required unless callback is provided');
|
||||
}
|
||||
if (!type) { type = 'string'; }
|
||||
options[name] = {
|
||||
type: type,
|
||||
defaultValue: defaultValue
|
||||
defaultValue: defaultValue,
|
||||
callback: callback
|
||||
};
|
||||
setOption(name, defaultValue);
|
||||
if (aliases) {
|
||||
for (var i = 0; i < aliases.length; i++) {
|
||||
options[aliases[i]] = options[name];
|
||||
}
|
||||
}
|
||||
if (defaultValue) {
|
||||
setOption(name, defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
function setOption(name, value, cm) {
|
||||
function setOption(name, value, cm, cfg) {
|
||||
var option = options[name];
|
||||
cfg = cfg || {};
|
||||
var scope = cfg.scope;
|
||||
if (!option) {
|
||||
throw Error('Unknown option: ' + name);
|
||||
}
|
||||
|
|
@ -1186,17 +1203,60 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
value = true;
|
||||
}
|
||||
}
|
||||
option.value = option.type == 'boolean' ? !!value : value;
|
||||
if (option.callback) {
|
||||
if (scope !== 'local') {
|
||||
option.callback(value, undefined);
|
||||
}
|
||||
if (scope !== 'global' && cm) {
|
||||
option.callback(value, cm);
|
||||
}
|
||||
} else {
|
||||
if (scope !== 'local') {
|
||||
option.value = option.type == 'boolean' ? !!value : value;
|
||||
}
|
||||
if (scope !== 'global' && cm) {
|
||||
cm.state.vim.options[name] = {value: value};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getOption(name) {
|
||||
function getOption(name, cm, cfg) {
|
||||
var option = options[name];
|
||||
cfg = cfg || {};
|
||||
var scope = cfg.scope;
|
||||
if (!option) {
|
||||
throw Error('Unknown option: ' + name);
|
||||
}
|
||||
return option.value;
|
||||
if (option.callback) {
|
||||
var local = cm && option.callback(undefined, cm);
|
||||
if (scope !== 'global' && local !== undefined) {
|
||||
return local;
|
||||
}
|
||||
if (scope !== 'local') {
|
||||
return option.callback();
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
var local = (scope !== 'global') && (cm && cm.state.vim.options[name]);
|
||||
return (local || (scope !== 'local') && option || {}).value;
|
||||
}
|
||||
}
|
||||
|
||||
defineOption('filetype', undefined, 'string', ['ft'], function(name, cm) {
|
||||
// Option is local. Do nothing for global.
|
||||
if (cm === undefined) {
|
||||
return;
|
||||
}
|
||||
// The 'filetype' option proxies to the CodeMirror 'mode' option.
|
||||
if (name === undefined) {
|
||||
var mode = cm.getMode().name;
|
||||
return mode == 'null' ? '' : mode;
|
||||
} else {
|
||||
var mode = name == '' ? 'null' : name;
|
||||
cm.setOption('mode', mode);
|
||||
}
|
||||
});
|
||||
|
||||
var createCircularJumpList = function() {
|
||||
var size = 100;
|
||||
var pointer = -1;
|
||||
|
|
@ -1349,8 +1409,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
visualBlock: false,
|
||||
lastSelection: null,
|
||||
lastPastedText: null,
|
||||
sel: {
|
||||
}
|
||||
sel: {},
|
||||
// Buffer-local/window-local values of vim options.
|
||||
options: {}
|
||||
};
|
||||
}
|
||||
return cm.state.vim;
|
||||
|
|
@ -1401,6 +1462,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
// Testing hook.
|
||||
maybeInitVimState_: maybeInitVimState,
|
||||
|
||||
suppressErrorLogging: false,
|
||||
|
||||
InsertModeKey: InsertModeKey,
|
||||
map: function(lhs, rhs, ctx) {
|
||||
// Add user defined key bindings.
|
||||
|
|
@ -1410,6 +1473,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
// remove user defined key bindings.
|
||||
exCommandDispatcher.unmap(lhs, ctx);
|
||||
},
|
||||
// TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace
|
||||
// them, or somehow make them work with the existing CodeMirror setOption/getOption API.
|
||||
setOption: setOption,
|
||||
getOption: getOption,
|
||||
defineOption: defineOption,
|
||||
|
|
@ -1551,7 +1616,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
// clear VIM state in case it's in a bad state.
|
||||
cm.state.vim = undefined;
|
||||
maybeInitVimState(cm);
|
||||
console['log'](e);
|
||||
if (!CodeMirror.Vim.suppressErrorLogging) {
|
||||
console['log'](e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -1561,7 +1628,16 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
},
|
||||
handleEx: function(cm, input) {
|
||||
exCommandDispatcher.processCommand(cm, input);
|
||||
}
|
||||
},
|
||||
|
||||
defineMotion: defineMotion,
|
||||
defineAction: defineAction,
|
||||
defineOperator: defineOperator,
|
||||
mapCommand: mapCommand,
|
||||
_mapCommand: _mapCommand,
|
||||
|
||||
exitVisualMode: exitVisualMode,
|
||||
exitInsertMode: exitInsertMode
|
||||
};
|
||||
|
||||
// Represents the current input state.
|
||||
|
|
@ -1811,12 +1887,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
break;
|
||||
case 'search':
|
||||
this.processSearch(cm, vim, command);
|
||||
clearInputState(cm);
|
||||
break;
|
||||
case 'ex':
|
||||
case 'keyToEx':
|
||||
this.processEx(cm, vim, command);
|
||||
clearInputState(cm);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -1909,6 +1983,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
updateSearchQuery(cm, query, ignoreCase, smartCase);
|
||||
} catch (e) {
|
||||
showConfirm(cm, 'Invalid regex: ' + query);
|
||||
clearInputState(cm);
|
||||
return;
|
||||
}
|
||||
commandDispatcher.processMotion(cm, vim, {
|
||||
|
|
@ -1951,15 +2026,21 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
function onPromptKeyDown(e, query, close) {
|
||||
var keyName = CodeMirror.keyName(e);
|
||||
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') {
|
||||
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
|
||||
(keyName == 'Backspace' && query == '')) {
|
||||
vimGlobalState.searchHistoryController.pushInput(query);
|
||||
vimGlobalState.searchHistoryController.reset();
|
||||
updateSearchQuery(cm, originalQuery);
|
||||
clearSearchHighlight(cm);
|
||||
cm.scrollTo(originalScrollPos.left, originalScrollPos.top);
|
||||
CodeMirror.e_stop(e);
|
||||
clearInputState(cm);
|
||||
close();
|
||||
cm.focus();
|
||||
} else if (keyName == 'Ctrl-U') {
|
||||
// Ctrl-U clears input.
|
||||
CodeMirror.e_stop(e);
|
||||
close('');
|
||||
}
|
||||
}
|
||||
switch (command.searchArgs.querySrc) {
|
||||
|
|
@ -2020,10 +2101,12 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
function onPromptKeyDown(e, input, close) {
|
||||
var keyName = CodeMirror.keyName(e), up;
|
||||
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') {
|
||||
if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' ||
|
||||
(keyName == 'Backspace' && input == '')) {
|
||||
vimGlobalState.exCommandHistoryController.pushInput(input);
|
||||
vimGlobalState.exCommandHistoryController.reset();
|
||||
CodeMirror.e_stop(e);
|
||||
clearInputState(cm);
|
||||
close();
|
||||
cm.focus();
|
||||
}
|
||||
|
|
@ -2031,6 +2114,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
up = keyName == 'Up' ? true : false;
|
||||
input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || '';
|
||||
close(input);
|
||||
} else if (keyName == 'Ctrl-U') {
|
||||
// Ctrl-U clears input.
|
||||
CodeMirror.e_stop(e);
|
||||
close('');
|
||||
} else {
|
||||
if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift')
|
||||
vimGlobalState.exCommandHistoryController.reset();
|
||||
|
|
@ -2042,7 +2129,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
} else {
|
||||
if (vim.visualMode) {
|
||||
showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>',
|
||||
onKeyDown: onPromptKeyDown});
|
||||
onKeyDown: onPromptKeyDown, select: false});
|
||||
} else {
|
||||
showPrompt(cm, { onClose: onPromptClose, prefix: ':',
|
||||
onKeyDown: onPromptKeyDown});
|
||||
|
|
@ -2060,8 +2147,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
var registerName = inputState.registerName;
|
||||
var sel = vim.sel;
|
||||
// TODO: Make sure cm and vim selections are identical outside visual mode.
|
||||
var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor('head'));
|
||||
var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor('anchor'));
|
||||
var origHead = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.head): cm.getCursor('head'));
|
||||
var origAnchor = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.anchor) : cm.getCursor('anchor'));
|
||||
var oldHead = copyCursor(origHead);
|
||||
var oldAnchor = copyCursor(origAnchor);
|
||||
var newHead, newAnchor;
|
||||
|
|
@ -2097,6 +2184,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
return;
|
||||
}
|
||||
if (motionArgs.toJumplist) {
|
||||
if (!operator)
|
||||
cm.ace.curOp.command.scrollIntoView = "center-animate"; // ace patch
|
||||
var jumpList = vimGlobalState.jumpList;
|
||||
// if the current motion is # or *, use cachedCursor
|
||||
var cachedCursor = jumpList.cachedCursor;
|
||||
|
|
@ -2118,11 +2207,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
newHead = copyCursor(origHead);
|
||||
}
|
||||
if (vim.visualMode) {
|
||||
|
||||
if (!(vim.visualBlock && motion === "moveToEol")) {
|
||||
if (!(vim.visualBlock && newHead.ch === Infinity)) {
|
||||
newHead = clipCursorToContent(cm, newHead, vim.visualBlock);
|
||||
}
|
||||
|
||||
if (newAnchor) {
|
||||
newAnchor = clipCursorToContent(cm, newAnchor, true);
|
||||
}
|
||||
|
|
@ -2236,7 +2323,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
var operatorMoveTo = operators[operator](
|
||||
cm, operatorArgs, cmSel.ranges, oldAnchor, newHead);
|
||||
if (vim.visualMode) {
|
||||
exitVisualMode(cm);
|
||||
exitVisualMode(cm, operatorMoveTo != null);
|
||||
}
|
||||
if (operatorMoveTo) {
|
||||
cm.setCursor(operatorMoveTo);
|
||||
|
|
@ -2382,6 +2469,15 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
(line > last && cur.line == last)) {
|
||||
return;
|
||||
}
|
||||
// /ace patch
|
||||
var fold = cm.ace.session.getFoldAt(line, endCh);
|
||||
if (fold) {
|
||||
if (motionArgs.forward)
|
||||
line = fold.end.row + 1;
|
||||
else
|
||||
line = fold.start.row - 1;
|
||||
}
|
||||
// /ace patche
|
||||
if (motionArgs.toFirstChar){
|
||||
endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line));
|
||||
vim.lastHPos = endCh;
|
||||
|
|
@ -2604,6 +2700,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
};
|
||||
|
||||
function defineMotion(name, fn) {
|
||||
motions[name] = fn;
|
||||
}
|
||||
|
||||
function fillArray(val, times) {
|
||||
var arr = [];
|
||||
for (var i = 0; i < times; i++) {
|
||||
|
|
@ -2625,10 +2725,11 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
var anchor = ranges[0].anchor,
|
||||
head = ranges[0].head;
|
||||
text = cm.getRange(anchor, head);
|
||||
if (!isWhiteSpaceString(text)) {
|
||||
var lastState = vim.lastEditInputState || {};
|
||||
if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) {
|
||||
// Exclude trailing whitespace if the range is not all whitespace.
|
||||
var match = (/\s+$/).exec(text);
|
||||
if (match) {
|
||||
if (match && lastState.motionArgs && lastState.motionArgs.forward) {
|
||||
head = offsetCursor(head, 0, - match[0].length);
|
||||
text = text.slice(0, - match[0].length);
|
||||
}
|
||||
|
|
@ -2686,7 +2787,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
vimGlobalState.registerController.pushText(
|
||||
args.registerName, 'delete', text,
|
||||
args.linewise, vim.visualBlock);
|
||||
return finalHead;
|
||||
return clipCursorToContent(cm, finalHead);
|
||||
},
|
||||
indent: function(cm, args, ranges) {
|
||||
var vim = cm.state.vim;
|
||||
|
|
@ -2754,6 +2855,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
};
|
||||
|
||||
function defineOperator(name, fn) {
|
||||
operators[name] = fn;
|
||||
}
|
||||
|
||||
var actions = {
|
||||
jumpListWalk: function(cm, actionArgs, vim) {
|
||||
if (vim.visualMode) {
|
||||
|
|
@ -2767,6 +2872,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
var markPos = mark ? mark.find() : undefined;
|
||||
markPos = markPos ? markPos : cm.getCursor();
|
||||
cm.setCursor(markPos);
|
||||
cm.ace.curOp.command.scrollIntoView = "center-animate"; // ace patch
|
||||
},
|
||||
scroll: function(cm, actionArgs, vim) {
|
||||
if (vim.visualMode) {
|
||||
|
|
@ -2970,6 +3076,11 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
if (vim.visualMode) {
|
||||
curStart = cm.getCursor('anchor');
|
||||
curEnd = cm.getCursor('head');
|
||||
if (cursorIsBefore(curEnd, curStart)) {
|
||||
var tmp = curEnd;
|
||||
curEnd = curStart;
|
||||
curStart = tmp;
|
||||
}
|
||||
curEnd.ch = lineLength(cm, curEnd.line) - 1;
|
||||
} else {
|
||||
// Repeat is the number of lines to join. Minimum 2 lines.
|
||||
|
|
@ -2988,10 +3099,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
cm.replaceRange(text, curStart, tmp);
|
||||
}
|
||||
var curFinalPos = Pos(curStart.line, finalCh);
|
||||
cm.setCursor(curFinalPos);
|
||||
if (vim.visualMode) {
|
||||
exitVisualMode(cm);
|
||||
exitVisualMode(cm, false);
|
||||
}
|
||||
cm.setCursor(curFinalPos);
|
||||
},
|
||||
newLineAndEnterInsertMode: function(cm, actionArgs, vim) {
|
||||
vim.insertMode = true;
|
||||
|
|
@ -3154,7 +3265,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
}
|
||||
if (vim.visualMode) {
|
||||
exitVisualMode(cm);
|
||||
exitVisualMode(cm, false);
|
||||
}
|
||||
cm.setCursor(curPosFinal);
|
||||
},
|
||||
|
|
@ -3212,7 +3323,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ?
|
||||
selections[0].anchor : selections[0].head;
|
||||
cm.setCursor(curStart);
|
||||
exitVisualMode(cm);
|
||||
exitVisualMode(cm, false);
|
||||
} else {
|
||||
cm.setCursor(offsetCursor(curEnd, 0, -1));
|
||||
}
|
||||
|
|
@ -3260,6 +3371,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
exitInsertMode: exitInsertMode
|
||||
};
|
||||
|
||||
function defineAction(name, fn) {
|
||||
actions[name] = fn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Below are miscellaneous utility functions used by vim.js
|
||||
*/
|
||||
|
|
@ -3389,9 +3504,6 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
function lineLength(cm, lineNum) {
|
||||
return cm.getLine(lineNum).length;
|
||||
}
|
||||
function reverse(s){
|
||||
return s.split('').reverse().join('');
|
||||
}
|
||||
function trim(s) {
|
||||
if (s.trim) {
|
||||
return s.trim();
|
||||
|
|
@ -3705,59 +3817,38 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
|
||||
// Seek to first word or non-whitespace character, depending on if
|
||||
// noSymbol is true.
|
||||
var textAfterIdx = line.substring(idx);
|
||||
var firstMatchedChar;
|
||||
if (noSymbol) {
|
||||
firstMatchedChar = textAfterIdx.search(/\w/);
|
||||
} else {
|
||||
firstMatchedChar = textAfterIdx.search(/\S/);
|
||||
var test = noSymbol ? wordCharTest[0] : bigWordCharTest [0];
|
||||
while (!test(line.charAt(idx))) {
|
||||
idx++;
|
||||
if (idx >= line.length) { return null; }
|
||||
}
|
||||
if (firstMatchedChar == -1) {
|
||||
return null;
|
||||
}
|
||||
idx += firstMatchedChar;
|
||||
textAfterIdx = line.substring(idx);
|
||||
var textBeforeIdx = line.substring(0, idx);
|
||||
|
||||
var matchRegex;
|
||||
// Greedy matchers for the "word" we are trying to expand.
|
||||
if (bigWord) {
|
||||
matchRegex = /^\S+/;
|
||||
test = bigWordCharTest[0];
|
||||
} else {
|
||||
if ((/\w/).test(line.charAt(idx))) {
|
||||
matchRegex = /^\w+/;
|
||||
} else {
|
||||
matchRegex = /^[^\w\s]+/;
|
||||
test = wordCharTest[0];
|
||||
if (!test(line.charAt(idx))) {
|
||||
test = wordCharTest[1];
|
||||
}
|
||||
}
|
||||
|
||||
var wordAfterRegex = matchRegex.exec(textAfterIdx);
|
||||
var wordStart = idx;
|
||||
var wordEnd = idx + wordAfterRegex[0].length;
|
||||
// TODO: Find a better way to do this. It will be slow on very long lines.
|
||||
var revTextBeforeIdx = reverse(textBeforeIdx);
|
||||
var wordBeforeRegex = matchRegex.exec(revTextBeforeIdx);
|
||||
if (wordBeforeRegex) {
|
||||
wordStart -= wordBeforeRegex[0].length;
|
||||
}
|
||||
var end = idx, start = idx;
|
||||
while (test(line.charAt(end)) && end < line.length) { end++; }
|
||||
while (test(line.charAt(start)) && start >= 0) { start--; }
|
||||
start++;
|
||||
|
||||
if (inclusive) {
|
||||
// If present, trim all whitespace after word.
|
||||
// Otherwise, trim all whitespace before word.
|
||||
var textAfterWordEnd = line.substring(wordEnd);
|
||||
var whitespacesAfterWord = textAfterWordEnd.match(/^\s*/)[0].length;
|
||||
if (whitespacesAfterWord > 0) {
|
||||
wordEnd += whitespacesAfterWord;
|
||||
} else {
|
||||
var revTrim = revTextBeforeIdx.length - wordStart;
|
||||
var textBeforeWordStart = revTextBeforeIdx.substring(revTrim);
|
||||
var whitespacesBeforeWord = textBeforeWordStart.match(/^\s*/)[0].length;
|
||||
wordStart -= whitespacesBeforeWord;
|
||||
// If present, include all whitespace after word.
|
||||
// Otherwise, include all whitespace before word, except indentation.
|
||||
var wordEnd = end;
|
||||
while (/\s/.test(line.charAt(end)) && end < line.length) { end++; }
|
||||
if (wordEnd == end) {
|
||||
var wordStart = start;
|
||||
while (/\s/.test(line.charAt(start - 1)) && start > 0) { start--; }
|
||||
if (!start) { start = wordStart; }
|
||||
}
|
||||
}
|
||||
|
||||
return { start: Pos(cur.line, wordStart),
|
||||
end: Pos(cur.line, wordEnd) };
|
||||
return { start: Pos(cur.line, start), end: Pos(cur.line, end) };
|
||||
}
|
||||
|
||||
function recordJumpPosition(cm, oldCur, newCur) {
|
||||
|
|
@ -3915,7 +4006,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
var pos = cur.ch;
|
||||
var line = cm.getLine(lineNum);
|
||||
var dir = forward ? 1 : -1;
|
||||
var regexps = bigWord ? bigWordRegexp : wordRegexp;
|
||||
var charTests = bigWord ? bigWordCharTest: wordCharTest;
|
||||
|
||||
if (emptyLineIsWord && line == '') {
|
||||
lineNum += dir;
|
||||
|
|
@ -3935,11 +4026,11 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
// Find bounds of next word.
|
||||
while (pos != stop) {
|
||||
var foundWord = false;
|
||||
for (var i = 0; i < regexps.length && !foundWord; ++i) {
|
||||
if (regexps[i].test(line.charAt(pos))) {
|
||||
for (var i = 0; i < charTests.length && !foundWord; ++i) {
|
||||
if (charTests[i](line.charAt(pos))) {
|
||||
wordStart = pos;
|
||||
// Advance to end of word.
|
||||
while (pos != stop && regexps[i].test(line.charAt(pos))) {
|
||||
while (pos != stop && charTests[i](line.charAt(pos))) {
|
||||
pos += dir;
|
||||
}
|
||||
wordEnd = pos;
|
||||
|
|
@ -4087,7 +4178,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
var min = cm.firstLine();
|
||||
var max = cm.lastLine();
|
||||
var start, end, i = line;
|
||||
function isEmpty(i) { return !cm.getLine(i); }
|
||||
function isEmpty(i) { return !/\S/.test(cm.getLine(i)); }
|
||||
function isBoundary(i, dir, any) {
|
||||
if (any) { return isEmpty(i) != isEmpty(i + dir); }
|
||||
return !isEmpty(i) && isEmpty(i + dir);
|
||||
|
|
@ -4256,6 +4347,12 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
},
|
||||
setReversed: function(reversed) {
|
||||
vimGlobalState.isReversed = reversed;
|
||||
},
|
||||
getScrollbarAnnotate: function() {
|
||||
return this.annotate;
|
||||
},
|
||||
setScrollbarAnnotate: function(annotate) {
|
||||
this.annotate = annotate;
|
||||
}
|
||||
};
|
||||
function getSearchState(cm) {
|
||||
|
|
@ -4265,7 +4362,8 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
function dialog(cm, template, shortText, onClose, options) {
|
||||
if (cm.openDialog) {
|
||||
cm.openDialog(template, onClose, { bottom: true, value: options.value,
|
||||
onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp });
|
||||
onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp,
|
||||
selectValueOnOpen: false});
|
||||
}
|
||||
else {
|
||||
onClose(prompt(shortText, ''));
|
||||
|
|
@ -4534,14 +4632,21 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
};
|
||||
}
|
||||
function highlightSearchMatches(cm, query) {
|
||||
var overlay = getSearchState(cm).getOverlay();
|
||||
var searchState = getSearchState(cm);
|
||||
var overlay = searchState.getOverlay();
|
||||
if (!overlay || query != overlay.query) {
|
||||
if (overlay) {
|
||||
cm.removeOverlay(overlay);
|
||||
}
|
||||
overlay = searchOverlay(query);
|
||||
cm.addOverlay(overlay);
|
||||
getSearchState(cm).setOverlay(overlay);
|
||||
if (cm.showMatchesOnScrollbar) {
|
||||
if (searchState.getScrollbarAnnotate()) {
|
||||
searchState.getScrollbarAnnotate().clear();
|
||||
}
|
||||
searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query));
|
||||
}
|
||||
searchState.setOverlay(overlay);
|
||||
}
|
||||
}
|
||||
function findNext(cm, prev, query, repeat) {
|
||||
|
|
@ -4566,8 +4671,13 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
});
|
||||
}
|
||||
function clearSearchHighlight(cm) {
|
||||
var state = getSearchState(cm);
|
||||
cm.removeOverlay(getSearchState(cm).getOverlay());
|
||||
getSearchState(cm).setOverlay(null);
|
||||
state.setOverlay(null);
|
||||
if (state.getScrollbarAnnotate()) {
|
||||
state.getScrollbarAnnotate().clear();
|
||||
state.setScrollbarAnnotate(null);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check if pos is in the specified range, INCLUSIVE.
|
||||
|
|
@ -4608,6 +4718,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
// pair of commands that have a shared prefix, at least one of their
|
||||
// shortNames must not match the prefix of the other command.
|
||||
var defaultExCommandMap = [
|
||||
{ name: 'colorscheme', shortName: 'colo' },
|
||||
{ name: 'map' },
|
||||
{ name: 'imap', shortName: 'im' },
|
||||
{ name: 'nmap', shortName: 'nm' },
|
||||
|
|
@ -4616,7 +4727,10 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
{ name: 'write', shortName: 'w' },
|
||||
{ name: 'undo', shortName: 'u' },
|
||||
{ name: 'redo', shortName: 'red' },
|
||||
{ name: 'set', shortName: 'set' },
|
||||
{ name: 'set', shortName: 'se' },
|
||||
{ name: 'set', shortName: 'se' },
|
||||
{ name: 'setlocal', shortName: 'setl' },
|
||||
{ name: 'setglobal', shortName: 'setg' },
|
||||
{ name: 'sort', shortName: 'sor' },
|
||||
{ name: 'substitute', shortName: 's', possiblyAsync: true },
|
||||
{ name: 'nohlsearch', shortName: 'noh' },
|
||||
|
|
@ -4629,6 +4743,13 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
};
|
||||
ExCommandDispatcher.prototype = {
|
||||
processCommand: function(cm, input, opt_params) {
|
||||
var that = this;
|
||||
cm.operation(function () {
|
||||
cm.curOp.isVimOp = true;
|
||||
that._processCommand(cm, input, opt_params);
|
||||
});
|
||||
},
|
||||
_processCommand: function(cm, input, opt_params) {
|
||||
var vim = cm.state.vim;
|
||||
var commandHistoryRegister = vimGlobalState.registerController.getRegister(':');
|
||||
var previousCommand = commandHistoryRegister.toString();
|
||||
|
|
@ -4841,6 +4962,13 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
};
|
||||
|
||||
var exCommands = {
|
||||
colorscheme: function(cm, params) {
|
||||
if (!params.args || params.args.length < 1) {
|
||||
showConfirm(cm, cm.getOption('theme'));
|
||||
return;
|
||||
}
|
||||
cm.setOption('theme', params.args[0]);
|
||||
},
|
||||
map: function(cm, params, ctx) {
|
||||
var mapArgs = params.args;
|
||||
if (!mapArgs || mapArgs.length < 2) {
|
||||
|
|
@ -4874,6 +5002,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
},
|
||||
set: function(cm, params) {
|
||||
var setArgs = params.args;
|
||||
// Options passed through to the setOption/getOption calls. May be passed in by the
|
||||
// local/global versions of the set command
|
||||
var setCfg = params.setCfg || {};
|
||||
if (!setArgs || setArgs.length < 1) {
|
||||
if (cm) {
|
||||
showConfirm(cm, 'Invalid mapping: ' + params.input);
|
||||
|
|
@ -4897,24 +5028,35 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
optionName = optionName.substring(2);
|
||||
value = false;
|
||||
}
|
||||
|
||||
var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean';
|
||||
if (optionIsBoolean && value == undefined) {
|
||||
// Calling set with a boolean option sets it to true.
|
||||
value = true;
|
||||
}
|
||||
if (!optionIsBoolean && !value || forceGet) {
|
||||
var oldValue = getOption(optionName);
|
||||
// If no value is provided, then we assume this is a get.
|
||||
// If no value is provided, then we assume this is a get.
|
||||
if (!optionIsBoolean && value === undefined || forceGet) {
|
||||
var oldValue = getOption(optionName, cm, setCfg);
|
||||
if (oldValue === true || oldValue === false) {
|
||||
showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName);
|
||||
} else {
|
||||
showConfirm(cm, ' ' + optionName + '=' + oldValue);
|
||||
}
|
||||
} else {
|
||||
setOption(optionName, value, cm);
|
||||
setOption(optionName, value, cm, setCfg);
|
||||
}
|
||||
},
|
||||
registers: function(cm,params) {
|
||||
setlocal: function (cm, params) {
|
||||
// setCfg is passed through to setOption
|
||||
params.setCfg = {scope: 'local'};
|
||||
this.set(cm, params);
|
||||
},
|
||||
setglobal: function (cm, params) {
|
||||
// setCfg is passed through to setOption
|
||||
params.setCfg = {scope: 'global'};
|
||||
this.set(cm, params);
|
||||
},
|
||||
registers: function(cm, params) {
|
||||
var regArgs = params.args;
|
||||
var registers = vimGlobalState.registerController.registers;
|
||||
var regInfo = '----------Registers----------<br><br>';
|
||||
|
|
@ -5394,6 +5536,19 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
}
|
||||
|
||||
function _mapCommand(command) {
|
||||
defaultKeymap.push(command);
|
||||
}
|
||||
|
||||
function mapCommand(keys, type, name, args, extra) {
|
||||
var command = {keys: keys, type: type};
|
||||
command[type] = name;
|
||||
command[type + "Args"] = args;
|
||||
for (var key in extra)
|
||||
command[key] = extra[key];
|
||||
_mapCommand(command);
|
||||
}
|
||||
|
||||
// The timeout in milliseconds for the two-character ESC keymap should be
|
||||
// adjusted according to your typing speed to prevent false positives.
|
||||
defineOption('insertModeEscKeysTimeout', 200, 'number');
|
||||
|
|
@ -5523,7 +5678,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
function updateFakeCursor(cm) {
|
||||
var vim = cm.state.vim;
|
||||
var from = copyCursor(vim.sel.head);
|
||||
var from = clipCursorToContent(cm, copyCursor(vim.sel.head));
|
||||
var to = offsetCursor(from, 0, 1);
|
||||
if (vim.fakeCursor) {
|
||||
vim.fakeCursor.clear();
|
||||
|
|
@ -5534,7 +5689,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
var anchor = cm.getCursor('anchor');
|
||||
var head = cm.getCursor('head');
|
||||
// Enter or exit visual mode to match mouse selection.
|
||||
if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) {
|
||||
if (vim.visualMode && !cm.somethingSelected()) {
|
||||
exitVisualMode(cm, false);
|
||||
} else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) {
|
||||
vim.visualMode = true;
|
||||
|
|
@ -5574,6 +5729,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
var macroModeState = vimGlobalState.macroModeState;
|
||||
var lastChange = macroModeState.lastInsertModeChanges;
|
||||
var keyName = CodeMirror.keyName(e);
|
||||
if (!keyName) { return; }
|
||||
function onKeyFound() {
|
||||
lastChange.changes.push(new InsertModeKey(keyName));
|
||||
return true;
|
||||
|
|
@ -5767,7 +5923,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}, true);
|
||||
}
|
||||
return isHandled;
|
||||
};
|
||||
}
|
||||
exports.CodeMirror = CodeMirror;
|
||||
var getVim = Vim.maybeInitVimState_;
|
||||
exports.handler = {
|
||||
|
|
@ -5781,9 +5937,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
if (!vim.insertMode) {
|
||||
var isbackwards = !sel.cursor
|
||||
? session.selection.isBackwards() || session.selection.isEmpty()
|
||||
: Range.comparePoints(sel.cursor, sel.start) <= 0
|
||||
: Range.comparePoints(sel.cursor, sel.start) <= 0;
|
||||
if (!isbackwards && left > w)
|
||||
left -= w
|
||||
left -= w;
|
||||
}
|
||||
if (!vim.insertMode && vim.status) {
|
||||
h = h / 2;
|
||||
|
|
@ -5944,16 +6100,16 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var renderVirtualNumbers = {
|
||||
getText: function(session, row) {
|
||||
return (Math.abs(session.selection.lead.row - row) || (row + 1 + (row < 9? "\xb7" : "" ))) + ""
|
||||
return (Math.abs(session.selection.lead.row - row) || (row + 1 + (row < 9? "\xb7" : "" ))) + "";
|
||||
},
|
||||
getWidth: function(session, lastLineNumber, config) {
|
||||
return session.getLength().toString().length * config.characterWidth;
|
||||
},
|
||||
update: function(e, editor) {
|
||||
editor.renderer.$loop.schedule(editor.renderer.CHANGE_GUTTER)
|
||||
editor.renderer.$loop.schedule(editor.renderer.CHANGE_GUTTER);
|
||||
},
|
||||
attach: function(editor) {
|
||||
editor.renderer.$gutterLayer.$renderer = this;
|
||||
|
|
@ -5971,6 +6127,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
},
|
||||
type: "boolean"
|
||||
}, false);
|
||||
Vim.defineEx('write', 'w', function() {
|
||||
console.log(':write is not implemented')
|
||||
});
|
||||
defaultKeymap.push(
|
||||
{ keys: 'zc', type: 'action', action: 'fold', actionArgs: { open: false } },
|
||||
{ keys: 'zC', type: 'action', action: 'fold', actionArgs: { open: false, all: true } },
|
||||
|
|
@ -5995,7 +6154,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
if (cm.ace.inVirtualSelectionMode)
|
||||
cm.ace.on("beforeEndOperation", delayedExecAceCommand);
|
||||
else
|
||||
delayedExecAceCommand(null, cm.ace)
|
||||
delayedExecAceCommand(null, cm.ace);
|
||||
};
|
||||
function delayedExecAceCommand(op, ace) {
|
||||
ace.off("beforeEndOperation", delayedExecAceCommand);
|
||||
|
|
@ -6014,5 +6173,5 @@ dom.importCssString(".normal-mode .ace_cursor{\
|
|||
exports.handler.actions = actions;
|
||||
exports.Vim = Vim;
|
||||
|
||||
Vim.map("Y", "yy");
|
||||
Vim.map("Y", "yy", "normal");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ editor.session.setMode(new JavaScriptMode());
|
|||
function CodeMirror(place, opts) {
|
||||
if (opts.value != null)
|
||||
editor.session.setValue(opts.value);
|
||||
editor.setOption("indentedSoftWrap", false);
|
||||
editor.setOption("wrap", opts.lineWrapping);
|
||||
editor.setOption("useSoftTabs", !opts.indentWithTabs);
|
||||
editor.setKeyboardHandler(null);
|
||||
|
|
@ -58,6 +59,7 @@ function CodeMirror(place, opts) {
|
|||
cm.setSize(500, 300);
|
||||
return cm;
|
||||
}
|
||||
CodeMirror.defineMode = function() {}
|
||||
for (var key in vim.CodeMirror)
|
||||
CodeMirror[key] = vim.CodeMirror[key];
|
||||
var editor;
|
||||
|
|
@ -73,6 +75,9 @@ function test(name, fn) {
|
|||
}
|
||||
|
||||
vim.CodeMirror.Vim.unmap("Y");
|
||||
vim.CodeMirror.Vim.defineEx('write', 'w', function(cm) {
|
||||
CodeMirror.commands.save(cm);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
|
@ -592,7 +597,7 @@ testVim('{', function(cm, vim, helpers) {
|
|||
helpers.doKeys('6', '{');
|
||||
helpers.assertCursorAt(0, 0);
|
||||
}, { value: 'a\n\nb\nc\n\nd' });
|
||||
testVim('paragraph motions', function(cm, vim, helpers) {
|
||||
testVim('paragraph_motions', function(cm, vim, helpers) {
|
||||
cm.setCursor(10, 0);
|
||||
helpers.doKeys('{');
|
||||
helpers.assertCursorAt(4, 0);
|
||||
|
|
@ -685,7 +690,7 @@ testVim('dl_eol', function(cm, vim, helpers) {
|
|||
var register = helpers.getRegisterController().getRegister();
|
||||
eq(' ', register.toString());
|
||||
is(!register.linewise);
|
||||
helpers.assertCursorAt(0, 6);
|
||||
helpers.assertCursorAt(0, 5);
|
||||
}, { value: ' word1 ' });
|
||||
testVim('dl_repeat', function(cm, vim, helpers) {
|
||||
var curStart = makeCursor(0, 0);
|
||||
|
|
@ -767,6 +772,16 @@ testVim('dw_word', function(cm, vim, helpers) {
|
|||
is(!register.linewise);
|
||||
eqPos(curStart, cm.getCursor());
|
||||
}, { value: ' word1 word2' });
|
||||
testVim('dw_unicode_word', function(cm, vim, helpers) {
|
||||
helpers.doKeys('d', 'w');
|
||||
eq(cm.getValue().length, 10);
|
||||
helpers.doKeys('d', 'w');
|
||||
eq(cm.getValue().length, 6);
|
||||
helpers.doKeys('d', 'w');
|
||||
eq(cm.getValue().length, 5);
|
||||
helpers.doKeys('d', 'e');
|
||||
eq(cm.getValue().length, 2);
|
||||
}, { value: ' \u0562\u0561\u0580\u0587\xbbe\xb5g ' });
|
||||
testVim('dw_only_word', function(cm, vim, helpers) {
|
||||
// Test that if there is only 1 word left, dw deletes till the end of the
|
||||
// line.
|
||||
|
|
@ -776,7 +791,7 @@ testVim('dw_only_word', function(cm, vim, helpers) {
|
|||
var register = helpers.getRegisterController().getRegister();
|
||||
eq('word1 ', register.toString());
|
||||
is(!register.linewise);
|
||||
helpers.assertCursorAt(0, 1);
|
||||
helpers.assertCursorAt(0, 0);
|
||||
}, { value: ' word1 ' });
|
||||
testVim('dw_eol', function(cm, vim, helpers) {
|
||||
// Assert that dw does not delete the newline if last word to delete is at end
|
||||
|
|
@ -787,7 +802,7 @@ testVim('dw_eol', function(cm, vim, helpers) {
|
|||
var register = helpers.getRegisterController().getRegister();
|
||||
eq('word1', register.toString());
|
||||
is(!register.linewise);
|
||||
helpers.assertCursorAt(0, 1);
|
||||
helpers.assertCursorAt(0, 0);
|
||||
}, { value: ' word1\nword2' });
|
||||
testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {
|
||||
// Assert that dw does not delete the newline if last word to delete is at end
|
||||
|
|
@ -798,7 +813,7 @@ testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {
|
|||
var register = helpers.getRegisterController().getRegister();
|
||||
eq('word1', register.toString());
|
||||
is(!register.linewise);
|
||||
helpers.assertCursorAt(0, 1);
|
||||
helpers.assertCursorAt(0, 0);
|
||||
}, { value: ' word1\n\nword2' });
|
||||
testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) {
|
||||
cm.setCursor(0, 0);
|
||||
|
|
@ -844,7 +859,7 @@ testVim('dw_repeat', function(cm, vim, helpers) {
|
|||
var register = helpers.getRegisterController().getRegister();
|
||||
eq('word1\nword2', register.toString());
|
||||
is(!register.linewise);
|
||||
helpers.assertCursorAt(0, 1);
|
||||
helpers.assertCursorAt(0, 0);
|
||||
}, { value: ' word1\nword2' });
|
||||
testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) {
|
||||
cm.setCursor(0, 0);
|
||||
|
|
@ -1062,6 +1077,17 @@ testVim('cc_multiply_repeat', function(cm, vim, helpers) {
|
|||
is(register.linewise);
|
||||
eq('vim-insert', cm.getOption('keyMap'));
|
||||
});
|
||||
testVim('ct', function(cm, vim, helpers) {
|
||||
cm.setCursor(0, 9);
|
||||
helpers.doKeys('c', 't', 'w');
|
||||
eq(' word1 word3', cm.getValue());
|
||||
helpers.doKeys('<Esc>', 'c', '|');
|
||||
eq(' word3', cm.getValue());
|
||||
helpers.assertCursorAt(0, 0);
|
||||
helpers.doKeys('<Esc>', '2', 'u', 'w', 'h');
|
||||
helpers.doKeys('c', '2', 'g', 'e');
|
||||
eq(' wordword3', cm.getValue());
|
||||
}, { value: ' word1 word2 word3'});
|
||||
testVim('cc_should_not_append_to_document', function(cm, vim, helpers) {
|
||||
var expectedLineCount = cm.lineCount();
|
||||
cm.setCursor(cm.lastLine(), 0);
|
||||
|
|
@ -1371,7 +1397,7 @@ testVim('D', function(cm, vim, helpers) {
|
|||
var register = helpers.getRegisterController().getRegister();
|
||||
eq('rd1', register.toString());
|
||||
is(!register.linewise);
|
||||
helpers.assertCursorAt(0, 3);
|
||||
helpers.assertCursorAt(0, 2);
|
||||
}, { value: ' word1\nword2\n word3' });
|
||||
testVim('C', function(cm, vim, helpers) {
|
||||
var curStart = makeCursor(0, 3);
|
||||
|
|
@ -1962,8 +1988,11 @@ testVim('visual_block_move_to_eol', function(cm, vim, helpers) {
|
|||
cm.setCursor(0, 0);
|
||||
helpers.doKeys('<C-v>', 'G', '$');
|
||||
var selections = cm.getSelections().join();
|
||||
console.log(selections);
|
||||
eq("123,45,6", selections);
|
||||
eq('123,45,6', selections);
|
||||
// Checks that with cursor at Infinity, finding words backwards still works.
|
||||
helpers.doKeys('2', 'k', 'b');
|
||||
selections = cm.getSelections().join();
|
||||
eq('1', selections);
|
||||
}, {value: '123\n45\n6'});
|
||||
testVim('visual_block_different_line_lengths', function(cm, vim, helpers) {
|
||||
// test the block selection with lines of different length
|
||||
|
|
@ -2053,6 +2082,11 @@ testVim('visual_join', function(cm, vim, helpers) {
|
|||
eq(' 1 2 3\n 4\n 5', cm.getValue());
|
||||
is(!vim.visualMode);
|
||||
}, { value: ' 1\n 2\n 3\n 4\n 5' });
|
||||
testVim('visual_join_2', function(cm, vim, helpers) {
|
||||
helpers.doKeys('G', 'V', 'g', 'g', 'J');
|
||||
eq('1 2 3 4 5 6 ', cm.getValue());
|
||||
is(!vim.visualMode);
|
||||
}, { value: '1\n2\n3\n4\n5\n6\n'});
|
||||
testVim('visual_blank', function(cm, vim, helpers) {
|
||||
helpers.doKeys('v', 'k');
|
||||
eq(vim.visualMode, true);
|
||||
|
|
@ -2260,6 +2294,15 @@ testVim('S_visual', function(cm, vim, helpers) {
|
|||
eq('\ncc', cm.getValue());
|
||||
}, { value: 'aa\nbb\ncc'});
|
||||
|
||||
testVim('d_/', function(cm, vim, helpers) {
|
||||
cm.openDialog = helpers.fakeOpenDialog('match');
|
||||
helpers.doKeys('2', 'd', '/');
|
||||
helpers.assertCursorAt(0, 0);
|
||||
eq('match \n next', cm.getValue());
|
||||
cm.openDialog = helpers.fakeOpenDialog('2');
|
||||
helpers.doKeys('d', ':');
|
||||
// TODO eq(' next', cm.getValue());
|
||||
}, { value: 'text match match \n next' });
|
||||
testVim('/ and n/N', function(cm, vim, helpers) {
|
||||
cm.openDialog = helpers.fakeOpenDialog('match');
|
||||
helpers.doKeys('/');
|
||||
|
|
@ -2777,6 +2820,44 @@ testVim('exCommand_history', function(cm, vim, helpers) {
|
|||
onKeyDown({keyCode: keyCodes.Up}, input, close);
|
||||
eq(input, 'sort');
|
||||
}, {value: ''});
|
||||
testVim('search_clear', function(cm, vim, helpers) {
|
||||
var onKeyDown;
|
||||
var input = '';
|
||||
var keyCodes = {
|
||||
Ctrl: 17,
|
||||
u: 85
|
||||
};
|
||||
cm.openDialog = function(template, callback, options) {
|
||||
onKeyDown = options.onKeyDown;
|
||||
};
|
||||
var close = function(newVal) {
|
||||
if (typeof newVal == 'string') input = newVal;
|
||||
}
|
||||
helpers.doKeys('/');
|
||||
input = 'foo';
|
||||
onKeyDown({keyCode: keyCodes.Ctrl}, input, close);
|
||||
onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close);
|
||||
eq(input, '');
|
||||
});
|
||||
testVim('exCommand_clear', function(cm, vim, helpers) {
|
||||
var onKeyDown;
|
||||
var input = '';
|
||||
var keyCodes = {
|
||||
Ctrl: 17,
|
||||
u: 85
|
||||
};
|
||||
cm.openDialog = function(template, callback, options) {
|
||||
onKeyDown = options.onKeyDown;
|
||||
};
|
||||
var close = function(newVal) {
|
||||
if (typeof newVal == 'string') input = newVal;
|
||||
}
|
||||
helpers.doKeys(':');
|
||||
input = 'foo';
|
||||
onKeyDown({keyCode: keyCodes.Ctrl}, input, close);
|
||||
onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close);
|
||||
eq(input, '');
|
||||
});
|
||||
testVim('.', function(cm, vim, helpers) {
|
||||
cm.setCursor(0, 0);
|
||||
helpers.doKeys('2', 'd', 'w');
|
||||
|
|
@ -3204,7 +3285,7 @@ testVim('scrollMotion', function(cm, vim, helpers){
|
|||
cm.refresh(); //ace!
|
||||
prevScrollInfo = cm.getScrollInfo();
|
||||
helpers.doKeys('<C-y>');
|
||||
eq(prevCursor.line - 1, cm.getCursor().line);
|
||||
eq(prevCursor.line - 1, cm.getCursor().line, "Y");
|
||||
is(prevScrollInfo.top > cm.getScrollInfo().top);
|
||||
}, { value: scrollMotionSandbox});
|
||||
|
||||
|
|
@ -3727,17 +3808,111 @@ testVim('set_string', function(cm, vim, helpers) {
|
|||
eq('c', CodeMirror.Vim.getOption('testoption'));
|
||||
});
|
||||
testVim('ex_set_string', function(cm, vim, helpers) {
|
||||
CodeMirror.Vim.defineOption('testoption', 'a', 'string');
|
||||
CodeMirror.Vim.defineOption('testopt', 'a', 'string');
|
||||
// Test default value is set.
|
||||
eq('a', CodeMirror.Vim.getOption('testoption'));
|
||||
eq('a', CodeMirror.Vim.getOption('testopt'));
|
||||
try {
|
||||
// Test fail to set 'notestoption'
|
||||
helpers.doEx('set notestoption=b');
|
||||
// Test fail to set 'notestopt'
|
||||
helpers.doEx('set notestopt=b');
|
||||
fail();
|
||||
} catch (expected) {};
|
||||
// Test setOption
|
||||
helpers.doEx('set testoption=c')
|
||||
eq('c', CodeMirror.Vim.getOption('testoption'));
|
||||
helpers.doEx('set testopt=c')
|
||||
eq('c', CodeMirror.Vim.getOption('testopt'));
|
||||
helpers.doEx('set testopt=c')
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global
|
||||
eq('c', CodeMirror.Vim.getOption('testopt')); // global
|
||||
// Test setOption global
|
||||
helpers.doEx('setg testopt=d')
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm));
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
|
||||
eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
|
||||
eq('d', CodeMirror.Vim.getOption('testopt'));
|
||||
// Test setOption local
|
||||
helpers.doEx('setl testopt=e')
|
||||
eq('e', CodeMirror.Vim.getOption('testopt', cm));
|
||||
eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
|
||||
eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
|
||||
eq('d', CodeMirror.Vim.getOption('testopt'));
|
||||
});
|
||||
testVim('ex_set_callback', function(cm, vim, helpers) {
|
||||
var global;
|
||||
|
||||
function cb(val, cm, cfg) {
|
||||
if (val === undefined) {
|
||||
// Getter
|
||||
if (cm) {
|
||||
return cm._local;
|
||||
} else {
|
||||
return global;
|
||||
}
|
||||
} else {
|
||||
// Setter
|
||||
if (cm) {
|
||||
cm._local = val;
|
||||
} else {
|
||||
global = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CodeMirror.Vim.defineOption('testopt', 'a', 'string', cb);
|
||||
// Test default value is set.
|
||||
eq('a', CodeMirror.Vim.getOption('testopt'));
|
||||
try {
|
||||
// Test fail to set 'notestopt'
|
||||
helpers.doEx('set notestopt=b');
|
||||
fail();
|
||||
} catch (expected) {};
|
||||
// Test setOption (Identical to the string tests, but via callback instead)
|
||||
helpers.doEx('set testopt=c')
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global
|
||||
eq('c', CodeMirror.Vim.getOption('testopt')); // global
|
||||
// Test setOption global
|
||||
helpers.doEx('setg testopt=d')
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm));
|
||||
eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
|
||||
eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
|
||||
eq('d', CodeMirror.Vim.getOption('testopt'));
|
||||
// Test setOption local
|
||||
helpers.doEx('setl testopt=e')
|
||||
eq('e', CodeMirror.Vim.getOption('testopt', cm));
|
||||
eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'}));
|
||||
eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'}));
|
||||
eq('d', CodeMirror.Vim.getOption('testopt'));
|
||||
})
|
||||
testVim('ex_set_filetype', function(cm, vim, helpers) {
|
||||
CodeMirror.defineMode('test_mode', function() {
|
||||
return {token: function(stream) {
|
||||
stream.match(/^\s+|^\S+/);
|
||||
}};
|
||||
});
|
||||
CodeMirror.defineMode('test_mode_2', function() {
|
||||
return {token: function(stream) {
|
||||
stream.match(/^\s+|^\S+/);
|
||||
}};
|
||||
});
|
||||
// Test mode is set.
|
||||
helpers.doEx('set filetype=test_mode');
|
||||
eq('test_mode', cm.getMode().name);
|
||||
// Test 'ft' alias also sets mode.
|
||||
helpers.doEx('set ft=test_mode_2');
|
||||
eq('test_mode_2', cm.getMode().name);
|
||||
});
|
||||
testVim('ex_set_filetype_null', function(cm, vim, helpers) {
|
||||
CodeMirror.defineMode('test_mode', function() {
|
||||
return {token: function(stream) {
|
||||
stream.match(/^\s+|^\S+/);
|
||||
}};
|
||||
});
|
||||
cm.setOption('mode', 'test_mode');
|
||||
// Test mode is set to null.
|
||||
helpers.doEx('set filetype=');
|
||||
eq('null', cm.getMode().name);
|
||||
});
|
||||
// TODO: Reset key maps after each test.
|
||||
testVim('ex_map_key2key', function(cm, vim, helpers) {
|
||||
|
|
|
|||
|
|
@ -120,9 +120,9 @@ var FontMetrics = exports.FontMetrics = function(parentEl, interval) {
|
|||
this.setPolling = function(val) {
|
||||
if (val) {
|
||||
this.$pollSizeChanges();
|
||||
} else {
|
||||
if (this.$pollSizeChangesTimer)
|
||||
this.$pollSizeChangesTimer;
|
||||
} else if (this.$pollSizeChangesTimer) {
|
||||
clearInterval(this.$pollSizeChangesTimer);
|
||||
this.$pollSizeChangesTimer = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -100,16 +100,14 @@ var Gutter = function(parentEl) {
|
|||
}
|
||||
};
|
||||
|
||||
this.$updateAnnotations = function (e) {
|
||||
this.$updateAnnotations = function (delta) {
|
||||
if (!this.$annotations.length)
|
||||
return;
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
var firstRow = range.start.row;
|
||||
var len = range.end.row - firstRow;
|
||||
var firstRow = delta.start.row;
|
||||
var len = delta.end.row - firstRow;
|
||||
if (len === 0) {
|
||||
// do nothing
|
||||
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
||||
} else if (delta.action == 'remove') {
|
||||
this.$annotations.splice(firstRow, len + 1, null);
|
||||
} else {
|
||||
var args = new Array(len + 1);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ var Marker = function(parentEl) {
|
|||
else
|
||||
this.drawMultiLineMarker(html, range, marker.clazz, config);
|
||||
} else {
|
||||
this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config);
|
||||
this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config);
|
||||
}
|
||||
}
|
||||
this.element.innerHTML = html.join("");
|
||||
|
|
@ -100,27 +100,30 @@ var Marker = function(parentEl) {
|
|||
return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
|
||||
};
|
||||
|
||||
function getBorderClass(tl, tr, br, bl) {
|
||||
return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0);
|
||||
}
|
||||
// Draws a marker, which spans a range of text on multiple lines
|
||||
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {
|
||||
// selection start
|
||||
var row = range.start.row;
|
||||
|
||||
var lineRange = new Range(
|
||||
row, range.start.column,
|
||||
row, this.session.getScreenLastRowColumn(row)
|
||||
);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " ace_start", layerConfig, 1, extraStyle);
|
||||
|
||||
// selection end
|
||||
row = range.end.row;
|
||||
lineRange = new Range(row, 0, row, range.end.column);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle);
|
||||
|
||||
for (row = range.start.row + 1; row < range.end.row; row++) {
|
||||
lineRange.start.row = row;
|
||||
lineRange.end.row = row;
|
||||
lineRange.end.column = this.session.getScreenLastRowColumn(row);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle);
|
||||
var session = this.session;
|
||||
var start = range.start.row;
|
||||
var end = range.end.row;
|
||||
var row = start;
|
||||
var prev = 0;
|
||||
var curr = 0;
|
||||
var next = session.getScreenLastRowColumn(row);
|
||||
var lineRange = new Range(row, range.start.column, row, curr);
|
||||
for (; row <= end; row++) {
|
||||
lineRange.start.row = lineRange.end.row = row;
|
||||
lineRange.start.column = row == start ? range.start.column : session.getRowWrapIndent(row);
|
||||
lineRange.end.column = next;
|
||||
prev = curr;
|
||||
curr = next;
|
||||
next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column;
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange,
|
||||
clazz + (row == start ? " ace_start" : "") + " ace_br"
|
||||
+ getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end),
|
||||
layerConfig, row == end ? 0 : 1, extraStyle);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -134,7 +137,7 @@ var Marker = function(parentEl) {
|
|||
extraStyle = extraStyle || "";
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, " ace_start' style='",
|
||||
"<div class='", clazz, " ace_br1 ace_start' style='",
|
||||
"height:", height, "px;",
|
||||
"right:0;",
|
||||
"top:", top, "px;",
|
||||
|
|
@ -146,7 +149,7 @@ var Marker = function(parentEl) {
|
|||
var width = range.end.column * config.characterWidth;
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, "' style='",
|
||||
"<div class='", clazz, " ace_br12' style='",
|
||||
"height:", height, "px;",
|
||||
"width:", width, "px;",
|
||||
"top:", top, "px;",
|
||||
|
|
@ -155,12 +158,14 @@ var Marker = function(parentEl) {
|
|||
|
||||
// all the complete lines
|
||||
height = (range.end.row - range.start.row - 1) * config.lineHeight;
|
||||
if (height < 0)
|
||||
if (height <= 0)
|
||||
return;
|
||||
top = this.$getTop(range.start.row + 1, config);
|
||||
|
||||
var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8);
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, "' style='",
|
||||
"<div class='", clazz, (radiusClass ? " ace_br" + radiusClass : ""), "' style='",
|
||||
"height:", height, "px;",
|
||||
"right:0;",
|
||||
"top:", top, "px;",
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ var Text = function(parentEl) {
|
|||
this.EOL_CHAR_LF = "\xAC";
|
||||
this.EOL_CHAR_CRLF = "\xa4";
|
||||
this.EOL_CHAR = this.EOL_CHAR_LF;
|
||||
this.TAB_CHAR = "\u2192"; //"\u21E5";
|
||||
this.TAB_CHAR = "\u2014"; //"\u21E5";
|
||||
this.SPACE_CHAR = "\xB7";
|
||||
this.$padding = 0;
|
||||
|
||||
|
|
@ -128,11 +128,10 @@ var Text = function(parentEl) {
|
|||
for (var i = 1; i < tabSize + 1; i++) {
|
||||
if (this.showInvisibles) {
|
||||
tabStr.push("<span class='ace_invisible ace_invisible_tab'>"
|
||||
+ this.TAB_CHAR
|
||||
+ lang.stringRepeat("\xa0", i - 1)
|
||||
+ lang.stringRepeat(this.TAB_CHAR, i)
|
||||
+ "</span>");
|
||||
} else {
|
||||
tabStr.push(lang.stringRepeat("\xa0", i));
|
||||
tabStr.push(lang.stringRepeat(" ", i));
|
||||
}
|
||||
}
|
||||
if (this.displayIndentGuides) {
|
||||
|
|
@ -145,9 +144,9 @@ var Text = function(parentEl) {
|
|||
spaceClass = " ace_invisible_space";
|
||||
tabClass = " ace_invisible_tab";
|
||||
var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);
|
||||
var tabContent = this.TAB_CHAR + lang.stringRepeat("\xa0", this.tabSize - 1);
|
||||
var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize);
|
||||
} else{
|
||||
var spaceContent = lang.stringRepeat("\xa0", this.tabSize);
|
||||
var spaceContent = lang.stringRepeat(" ", this.tabSize);
|
||||
var tabContent = spaceContent;
|
||||
}
|
||||
|
||||
|
|
@ -325,9 +324,9 @@ var Text = function(parentEl) {
|
|||
var replaceReg = /\t|&|<|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g;
|
||||
var replaceFunc = function(c, a, b, tabIdx, idx4) {
|
||||
if (a) {
|
||||
return self.showInvisibles ?
|
||||
"<span class='ace_invisible ace_invisible_space'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>" :
|
||||
lang.stringRepeat("\xa0", c.length);
|
||||
return self.showInvisibles
|
||||
? "<span class='ace_invisible ace_invisible_space'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>"
|
||||
: c;
|
||||
} else if (c == "&") {
|
||||
return "&";
|
||||
} else if (c == "<") {
|
||||
|
|
@ -420,6 +419,8 @@ var Text = function(parentEl) {
|
|||
);
|
||||
}
|
||||
|
||||
stringBuilder.push(lang.stringRepeat("\xa0", splits.indent));
|
||||
|
||||
split ++;
|
||||
screenColumn = 0;
|
||||
splitChars = splits[split] || Number.MAX_VALUE;
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ module.exports = {
|
|||
"test rendering of indent guides" : function() {
|
||||
var textLayer = this.textLayer
|
||||
var EOL = "<span class='ace_invisible ace_invisible_eol'>" + textLayer.EOL_CHAR + "</span>";
|
||||
var SPACE = function(i) {return Array(i+1).join("\xa0")}
|
||||
var SPACE = function(i) {return Array(i+1).join(" ")}
|
||||
var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR)}
|
||||
var TAB = function(i) {return textLayer.TAB_CHAR + SPACE(i-1)}
|
||||
var TAB = function(i) {return Array(i+1).join(textLayer.TAB_CHAR)}
|
||||
function testRender(results) {
|
||||
for (var i = results.length; i--; ) {
|
||||
var stringBuilder = [];
|
||||
|
|
|
|||
|
|
@ -91,6 +91,11 @@ exports.toggleCssClass = function(el, name) {
|
|||
return add;
|
||||
};
|
||||
|
||||
if (typeof document == "undefined") {
|
||||
exports.importCssString = function() {};
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add or remove a CSS class from the list of classes on the given node
|
||||
* depending on the value of <tt>include</tt>
|
||||
|
|
@ -173,9 +178,6 @@ exports.getInnerHeight = function(element) {
|
|||
};
|
||||
|
||||
|
||||
if (typeof document == "undefined")
|
||||
return;
|
||||
|
||||
if (window.pageYOffset !== undefined) {
|
||||
exports.getPageScrollTop = function() {
|
||||
return window.pageYOffset;
|
||||
|
|
|
|||
|
|
@ -241,12 +241,11 @@ function normalizeCommandKeys(callback, e, keyCode) {
|
|||
if (keyCode === 18 || keyCode === 17) {
|
||||
var location = "location" in e ? e.location : e.keyLocation;
|
||||
if (keyCode === 17 && location === 1) {
|
||||
ts = e.timeStamp;
|
||||
if (pressedKeys[keyCode] == 1)
|
||||
ts = e.timeStamp;
|
||||
} else if (keyCode === 18 && hashId === 3 && location === 2) {
|
||||
var dt = -ts;
|
||||
ts = e.timeStamp;
|
||||
dt += ts;
|
||||
if (dt < 3)
|
||||
var dt = e.timeStamp - ts;
|
||||
if (dt < 50)
|
||||
pressedKeys.altGr = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -309,7 +308,7 @@ exports.addCommandKeyListener = function(el, callback) {
|
|||
var lastDefaultPrevented = null;
|
||||
|
||||
addListener(el, "keydown", function(e) {
|
||||
pressedKeys[e.keyCode] = true;
|
||||
pressedKeys[e.keyCode] = (pressedKeys[e.keyCode] || 0) + 1;
|
||||
var result = normalizeCommandKeys(callback, e, e.keyCode);
|
||||
lastDefaultPrevented = e.defaultPrevented;
|
||||
return result;
|
||||
|
|
@ -327,13 +326,14 @@ exports.addCommandKeyListener = function(el, callback) {
|
|||
});
|
||||
|
||||
if (!pressedKeys) {
|
||||
pressedKeys = Object.create(null);
|
||||
addListener(window, "focus", function(e) {
|
||||
pressedKeys = Object.create(null);
|
||||
});
|
||||
resetPressedKeys();
|
||||
addListener(window, "focus", resetPressedKeys);
|
||||
}
|
||||
}
|
||||
};
|
||||
function resetPressedKeys(e) {
|
||||
pressedKeys = Object.create(null);
|
||||
}
|
||||
|
||||
if (window.postMessage && !useragent.isOldIE) {
|
||||
var postMessageId = 1;
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ var Keys = (function() {
|
|||
73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o',
|
||||
80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v',
|
||||
87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.',
|
||||
187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', 219: '[',
|
||||
220: '\\',221: ']', 222: '\''
|
||||
186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`',
|
||||
219: '[', 220: '\\',221: ']', 222: '\''
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -81,20 +81,24 @@ exports.copyArray = function(array){
|
|||
return copy;
|
||||
};
|
||||
|
||||
exports.deepCopy = function (obj) {
|
||||
exports.deepCopy = function deepCopy(obj) {
|
||||
if (typeof obj !== "object" || !obj)
|
||||
return obj;
|
||||
var copy;
|
||||
if (Array.isArray(obj)) {
|
||||
copy = [];
|
||||
for (var key = 0; key < obj.length; key++) {
|
||||
copy[key] = deepCopy(obj[key]);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
var cons = obj.constructor;
|
||||
if (cons === RegExp)
|
||||
return obj;
|
||||
|
||||
var copy = cons();
|
||||
copy = cons();
|
||||
for (var key in obj) {
|
||||
if (typeof obj[key] === "object") {
|
||||
copy[key] = exports.deepCopy(obj[key]);
|
||||
} else {
|
||||
copy[key] = obj[key];
|
||||
}
|
||||
copy[key] = deepCopy(obj[key]);
|
||||
}
|
||||
return copy;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -113,18 +113,16 @@ function LineWidgets(session) {
|
|||
});
|
||||
};
|
||||
|
||||
this.updateOnChange = function(e) {
|
||||
this.updateOnChange = function(delta) {
|
||||
var lineWidgets = this.session.lineWidgets;
|
||||
if (!lineWidgets) return;
|
||||
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
var startRow = range.start.row;
|
||||
var len = range.end.row - startRow;
|
||||
|
||||
var startRow = delta.start.row;
|
||||
var len = delta.end.row - startRow;
|
||||
|
||||
if (len === 0) {
|
||||
// return
|
||||
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
||||
} else if (delta.action == 'remove') {
|
||||
var removed = lineWidgets.splice(startRow + 1, len);
|
||||
removed.forEach(function(w) {
|
||||
w && this.removeLineWidget(w);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
[1, +1, -1, 12_345, 0.000_1,
|
||||
_, 3_1, 1_2, 1_.0, 0._1];
|
||||
|
||||
{:id => 34, :key => "value"}
|
||||
{:id => ?", :key => "value", anotherKey: [x, y?]}
|
||||
|
||||
=begin
|
||||
=end
|
||||
|
|
|
|||
2207
lib/ace/mode/_test/tokens_abc.json
Normal file
2207
lib/ace/mode/_test/tokens_abc.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -56,34 +56,34 @@
|
|||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
["comment","| "],
|
||||
["string","start "],
|
||||
["comment","| "],
|
||||
["string","eat "],
|
||||
["comment","| "],
|
||||
["string","left "],
|
||||
["comment","|"],
|
||||
["string"," start "],
|
||||
["comment","|"],
|
||||
["string"," eat "],
|
||||
["comment","|"],
|
||||
["string"," left "],
|
||||
["comment","|"]
|
||||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
["comment","| "],
|
||||
["string"," 12 "],
|
||||
["comment","| "],
|
||||
["string"," 5 "],
|
||||
["comment","| "],
|
||||
["string"," 7 "],
|
||||
["comment","|"],
|
||||
["string"," 12 "],
|
||||
["comment","|"],
|
||||
["string"," 5 "],
|
||||
["comment","|"],
|
||||
["string"," 7 "],
|
||||
["comment","|"]
|
||||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
["comment","| "],
|
||||
["string"," 20 "],
|
||||
["comment","| "],
|
||||
["string"," 5 "],
|
||||
["comment","| "],
|
||||
["string"," 15 "],
|
||||
["comment","| "],
|
||||
["string"," "]
|
||||
["comment","|"],
|
||||
["string"," 20 "],
|
||||
["comment","|"],
|
||||
["string"," 5 "],
|
||||
["comment","|"],
|
||||
["string"," 15 "],
|
||||
["comment","|"],
|
||||
["string"," "]
|
||||
],[
|
||||
"start"
|
||||
],[
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@
|
|||
["text"," "],
|
||||
["punctuation.separator.key-value","=>"],
|
||||
["text"," "],
|
||||
["constant.numeric","34"],
|
||||
["string.character","?\""],
|
||||
["text",", "],
|
||||
["constant.other.symbol.ruby",":key"],
|
||||
["text"," "],
|
||||
|
|
@ -148,7 +148,15 @@
|
|||
["string.start","\""],
|
||||
["string","value"],
|
||||
["string.end","\""],
|
||||
["paren.rparen","}"]
|
||||
["text",", "],
|
||||
["identifier","anotherKey"],
|
||||
["text",": "],
|
||||
["paren.lparen","["],
|
||||
["identifier","x"],
|
||||
["text",", "],
|
||||
["identifier","y"],
|
||||
["text","?"],
|
||||
["paren.rparen","]}"]
|
||||
],[
|
||||
"start"
|
||||
],[
|
||||
|
|
|
|||
|
|
@ -10,10 +10,9 @@
|
|||
],[
|
||||
"start",
|
||||
["keyword.source.rust","fn"],
|
||||
["meta.function.source.rust"," "],
|
||||
["text"," "],
|
||||
["entity.name.function.source.rust","main"],
|
||||
["meta.function.source.rust","("],
|
||||
["text",") {"]
|
||||
["text","() {"]
|
||||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
|
|
@ -88,10 +87,14 @@
|
|||
],[
|
||||
"start",
|
||||
["keyword.source.rust","fn"],
|
||||
["meta.function.source.rust"," "],
|
||||
["entity.name.function.source.rust","map<T, U>"],
|
||||
["meta.function.source.rust","("],
|
||||
["text","vector: &[T]"],
|
||||
["text"," "],
|
||||
["entity.name.function.source.rust","map"],
|
||||
["keyword.operator","<"],
|
||||
["text","T"],
|
||||
["keyword.operator",","],
|
||||
["text"," U"],
|
||||
["keyword.operator",">"],
|
||||
["text","(vector: &[T]"],
|
||||
["keyword.operator",","],
|
||||
["text"," function: &fn(v: &T) "],
|
||||
["keyword.operator","->"],
|
||||
|
|
|
|||
|
|
@ -199,7 +199,5 @@
|
|||
["string.quoted.double.asp"," ... updated.\""]
|
||||
],[
|
||||
"start",
|
||||
["support.function.asp","End"],
|
||||
["text"," "],
|
||||
["storage.type.asp","Sub"]
|
||||
["storage.type.asp","End Sub"]
|
||||
]]
|
||||
|
|
@ -126,7 +126,7 @@ var AbapHighlightRules = function() {
|
|||
{token : "string", regex : "`", next : "start"},
|
||||
{defaultToken : "string"}
|
||||
]
|
||||
}
|
||||
};
|
||||
};
|
||||
oop.inherits(AbapHighlightRules, TextHighlightRules);
|
||||
|
||||
|
|
|
|||
58
lib/ace/mode/abc.js
Normal file
58
lib/ace/mode/abc.js
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2012, 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 ***** */
|
||||
|
||||
/*
|
||||
THIS FILE WAS AUTOGENERATED BY mode.tmpl.js
|
||||
*/
|
||||
|
||||
define(function (require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextMode = require("./text").Mode;
|
||||
var ABCHighlightRules = require("./abc_highlight_rules").ABCHighlightRules;
|
||||
// TODO: pick appropriate fold mode
|
||||
var FoldMode = require("./folding/cstyle").FoldMode;
|
||||
|
||||
var Mode = function () {
|
||||
this.HighlightRules = ABCHighlightRules;
|
||||
this.foldingRules = new FoldMode();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function () {
|
||||
// this.lineCommentStart = ""%.*"";
|
||||
// this.blockComment = {start: ""/*"", end: ""*/""};
|
||||
// Extra logic goes here.
|
||||
this.$id = "ace/mode/abc"
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
114
lib/ace/mode/abc_highlight_rules.js
Normal file
114
lib/ace/mode/abc_highlight_rules.js
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/* This file was partially autogenerated from https://github.com/jimhawkridge/SublimeABC
|
||||
|
||||
Modifications
|
||||
|
||||
- more classes to express the abc semantic
|
||||
- added syntax highlighting for Zupfnoter conventions (https://github.com/bwl21/zupfnoter)
|
||||
- separate note pitch and note duration - even if it looks the same
|
||||
|
||||
***********************************************************************************************/
|
||||
|
||||
|
||||
define(function (require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var ABCHighlightRules = function () {
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
start: [
|
||||
{
|
||||
token: ['zupfnoter.information.comment.line.percentage', 'information.keyword', 'in formation.keyword.embedded'],
|
||||
regex: '(%%%%)(hn\\.[a-z]*)(.*)',
|
||||
comment: 'Instruction Comment'
|
||||
},
|
||||
{
|
||||
token: ['information.comment.line.percentage', 'information.keyword.embedded'],
|
||||
regex: '(%%)(.*)',
|
||||
comment: 'Instruction Comment'
|
||||
},
|
||||
|
||||
{
|
||||
token: 'comment.line.percentage',
|
||||
regex: '%.*',
|
||||
comment: 'Comments'
|
||||
},
|
||||
|
||||
{
|
||||
token: 'barline.keyword.operator',
|
||||
regex: '[\\[:]*[|:][|\\]:]*(?:\\[?[0-9]+)?|\\[[0-9]+',
|
||||
comment: 'Bar lines'
|
||||
},
|
||||
{
|
||||
token: ['information.keyword.embedded', 'information.argument.string.unquoted'],
|
||||
regex: '(\\[[A-Za-z]:)([^\\]]*\\])',
|
||||
comment: 'embedded Header lines'
|
||||
},
|
||||
{
|
||||
token: ['information.keyword', 'information.argument.string.unquoted'],
|
||||
regex: '^([A-Za-z]:)([^%\\\\]*)',
|
||||
comment: 'Header lines'
|
||||
},
|
||||
{
|
||||
token: ['text', 'entity.name.function', 'string.unquoted', 'text'],
|
||||
regex: '(\\[)([A-Z]:)(.*?)(\\])',
|
||||
comment: 'Inline fields'
|
||||
},
|
||||
{
|
||||
token: ['accent.constant.language', 'pitch.constant.numeric', 'duration.constant.numeric'],
|
||||
regex: '([\\^=_]*)([A-Ga-gz][,\']*)([0-9]*/*[><0-9]*)',
|
||||
comment: 'Notes'
|
||||
},
|
||||
{
|
||||
token: 'zupfnoter.jumptarget.string.quoted',
|
||||
regex: '[\\"!]\\^\\:.*?[\\"!]',
|
||||
comment: 'Zupfnoter jumptarget'
|
||||
}, {
|
||||
token: 'zupfnoter.goto.string.quoted',
|
||||
regex: '[\\"!]\\^\\@.*?[\\"!]',
|
||||
comment: 'Zupfnoter goto'
|
||||
},
|
||||
{
|
||||
token: 'zupfnoter.annotation.string.quoted',
|
||||
regex: '[\\"!]\\^\\!.*?[\\"!]',
|
||||
comment: 'Zupfnoter annoation'
|
||||
},
|
||||
{
|
||||
token: 'zupfnoter.annotationref.string.quoted',
|
||||
regex: '[\\"!]\\^\\#.*?[\\"!]',
|
||||
comment: 'Zupfnoter annotation reference'
|
||||
},
|
||||
{
|
||||
token: 'chordname.string.quoted',
|
||||
regex: '[\\"!]\\^.*?[\\"!]',
|
||||
comment: 'abc chord'
|
||||
},
|
||||
{
|
||||
token: 'string.quoted',
|
||||
regex: '[\\"!].*?[\\"!]',
|
||||
comment: 'abc annotation'
|
||||
}
|
||||
|
||||
]
|
||||
};
|
||||
|
||||
// this.embedRules(JsonHighlightRules, "json-")
|
||||
|
||||
this.normalizeRules();
|
||||
};
|
||||
|
||||
ABCHighlightRules.metaData = {
|
||||
fileTypes: ['abc'],
|
||||
name: 'ABC',
|
||||
scopeName: 'text.abcnotation'
|
||||
};
|
||||
|
||||
|
||||
oop.inherits(ABCHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.ABCHighlightRules = ABCHighlightRules;
|
||||
});
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
if (typeof process !== "undefined") {
|
||||
require("amd-loader");
|
||||
require("../../test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
|
@ -42,6 +43,7 @@ var Editor = require("../../editor").Editor;
|
|||
var EditSession = require("../../edit_session").EditSession;
|
||||
var MockRenderer = require("../../test/mockrenderer").MockRenderer;
|
||||
var JavaScriptMode = require("../javascript").Mode;
|
||||
var XMLMode = require("../xml").Mode;
|
||||
var editor;
|
||||
var exec = function(name, times, args) {
|
||||
do {
|
||||
|
|
@ -117,9 +119,9 @@ module.exports = {
|
|||
|
||||
editor.setValue("");
|
||||
exec("insertstring", 1, "{");
|
||||
assert.equal(editor.getValue(), "{")
|
||||
assert.equal(editor.getValue(), "{");
|
||||
exec("insertstring", 1, "\n");
|
||||
assert.equal(editor.getValue(), "{\n \n}")
|
||||
assert.equal(editor.getValue(), "{\n \n}");
|
||||
|
||||
editor.setValue("");
|
||||
exec("insertstring", 1, "(");
|
||||
|
|
@ -129,6 +131,44 @@ module.exports = {
|
|||
exec("backspace", 1);
|
||||
exec("insertstring", 1, '"');
|
||||
assert.equal(editor.getValue(), '("")');
|
||||
|
||||
editor.setValue("('foo')", 1);
|
||||
exec("gotoleft", 1);
|
||||
exec("selectleft", 1);
|
||||
exec("selectMoreBefore", 1);
|
||||
exec("insertstring", 1, "'");
|
||||
assert.equal(editor.getValue(), "('foo')");
|
||||
exec("selectleft", 1);
|
||||
exec("insertstring", 1, '"');
|
||||
assert.equal(editor.getValue(), '("foo")');
|
||||
exec("selectleft", 1);
|
||||
exec("insertstring", 1, '"');
|
||||
assert.equal(editor.getValue(), '("foo")');
|
||||
|
||||
editor.setValue("", 1);
|
||||
exec("selectleft", 1);
|
||||
exec("insertstring", 1, '"');
|
||||
assert.equal(editor.getValue(), '""');
|
||||
exec("insertstring", 1, '\\');
|
||||
exec("insertstring", 1, 'n');
|
||||
exec("insertstring", 1, '"');
|
||||
assert.equal(editor.getValue(), '"\\n"');
|
||||
|
||||
},
|
||||
"test: xml": function() {
|
||||
editor = new Editor(new MockRenderer());
|
||||
editor.setValue(["<OuterTag>",
|
||||
" <SelfClosingTag />"
|
||||
].join("\n"));
|
||||
editor.session.setMode(new XMLMode);
|
||||
exec("gotolinedown", 1);
|
||||
exec("gotolineend", 1);
|
||||
exec("insertstring", 1, '\n');
|
||||
assert.equal(editor.session.getLine(2), " ");
|
||||
exec("gotolineup", 1);
|
||||
exec("gotolineend", 1);
|
||||
exec("insertstring", 1, '\n');
|
||||
assert.equal(editor.session.getLine(2), " ");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,19 @@ var initContext = function(editor) {
|
|||
};
|
||||
};
|
||||
|
||||
var getWrapped = function(selection, selected, opening, closing) {
|
||||
var rowDiff = selection.end.row - selection.start.row;
|
||||
return {
|
||||
text: opening + selected + closing,
|
||||
selection: [
|
||||
0,
|
||||
selection.start.column + 1,
|
||||
rowDiff,
|
||||
selection.end.column + (rowDiff ? 0 : 1)
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
var CstyleBehaviour = function() {
|
||||
this.add("braces", "insertion", function(state, action, editor, session, text) {
|
||||
var cursor = editor.getCursorPosition();
|
||||
|
|
@ -72,10 +85,7 @@ var CstyleBehaviour = function() {
|
|||
var selection = editor.getSelectionRange();
|
||||
var selected = session.doc.getTextRange(selection);
|
||||
if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) {
|
||||
return {
|
||||
text: '{' + selected + '}',
|
||||
selection: false
|
||||
};
|
||||
return getWrapped(selection, selected, '{', '}');
|
||||
} else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
|
||||
if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) {
|
||||
CstyleBehaviour.recordAutoInsert(editor, session, "}");
|
||||
|
|
@ -155,10 +165,7 @@ var CstyleBehaviour = function() {
|
|||
var selection = editor.getSelectionRange();
|
||||
var selected = session.doc.getTextRange(selection);
|
||||
if (selected !== "" && editor.getWrapBehavioursEnabled()) {
|
||||
return {
|
||||
text: '(' + selected + ')',
|
||||
selection: false
|
||||
};
|
||||
return getWrapped(selection, selected, '(', ')');
|
||||
} else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
|
||||
CstyleBehaviour.recordAutoInsert(editor, session, ")");
|
||||
return {
|
||||
|
|
@ -203,10 +210,7 @@ var CstyleBehaviour = function() {
|
|||
var selection = editor.getSelectionRange();
|
||||
var selected = session.doc.getTextRange(selection);
|
||||
if (selected !== "" && editor.getWrapBehavioursEnabled()) {
|
||||
return {
|
||||
text: '[' + selected + ']',
|
||||
selection: false
|
||||
};
|
||||
return getWrapped(selection, selected, '[', ']');
|
||||
} else if (CstyleBehaviour.isSaneInsertion(editor, session)) {
|
||||
CstyleBehaviour.recordAutoInsert(editor, session, "]");
|
||||
return {
|
||||
|
|
@ -252,11 +256,8 @@ var CstyleBehaviour = function() {
|
|||
var selection = editor.getSelectionRange();
|
||||
var selected = session.doc.getTextRange(selection);
|
||||
if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) {
|
||||
return {
|
||||
text: quote + selected + quote,
|
||||
selection: false
|
||||
};
|
||||
} else {
|
||||
return getWrapped(selection, selected, quote, quote);
|
||||
} else if (!selected) {
|
||||
var cursor = editor.getCursorPosition();
|
||||
var line = session.doc.getLine(cursor.row);
|
||||
var leftChar = line.substring(cursor.column-1, cursor.column);
|
||||
|
|
@ -268,8 +269,8 @@ var CstyleBehaviour = function() {
|
|||
if (leftChar == "\\" && token && /escape/.test(token.type))
|
||||
return null;
|
||||
|
||||
var stringBefore = token && /string/.test(token.type);
|
||||
var stringAfter = !rightToken || /string/.test(rightToken.type);
|
||||
var stringBefore = token && /string|escape/.test(token.type);
|
||||
var stringAfter = !rightToken || /string|escape/.test(rightToken.type);
|
||||
|
||||
var pair;
|
||||
if (rightChar == quote) {
|
||||
|
|
@ -278,7 +279,7 @@ var CstyleBehaviour = function() {
|
|||
if (stringBefore && !stringAfter)
|
||||
return null; // wrap string with different quote
|
||||
if (stringBefore && stringAfter)
|
||||
return null; // do not pair quotes inside strings
|
||||
return null; // do not pair quotes inside strings
|
||||
var wordRe = session.$mode.tokenRe;
|
||||
wordRe.lastIndex = 0;
|
||||
var isWordBefore = wordRe.test(leftChar);
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ var XmlBehaviour = function () {
|
|||
var token = iterator.getCurrentToken();
|
||||
|
||||
if (token && token.type.indexOf("tag-close") !== -1) {
|
||||
if (token.value == "/>")
|
||||
return;
|
||||
//get tag name
|
||||
while (token && token.type.indexOf("tag-name") === -1) {
|
||||
token = iterator.stepBackward();
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ var c_cppHighlightRules = function() {
|
|||
var storageType = (
|
||||
"asm|__asm__|auto|bool|_Bool|char|_Complex|double|enum|float|" +
|
||||
"_Imaginary|int|long|short|signed|struct|typedef|union|unsigned|void|" +
|
||||
"class|wchar_t|template"
|
||||
"class|wchar_t|template|char16_t|char32_t"
|
||||
);
|
||||
|
||||
var storageModifiers = (
|
||||
"const|extern|register|restrict|static|volatile|inline|private|" +
|
||||
"protected|public|friend|explicit|virtual|export|mutable|typename|" +
|
||||
"constexpr|new|delete"
|
||||
"constexpr|new|delete|alignas|alignof|decltype|noexcept|thread_local"
|
||||
);
|
||||
|
||||
var keywordOperators = (
|
||||
|
|
@ -33,7 +33,7 @@ var c_cppHighlightRules = function() {
|
|||
);
|
||||
|
||||
var builtinConstants = (
|
||||
"NULL|true|false|TRUE|FALSE"
|
||||
"NULL|true|false|TRUE|FALSE|nullptr"
|
||||
);
|
||||
|
||||
var keywordMapper = this.$keywords = this.createKeywordMapper({
|
||||
|
|
|
|||
|
|
@ -116,11 +116,11 @@ oop.inherits(Mode, TextMode);
|
|||
var worker = new WorkerClient(["ace"], "ace/mode/coffee_worker", "Worker");
|
||||
worker.attachToDocument(session.getDocument());
|
||||
|
||||
worker.on("error", function(e) {
|
||||
session.setAnnotations([e.data]);
|
||||
worker.on("annotate", function(e) {
|
||||
session.setAnnotations(e.data);
|
||||
});
|
||||
|
||||
worker.on("ok", function(e) {
|
||||
worker.on("terminate", function() {
|
||||
session.clearAnnotations();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -49,13 +49,13 @@ oop.inherits(Worker, Mirror);
|
|||
|
||||
this.onUpdate = function() {
|
||||
var value = this.doc.getValue();
|
||||
|
||||
var errors = [];
|
||||
try {
|
||||
coffee.parse(value).compile();
|
||||
} catch(e) {
|
||||
var loc = e.location;
|
||||
if (loc) {
|
||||
this.sender.emit("error", {
|
||||
errors.push({
|
||||
row: loc.first_line,
|
||||
column: loc.first_column,
|
||||
endRow: loc.last_line,
|
||||
|
|
@ -64,9 +64,8 @@ oop.inherits(Worker, Mirror);
|
|||
type: "error"
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.sender.emit("ok");
|
||||
this.sender.emit("annotate", errors);
|
||||
};
|
||||
|
||||
}).call(Worker.prototype);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ oop.inherits(Mode, TextMode);
|
|||
var worker = new WorkerClient(["ace"], "ace/mode/css_worker", "Worker");
|
||||
worker.attachToDocument(session.getDocument());
|
||||
|
||||
worker.on("csslint", function(e) {
|
||||
worker.on("annotate", function(e) {
|
||||
session.setAnnotations(e.data);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ var supportType = exports.supportType = "animation-fill-mode|alignment-adjust|al
|
|||
var supportFunction = exports.supportFunction = "rgb|rgba|url|attr|counter|counters";
|
||||
var supportConstant = exports.supportConstant = "absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero";
|
||||
var supportConstantColor = exports.supportConstantColor = "aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow";
|
||||
var supportConstantFonts = exports.supportConstantFonts = "arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace";
|
||||
var supportConstantFonts = exports.supportConstantFonts = "arial|century|comic|courier|cursive|fantasy|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace";
|
||||
|
||||
var numRe = exports.numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
|
||||
var pseudoElements = exports.pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b";
|
||||
|
|
|
|||
|
|
@ -80,11 +80,11 @@ oop.inherits(Worker, Mirror);
|
|||
this.onUpdate = function() {
|
||||
var value = this.doc.getValue();
|
||||
if (!value)
|
||||
return this.sender.emit("csslint", []);
|
||||
return this.sender.emit("annotate", []);
|
||||
var infoRules = this.infoRules;
|
||||
|
||||
var result = CSSLint.verify(value, this.ruleset);
|
||||
this.sender.emit("csslint", result.messages.map(function(msg) {
|
||||
this.sender.emit("annotate", result.messages.map(function(msg) {
|
||||
return {
|
||||
row: msg.line - 1,
|
||||
column: msg.col - 1,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ oop.inherits(FoldMode, BaseFoldMode);
|
|||
this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/;
|
||||
this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/;
|
||||
this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
|
||||
this.startRegionRe = /^\s*(\/\*|\/\/)#region\b/;
|
||||
this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
|
||||
|
||||
//prevent naming conflict with any modes that inherit from cstyle and override this (like csharp)
|
||||
this._getFoldWidgetBase = this.getFoldWidget;
|
||||
|
|
@ -69,6 +69,8 @@ oop.inherits(FoldMode, BaseFoldMode);
|
|||
*
|
||||
* @example tripleStarFoldingSection
|
||||
* /*** this folds even though 1 line because it has 3 stars ***[/]
|
||||
*
|
||||
* @note the pound symbol for region tags is optional
|
||||
*/
|
||||
this.getFoldWidget = function(session, foldStyle, row) {
|
||||
var line = session.getLine(row);
|
||||
|
|
@ -158,12 +160,16 @@ oop.inherits(FoldMode, BaseFoldMode);
|
|||
return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
|
||||
};
|
||||
|
||||
/**
|
||||
* gets comment region block with end region assumed to be start of comment in any cstyle mode or SQL mode (--) which inherits from this.
|
||||
* There may optionally be a pound symbol before the region/endregion statement
|
||||
*/
|
||||
this.getCommentRegionBlock = function(session, line, row) {
|
||||
var startColumn = line.search(/\s*$/);
|
||||
var maxRow = session.getLength();
|
||||
var startRow = row;
|
||||
|
||||
var re = /^\s*(?:\/\*|\/\/)#(end)?region\b/;
|
||||
var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
|
||||
var depth = 1;
|
||||
while (++row < maxRow) {
|
||||
line = session.getLine(row);
|
||||
|
|
|
|||
111
lib/ace/mode/folding/sqlserver.js
Normal file
111
lib/ace/mode/folding/sqlserver.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/* ***** 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) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../../lib/oop");
|
||||
var Range = require("../../range").Range;
|
||||
var BaseFoldMode = require("./cstyle").FoldMode;
|
||||
|
||||
var FoldMode = exports.FoldMode = function() {};
|
||||
|
||||
oop.inherits(FoldMode, BaseFoldMode);
|
||||
|
||||
(function() {
|
||||
/**
|
||||
* Inheriting cstyle folding because it handles the region comment folding
|
||||
* and special block comment folding appropriately.
|
||||
*
|
||||
* Cstyle's getCommentRegionBlock() contains the sql comment characters '--' for end region block.
|
||||
*/
|
||||
|
||||
this.foldingStartMarker = /(\bCASE\b|\bBEGIN\b)|^\s*(\/\*)/i;
|
||||
// this.foldingStopMarker = /(\bEND\b)|^[\s\*]*(\*\/)/i;
|
||||
this.startRegionRe = /^\s*(\/\*|--)#?region\b/;
|
||||
|
||||
this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) {
|
||||
var line = session.getLine(row);
|
||||
|
||||
if (this.startRegionRe.test(line)) return this.getCommentRegionBlock(session, line, row);
|
||||
|
||||
var match = line.match(this.foldingStartMarker);
|
||||
if (match) {
|
||||
var i = match.index;
|
||||
if (match[1]) return this.getBeginEndBlock(session, row, i, match[1]);
|
||||
|
||||
var range = session.getCommentFoldRange(row, i + match[0].length, 1);
|
||||
if (range && !range.isMultiLine()) {
|
||||
if (forceMultiline) {
|
||||
range = this.getSectionRange(session, row);
|
||||
}
|
||||
else if (foldStyle != "all") range = null;
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
if (foldStyle === "markbegin") return;
|
||||
//TODO: add support for end folding markers
|
||||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {range} folding block for sequence that starts with 'CASE' or 'BEGIN' and ends with 'END'
|
||||
* @param {string} matchSequence - the sequence of charaters that started the fold widget, which should remain visible when the fold widget is folded
|
||||
*/
|
||||
this.getBeginEndBlock = function(session, row, column, matchSequence) {
|
||||
var start = {
|
||||
row: row,
|
||||
column: column + matchSequence.length
|
||||
};
|
||||
var maxRow = session.getLength();
|
||||
var line;
|
||||
|
||||
var depth = 1;
|
||||
var re = /(\bCASE\b|\bBEGIN\b)|(\bEND\b)/i;
|
||||
while (++row < maxRow) {
|
||||
line = session.getLine(row);
|
||||
var m = re.exec(line);
|
||||
if (!m) continue;
|
||||
if (m[1]) depth++;
|
||||
else depth--;
|
||||
|
||||
if (!depth) break;
|
||||
}
|
||||
var endRow = row;
|
||||
if (endRow > start.row) {
|
||||
return new Range(start.row, start.column, endRow, line.length);
|
||||
}
|
||||
};
|
||||
|
||||
}).call(FoldMode.prototype);
|
||||
|
||||
});
|
||||
|
|
@ -36,18 +36,18 @@ var stringEscape = "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]
|
|||
|
||||
var GherkinHighlightRules = function() {
|
||||
|
||||
// need to include constant ints
|
||||
// need to include constant ints
|
||||
this.$rules = {
|
||||
start : [{
|
||||
start : [{
|
||||
token: 'constant.numeric',
|
||||
regex: "(?:(?:[1-9]\\d*)|(?:0))"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
token : "keyword",
|
||||
regex : "Feature:|Background:|Scenario:|Scenario\ Outline:|Examples:|Given|When|Then|And|But|\\*",
|
||||
}, {
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
token : "keyword",
|
||||
regex : "Feature:|Background:|Scenario:|Scenario\ Outline:|Examples:|Given|When|Then|And|But|\\*",
|
||||
}, {
|
||||
token : "string", // multi line """ string start
|
||||
regex : '"{3}',
|
||||
next : "qqstring3"
|
||||
|
|
@ -56,22 +56,22 @@ var GherkinHighlightRules = function() {
|
|||
regex : '"',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "@[A-Za-z0-9]+",
|
||||
next : "start"
|
||||
token : "comment",
|
||||
regex : "@[A-Za-z0-9]+",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "<.+>"
|
||||
token : "comment",
|
||||
regex : "<.+>"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "\\| ",
|
||||
next : "table-item"
|
||||
token : "comment",
|
||||
regex : "\\|(?=.)",
|
||||
next : "table-item"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "\\|$",
|
||||
next : "start"
|
||||
token : "comment",
|
||||
regex : "\\|$",
|
||||
next : "start"
|
||||
}],
|
||||
"qqstring3" : [ {
|
||||
"qqstring3" : [ {
|
||||
token : "constant.language.escape",
|
||||
regex : stringEscape
|
||||
}, {
|
||||
|
|
@ -81,7 +81,7 @@ var GherkinHighlightRules = function() {
|
|||
}, {
|
||||
defaultToken : "string"
|
||||
}],
|
||||
"qqstring" : [{
|
||||
"qqstring" : [{
|
||||
token : "constant.language.escape",
|
||||
regex : stringEscape
|
||||
}, {
|
||||
|
|
@ -96,15 +96,19 @@ var GherkinHighlightRules = function() {
|
|||
defaultToken: "string"
|
||||
}],
|
||||
"table-item" : [{
|
||||
token : "comment",
|
||||
regex : /$/,
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : /\|/
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "[A-Za-z0-9 ]*",
|
||||
next : "start"
|
||||
}],
|
||||
regex : /\\./
|
||||
}, {
|
||||
defaultToken : "string"
|
||||
}]
|
||||
};
|
||||
|
||||
|
||||
//new TextHighlightRules().getRules();
|
||||
|
||||
}
|
||||
|
||||
oop.inherits(GherkinHighlightRules, TextHighlightRules);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ var Mode = function() {
|
|||
HtmlMode.call(this);
|
||||
this.HighlightRules = HandlebarsHighlightRules;
|
||||
this.$behaviour = new HtmlBehaviour();
|
||||
|
||||
|
||||
this.foldingRules = new HtmlFoldMode();
|
||||
};
|
||||
|
|
@ -21,7 +20,7 @@ var Mode = function() {
|
|||
oop.inherits(Mode, HtmlMode);
|
||||
|
||||
(function() {
|
||||
this.blockComment = {start: "{!--", end: "--}"};
|
||||
this.blockComment = {start: "{{!--", end: "--}}"};
|
||||
this.$id = "ace/mode/handlebars";
|
||||
}).call(Mode.prototype);
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ var HtmlHighlightRules = function() {
|
|||
include : "tag_whitespace"
|
||||
}, {
|
||||
token : "entity.other.attribute-name.xml",
|
||||
regex : "[-_a-zA-Z0-9:]+"
|
||||
regex : "[-_a-zA-Z0-9:.]+"
|
||||
}, {
|
||||
token : "keyword.operator.attribute-equals.xml",
|
||||
regex : "=",
|
||||
|
|
@ -89,7 +89,7 @@ var HtmlHighlightRules = function() {
|
|||
return ["meta.tag.punctuation." + (start == "<" ? "" : "end-") + "tag-open.xml",
|
||||
"meta.tag" + (group ? "." + group : "") + ".tag-name.xml"];
|
||||
},
|
||||
regex : "(</?)([-_a-zA-Z0-9:]+)",
|
||||
regex : "(</?)([-_a-zA-Z0-9:.]+)",
|
||||
next: "tag_stuff"
|
||||
}],
|
||||
tag_stuff: [
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ oop.inherits(Mode, TextMode);
|
|||
var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker");
|
||||
worker.attachToDocument(session.getDocument());
|
||||
|
||||
worker.on("jslint", function(results) {
|
||||
worker.on("annotate", function(results) {
|
||||
session.setAnnotations(results.data);
|
||||
});
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -172,7 +172,7 @@ var JavaScriptHighlightRules = function(options) {
|
|||
regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
|
||||
}, {
|
||||
token : ["punctuation.operator", "support.function.dom"],
|
||||
regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
|
||||
regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
|
||||
}, {
|
||||
token : ["punctuation.operator", "support.constant"],
|
||||
regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
|
||||
|
|
|
|||
|
|
@ -116,12 +116,10 @@ oop.inherits(JavaScriptWorker, Mirror);
|
|||
this.onUpdate = function() {
|
||||
var value = this.doc.getValue();
|
||||
value = value.replace(/^#!.*\n/, "\n");
|
||||
if (!value) {
|
||||
this.sender.emit("jslint", []);
|
||||
return;
|
||||
}
|
||||
var errors = [];
|
||||
if (!value)
|
||||
return this.sender.emit("annotate", []);
|
||||
|
||||
var errors = [];
|
||||
// jshint reports many false errors
|
||||
// report them as error only if code is actually invalid
|
||||
var maxErrorLevel = this.isValidJS(value) ? "warning" : "error";
|
||||
|
|
@ -179,7 +177,7 @@ oop.inherits(JavaScriptWorker, Mirror);
|
|||
}
|
||||
// console.log("lint time: " + (new Date() - start));
|
||||
|
||||
this.sender.emit("jslint", errors);
|
||||
this.sender.emit("annotate", errors);
|
||||
};
|
||||
|
||||
}).call(JavaScriptWorker.prototype);
|
||||
|
|
|
|||
|
|
@ -74,11 +74,11 @@ oop.inherits(Mode, TextMode);
|
|||
var worker = new WorkerClient(["ace"], "ace/mode/json_worker", "JsonWorker");
|
||||
worker.attachToDocument(session.getDocument());
|
||||
|
||||
worker.on("error", function(e) {
|
||||
session.setAnnotations([e.data]);
|
||||
worker.on("annotate", function(e) {
|
||||
session.setAnnotations(e.data);
|
||||
});
|
||||
|
||||
worker.on("ok", function() {
|
||||
worker.on("terminate", function() {
|
||||
session.clearAnnotations();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -46,21 +46,20 @@ oop.inherits(JsonWorker, Mirror);
|
|||
|
||||
this.onUpdate = function() {
|
||||
var value = this.doc.getValue();
|
||||
|
||||
var errors = [];
|
||||
try {
|
||||
if (value)
|
||||
parse(value);
|
||||
} catch (e) {
|
||||
var pos = this.doc.indexToPosition(e.at-1);
|
||||
this.sender.emit("error", {
|
||||
errors.push({
|
||||
row: pos.row,
|
||||
column: pos.column,
|
||||
text: e.message,
|
||||
type: "error"
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.sender.emit("ok");
|
||||
this.sender.emit("annotate", errors);
|
||||
};
|
||||
|
||||
}).call(JsonWorker.prototype);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ module.exports = {
|
|||
worker.setValue("{}");
|
||||
worker.deferredUpdate.call();
|
||||
|
||||
assert.equal(this.sender.events[0][0], "ok");
|
||||
assert.equal(this.sender.events[0][1].length, 0);
|
||||
},
|
||||
|
||||
"test check for syntax error": function() {
|
||||
|
|
@ -71,11 +71,12 @@ module.exports = {
|
|||
worker.deferredUpdate.call();
|
||||
|
||||
var event = this.sender.events[0];
|
||||
assert.equal(event[0], "error");
|
||||
assert.equal(event[1].type, "error");
|
||||
assert.equal(event[1].text, "Bad string");
|
||||
assert.equal(event[1].row, 1);
|
||||
assert.equal(event[1].column, 0);
|
||||
assert.equal(event[0], "annotate");
|
||||
assert.equal(event[1].length, 1);
|
||||
assert.equal(event[1][0].type, "error");
|
||||
assert.equal(event[1][0].text, "Bad string");
|
||||
assert.equal(event[1][0].row, 1);
|
||||
assert.equal(event[1][0].column, 0);
|
||||
|
||||
},
|
||||
|
||||
|
|
@ -85,11 +86,11 @@ module.exports = {
|
|||
worker.deferredUpdate.call();
|
||||
|
||||
var event = this.sender.events[0];
|
||||
assert.equal(event[0], "error");
|
||||
assert.equal(event[1].type, "error");
|
||||
assert.equal(event[1].text, "Unexpected 'x'");
|
||||
assert.equal(event[1].row, 0);
|
||||
assert.equal(event[1].column, 0);
|
||||
assert.equal(event[0], "annotate");
|
||||
assert.equal(event[1][0].type, "error");
|
||||
assert.equal(event[1][0].text, "Unexpected 'x'");
|
||||
assert.equal(event[1][0].row, 0);
|
||||
assert.equal(event[1][0].column, 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
101
lib/ace/mode/lean.js
Normal file
101
lib/ace/mode/lean.js
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/* ***** 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) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextMode = require("./text").Mode;
|
||||
var leanHighlightRules = require("./lean_highlight_rules").leanHighlightRules;
|
||||
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
|
||||
var Range = require("../range").Range;
|
||||
// TODO(soonhok): figure out behavior and foldmode
|
||||
// var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
|
||||
// var CStyleFoldMode = require("./folding/cstyle").FoldMode;
|
||||
|
||||
var Mode = function() {
|
||||
this.HighlightRules = leanHighlightRules;
|
||||
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
// this.$behaviour = new CstyleBehaviour();
|
||||
// this.foldingRules = new CStyleFoldMode();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.lineCommentStart = "--";
|
||||
this.blockComment = {start: "/-", end: "-/"};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
var endState = tokenizedLine.state;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
} else if (state == "doc-start") {
|
||||
if (endState == "start") {
|
||||
return "";
|
||||
}
|
||||
var match = line.match(/^\s*(\/?)\*/);
|
||||
if (match) {
|
||||
if (match[1]) {
|
||||
indent += " ";
|
||||
}
|
||||
indent += "- ";
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
this.$id = "ace/mode/lean";
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
156
lib/ace/mode/lean_highlight_rules.js
Normal file
156
lib/ace/mode/lean_highlight_rules.js
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/* ***** 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) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
|
||||
var leanHighlightRules = function() {
|
||||
|
||||
var keywordControls = (
|
||||
[ "add_rewrite", "alias", "as", "assume", "attribute",
|
||||
"begin", "by", "calc", "calc_refl", "calc_subst", "calc_trans", "check",
|
||||
"classes", "coercions", "conjecture", "constants", "context",
|
||||
"corollary", "else", "end", "environment", "eval", "example",
|
||||
"exists", "exit", "export", "exposing", "extends", "fields", "find_decl",
|
||||
"forall", "from", "fun", "have", "help", "hiding", "if",
|
||||
"import", "in", "infix", "infixl", "infixr", "instances",
|
||||
"let", "local", "match", "namespace", "notation", "obtain", "obtains",
|
||||
"omit", "opaque", "open", "options", "parameter", "parameters", "postfix",
|
||||
"precedence", "prefix", "premise", "premises", "print", "private", "proof",
|
||||
"protected", "qed", "raw", "renaming", "section", "set_option",
|
||||
"show", "tactic_hint", "take", "then", "universe",
|
||||
"universes", "using", "variable", "variables", "with"].join("|")
|
||||
);
|
||||
|
||||
var nameProviders = (
|
||||
["inductive", "structure", "record", "theorem", "axiom",
|
||||
"axioms", "lemma", "hypothesis", "definition", "constant"].join("|")
|
||||
);
|
||||
|
||||
var storageType = (
|
||||
["Prop", "Type", "Type'", "Type₊", "Type₁", "Type₂", "Type₃"].join("|")
|
||||
);
|
||||
|
||||
var storageModifiers = (
|
||||
"\\[(" +
|
||||
["abbreviations", "all-transparent", "begin-end-hints", "class", "classes", "coercion",
|
||||
"coercions", "declarations", "decls", "instance", "irreducible",
|
||||
"multiple-instances", "notation", "notations", "parsing-only", "persistent",
|
||||
"reduce-hints", "reducible", "tactic-hints", "visible", "wf", "whnf"
|
||||
].join("|") +
|
||||
")\\]"
|
||||
);
|
||||
|
||||
var keywordOperators = (
|
||||
[].join("|")
|
||||
);
|
||||
|
||||
var keywordMapper = this.$keywords = this.createKeywordMapper({
|
||||
"keyword.control" : keywordControls,
|
||||
"storage.type" : storageType,
|
||||
"keyword.operator" : keywordOperators,
|
||||
"variable.language": "sorry",
|
||||
}, "identifier");
|
||||
|
||||
var identifierRe = "[A-Za-z_\u03b1-\u03ba\u03bc-\u03fb\u1f00-\u1ffe\u2100-\u214f][A-Za-z0-9_'\u03b1-\u03ba\u03bc-\u03fb\u1f00-\u1ffe\u2070-\u2079\u207f-\u2089\u2090-\u209c\u2100-\u214f]*";
|
||||
var operatorRe = new RegExp(["#", "@", "->", "∼", "↔", "/", "==", "=", ":=", "<->",
|
||||
"/\\", "\\/", "∧", "∨", "≠", "<", ">", "≤", "≥", "¬",
|
||||
"<=", ">=", "⁻¹", "⬝", "▸", "\\+", "\\*", "-", "/",
|
||||
"λ", "→", "∃", "∀", ":="].join("|"));
|
||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||
// regexps are ordered -> the first match is used
|
||||
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token : "comment", // single line comment "--"
|
||||
regex : "--.*$"
|
||||
},
|
||||
DocCommentHighlightRules.getStartRule("doc-start"),
|
||||
{
|
||||
token : "comment", // multi line comment "/-"
|
||||
regex : "\\/-",
|
||||
next : "comment"
|
||||
}, {
|
||||
stateName: "qqstring",
|
||||
token : "string.start", regex : '"', next : [
|
||||
{token : "string.end", regex : '"', next : "start"},
|
||||
{token : "constant.language.escape", regex : /\\[n"\\]/},
|
||||
{defaultToken: "string"}
|
||||
]
|
||||
}, {
|
||||
token : "keyword.control", regex : nameProviders, next : [
|
||||
{token : "variable.language", regex : identifierRe, next : "start"} ]
|
||||
}, {
|
||||
token : "constant.numeric", // hex
|
||||
regex : "0[xX][0-9a-fA-F]+(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b"
|
||||
}, {
|
||||
token : "storage.modifier",
|
||||
regex : storageModifiers
|
||||
}, {
|
||||
token : keywordMapper,
|
||||
regex : identifierRe
|
||||
}, {
|
||||
token : "operator",
|
||||
regex : operatorRe
|
||||
}, {
|
||||
token : "punctuation.operator",
|
||||
regex : "\\?|\\:|\\,|\\;|\\."
|
||||
}, {
|
||||
token : "paren.lparen",
|
||||
regex : "[[({]"
|
||||
}, {
|
||||
token : "paren.rparen",
|
||||
regex : "[\\])}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
}
|
||||
],
|
||||
"comment" : [ {token: "comment", regex: "-/", next: "start"},
|
||||
{defaultToken: "comment"} ]
|
||||
};
|
||||
|
||||
this.embedRules(DocCommentHighlightRules, "doc-",
|
||||
[ DocCommentHighlightRules.getEndRule("start") ]);
|
||||
this.normalizeRules();
|
||||
};
|
||||
|
||||
oop.inherits(leanHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.leanHighlightRules = leanHighlightRules;
|
||||
});
|
||||
|
|
@ -231,7 +231,7 @@ var LessHighlightRules = function() {
|
|||
regex: "\\.[a-z0-9-_]+"
|
||||
}, {
|
||||
token: "variable.language",
|
||||
regex: ":[a-z0-9-_]+"
|
||||
regex: ":[a-z_][a-z0-9-_]*"
|
||||
}, {
|
||||
token: "constant",
|
||||
regex: "[a-z0-9-_]+"
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue